Skip to content

Commit 7063a81

Browse files
authored
Merge pull request #658 from sigstore/must-have-inclusion-proof
Inclusion proof is required
2 parents 741d356 + 40c04c2 commit 7063a81

File tree

16 files changed

+38
-72
lines changed

16 files changed

+38
-72
lines changed

fuzzing/src/main/java/fuzzing/RekorVerifierFuzzer.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
4040
RekorVerifier verifier = RekorVerifier.newRekorVerifier(tLogs);
4141

4242
verifier.verifyEntry(entry);
43-
verifier.verifyInclusionProof(entry);
4443
} catch (URISyntaxException | RekorParseException | RekorVerificationException e) {
4544
// Known exception
4645
}

sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,17 +180,6 @@ public void verify(byte[] artifactDigest, KeylessVerificationRequest request)
180180
throw new KeylessVerificationException("Rekor entry signature was not valid");
181181
}
182182

183-
// verify any inclusion proof
184-
if (rekorEntry.getVerification().getInclusionProof().isPresent()) {
185-
try {
186-
rekorVerifier.verifyInclusionProof(rekorEntry);
187-
} catch (RekorVerificationException ex) {
188-
throw new KeylessVerificationException("Rekor entry inclusion proof was not valid");
189-
}
190-
} else if (request.getVerificationOptions().alwaysUseRemoteRekorEntry()) {
191-
throw new KeylessVerificationException("Rekor entry did not contain inclusion proof");
192-
}
193-
194183
// check if the time of entry inclusion in the log (a stand-in for signing time) is within the
195184
// validity period for the certificate
196185
var entryTime = Date.from(rekorEntry.getIntegratedTimeInstant());

sigstore-java/src/main/java/dev/sigstore/bundle/BundleFactoryInternal.java

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
import java.security.cert.CertificateException;
4444
import java.util.Base64;
4545
import java.util.List;
46-
import java.util.Optional;
4746
import java.util.stream.Collectors;
4847
import org.bouncycastle.util.encoders.Hex;
4948

