Skip to content

Commit

Permalink
fix: corpus image generation
Browse files Browse the repository at this point in the history
Add OptSignWithoutPGPSignatureSalt, which disables randomization of
signature generation, and use that in the corpus to generate images
deterministically.

Update corpus images and related golden files to reflect the signatures
generated by the new version of go-crypto.
  • Loading branch information
tri-adam committed Nov 8, 2024
1 parent 869cab3 commit 071c3a8
Show file tree
Hide file tree
Showing 13 changed files with 62 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
Group ID: NONE
Linked ID: 1 (G)
Offset: 303104
Size: 1054
Size: 1048
Hash Type: SHA-256
Entity: 12045C8C0B1004D058DE4BEDA20C27EE7FF7BA84
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE
------------------------------------------------------------------------------
1 |1 |NONE |32768-32772 |FS (Raw/System/386)
2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386)
3 |NONE |1 (G) |40960-42014 |Signature (SHA-256)
3 |NONE |1 (G) |40960-42008 |Signature (SHA-256)
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE
1 |1 |NONE |32768-32772 |FS (Raw/System/386)
2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386)
3 |2 |NONE |40960-303104 |FS (Ext3/System/amd64)
4 |NONE |1 (G) |303104-304158 |Signature (SHA-256)
5 |NONE |2 (G) |304158-305013 |Signature (SHA-256)
4 |NONE |1 (G) |303104-304152 |Signature (SHA-256)
5 |NONE |2 (G) |304152-305001 |Signature (SHA-256)
15 changes: 6 additions & 9 deletions pkg/integrity/clearsign.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023, Sylabs Inc. All rights reserved.
// Copyright (c) 2020-2024, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the LICENSE.md file
// distributed with the sources of this project regarding your rights to use or distribute this
// software.
Expand All @@ -11,7 +11,6 @@ import (
"crypto"
"errors"
"io"
"time"

"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/clearsign"
Expand All @@ -25,14 +24,12 @@ type clearsignEncoder struct {
config *packet.Config
}

// newClearsignEncoder returns an encoder that signs messages in clear-sign format using entity e.
// If timeFunc is not nil, it is used to generate signature timestamps.
func newClearsignEncoder(e *openpgp.Entity, timeFunc func() time.Time) *clearsignEncoder {
// newClearsignEncoder returns an encoder that signs messages in clear-sign format using entity e,
// according to config.
func newClearsignEncoder(e *openpgp.Entity, config *packet.Config) *clearsignEncoder {
return &clearsignEncoder{
e: e,
config: &packet.Config{
Time: timeFunc,
},
e: e,
config: config,
}
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/integrity/clearsign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ func Test_clearsignEncoder_signMessage(t *testing.T) {
}{
{
name: "EncryptedKey",
en: newClearsignEncoder(encrypted, fixedTime),
en: newClearsignEncoder(encrypted, &packet.Config{Time: fixedTime}),
wantErr: true,
},
{
name: "OK",
en: newClearsignEncoder(e, fixedTime),
en: newClearsignEncoder(e, &packet.Config{Time: fixedTime}),
de: newClearsignDecoder(openpgp.EntityList{e}),
wantHash: crypto.SHA256,
},
Expand Down
35 changes: 23 additions & 12 deletions pkg/integrity/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sylabs/sif/v2/pkg/sif"
)
Expand Down Expand Up @@ -179,13 +180,14 @@ func (gs *groupSigner) sign(ctx context.Context) (sif.DescriptorInput, error) {
}

type signOpts struct {
ss []signature.Signer
e *openpgp.Entity
groupIDs []uint32
objectIDs [][]uint32
timeFunc func() time.Time
deterministic bool
ctx context.Context //nolint:containedctx
ss []signature.Signer
e *openpgp.Entity
groupIDs []uint32
objectIDs [][]uint32
timeFunc func() time.Time
deterministic bool
ctx context.Context //nolint:containedctx
withoutPGPSignatureSalt bool
}

// SignerOpt are used to configure so.
Expand Down Expand Up @@ -257,6 +259,16 @@ func OptSignWithContext(ctx context.Context) SignerOpt {
}
}

// OptSignWithoutPGPSignatureSalt disables the addition of a salt notation for v4 and v5 PGP keys.
// While this increases determinism, it should be used with caution as the salt notation increases
// protection for certain kinds of attacks.
func OptSignWithoutPGPSignatureSalt() SignerOpt {
return func(so *signOpts) error {
so.withoutPGPSignatureSalt = true
return nil
}
}

// withGroupedObjects splits the objects represented by ids into object groups, and calls fn once
// per object group.
func withGroupedObjects(f *sif.FileImage, ids []uint32, fn func(uint32, []uint32) error) error {
Expand Down Expand Up @@ -339,11 +351,10 @@ func NewSigner(f *sif.FileImage, opts ...SignerOpt) (*Signer, error) {
case so.ss != nil:
en = newDSSEEncoder(so.ss)
case so.e != nil:
timeFunc := time.Now
if so.timeFunc != nil {
timeFunc = so.timeFunc
}
en = newClearsignEncoder(so.e, timeFunc)
en = newClearsignEncoder(so.e, &packet.Config{
Time: so.timeFunc,
NonDeterministicSignaturesViaNotation: packet.BoolPointer(!so.withoutPGPSignatureSalt),
})
commonOpts = append(commonOpts, optSignGroupFingerprint(so.e.PrimaryKey.Fingerprint))
default:
return nil, fmt.Errorf("integrity: %w", ErrNoKeyMaterial)
Expand Down
24 changes: 21 additions & 3 deletions pkg/integrity/sign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"testing"

"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/sylabs/sif/v2/pkg/sif"
)

Expand Down Expand Up @@ -195,7 +196,7 @@ func TestNewGroupSigner(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
en := newClearsignEncoder(getTestEntity(t), fixedTime)
en := newClearsignEncoder(getTestEntity(t), &packet.Config{Time: fixedTime})

s, err := newGroupSigner(en, tt.fi, tt.groupID, tt.opts...)
if got, want := err, tt.wantErr; !errors.Is(got, want) {
Expand Down Expand Up @@ -254,12 +255,12 @@ func TestGroupSigner_Sign(t *testing.T) {
}

e := getTestEntity(t)
clearsign := newClearsignEncoder(e, fixedTime)
clearsign := newClearsignEncoder(e, &packet.Config{Time: fixedTime})

encrypted := getTestEntity(t)
encrypted.PrivateKey.Encrypted = true

clearsignEncrypted := newClearsignEncoder(encrypted, fixedTime)
clearsignEncrypted := newClearsignEncoder(encrypted, &packet.Config{Time: fixedTime})

tests := []struct {
name string
Expand Down Expand Up @@ -449,6 +450,11 @@ func TestNewSigner(t *testing.T) {
},
wantErr: sif.ErrNoObjects,
},
{
name: "NoKeyMaterial",
fi: oneGroupImage,
wantErr: ErrNoKeyMaterial,
},
{
name: "InvalidObjectID",
fi: oneGroupImage,
Expand Down Expand Up @@ -820,6 +826,18 @@ func TestSigner_Sign(t *testing.T) {
OptVerifyWithKeyRing(openpgp.EntityList{e}),
},
},
{
name: "OptSignWithoutPGPSignatureSalt",
inputFile: "one-group.sif",
signOpts: []SignerOpt{
OptSignWithEntity(e),
OptSignWithTime(fixedTime),
OptSignWithoutPGPSignatureSalt(),
},
verifyOpts: []VerifierOpt{
OptVerifyWithKeyRing(openpgp.EntityList{e}),
},
},
}

for _, tt := range tests {
Expand Down
2 changes: 1 addition & 1 deletion pkg/siftool/testdata/Test_command_getInfo/Three/out.golden
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
Group ID: NONE
Linked ID: 1 (G)
Offset: 40960
Size: 1054
Size: 1048
Hash Type: SHA-256
Entity: 12045C8C0B1004D058DE4BEDA20C27EE7FF7BA84
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE
------------------------------------------------------------------------------
1 |1 |NONE |32768-32772 |FS (Raw/System/386)
2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386)
3 |NONE |1 (G) |40960-42014 |Signature (SHA-256)
3 |NONE |1 (G) |40960-42008 |Signature (SHA-256)
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ ID |GROUP |LINK |SIF POSITION (start-end) |TYPE
1 |1 |NONE |32768-32772 |FS (Raw/System/386)
2 |1 |NONE |36864-40960 |FS (Squashfs/*System/386)
3 |2 |NONE |40960-303104 |FS (Ext3/System/amd64)
4 |NONE |1 (G) |303104-304158 |Signature (SHA-256)
5 |NONE |2 (G) |304158-305013 |Signature (SHA-256)
4 |NONE |1 (G) |303104-304152 |Signature (SHA-256)
5 |NONE |2 (G) |304152-305001 |Signature (SHA-256)
3 changes: 2 additions & 1 deletion test/images/gen_sifs.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2020-2023, Sylabs Inc. All rights reserved.
// Copyright (c) 2020-2024, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the LICENSE.md file
// distributed with the sources of this project regarding your rights to use or distribute this
// software.
Expand Down Expand Up @@ -294,6 +294,7 @@ func generateImages() error {
opts = append(opts,
integrity.OptSignWithTime(func() time.Time { return time.Date(2020, 6, 30, 0, 1, 56, 0, time.UTC) }),
integrity.OptSignDeterministic(),
integrity.OptSignWithoutPGPSignatureSalt(),
)

s, err := integrity.NewSigner(f, opts...)
Expand Down
Binary file modified test/images/one-group-signed-pgp.sif
Binary file not shown.
Binary file modified test/images/two-groups-signed-pgp.sif
Binary file not shown.

0 comments on commit 071c3a8

Please sign in to comment.