@@ -132,43 +132,31 @@ public Builder trustedRootProvider(TrustedRootProvider trustedRootProvider) {
132132 private AlgorithmRegistry .HashAlgorithm findHashAlgorithm (Bundle bundle )
133133 throws KeylessVerificationException {
134134 try {
135- // When the bundle has no transparency-log entry (e.g. a signed-timestamp-only bundle),
136- // derive the hash algorithm without one: DSSE bundles use SHA-256 (as in the dsse:0.0.1
137- // case below), otherwise fall back to the signing certificate's algorithm. Whether such a
138- // bundle is permitted at all is enforced in verify(...) via
139- // VerificationOptions#allowNonTransparencyLogVerification.
140- if (bundle .getEntries ().isEmpty ()) {
141- if (bundle .getDsseEnvelope ().isPresent ()) {
142- return AlgorithmRegistry .HashAlgorithm .SHA2_256 ;
143- }
144- var publicKey = Certificates .getLeaf (bundle .getCertPath ()).getPublicKey ();
145- return AlgorithmRegistry .getSigningAlgorithm (publicKey ).getHashAlgorithm ();
146- }
147- var rekorEntry = bundle .getEntries ().get (0 );
148- var body = rekorEntry .getBodyDecoded ();
149- if ("0.0.1" .equals (body .getApiVersion ())) {
150- if ("hashedrekord" .equals (body .getKind ())) {
151- var entry = RekorTypes .getHashedRekordV001 (rekorEntry );
152- switch (entry .getData ().getHash ().getAlgorithm ()) {
153- case SHA_256 :
154- return AlgorithmRegistry .HashAlgorithm .SHA2_256 ;
155- case SHA_384 :
156- return AlgorithmRegistry .HashAlgorithm .SHA2_384 ;
157- case SHA_512 :
158- return AlgorithmRegistry .HashAlgorithm .SHA2_512 ;
135+ // rekor 0.0.1 hashedrekord entries encode the hash algorithm in the entry itself. Others
136+ // (rekor 0.0.2, a bundle with no transparency-log entry) derive it from the signing
137+ // certificate's public key.
138+ if (!bundle .getEntries ().isEmpty ()) {
139+ var rekorEntry = bundle .getEntries ().get (0 );
140+ var body = rekorEntry .getBodyDecoded ();
141+ if ("0.0.1" .equals (body .getApiVersion ())) {
142+ if ("hashedrekord" .equals (body .getKind ())) {
143+ var entry = RekorTypes .getHashedRekordV001 (rekorEntry );
144+ switch (entry .getData ().getHash ().getAlgorithm ()) {
145+ case SHA_256 :
146+ return AlgorithmRegistry .HashAlgorithm .SHA2_256 ;
147+ case SHA_384 :
148+ return AlgorithmRegistry .HashAlgorithm .SHA2_384 ;
149+ case SHA_512 :
150+ return AlgorithmRegistry .HashAlgorithm .SHA2_512 ;
151+ }
152+ } else if ("dsse" .equals (body .getKind ())) {
153+ // dsse:0.0.1 is always sha256
154+ return AlgorithmRegistry .HashAlgorithm .SHA2_256 ;
159155 }
160- } else if ("dsse" .equals (body .getKind ())) {
161- // dsse:0.0.1 is always sha256
162- return AlgorithmRegistry .HashAlgorithm .SHA2_256 ;
163156 }
164- } else if ("0.0.2" .equals (body .getApiVersion ())) {
165- // rekor v2 entries must conform to the Algorithm Registry
166- var publicKey = Certificates .getLeaf (bundle .getCertPath ()).getPublicKey ();
167- var signingAlgorithm = AlgorithmRegistry .getSigningAlgorithm (publicKey );
168- return signingAlgorithm .getHashAlgorithm ();
169157 }
170- throw new KeylessVerificationException (
171- "Unsupported entry type: '" + body . getKind () + ":" + body . getApiVersion () + "'" );
158+ var publicKey = Certificates . getLeaf ( bundle . getCertPath ()). getPublicKey ();
159+ return AlgorithmRegistry . getSigningAlgorithm ( publicKey ). getHashAlgorithm ( );
172160 } catch (JsonParseException | RekorTypeException | UnsupportedAlgorithmException ex ) {
173161 throw new KeylessVerificationException (
174162 "Could not determine hash algorithm from sigstore bundle" , ex );
@@ -211,8 +199,7 @@ public void verify(byte[] artifactDigest, Bundle bundle, VerificationOptions opt
211199
212200 // a trusted CT log
213201 try {
214- fulcioVerifier .verifySigningCertificate (
215- signingCert , options .allowNonTransparencyLogVerification ());
202+ fulcioVerifier .verifySigningCertificate (signingCert , options .getCtLogOptions ());
216203 } catch (FulcioVerificationException | IOException ex ) {
217204 throw new KeylessVerificationException (
218205 "Fulcio certificate was not valid: " + ex .getMessage (), ex );
@@ -223,17 +210,17 @@ public void verify(byte[] artifactDigest, Bundle bundle, VerificationOptions opt
223210
224211 var hashAlgorithm = findHashAlgorithm (bundle );
225212
226- // A transparency-log entry is required by default. Bundles from instances that do not publish
227- // to a log (e.g. GitHub's Sigstore instance for private repositories) carry only a signed
228- // timestamp; verifying those requires opting in and relies on the RFC 3161 timestamp (verified
229- // below) for trusted time.
213+ // A transparency-log entry is required unless disabled (e.g. a private deployment that verifies
214+ // via a signed timestamp instead). We also refuse to ignore an entry that is present, so a
215+ // disabled policy cannot silently skip verifying a log entry the bundle actually contains.
230216 var entries = bundle .getEntries ();
231- if (entries .isEmpty () && !options .allowNonTransparencyLogVerification ()) {
217+ if (entries .isEmpty () && options .getTLogOptions ().isEnabled ()) {
218+ throw new KeylessVerificationException (
219+ "No transparency log entry found and transparency-log verification is required" );
220+ }
221+ if (!entries .isEmpty () && !options .getTLogOptions ().isEnabled ()) {
232222 throw new KeylessVerificationException (
233- "Bundle does not contain a transparency log entry. If it is from an instance that does "
234- + "not publish to a transparency log, set "
235- + "VerificationOptions.allowNonTransparencyLogVerification(true) to verify using its "
236- + "signed timestamp instead." );
223+ "Bundle contains a transparency log entry but transparency-log verification is disabled" );
237224 }
238225 var rekorEntry = entries .isEmpty () ? null : entries .get (0 );
239226
0 commit comments