Skip to content

Commit 361cc17

Browse files
committed
added public key check for SCTs
Signed-off-by: Horiodino <[email protected]> added public key check for SCTs Signed-off-by: Horiodino <[email protected]>
1 parent 693bbb2 commit 361cc17

File tree

7 files changed

+46
-34
lines changed

7 files changed

+46
-34
lines changed

examples/sigstore-go-verification/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ func run() error {
186186
return errors.New("no trusted material provided")
187187
}
188188

189-
sev, err := verify.NewSignedEntityVerifier(trustedMaterial, verifierConfig...)
189+
sev, err := verify.NewSignedEntityVerifier(trustedMaterial, b, verifierConfig...)
190190
if err != nil {
191191
return err
192192
}

pkg/sign/signer.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,12 +139,12 @@ func Bundle(content Content, keypair Keypair, opts BundleOptions) (*protobundle.
139139
}
140140

141141
if opts.TrustedRoot != nil && len(verifierOptions) > 0 {
142-
sev, err := verify.NewSignedEntityVerifier(opts.TrustedRoot, verifierOptions...)
142+
protobundle, err := verifyBundle.NewBundle(bundle)
143143
if err != nil {
144144
return nil, err
145145
}
146146

147-
protobundle, err := verifyBundle.NewBundle(bundle)
147+
sev, err := verify.NewSignedEntityVerifier(opts.TrustedRoot, protobundle, verifierOptions...)
148148
if err != nil {
149149
return nil, err
150150
}

pkg/verify/fuzz_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func FuzzSignedEntityVerifier(f *testing.F) {
123123
if err != nil {
124124
t.Skip()
125125
}
126-
v, err := verify.NewSignedEntityVerifier(trustedRoot,
126+
v, err := verify.NewSignedEntityVerifier(trustedRoot, entity,
127127
verify.WithTransparencyLog(1),
128128
verify.WithObserverTimestamps(1))
129129
if err != nil {

pkg/verify/signature_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func TestEnvelopeSubject(t *testing.T) {
7272
entity, err := virtualSigstore.Attest("[email protected]", "issuer", statement)
7373
assert.NoError(t, err)
7474

75-
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
75+
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, entity, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
7676
assert.NoError(t, err)
7777

7878
_, err = verifier.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -101,7 +101,7 @@ func TestSignatureVerifierMessageSignature(t *testing.T) {
101101
entity, err := virtualSigstore.Sign("[email protected]", "issuer", []byte(artifact))
102102
assert.NoError(t, err)
103103

104-
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
104+
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, entity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
105105
assert.NoError(t, err)
106106

107107
result, err := verifier.Verify(entity, verify.NewPolicy(verify.WithArtifact(bytes.NewBufferString(artifact)), verify.WithoutIdentitiesUnsafe()))
@@ -137,7 +137,7 @@ func TestTooManySubjects(t *testing.T) {
137137
tooManySubjectsEntity, err := virtualSigstore.Attest("[email protected]", "issuer", tooManySubjectsStatementBytes)
138138
assert.NoError(t, err)
139139

140-
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
140+
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, tooManySubjectsEntity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
141141
assert.NoError(t, err)
142142

143143
artifact := "Hi, I am an artifact!" //nolint:goconst
@@ -167,7 +167,7 @@ func TestTooManyDigests(t *testing.T) {
167167
tooManySubjectsEntity, err := virtualSigstore.Attest("[email protected]", "issuer", tooManySubjectsStatementBytes)
168168
assert.NoError(t, err)
169169

170-
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
170+
verifier, err := verify.NewSignedEntityVerifier(virtualSigstore, tooManySubjectsEntity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
171171
assert.NoError(t, err)
172172

173173
artifact := "Hi, I am an artifact!" //nolint:goconst

pkg/verify/signed_entity.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ type VerifierOption func(*VerifierConfig) error
8383
// VerifierConfig's set of options should match the properties of a given
8484
// Sigstore deployment, i.e. whether to expect SCTs, Tlog entries, or signed
8585
// timestamps.
86-
func NewSignedEntityVerifier(trustedMaterial root.TrustedMaterial, options ...VerifierOption) (*SignedEntityVerifier, error) {
86+
func NewSignedEntityVerifier(trustedMaterial root.TrustedMaterial, entity SignedEntity, options ...VerifierOption) (*SignedEntityVerifier, error) {
8787
var err error
8888
c := VerifierConfig{}
8989

@@ -104,6 +104,18 @@ func NewSignedEntityVerifier(trustedMaterial root.TrustedMaterial, options ...Ve
104104
config: c,
105105
}
106106

107+
// Early check: If SCTs are required, ensure the bundle is certificate-signed not public key-signed
108+
if v.config.requireSCTs {
109+
verificationContent, err := entity.VerificationContent()
110+
if err != nil {
111+
return nil, fmt.Errorf("failed to fetch verification content: %w", err)
112+
}
113+
114+
if verificationContent.PublicKey() != nil {
115+
return nil, errors.New("SCTs required but bundle is signed with a public key, which cannot contain SCTs")
116+
}
117+
}
118+
107119
return v, nil
108120
}
109121

pkg/verify/signed_entity_test.go

+24-24
Original file line numberDiff line numberDiff line change
@@ -34,43 +34,43 @@ func TestSignedEntityVerifierInitialization(t *testing.T) {
3434
tr := data.TrustedRoot(t, "public-good.json")
3535

3636
// can't create a verifier without specifying either tlog or tsa
37-
_, err := verify.NewSignedEntityVerifier(tr)
37+
_, err := verify.NewSignedEntityVerifier(tr, nil)
3838
assert.NotNil(t, err)
3939

4040
// can create a verifier with both of them
41-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
41+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
4242
assert.Nil(t, err)
4343

4444
// unless we are really sure we want a verifier without either tlog or tsa
45-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithCurrentTime())
45+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithCurrentTime())
4646
assert.Nil(t, err)
4747

4848
// can configure the verifiers with thresholds
49-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(2), verify.WithSignedTimestamps(10))
49+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(2), verify.WithSignedTimestamps(10))
5050

5151
assert.Nil(t, err)
5252

5353
// can't configure them with < 1 thresholds
54-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(0), verify.WithSignedTimestamps(-10))
54+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(0), verify.WithSignedTimestamps(-10))
5555
assert.Error(t, err)
5656
}
5757

5858
func TestSignedEntityVerifierInitRequiresTimestamp(t *testing.T) {
5959
tr := data.TrustedRoot(t, "public-good.json")
6060

61-
_, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1))
61+
_, err := verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(1))
6262
assert.Error(t, err)
6363
if !strings.Contains(err.Error(), "you must specify at least one of") {
6464
t.Errorf("expected error missing timestamp verifier, got: %v", err)
6565
}
6666

67-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
67+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
6868
assert.NoError(t, err)
69-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
69+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
7070
assert.NoError(t, err)
71-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
71+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
7272
assert.NoError(t, err)
73-
_, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithCurrentTime())
73+
_, err = verify.NewSignedEntityVerifier(tr, nil, verify.WithTransparencyLog(1), verify.WithCurrentTime())
7474
assert.NoError(t, err)
7575
}
7676

