24
24
import com .google .errorprone .annotations .concurrent .GuardedBy ;
25
25
import com .google .protobuf .ByteString ;
26
26
import dev .sigstore .bundle .Bundle ;
27
- import dev .sigstore .bundle .Bundle .HashAlgorithm ;
28
27
import dev .sigstore .bundle .Bundle .MessageSignature ;
29
28
import dev .sigstore .bundle .ImmutableBundle ;
30
29
import dev .sigstore .bundle .ImmutableTimestamp ;
41
40
import dev .sigstore .oidc .client .OidcException ;
42
41
import dev .sigstore .oidc .client .OidcToken ;
43
42
import dev .sigstore .oidc .client .OidcTokenMatcher ;
44
- import dev .sigstore .proto .common . v1 . PublicKeyDetails ;
43
+ import dev .sigstore .proto .ProtoMutators ;
45
44
import dev .sigstore .proto .common .v1 .X509Certificate ;
46
45
import dev .sigstore .proto .rekor .v2 .HashedRekordRequestV002 ;
47
46
import dev .sigstore .proto .rekor .v2 .Signature ;
@@ -114,6 +113,7 @@ public class KeylessSigner implements AutoCloseable {
114
113
private final OidcClients oidcClients ;
115
114
private final List <OidcTokenMatcher > oidcIdentities ;
116
115
private final Signer signer ;
116
+ private final AlgorithmRegistry .SigningAlgorithm signingAlgorithm ;
117
117
private final Duration minSigningCertificateLifetime ;
118
118
119
119
/** The code signing certificate from Fulcio. */
@@ -150,6 +150,7 @@ private KeylessSigner(
150
150
OidcClients oidcClients ,
151
151
List <OidcTokenMatcher > oidcIdentities ,
152
152
Signer signer ,
153
+ AlgorithmRegistry .SigningAlgorithm signingAlgorithm ,
153
154
Duration minSigningCertificateLifetime ) {
154
155
this .fulcioClient = fulcioClient ;
155
156
this .fulcioVerifier = fulcioVerifier ;
@@ -161,6 +162,7 @@ private KeylessSigner(
161
162
this .oidcClients = oidcClients ;
162
163
this .oidcIdentities = oidcIdentities ;
163
164
this .signer = signer ;
165
+ this .signingAlgorithm = signingAlgorithm ;
164
166
this .minSigningCertificateLifetime = minSigningCertificateLifetime ;
165
167
}
166
168
@@ -186,7 +188,7 @@ public static class Builder {
186
188
private SigningConfigProvider signingConfigProvider ;
187
189
private OidcClients oidcClients ;
188
190
private List <OidcTokenMatcher > oidcIdentities = Collections .emptyList ();
189
- private Signer signer ;
191
+ private AlgorithmRegistry . SigningAlgorithm signingAlgorithm ;
190
192
private Duration minSigningCertificateLifetime = DEFAULT_MIN_SIGNING_CERTIFICATE_LIFETIME ;
191
193
private boolean enableRekorV2 = false ;
192
194
@@ -239,8 +241,8 @@ public Builder allowedOidcIdentities(List<OidcTokenMatcher> oidcIdentities) {
239
241
}
240
242
241
243
@ CanIgnoreReturnValue
242
- public Builder signer ( Signer signer ) {
243
- this .signer = signer ;
244
+ public Builder signingAlgorithm ( AlgorithmRegistry . SigningAlgorithm signingAlgorithm ) {
245
+ this .signingAlgorithm = signingAlgorithm ;
244
246
return this ;
245
247
}
246
248
@@ -276,7 +278,7 @@ public KeylessSigner build()
276
278
Preconditions .checkNotNull (signingConfigProvider );
277
279
var signingConfig = signingConfigProvider .get ();
278
280
Preconditions .checkNotNull (oidcIdentities );
279
- Preconditions .checkNotNull (signer );
281
+ Preconditions .checkNotNull (signingAlgorithm );
280
282
Preconditions .checkNotNull (minSigningCertificateLifetime );
281
283
var fulcioService = Service .select (signingConfig .getCas (), List .of (1 ));
282
284
if (fulcioService .isEmpty ()) {
@@ -328,6 +330,12 @@ public KeylessSigner build()
328
330
oidcClients = OidcClients .from (oidcService .get ());
329
331
}
330
332
333
+ if (!signingAlgorithm .getHashing ().equals (AlgorithmRegistry .HashAlgorithm .SHA2_256 )) {
334
+ throw new SigstoreConfigurationException ("Signing algorithm must use sha256" );
335
+ }
336
+
337
+ var signer = Signers .from (signingAlgorithm );
338
+
331
339
return new KeylessSigner (
332
340
fulcioClient ,
333
341
fulcioVerifier ,
@@ -339,6 +347,7 @@ public KeylessSigner build()
339
347
oidcClients ,
340
348
oidcIdentities ,
341
349
signer ,
350
+ signingAlgorithm ,
342
351
minSigningCertificateLifetime );
343
352
}
344
353
@@ -354,7 +363,7 @@ public Builder sigstorePublicDefaults() {
354
363
signingConfigProvider =
355
364
SigningConfigProvider .fromOrDefault (
356
365
sigstoreTufClientBuilder , LegacySigningConfig .PUBLIC_GOOD );
357
- signer ( Signers . newEcdsaSigner ()) ;
366
+ signingAlgorithm = AlgorithmRegistry . SigningAlgorithm . PKIX_ECDSA_P256_SHA_256 ;
358
367
minSigningCertificateLifetime (DEFAULT_MIN_SIGNING_CERTIFICATE_LIFETIME );
359
368
return this ;
360
369
}
@@ -368,7 +377,7 @@ public Builder sigstoreStagingDefaults() {
368
377
var sigstoreTufClientBuilder = SigstoreTufClient .builder ().useStagingInstance ();
369
378
trustedRootProvider = TrustedRootProvider .from (sigstoreTufClientBuilder );
370
379
signingConfigProvider = SigningConfigProvider .from (sigstoreTufClientBuilder );
371
- signer ( Signers . newEcdsaSigner ()) ;
380
+ signingAlgorithm = AlgorithmRegistry . SigningAlgorithm . PKIX_ECDSA_P256_SHA_256 ;
372
381
minSigningCertificateLifetime (DEFAULT_MIN_SIGNING_CERTIFICATE_LIFETIME );
373
382
return this ;
374
383
}
@@ -384,11 +393,20 @@ public Builder sigstoreStagingDefaults() {
384
393
*/
385
394
@ CheckReturnValue
386
395
public List <Bundle > sign (List <byte []> artifactDigests ) throws KeylessSignerException {
387
-
388
- if (artifactDigests .size () == 0 ) {
396
+ if (artifactDigests .isEmpty ()) {
389
397
throw new IllegalArgumentException ("Require one or more digests" );
390
398
}
391
399
400
+ for (var digest : artifactDigests ) {
401
+ if (signingAlgorithm .getHashing ().getLength () != digest .length ) {
402
+ throw new KeylessSignerException (
403
+ "Invalid digest length: "
404
+ + digest .length
405
+ + " for signing Algorithm "
406
+ + signingAlgorithm );
407
+ }
408
+ }
409
+
392
410
var result = ImmutableList .<Bundle >builder ();
393
411
394
412
for (var artifactDigest : artifactDigests ) {
@@ -435,7 +453,7 @@ public List<Bundle> sign(List<byte[]> artifactDigests) throws KeylessSignerExcep
435
453
ImmutableBundle .builder ()
436
454
.certPath (signingCert )
437
455
.messageSignature (
438
- MessageSignature .of (HashAlgorithm . SHA2_256 , artifactDigest , signature ));
456
+ MessageSignature .of (signingAlgorithm . getHashing () , artifactDigest , signature ));
439
457
440
458
if (rekorV2Client != null ) { // Using Rekor v2 and a TSA
441
459
Preconditions .checkNotNull (
@@ -475,7 +493,7 @@ public List<Bundle> sign(List<byte[]> artifactDigests) throws KeylessSignerExcep
475
493
X509Certificate .newBuilder ()
476
494
.setRawBytes (ByteString .copyFrom (encodedCert ))
477
495
.build ())
478
- .setKeyDetails (PublicKeyDetails . PKIX_ECDSA_P256_SHA_256 )
496
+ .setKeyDetails (ProtoMutators . toPublicKeyDetails ( signingAlgorithm ) )
479
497
.build ();
480
498
481
499
var reqSignature =
@@ -610,7 +628,7 @@ private void renewSigningCertificate()
610
628
/**
611
629
* Convenience wrapper around {@link #sign(List)} to sign a single digest
612
630
*
613
- * @param artifactDigest sha256 digest of the artifact to sign.
631
+ * @param artifactDigest sha256 digest of the artifacts to sign.
614
632
* @return a keyless singing results.
615
633
*/
616
634
@ CheckReturnValue
@@ -626,14 +644,15 @@ public Bundle sign(byte[] artifactDigest) throws KeylessSignerException {
626
644
*/
627
645
@ CheckReturnValue
628
646
public Map <Path , Bundle > signFiles (List <Path > artifacts ) throws KeylessSignerException {
629
- if (artifacts .size () == 0 ) {
647
+ if (artifacts .isEmpty () ) {
630
648
throw new IllegalArgumentException ("Require one or more paths" );
631
649
}
632
650
var digests = new ArrayList <byte []>(artifacts .size ());
633
651
for (var artifact : artifacts ) {
634
652
var artifactByteSource = com .google .common .io .Files .asByteSource (artifact .toFile ());
635
653
try {
636
- digests .add (artifactByteSource .hash (Hashing .sha256 ()).asBytes ());
654
+ digests .add (
655
+ artifactByteSource .hash (signingAlgorithm .getHashing ().getHashFunction ()).asBytes ());
637
656
} catch (IOException ex ) {
638
657
throw new KeylessSignerException ("Failed to hash artifact " + artifact );
639
658
}
@@ -656,13 +675,4 @@ public Map<Path, Bundle> signFiles(List<Path> artifacts) throws KeylessSignerExc
656
675
public Bundle signFile (Path artifact ) throws KeylessSignerException {
657
676
return signFiles (List .of (artifact )).get (artifact );
658
677
}
659
-
660
- /**
661
- * Convenience wrapper around {@link #sign(List)} to accept a single file Compat - to be removed
662
- * before 1.0.0
663
- */
664
- @ Deprecated
665
- public Bundle signFile2 (Path artifact ) throws KeylessSignerException {
666
- return signFiles (List .of (artifact )).get (artifact );
667
- }
668
678
}
0 commit comments