Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update protobuf-spec to 0.2.1 #544

Merged
merged 1 commit into from
Oct 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sigstore-java/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ dependencies {

implementation("io.github.erdtman:java-json-canonicalization:1.1")

implementation("dev.sigstore:protobuf-specs:0.1.0") {
implementation("dev.sigstore:protobuf-specs:0.2.1") {
because("It generates Sigstore Bundle file")
}
implementation(platform("com.google.protobuf:protobuf-bom:3.24.3"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@

@Value.Immutable
public interface KeylessSignature {
/** The sha256 hash digest of the artifact */
/**
* The sha256 hash digest of the artifact, this may be empty and should be treated as not present
* in that case.
*/
byte[] getDigest();

/**
Expand Down
17 changes: 10 additions & 7 deletions sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,16 @@ public void verify(byte[] artifactDigest, KeylessVerificationRequest request)

// this ensures the provided artifact digest matches what may have come from a bundle (in
// keyless signature)
if (!Arrays.equals(artifactDigest, request.getKeylessSignature().getDigest())) {
throw new KeylessVerificationException(
"Provided artifact sha256 digest does not match digest used for verification"
+ "\nprovided(hex) : "
+ Hex.toHexString(artifactDigest)
+ "\nverification : "
+ Hex.toHexString(request.getKeylessSignature().getDigest()));
var digest = request.getKeylessSignature().getDigest();
if (digest.length > 0) {
if (!Arrays.equals(artifactDigest, digest)) {
throw new KeylessVerificationException(
"Provided artifact sha256 digest does not match digest used for verification"
+ "\nprovided(hex) : "
+ Hex.toHexString(artifactDigest)
+ "\nverification : "
+ Hex.toHexString(digest));
}
}

// verify the certificate chains up to a trusted root (fulcio) and contains a valid SCT from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.bouncycastle.util.encoders.Hex;

Expand All @@ -68,8 +67,12 @@ class BundleFactoryInternal {
* @return Sigstore Bundle in protobuf builder format
*/
static Bundle.Builder createBundleBuilder(KeylessSignature signingResult) {
if (signingResult.getDigest().length == 0) {
throw new IllegalStateException(
"keyless signature must have artifact digest when serializing to bundle");
}
return Bundle.newBuilder()
.setMediaType("application/vnd.dev.sigstore.bundle+json;version=0.1")
.setMediaType("application/vnd.dev.sigstore.bundle+json;version=0.2")
.setVerificationMaterial(buildVerificationMaterial(signingResult))
.setMessageSignature(
MessageSignature.newBuilder()
Expand Down Expand Up @@ -157,35 +160,47 @@ static KeylessSignature readBundle(Reader jsonReader) throws BundleParseExceptio
}
Bundle bundle = bundleBuilder.build();

// TODO: only allow v0.2 bundles at some point, we will only be producing v0.2 bundles
// TODO: in our GA release.
// var supportedMediaType = "application/vnd.dev.sigstore.bundle+json;version=0.2";
// if (!supportedMediaType.equals(bundle.getMediaType())) {
// throw new BundleParseException(
// "Unsupported media type '"
// + bundle.getMediaType()
// + "', only '"
// + supportedMediaType
// + "' is supported");
// }

if (bundle.getVerificationMaterial().getTlogEntriesCount() == 0) {
throw new BundleParseException("Could not find any tlog entries in bundle json");
}
var bundleEntry = bundle.getVerificationMaterial().getTlogEntries(0);
if (!bundleEntry.hasInclusionProof()) {
throw new BundleParseException("Could not find an inclusion proof");
}
var bundleInclusionProof = bundleEntry.getInclusionProof();

ImmutableInclusionProof inclusionProof = null;
if (bundleEntry.hasInclusionProof()) {
inclusionProof =
ImmutableInclusionProof.builder()
.logIndex(bundleInclusionProof.getLogIndex())
.rootHash(Hex.toHexString(bundleInclusionProof.getRootHash().toByteArray()))
.treeSize(bundleInclusionProof.getTreeSize())
.checkpoint(bundleInclusionProof.getCheckpoint().getEnvelope())
.addAllHashes(
bundleInclusionProof.getHashesList().stream()
.map(ByteString::toByteArray)
.map(Hex::toHexString)
.collect(Collectors.toList()))
.build();
}
ImmutableInclusionProof inclusionProof =
ImmutableInclusionProof.builder()
.logIndex(bundleInclusionProof.getLogIndex())
.rootHash(Hex.toHexString(bundleInclusionProof.getRootHash().toByteArray()))
.treeSize(bundleInclusionProof.getTreeSize())
.checkpoint(bundleInclusionProof.getCheckpoint().getEnvelope())
.addAllHashes(
bundleInclusionProof.getHashesList().stream()
.map(ByteString::toByteArray)
.map(Hex::toHexString)
.collect(Collectors.toList()))
.build();

var verification =
ImmutableVerification.builder()
.signedEntryTimestamp(
Base64.getEncoder()
.encodeToString(
bundleEntry.getInclusionPromise().getSignedEntryTimestamp().toByteArray()))
.inclusionProof(Optional.ofNullable(inclusionProof))
.inclusionProof(inclusionProof)
.build();

var rekorEntry =
Expand All @@ -199,18 +214,23 @@ static KeylessSignature readBundle(Reader jsonReader) throws BundleParseExceptio
.verification(verification)
.build();

var hashAlgorithm = bundle.getMessageSignature().getMessageDigest().getAlgorithm();
if (hashAlgorithm != HashAlgorithm.SHA2_256) {
throw new BundleParseException(
"Cannot read message digests of type "
+ hashAlgorithm
+ ", only "
+ HashAlgorithm.SHA2_256
+ " is supported");
var digest = new byte[] {};
if (bundle.getMessageSignature().hasMessageDigest()) {
var hashAlgorithm = bundle.getMessageSignature().getMessageDigest().getAlgorithm();
if (hashAlgorithm != HashAlgorithm.SHA2_256) {
throw new BundleParseException(
"Cannot read message digests of type "
+ hashAlgorithm
+ ", only "
+ HashAlgorithm.SHA2_256
+ " is supported");
}
digest = bundle.getMessageSignature().getMessageDigest().getDigest().toByteArray();
}

try {
return KeylessSignature.builder()
.digest(bundle.getMessageSignature().getMessageDigest().getDigest().toByteArray())
.digest(digest)
.certPath(
toCertPath(
bundle.getVerificationMaterial().getX509CertificateChain().getCertificatesList()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ private static String subMessagePrefix(
}

static boolean isRequired(Descriptors.FieldDescriptor field) {
// while this isn't configured into the spec, we do not support rfc3161 timestamps in java yet,
// so make SETs from rekor required in code here
if (field
.getFullName()
.equals("dev.sigstore.rekor.v1.TransparencyLogEntry.inclusion_promise")) {
return true;
}
return field.isRequired()
|| field
.toProto()
Expand Down
4 changes: 1 addition & 3 deletions sigstore-java/src/test/java/dev/sigstore/KeylessTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public static void setupArtifact() throws IOException {
}

@Test
@SuppressWarnings("deprecation")
@EnabledIfOidcExists(provider = OidcProviderType.ANY)
public void sign_production() throws Exception {
var signer = KeylessSigner.builder().sigstorePublicDefaults().build();
Expand All @@ -78,7 +77,6 @@ public void sign_production() throws Exception {
}

@Test
@SuppressWarnings("deprecation")
@EnabledIfOidcExists(provider = OidcProviderType.ANY)
public void sign_staging() throws Exception {
var signer = KeylessSigner.builder().sigstoreStagingDefaults().build();
Expand Down Expand Up @@ -108,7 +106,7 @@ private void verifySigningResult(List<KeylessSignature> results)
Assertions.assertNotNull(result.getSignature());

var hr = RekorTypes.getHashedRekord(result.getEntry().get());
// check if ht rekor entry has the digest we sent
// check if the rekor entry has the digest we sent
Assertions.assertArrayEquals(artifactDigest, result.getDigest());
// check if the rekor entry has the signature we sent
Assertions.assertArrayEquals(
Expand Down
18 changes: 18 additions & 0 deletions sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ public void testVerify(boolean isOnline) throws Exception {
verifier.verify(Path.of(artifact), verificationReq);
}

@ParameterizedTest
@ValueSource(booleans = {true, false})
public void testVerify_noDigestInBundle(boolean isOnline) throws Exception {
var bundleFile =
Resources.toString(
Resources.getResource("dev/sigstore/samples/bundles/bundle-no-digest.sigstore"),
StandardCharsets.UTF_8);
var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath();

var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
var verificationReq =
KeylessVerificationRequest.builder()
.keylessSignature(BundleFactory.readBundle(new StringReader(bundleFile)))
.verificationOptions(VerificationOptions.builder().isOnline(isOnline).build())
.build();
verifier.verify(Path.of(artifact), verificationReq);
}

@ParameterizedTest
@ValueSource(booleans = {true, false})
public void testVerify_mismatchedSet(boolean isOnline) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,38 @@ void allRequiredFieldsInBundle() {
+ "dev.sigstore.common.v1.LogId\n"
+ " key_id\n"
+ "\n"
+ "dev.sigstore.rekor.v1.KindVersion\n"
+ " kind\n"
+ " version\n"
+ "\n"
+ "dev.sigstore.rekor.v1.InclusionPromise\n"
+ " signed_entry_timestamp\n"
+ "\n"
+ "dev.sigstore.rekor.v1.Checkpoint\n"
+ " envelope\n"
+ "\n"
+ "dev.sigstore.rekor.v1.InclusionProof\n"
+ " log_index\n"
+ " root_hash\n"
+ " tree_size\n"
+ " hashes\n"
+ " checkpoint\n"
+ "\n"
+ "dev.sigstore.rekor.v1.TransparencyLogEntry\n"
+ " log_index\n"
+ " log_id\n"
+ " kind_version\n"
+ " integrated_time\n"
+ " inclusion_promise\n"
+ " inclusion_proof\n"
+ "\n"
+ "dev.sigstore.common.v1.RFC3161SignedTimestamp\n"
+ " signed_timestamp\n"
+ "\n"
+ "dev.sigstore.bundle.v1.VerificationMaterial\n"
+ " content\n"
+ "\n"
+ "dev.sigstore.common.v1.MessageSignature\n"
+ " message_digest\n"
+ " signature\n"
+ "\n"
+ "dev.sigstore.bundle.v1.Bundle\n"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"mediaType":"application/vnd.dev.sigstore.bundle+json;version=0.2","verificationMaterial":{"x509CertificateChain":{"certificates":[{"rawBytes":"MIICyDCCAk6gAwIBAgIUenpCAKVU2BcGqhnsCe0doys6ibwwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjMxMDExMTQyODAzWhcNMjMxMDExMTQzODAzWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC0NNg9GUBzDJz2+i3Ffl1RiCwBekqVQvaYdjXJu6O7zd0WOofuc9zaBQ3WhE8o3EXH0Y5prD6bGajd2XEaMW6KOCAW0wggFpMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQULM+gqZePC3pfVoEclUSrtVPwGwgwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wHQYDVR0RAQH/BBMwEYEPYXBwdUBnb29nbGUuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABix8jOOQAAAQDAEcwRQIhANeveOTEE7bNqX0UyaSYlSoOXtOntGNsEAO9FUaa/p/XAiBaMNu8aUovaFnoY+e3VIwsLfKoQls17tZbbH6sY+RZQjAKBggqhkjOPQQDAwNoADBlAjB63/BTZjqtZFoKpilCsvEzz4a6eBGf0dbnqhhDS/9ELuKjj2H7jQuNICxqED5p9vECMQDxUugt9pitEpNkOR4gnHdEAS726LUKhCic2QUhwbNJt/+Th+O7MyvyfoDjdlgGGMI="}]},"tlogEntries":[{"logIndex":"41958702","logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="},"kindVersion":{"kind":"hashedrekord","version":"0.0.1"},"integratedTime":"1697034484","inclusionPromise":{"signedEntryTimestamp":"MEUCIFJST52F75FnhiyWApcgiQWgszyb/rf6J5wIRHEFb6LiAiEAgK/el1WsJLdpoRn0Pp9np9LPbY4ebQyyX03j8325Q48="},"inclusionProof":{"logIndex":"37795271","rootHash":"60ll7idWI1jYRZzxc+jKflYoW+4jWxgZaGR15ASsWt4=","treeSize":"37795272","hashes":["ZIU3md9RFYeb/QLydGOwhQ3ND+W4anIY65AcncCDATg=","FW20NiNv2Sqj0JVrVV0jxM2orMbQ9xh+VP1lTkSDl/Q=","S+iI/+iSshhUyd1Q7CAhJL1r0ztj4VmlB+Mz6EIYVnc=","IarfFu1ExpVVeg2h4fG1IWKYMs6BKCBnp46dlDN+iRA=","lMgRhGHIJoON6m0fp7dqo58UDMgHbflIjryXEw8/6GI=","wFBMBVQ5HXrKMuf5XOphsNlin7vSAfDFJnQq5YDxVrY=","FBAwNrNC3qhOjCcwdeB59P7bwQ40jtBUib0Y/j87xpE=","FTHlMv8QQyKAsmnkVAwWZSzP3mApzQXkiZrN+bQGg08=","5Lrnz5mdl9fOisdC44l0ljBJi9bwDSb/ArXsvCpgCiQ=","dA4IFz5UaTwkR83x1QUkZLq0UZJu9kRZJuSDsU7kVkE=","EqXDaDjlrIheY/2CQ/d0+pp4EBeqLlaq2/0ociyo5AY=","aWnEm9c/Gb8operqvTMd3WBQLe+yzT2W4Xt0HICt7Gw="],"checkpoint":{"envelope":"rekor.sigstore.dev - 2605736670972794746\n37795272\n60ll7idWI1jYRZzxc+jKflYoW+4jWxgZaGR15ASsWt4=\nTimestamp: 1697034484441201852\n\n— rekor.sigstore.dev wNI9ajBGAiEAlWUH2HSPa6IMIRBgFcIXph3Mj9xM70WR0VVADvGIl/oCIQCgfvUUjR/X5jewlqpAWI8NuJIicKpTG64vo6UM5fpSgQ==\n"}},"canonicalizedBody":"eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJhMGNmYzcxMjcxZDZlMjc4ZTU3Y2QzMzJmZjk1N2MzZjcwNDNmZGRhMzU0YzRjYmIxOTBhMzBkNTZlZmEwMWJmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJRG9xaGp4NWJ6Z1EwS3dNRDFtNzJDTGR4bTZMRHNhWU9oWE94L1NkS0NiRkFpRUExalY0V3kxUkhSN0pWS1FHUmZ5UGpLQTVzRUhWb0M0VUJnRHhpZjJ2Nmx3PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTjVSRU5EUVdzMlowRjNTVUpCWjBsVlpXNXdRMEZMVmxVeVFtTkhjV2h1YzBObE1HUnZlWE0yYVdKM2QwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcE5lRTFFUlhoTlZGRjVUMFJCZWxkb1kwNU5hazE0VFVSRmVFMVVVWHBQUkVGNlYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZETUU1T1p6bEhWVUo2UkVwNk1pdHBNMFptYkRGU2FVTjNRbVZyY1ZaUmRtRlpaR29LV0VwMU5rODNlbVF3VjA5dlpuVmpPWHBoUWxFelYyaEZPRzh6UlZoSU1GazFjSEpFTm1KSFlXcGtNbGhGWVUxWE5rdFBRMEZYTUhkblowWndUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZNVFN0bkNuRmFaVkJETTNCbVZtOUZZMnhWVTNKMFZsQjNSM2RuZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDBoUldVUldVakJTUVZGSUwwSkNUWGRGV1VWUVdWaENkMlJWUW01aU1qbHVZa2RWZFZreU9YUk5RMnRIUTJselIwRlJVVUpuTnpoM1FWRkZSUXBITW1nd1pFaENlazlwT0haWlYwNXFZak5XZFdSSVRYVmFNamwyV2pKNGJFeHRUblppVkVGeVFtZHZja0puUlVWQldVOHZUVUZGU1VKQ01FMUhNbWd3Q21SSVFucFBhVGgyV1ZkT2FtSXpWblZrU0UxMVdqSTVkbG95ZUd4TWJVNTJZbFJEUW1sbldVdExkMWxDUWtGSVYyVlJTVVZCWjFJNFFraHZRV1ZCUWpJS1FVNHdPVTFIY2tkNGVFVjVXWGhyWlVoS2JHNU9kMHRwVTJ3Mk5ETnFlWFF2TkdWTFkyOUJka3RsTms5QlFVRkNhWGc0YWs5UFVVRkJRVkZFUVVWamR3cFNVVWxvUVU1bGRtVlBWRVZGTjJKT2NWZ3dWWGxoVTFsc1UyOVBXSFJQYm5SSFRuTkZRVTg1UmxWaFlTOXdMMWhCYVVKaFRVNTFPR0ZWYjNaaFJtNXZDbGtyWlROV1NYZHpUR1pMYjFGc2N6RTNkRnBpWWtnMmMxa3JVbHBSYWtGTFFtZG5jV2hyYWs5UVVWRkVRWGRPYjBGRVFteEJha0kyTXk5Q1ZGcHFjWFFLV2tadlMzQnBiRU56ZGtWNmVqUmhObVZDUjJZd1pHSnVjV2hvUkZNdk9VVk1kVXRxYWpKSU4ycFJkVTVKUTNoeFJVUTFjRGwyUlVOTlVVUjRWWFZuZEFvNWNHbDBSWEJPYTA5U05HZHVTR1JGUVZNM01qWk1WVXRvUTJsak1sRlZhSGRpVGtwMEx5dFVhQ3RQTjAxNWRubG1iMFJxWkd4blIwZE5TVDBLTFMwdExTMUZUa1FnUTBWU1ZFbEdTVU5CVkVVdExTMHRMUW89In19fX0="}]},"messageSignature":{"signature":"MEUCIDoqhjx5bzgQ0KwMD1m72CLdxm6LDsaYOhXOx/SdKCbFAiEA1jV4Wy1RHR7JVKQGRfyPjKA5sEHVoC4UBgDxif2v6lw="}}
Loading
Loading