@@ -127,14 +126,7 @@ private static TransparencyLogEntry.Builder buildTlogEntries(RekorEntry entry) {
127126

128127
private static void addInclusionProof(
129128
TransparencyLogEntry.Builder transparencyLogEntry, RekorEntry entry) {
130-
RekorEntry.InclusionProof inclusionProof =
131-
entry
132-
.getVerification()
133-
.getInclusionProof()
134-
.orElseThrow(
135-
() ->
136-
new IllegalArgumentException(
137-
"An inclusion proof must be present in the log entry in the signing result"));
129+
RekorEntry.InclusionProof inclusionProof = entry.getVerification().getInclusionProof();
138130
transparencyLogEntry.setInclusionProof(
139131
InclusionProof.newBuilder()
140132
.setLogIndex(inclusionProof.getLogIndex())
@@ -166,9 +158,8 @@ static KeylessSignature readBundle(Reader jsonReader) throws BundleParseExceptio
166158
var bundleEntry = bundle.getVerificationMaterial().getTlogEntries(0);
167159
RekorEntry.InclusionProof inclusionProof = null;
168160
if (!bundleEntry.hasInclusionProof()) {
169-
if (!bundle.getMediaType().equals(BUNDLE_V_0_1)) {
170-
throw new BundleParseException("Could not find an inclusion proof");
171-
}
161+
// all consumed bundles must have an inclusion proof
162+
throw new BundleParseException("Could not find an inclusion proof");
172163
} else {
173164
var bundleInclusionProof = bundleEntry.getInclusionProof();
174165

@@ -192,7 +183,7 @@ static KeylessSignature readBundle(Reader jsonReader) throws BundleParseExceptio
192183
Base64.getEncoder()
193184
.encodeToString(
194185
bundleEntry.getInclusionPromise().getSignedEntryTimestamp().toByteArray()))
195-
.inclusionProof(Optional.ofNullable(inclusionProof))
186+
.inclusionProof(inclusionProof)
196187
.build();
197188

198189
var rekorEntry =

sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorEntry.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ interface Verification {
3838
/** Return the signed entry timestamp. */
3939
String getSignedEntryTimestamp();
4040

41-
Optional<InclusionProof> getInclusionProof();
41+
/** Return the inclusion proof. */
42+
InclusionProof getInclusionProof();
4243
}
4344

4445
/**

sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorVerifier.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -81,24 +81,15 @@ public void verifyEntry(RekorEntry entry) throws RekorVerificationException {
8181
} catch (NoSuchAlgorithmException nsae) {
8282
throw new AssertionError("Required verification algorithm 'SHA256withECDSA' not found.");
8383
}
84+
85+
// verify inclusion proof
86+
verifyInclusionProof(entry);
8487
}
8588

86-
/**
87-
* Verify that a Rekor Entry is in the log by checking inclusion proof.
88-
*
89-
* @param entry the entry to verify
90-
* @throws RekorVerificationException if the entry cannot be verified
91-
*/
92-
public void verifyInclusionProof(RekorEntry entry) throws RekorVerificationException {
89+
/** Verify that a Rekor Entry is in the log by checking inclusion proof. */
90+
private void verifyInclusionProof(RekorEntry entry) throws RekorVerificationException {
9391

94-
var inclusionProof =
95-
entry
96-
.getVerification()
97-
.getInclusionProof()
98-
.orElseThrow(
99-
() ->
100-
new RekorVerificationException(
101-
"No inclusion proof was found in the rekor entry"));
92+
var inclusionProof = entry.getVerification().getInclusionProof();
10293

10394
var leafHash =
10495
Hashing.sha256()

sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ public void testVerify_mismatchedSet() throws Exception {
6969

7070
@Test
7171
public void testVerify_canVerifyV01Bundle() throws Exception {
72+
// note that this v1 bundle contains an inclusion proof
7273
verifyBundle(
7374
"dev/sigstore/samples/bundles/artifact.txt",
7475
"dev/sigstore/samples/bundles/bundle.v1.sigstore");

sigstore-java/src/test/java/dev/sigstore/bundle/BundleFactoryTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ public void readV1Bundle() throws Exception {
2929
readBundle("dev/sigstore/samples/bundles/bundle.v1.sigstore");
3030
}
3131

32+
@Test
33+
public void readV1Bundle_noInclusion() {
34+
var ex =
35+
Assertions.assertThrows(
36+
BundleParseException.class,
37+
() -> readBundle("dev/sigstore/samples/bundles/bundle.v1.no.inclusion.sigstore"));
38+
Assertions.assertEquals("Could not find an inclusion proof", ex.getMessage());
39+
}
40+
3241
@Test
3342
public void readV2Bundle() throws Exception {
3443
readBundle("dev/sigstore/samples/bundles/bundle.v2.sigstore");

sigstore-java/src/test/java/dev/sigstore/rekor/client/RekorClientTest.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,10 @@ public void getEntry_hashedRekordRequest_byCalculatedUuid() throws Exception {
170170
private void assertEntry(RekorResponse resp, Optional<RekorEntry> entry) {
171171
assertTrue(entry.isPresent());
172172
assertEquals(resp.getEntry().getLogID(), entry.get().getLogID());
173-
assertTrue(entry.get().getVerification().getInclusionProof().isPresent());
174-
assertNotNull(entry.get().getVerification().getInclusionProof().get().getTreeSize());
175-
assertNotNull(entry.get().getVerification().getInclusionProof().get().getRootHash());
176-
assertNotNull(entry.get().getVerification().getInclusionProof().get().getLogIndex());
177-
assertTrue(entry.get().getVerification().getInclusionProof().get().getHashes().size() > 0);
173+
assertNotNull(entry.get().getVerification().getInclusionProof().getTreeSize());
174+
assertNotNull(entry.get().getVerification().getInclusionProof().getRootHash());
175+
assertNotNull(entry.get().getVerification().getInclusionProof().getLogIndex());
176+
assertTrue(entry.get().getVerification().getInclusionProof().getHashes().size() > 0);
178177
}
179178

180179
@Test

sigstore-java/src/test/java/dev/sigstore/rekor/client/RekorTypesTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ private RekorEntry fromResource(String path) throws Exception {
3232

3333
@Test
3434
public void getHashedRekord_pass() throws Exception {
35-
var entry = fromResource("dev/sigstore/samples/rekor-response/valid/response.json");
35+
var entry = fromResource("dev/sigstore/samples/rekor-response/valid/entry.json");
3636

3737
var hashedRekord = RekorTypes.getHashedRekord(entry);
3838
Assertions.assertNotNull(hashedRekord);
3939
}
4040

4141
@Test
4242
public void getHashedRekord_badType() throws Exception {
43-
var entry = fromResource("dev/sigstore/samples/rekor-response/valid/jar-response.json");
43+
var entry = fromResource("dev/sigstore/samples/rekor-response/valid/jar-entry.json");
4444

4545
var exception =
4646
Assertions.assertThrows(RekorTypeException.class, () -> RekorTypes.getHashedRekord(entry));

sigstore-java/src/test/java/dev/sigstore/rekor/client/RekorVerifierTest.java

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141

4242
public class RekorVerifierTest {
4343
public String rekorResponse;
44-
public String rekorQueryResponse;
4544
public byte[] rekorPub;
4645

4746
public static SigstoreTrustedRoot trustRoot;
@@ -50,15 +49,11 @@ public class RekorVerifierTest {
5049
public void loadResources() throws IOException {
5150
rekorResponse =
5251
Resources.toString(
53-
Resources.getResource("dev/sigstore/samples/rekor-response/valid/response.json"),
52+
Resources.getResource("dev/sigstore/samples/rekor-response/valid/entry.json"),
5453
StandardCharsets.UTF_8);
5554
rekorPub =
5655
Resources.toByteArray(
5756
Resources.getResource("dev/sigstore/samples/rekor-response/valid/rekor.pub"));
58-
rekorQueryResponse =
59-
Resources.toString(
60-
Resources.getResource("dev/sigstore/samples/rekor-response/valid/query-response.json"),
61-
StandardCharsets.UTF_8);
6257
}
6358

6459
@BeforeAll
@@ -73,18 +68,10 @@ public static void initTrustRoot() throws IOException, CertificateException {
7368
trustRoot = SigstoreTrustedRoot.from(builder.build());
7469
}
7570

76-
@Test
77-
public void verifyEntry_valid() throws Exception {
78-
var response = RekorResponse.newRekorResponse(new URI("https://somewhere"), rekorResponse);
79-
var verifier = RekorVerifier.newRekorVerifier(trustRoot);
80-
81-
verifier.verifyEntry(response.getEntry());
82-
}
83-
8471
@Test
8572
public void verifyEntry_invalid() throws Exception {
8673
// change the logindex
87-
var invalidResponse = rekorResponse.replace("79", "80");
74+
var invalidResponse = rekorResponse.replace("1688", "1700");
8875
var response = RekorResponse.newRekorResponse(new URI("https://somewhere"), invalidResponse);
8976
var verifier = RekorVerifier.newRekorVerifier(trustRoot);
9077

@@ -95,29 +82,27 @@ public void verifyEntry_invalid() throws Exception {
9582
}
9683

9784
@Test
98-
public void verifyEntry_withInclusionProof() throws Exception {
99-
var response = RekorResponse.newRekorResponse(new URI("https://somewhere"), rekorQueryResponse);
85+
public void verifyEntry() throws Exception {
86+
var response = RekorResponse.newRekorResponse(new URI("https://somewhere"), rekorResponse);
10087
var verifier = RekorVerifier.newRekorVerifier(trustRoot);
10188

10289
var entry = response.getEntry();
10390
verifier.verifyEntry(entry);
104-
verifier.verifyInclusionProof(entry);
10591
}
10692

10793
@Test
10894
public void verifyEntry_withInvalidInclusionProof() throws Exception {
10995
// replace a hash in the inclusion proof to make it bad
110-
var invalidResponse = rekorQueryResponse.replace("b4439e", "aaaaaa");
96+
var invalidResponse = rekorResponse.replace("b4439e", "aaaaaa");
11197

11298
var response = RekorResponse.newRekorResponse(new URI("https://somewhere"), invalidResponse);
11399
var verifier = RekorVerifier.newRekorVerifier(trustRoot);
114100

115101
var entry = response.getEntry();
116-
verifier.verifyEntry(entry);
117-
118102
var thrown =
119103
Assertions.assertThrows(
120-
RekorVerificationException.class, () -> verifier.verifyInclusionProof(entry));
104+
RekorVerificationException.class, () -> verifier.verifyEntry(entry));
105+
121106
MatcherAssert.assertThat(
122107
thrown.getMessage(),
123108
CoreMatchers.startsWith(

0 commit comments

Comments
 (0)