2424import com .google .errorprone .annotations .concurrent .GuardedBy ;
2525import com .google .protobuf .ByteString ;
2626import dev .sigstore .bundle .Bundle ;
27- import dev .sigstore .bundle .Bundle .HashAlgorithm ;
2827import dev .sigstore .bundle .Bundle .MessageSignature ;
2928import dev .sigstore .bundle .ImmutableBundle ;
3029import dev .sigstore .bundle .ImmutableTimestamp ;
4140import dev .sigstore .oidc .client .OidcException ;
4241import dev .sigstore .oidc .client .OidcToken ;
4342import dev .sigstore .oidc .client .OidcTokenMatcher ;
44- import dev .sigstore .proto .common . v1 . PublicKeyDetails ;
43+ import dev .sigstore .proto .ProtoMutators ;
4544import dev .sigstore .proto .common .v1 .X509Certificate ;
4645import dev .sigstore .proto .rekor .v2 .HashedRekordRequestV002 ;
4746import dev .sigstore .proto .rekor .v2 .Signature ;
@@ -114,6 +113,7 @@ public class KeylessSigner implements AutoCloseable {
114113 private final OidcClients oidcClients ;
115114 private final List <OidcTokenMatcher > oidcIdentities ;
116115 private final Signer signer ;
116+ private final AlgorithmRegistry .SigningAlgorithm signingAlgorithm ;
117117 private final Duration minSigningCertificateLifetime ;
118118
119119 /** The code signing certificate from Fulcio. */
@@ -150,6 +150,7 @@ private KeylessSigner(
150150 OidcClients oidcClients ,
151151 List <OidcTokenMatcher > oidcIdentities ,
152152 Signer signer ,
153+ AlgorithmRegistry .SigningAlgorithm signingAlgorithm ,
153154 Duration minSigningCertificateLifetime ) {
154155 this .fulcioClient = fulcioClient ;
155156 this .fulcioVerifier = fulcioVerifier ;
@@ -161,6 +162,7 @@ private KeylessSigner(
161162 this .oidcClients = oidcClients ;
162163 this .oidcIdentities = oidcIdentities ;
163164 this .signer = signer ;
165+ this .signingAlgorithm = signingAlgorithm ;
164166 this .minSigningCertificateLifetime = minSigningCertificateLifetime ;
165167 }
166168
@@ -186,7 +188,7 @@ public static class Builder {
186188 private SigningConfigProvider signingConfigProvider ;
187189 private OidcClients oidcClients ;
188190 private List <OidcTokenMatcher > oidcIdentities = Collections .emptyList ();
189- private Signer signer ;
191+ private AlgorithmRegistry . SigningAlgorithm signingAlgorithm ;
190192 private Duration minSigningCertificateLifetime = DEFAULT_MIN_SIGNING_CERTIFICATE_LIFETIME ;
191193 private boolean enableRekorV2 = false ;
192194
@@ -239,8 +241,8 @@ public Builder allowedOidcIdentities(List<OidcTokenMatcher> oidcIdentities) {
239241 }
240242
241243 @ CanIgnoreReturnValue
242- public Builder signer ( Signer signer ) {
243- this .signer = signer ;
244+ public Builder signingAlgorithm ( AlgorithmRegistry . SigningAlgorithm signingAlgorithm ) {
245+ this .signingAlgorithm = signingAlgorithm ;
244246 return this ;
245247 }
246248
@@ -276,7 +278,7 @@ public KeylessSigner build()
276278 Preconditions .checkNotNull (signingConfigProvider );
277279 var signingConfig = signingConfigProvider .get ();
278280 Preconditions .checkNotNull (oidcIdentities );
279- Preconditions .checkNotNull (signer );
281+ Preconditions .checkNotNull (signingAlgorithm );
280282 Preconditions .checkNotNull (minSigningCertificateLifetime );
281283 var fulcioService = Service .select (signingConfig .getCas (), List .of (1 ));
282284 if (fulcioService .isEmpty ()) {
@@ -328,6 +330,12 @@ public KeylessSigner build()
328330 oidcClients = OidcClients .from (oidcService .get ());
329331 }
330332
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+
331339 return new KeylessSigner (
332340 fulcioClient ,
333341 fulcioVerifier ,
@@ -339,6 +347,7 @@ public KeylessSigner build()
339347 oidcClients ,
340348 oidcIdentities ,
341349 signer ,
350+ signingAlgorithm ,
342351 minSigningCertificateLifetime );
343352 }
344353
@@ -354,7 +363,7 @@ public Builder sigstorePublicDefaults() {
354363 signingConfigProvider =
355364 SigningConfigProvider .fromOrDefault (
356365 sigstoreTufClientBuilder , LegacySigningConfig .PUBLIC_GOOD );
357- signer ( Signers . newEcdsaSigner ()) ;
366+ signingAlgorithm = AlgorithmRegistry . SigningAlgorithm . PKIX_ECDSA_P256_SHA_256 ;
358367 minSigningCertificateLifetime (DEFAULT_MIN_SIGNING_CERTIFICATE_LIFETIME );
359368 return this ;
360369 }
@@ -368,7 +377,7 @@ public Builder sigstoreStagingDefaults() {
368377 var sigstoreTufClientBuilder = SigstoreTufClient .builder ().useStagingInstance ();
369378 trustedRootProvider = TrustedRootProvider .from (sigstoreTufClientBuilder );
370379 signingConfigProvider = SigningConfigProvider .from (sigstoreTufClientBuilder );
371- signer ( Signers . newEcdsaSigner ()) ;
380+ signingAlgorithm = AlgorithmRegistry . SigningAlgorithm . PKIX_ECDSA_P256_SHA_256 ;
372381 minSigningCertificateLifetime (DEFAULT_MIN_SIGNING_CERTIFICATE_LIFETIME );
373382 return this ;
374383 }
@@ -384,11 +393,20 @@ public Builder sigstoreStagingDefaults() {
384393 */
385394 @ CheckReturnValue
386395 public List <Bundle > sign (List <byte []> artifactDigests ) throws KeylessSignerException {
387-
388- if (artifactDigests .size () == 0 ) {
396+ if (artifactDigests .isEmpty ()) {
389397 throw new IllegalArgumentException ("Require one or more digests" );
390398 }
391399
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+
392410 var result = ImmutableList .<Bundle >builder ();
393411
394412 for (var artifactDigest : artifactDigests ) {
@@ -435,7 +453,7 @@ public List<Bundle> sign(List<byte[]> artifactDigests) throws KeylessSignerExcep
435453 ImmutableBundle .builder ()
436454 .certPath (signingCert )
437455 .messageSignature (
438- MessageSignature .of (HashAlgorithm . SHA2_256 , artifactDigest , signature ));
456+ MessageSignature .of (signingAlgorithm . getHashing () , artifactDigest , signature ));
439457
440458 if (rekorV2Client != null ) { // Using Rekor v2 and a TSA
441459 Preconditions .checkNotNull (
@@ -475,7 +493,7 @@ public List<Bundle> sign(List<byte[]> artifactDigests) throws KeylessSignerExcep
475493 X509Certificate .newBuilder ()
476494 .setRawBytes (ByteString .copyFrom (encodedCert ))
477495 .build ())
478- .setKeyDetails (PublicKeyDetails . PKIX_ECDSA_P256_SHA_256 )
496+ .setKeyDetails (ProtoMutators . toPublicKeyDetails ( signingAlgorithm ) )
479497 .build ();
480498
481499 var reqSignature =
@@ -610,7 +628,7 @@ private void renewSigningCertificate()
610628 /**
611629 * Convenience wrapper around {@link #sign(List)} to sign a single digest
612630 *
613- * @param artifactDigest sha256 digest of the artifact to sign.
631+ * @param artifactDigest sha256 digest of the artifacts to sign.
614632 * @return a keyless singing results.
615633 */
616634 @ CheckReturnValue
@@ -626,14 +644,15 @@ public Bundle sign(byte[] artifactDigest) throws KeylessSignerException {
626644 */
627645 @ CheckReturnValue
628646 public Map <Path , Bundle > signFiles (List <Path > artifacts ) throws KeylessSignerException {
629- if (artifacts .size () == 0 ) {
647+ if (artifacts .isEmpty () ) {
630648 throw new IllegalArgumentException ("Require one or more paths" );
631649 }
632650 var digests = new ArrayList <byte []>(artifacts .size ());
633651 for (var artifact : artifacts ) {
634652 var artifactByteSource = com .google .common .io .Files .asByteSource (artifact .toFile ());
635653 try {
636- digests .add (artifactByteSource .hash (Hashing .sha256 ()).asBytes ());
654+ digests .add (
655+ artifactByteSource .hash (signingAlgorithm .getHashing ().getHashFunction ()).asBytes ());
637656 } catch (IOException ex ) {
638657 throw new KeylessSignerException ("Failed to hash artifact " + artifact );
639658 }
@@ -656,13 +675,4 @@ public Map<Path, Bundle> signFiles(List<Path> artifacts) throws KeylessSignerExc
656675 public Bundle signFile (Path artifact ) throws KeylessSignerException {
657676 return signFiles (List .of (artifact )).get (artifact );
658677 }
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- }
668678}
0 commit comments