@@ -83,7 +83,7 @@ func TestEntitySignedByPublicGoodWithTlogVerifiesSuccessfully(t *testing.T) {
8383
tr := data.TrustedRoot(t, "public-good.json")
8484
entity := data.Bundle(t, "[email protected]")
8585

86-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
86+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
8787
assert.NoError(t, err)
8888

8989
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -99,7 +99,7 @@ func TestEntitySignedByPublicGoodWithTlogVerifiesSuccessfully(t *testing.T) {
9999
assert.Equal(t, "https://rekor.sigstore.dev", res.VerifiedTimestamps[0].URI)
100100

101101
// verifies with integrated timestamp threshold too
102-
v, err = verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
102+
v, err = verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
103103
assert.NoError(t, err)
104104
res, err = v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
105105
assert.NoError(t, err)
@@ -110,7 +110,7 @@ func TestEntitySignedByPublicGoodWithoutTimestampsVerifiesSuccessfully(t *testin
110110
tr := data.TrustedRoot(t, "public-good.json")
111111
entity := data.Bundle(t, "[email protected]")
112112

113-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
113+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
114114
assert.NoError(t, err)
115115

116116
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -122,7 +122,7 @@ func TestEntitySignedByPublicGoodWithHighTlogThresholdFails(t *testing.T) {
122122
tr := data.TrustedRoot(t, "public-good.json")
123123
entity := data.Bundle(t, "[email protected]")
124124

125-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(2), verify.WithObserverTimestamps(1))
125+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(2), verify.WithObserverTimestamps(1))
126126
assert.NoError(t, err)
127127

128128
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -137,7 +137,7 @@ func TestEntitySignedByPublicGoodWithoutVerifyingLogEntryFails(t *testing.T) {
137137
tr := data.TrustedRoot(t, "public-good.json")
138138
entity := data.Bundle(t, "[email protected]")
139139

140-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithObserverTimestamps(1))
140+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithObserverTimestamps(1))
141141
assert.NoError(t, err)
142142

143143
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -148,7 +148,7 @@ func TestEntitySignedByPublicGoodWithoutVerifyingLogEntryFails(t *testing.T) {
148148
}
149149

150150
// also fails trying to use integrated timestamps without verifying the log
151-
v, err = verify.NewSignedEntityVerifier(tr, verify.WithIntegratedTimestamps(1))
151+
v, err = verify.NewSignedEntityVerifier(tr, entity, verify.WithIntegratedTimestamps(1))
152152
assert.NoError(t, err)
153153
res, err = v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
154154
assert.Error(t, err)
@@ -162,7 +162,7 @@ func TestEntitySignedByPublicGoodWithHighLogTimestampThresholdFails(t *testing.T
162162
tr := data.TrustedRoot(t, "public-good.json")
163163
entity := data.Bundle(t, "[email protected]")
164164

165-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(2))
165+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(2))
166166
assert.NoError(t, err)
167167

168168
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -177,7 +177,7 @@ func TestEntitySignedByPublicGoodExpectingTSAFails(t *testing.T) {
177177
tr := data.TrustedRoot(t, "public-good.json")
178178
entity := data.Bundle(t, "[email protected]")
179179

180-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
180+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithSignedTimestamps(1))
181181
assert.NoError(t, err)
182182

183183
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -192,7 +192,7 @@ func TestEntitySignedByPublicGoodWithHighObserverTimestampThresholdFails(t *test
192192
tr := data.TrustedRoot(t, "public-good.json")
193193
entity := data.Bundle(t, "[email protected]")
194194

195-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(2))
195+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(2))
196196
assert.NoError(t, err)
197197

198198
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -207,7 +207,7 @@ func TestEntityWithOthernameSan(t *testing.T) {
207207
tr := data.TrustedRoot(t, "scaffolding.json")
208208
entity := data.Bundle(t, "othername.sigstore.json")
209209

210-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
210+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
211211
assert.NoError(t, err)
212212

213213
digest, err := hex.DecodeString("bc103b4a84971ef6459b294a2b98568a2bfb72cded09d4acd1e16366a401f95b")
@@ -235,7 +235,7 @@ func TestVerifyPolicyOptionErors(t *testing.T) {
235235
tr := data.TrustedRoot(t, "public-good.json")
236236
entity := data.Bundle(t, "[email protected]")
237237

238-
verifier, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
238+
verifier, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
239239
assert.Nil(t, err)
240240

241241
goodCertID, err := verify.NewShortCertificateIdentity(verify.ActionsIssuerValue, "", "", verify.SigstoreSanRegex)
@@ -332,7 +332,7 @@ func TestEntitySignedByPublicGoodWithCertificateIdentityVerifiesSuccessfully(t *
332332
goodCI, _ := verify.NewShortCertificateIdentity(verify.ActionsIssuerValue, "", "", verify.SigstoreSanRegex)
333333
badCI, _ := verify.NewShortCertificateIdentity(verify.ActionsIssuerValue, "", "BadSANValue", "")
334334

335-
verifier, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
335+
verifier, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
336336

337337
assert.Nil(t, err)
338338

@@ -380,7 +380,7 @@ func TestThatAllTheJSONKeysStartWithALowerCase(t *testing.T) {
380380
tr := data.TrustedRoot(t, "public-good.json")
381381
entity := data.Bundle(t, "[email protected]")
382382

383-
verifier, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
383+
verifier, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
384384
assert.Nil(t, err)
385385

386386
res, err := verifier.Verify(entity, SkipArtifactAndIdentitiesPolicy)
@@ -417,7 +417,7 @@ func TestSigstoreBundle2Sig(t *testing.T) {
417417
tr := data.TrustedRoot(t, "public-good.json")
418418
entity := data.Bundle(t, "dsse-2sigs.sigstore.json")
419419

420-
v, err := verify.NewSignedEntityVerifier(tr, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
420+
v, err := verify.NewSignedEntityVerifier(tr, entity, verify.WithTransparencyLog(1), verify.WithObserverTimestamps(1))
421421
assert.NoError(t, err)
422422

423423
res, err := v.Verify(entity, SkipArtifactAndIdentitiesPolicy)

test/conformance/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ func main() {
247247
verifierConfig = append(verifierConfig, verify.WithTransparencyLog(1), verify.WithIntegratedTimestamps(1))
248248
}
249249

250-
sev, err := verify.NewSignedEntityVerifier(tr, verifierConfig...)
250+
sev, err := verify.NewSignedEntityVerifier(tr, b, verifierConfig...)
251251
if err != nil {
252252
log.Fatal(err)
253253
}

0 commit comments

Comments
 (0)