Skip to content

Commit 6efb1c2

Browse files
authored
Merge pull request #1031 from sigstore/rekor-v2-dsse
Add DSSE envelope checks for Rekor v2
2 parents 1a01a6c + 75e58f9 commit 6efb1c2

File tree

6 files changed

+239
-38
lines changed

6 files changed

+239
-38
lines changed

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

Lines changed: 103 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@
3333
import dev.sigstore.fulcio.client.FulcioVerifier;
3434
import dev.sigstore.json.ProtoJson;
3535
import dev.sigstore.proto.common.v1.HashAlgorithm;
36+
import dev.sigstore.proto.rekor.v2.DSSELogEntryV002;
3637
import dev.sigstore.proto.rekor.v2.HashedRekordLogEntryV002;
38+
import dev.sigstore.proto.rekor.v2.Signature;
3739
import dev.sigstore.rekor.client.HashedRekordRequest;
3840
import dev.sigstore.rekor.client.RekorEntry;
3941
import dev.sigstore.rekor.client.RekorTypeException;
@@ -306,18 +308,22 @@ private void checkMessageSignature(
306308
throw new KeylessVerificationException(
307309
"Could not parse HashedRekordLogEntryV002 from log entry body");
308310
}
311+
309312
if (!logEntrySpec.getData().getAlgorithm().equals(HashAlgorithm.SHA2_256)) {
310313
throw new KeylessVerificationException(
311314
"Unsupported digest algorithm in log entry: " + logEntrySpec.getData().getAlgorithm());
312315
}
316+
313317
if (!Arrays.equals(logEntrySpec.getData().getDigest().toByteArray(), artifactDigest)) {
314318
throw new KeylessVerificationException(
315319
"Artifact digest does not match digest in log entry spec");
316320
}
321+
317322
if (!Arrays.equals(logEntrySpec.getSignature().getContent().toByteArray(), signature)) {
318323
throw new KeylessVerificationException(
319324
"Signature does not match signature in log entry spec");
320325
}
326+
321327
var verifier = logEntrySpec.getSignature().getVerifier();
322328
if (!verifier.hasX509Certificate()) {
323329
throw new KeylessVerificationException("Rekor entry verifier is missing X.509 certificate");
@@ -399,46 +405,108 @@ private void checkDsseEnvelope(
399405
throw new KeylessVerificationException("Signature could not be processed", se);
400406
}
401407

402-
// check if the digest over the dsse payload matches the digest in the transparency log entry
403-
Dsse rekorDsse;
404-
try {
405-
rekorDsse = RekorTypes.getDsse(rekorEntry);
406-
} catch (RekorTypeException re) {
407-
throw new KeylessVerificationException("Unexpected rekor type", re);
408-
}
408+
String version = rekorEntry.getBodyDecoded().getApiVersion();
409+
if ("0.0.1".equals(version)) {
410+
Dsse rekorDsse;
411+
try {
412+
rekorDsse = RekorTypes.getDsse(rekorEntry);
413+
} catch (RekorTypeException re) {
414+
throw new KeylessVerificationException("Unexpected rekor type", re);
415+
}
409416

410-
var algorithm = rekorDsse.getPayloadHash().getAlgorithm();
411-
if (algorithm != PayloadHash.Algorithm.SHA_256) {
412-
throw new KeylessVerificationException(
413-
"Cannot process DSSE entry with hashing algorithm " + algorithm.toString());
414-
}
417+
var algorithm = rekorDsse.getPayloadHash().getAlgorithm();
418+
if (algorithm != PayloadHash.Algorithm.SHA_256) {
419+
throw new KeylessVerificationException(
420+
"Cannot process DSSE entry with hashing algorithm " + algorithm.toString());
421+
}
415422

416-
byte[] payloadDigest;
417-
try {
418-
payloadDigest = Hex.decode(rekorDsse.getPayloadHash().getValue());
419-
} catch (DecoderException de) {
420-
throw new KeylessVerificationException(
421-
"Could not decode hex sha256 artifact hash in hashrekord", de);
422-
}
423+
// check if the digest over the dsse payload matches the digest in the transparency log entry
424+
byte[] payloadDigest;
425+
try {
426+
payloadDigest = Hex.decode(rekorDsse.getPayloadHash().getValue());
427+
} catch (DecoderException de) {
428+
throw new KeylessVerificationException(
429+
"Could not decode hex sha256 artifact hash in hashrekord", de);
430+
}
423431

424-
byte[] calculatedDigest = Hashing.sha256().hashBytes(dsseEnvelope.getPayload()).asBytes();
425-
if (!Arrays.equals(calculatedDigest, payloadDigest)) {
426-
throw new KeylessVerificationException(
427-
"Digest of DSSE payload in bundle does not match DSSE payload digest in log entry");
428-
}
432+
byte[] calculatedDigest = Hashing.sha256().hashBytes(dsseEnvelope.getPayload()).asBytes();
433+
if (!Arrays.equals(calculatedDigest, payloadDigest)) {
434+
throw new KeylessVerificationException(
435+
"Digest of DSSE payload in bundle does not match DSSE payload digest in log entry");
436+
}
429437

430-
// check if the signature over the dsse payload matches the signature in the rekorEntry
431-
if (rekorDsse.getSignatures().size() != 1) {
432-
throw new KeylessVerificationException(
433-
"DSSE log entry must have exactly 1 signature, but found: "
434-
+ rekorDsse.getSignatures().size());
435-
}
438+
// check if the signature over the dsse payload matches the signature in the rekorEntry
439+
if (rekorDsse.getSignatures().size() != 1) {
440+
throw new KeylessVerificationException(
441+
"DSSE log entry must have exactly 1 signature, but found: "
442+
+ rekorDsse.getSignatures().size());
443+
}
436444

437-
if (!Base64.getEncoder()
438-
.encodeToString(dsseEnvelope.getSignature())
439-
.equals(rekorDsse.getSignatures().get(0).getSignature())) {
440-
throw new KeylessVerificationException(
441-
"Provided DSSE signature materials are inconsistent with DSSE log entry");
445+
if (!Base64.getEncoder()
446+
.encodeToString(dsseEnvelope.getSignature())
447+
.equals(rekorDsse.getSignatures().get(0).getSignature())) {
448+
throw new KeylessVerificationException(
449+
"Provided DSSE signature materials are inconsistent with DSSE log entry");
450+
}
451+
} else if ("0.0.2".equals(version)) {
452+
DSSELogEntryV002 logEntrySpec;
453+
try {
454+
DSSELogEntryV002.Builder builder = DSSELogEntryV002.newBuilder();
455+
ProtoJson.parser()
456+
.merge(
457+
new Gson()
458+
.toJson(
459+
rekorEntry.getBodyDecoded().getSpec().getAsJsonObject().get("dsseV002")),
460+
builder);
461+
logEntrySpec = builder.build();
462+
} catch (InvalidProtocolBufferException ipbe) {
463+
throw new KeylessVerificationException(
464+
"Could not parse DSSELogEntryV002 from log entry body", ipbe);
465+
}
466+
467+
if (!logEntrySpec.getPayloadHash().getAlgorithm().equals(HashAlgorithm.SHA2_256)) {
468+
throw new KeylessVerificationException(
469+
"Unsupported digest algorithm in log entry: "
470+
+ logEntrySpec.getPayloadHash().getAlgorithm());
471+
}
472+
473+
// check if the digest over the dsse payload matches the digest in the transparency log entry
474+
byte[] calculatedDigest = Hashing.sha256().hashBytes(dsseEnvelope.getPayload()).asBytes();
475+
if (!Arrays.equals(
476+
logEntrySpec.getPayloadHash().getDigest().toByteArray(), calculatedDigest)) {
477+
throw new KeylessVerificationException(
478+
"Digest of DSSE payload in bundle does not match DSSE payload digest in log entry");
479+
}
480+
481+
// check if the signature over the dsse payload matches the signature in the rekorEntry
482+
if (logEntrySpec.getSignaturesCount() != 1) {
483+
throw new KeylessVerificationException(
484+
"Log entry spec must have exactly 1 signature, but found: "
485+
+ logEntrySpec.getSignaturesCount());
486+
}
487+
488+
Signature logSignature = logEntrySpec.getSignatures(0);
489+
if (!Arrays.equals(dsseEnvelope.getSignature(), logSignature.getContent().toByteArray())) {
490+
throw new KeylessVerificationException(
491+
"Signature in DSSE envelope does not match signature in log entry spec");
492+
}
493+
494+
var verifier = logSignature.getVerifier();
495+
if (!verifier.hasX509Certificate()) {
496+
throw new KeylessVerificationException(
497+
"Rekor entry DSSE verifier is missing X.509 certificate");
498+
}
499+
try {
500+
byte[] certFromRekor = verifier.getX509Certificate().getRawBytes().toByteArray();
501+
byte[] certFromBundle = leafCert.getEncoded();
502+
if (!Arrays.equals(certFromRekor, certFromBundle)) {
503+
throw new KeylessVerificationException(
504+
"Certificate in rekor entry does not match certificate in bundle");
505+
}
506+
} catch (CertificateEncodingException e) {
507+
throw new KeylessVerificationException(
508+
"Could not encode leaf certificate for comparison", e);
509+
}
442510
}
443511
}
444512
}

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

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -436,19 +436,33 @@ static Stream<Arguments> badDsseProvider() {
436436
"Digest of DSSE payload in bundle does not match DSSE payload digest in log entry"),
437437
Arguments.arguments(
438438
"bundle.dsse.mismatched-signature.sigstore",
439-
"Provided DSSE signature materials are inconsistent with DSSE log entry"));
439+
"Provided DSSE signature materials are inconsistent with DSSE log entry"),
440+
Arguments.arguments(
441+
"bundle.dsse.rekor-v2.bad-signature.sigstore", "DSSE signature was not valid"),
442+
Arguments.arguments(
443+
"bundle.dsse.rekor-v2.mismatched-payload.sigstore",
444+
"Digest of DSSE payload in bundle does not match DSSE payload digest in log entry"),
445+
Arguments.arguments(
446+
"bundle.dsse.rekor-v2.mismatched-signature.sigstore",
447+
"Signature in DSSE envelope does not match signature in log entry spec"));
440448
}
441449

442450
@ParameterizedTest
443451
@MethodSource("badDsseProvider")
444-
public void testVerify_dsseBundleBadSignature_rekorV1(String bundleName, String expectedError)
452+
public void testVerify_dsseBundleInvalid(String bundleName, String expectedError)
445453
throws Exception {
446454
var bundleFile =
447455
Resources.toString(
448456
Resources.getResource("dev/sigstore/samples/bundles/" + bundleName),
449457
StandardCharsets.UTF_8);
450458
var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath();
451-
var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
459+
var builder = KeylessVerifier.builder();
460+
if (bundleName.contains("rekor-v2")) {
461+
builder.sigstoreStagingDefaults();
462+
} else {
463+
builder.sigstorePublicDefaults();
464+
}
465+
var verifier = builder.build();
452466

453467
var ex =
454468
Assertions.assertThrows(
@@ -682,6 +696,43 @@ public void testVerify_canVerifyV03Bundle_rekorV2() throws Exception {
682696
Path.of(artifact), Bundle.from(new StringReader(bundleFile)), VerificationOptions.empty());
683697
}
684698

699+
@Test
700+
public void testVerify_dsseBundle_rekorV2() throws Exception {
701+
var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath();
702+
var bundleFile =
703+
Resources.toString(
704+
Resources.getResource("dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.sigstore"),
705+
StandardCharsets.UTF_8);
706+
707+
var verifier = KeylessVerifier.builder().sigstoreStagingDefaults().build();
708+
verifier.verify(
709+
Path.of(artifact), Bundle.from(new StringReader(bundleFile)), VerificationOptions.empty());
710+
}
711+
712+
@Test
713+
public void testVerify_dsseBundleArtifactNotInSubjects_rekorV2() throws Exception {
714+
var bundleFile =
715+
Resources.toString(
716+
Resources.getResource("dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.sigstore"),
717+
StandardCharsets.UTF_8);
718+
var badArtifactDigest =
719+
Hashing.sha256().hashString("nonsense", StandardCharsets.UTF_8).asBytes();
720+
var verifier = KeylessVerifier.builder().sigstoreStagingDefaults().build();
721+
722+
var ex =
723+
Assertions.assertThrows(
724+
KeylessVerificationException.class,
725+
() ->
726+
verifier.verify(
727+
badArtifactDigest,
728+
Bundle.from(new StringReader(bundleFile)),
729+
VerificationOptions.empty()));
730+
MatcherAssert.assertThat(
731+
ex.getMessage(),
732+
CoreMatchers.startsWith(
733+
"Provided artifact digest does not match any subject sha256 digests in DSSE payload"));
734+
}
735+
685736
@Test
686737
public void testVerify_noRfc3161Timestamps_rekorV2() throws Exception {
687738
var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICyzCCAlKgAwIBAgIUKV93VRE8+giR4U3JmE46FfjWQPEwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNzIyMTg0NjI4WhcNMjUwNzIyMTg1NjI4WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEibOnv7mMVdCDKGzvkqnOG6Edv2c3/iGzYezZsyS75ZUtYWh1rnzT7rmrrMdqtetsZ1+lFAYKm8RKY8FmOm9cIqOCAXEwggFtMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUxwW/jGsI9VVYFl8GGAHjP0BeVeMwHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwIQYDVR0RAQH/BBcwFYETYWFyb25sZXdAZ29vZ2xlLmNvbTApBgorBgEEAYO/MAEBBBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wKwYKKwYBBAGDvzABCAQdDBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wgYoGCisGAQQB1nkCBAIEfAR6AHgAdgArMLzcaIjJ4uHYJiledB9IOTGWAvKcM8teQ0D+sqyGegAAAZgzdWZsAAAEAwBHMEUCIEKunFqu8GdmhXDsFwg/xbT67q99jPfAxsckPMFVwVgUAiEAvHnFz6h5BCXlyTCj225FD0bWKyDTmz/3fG0SiN51C2IwCgYIKoZIzj0EAwMDZwAwZAIwZeLswpKDDMuxCywKKM+phTSbvHN+024YeOGEoGOevo4GrBMGcm2QXapyN4U+MKY2AjAY8oryNBlotXqECqeYVUHCsBOu2I/G43KjTagDNhTmxPJc4oKsZeEmY8azL6H6QfQ="}, "tlogEntries": [{"logIndex": "6599", "logId": {"keyId": "8w1amZ2S5mJIQkQmPxdMuOrL/oJkvFg9MnQXmeOCXck="}, "kindVersion": {"kind": "dsse", "version": "0.0.2"}, "inclusionProof": {"logIndex": "6599", "rootHash": "dkGnJ+1zBeCDPO3w+CMSyZBL30cTl8vfPPO5OJjgpFk=", "treeSize": "6600", "hashes": ["1o6HtTnpjCIPmqgZaNcQVZO+XD95kYFUyFpIiuQt08c=", "7fw4fFrLFNo4v9ao7ecWVaihhyP1AONn8XqKVlbdMB0=", "63rDNjdnW14mVVe5PB9vf249qu9JU0qCbWtREGFp0Q0=", "A+VlB+XR92aS2txcqdoEfCb3QqZ89UHRDE87bcK7JiU=", "HhgSw1jzUj25LbExsCl8FbDRO6eJnxb9iGu259pM3ms=", "gpAC2IEHOQH0Mluo3QTOJzs2KTswWJ+2JiODSInqpyg=", "Ag03a73jphtOkMBVhp+MkrJwDkx2NE69NESHMFcwcfI=", "xbDsGnxf1siByWHEuiK85p0reQCaKKWUjf8YNl9s/Vo="], "checkpoint": {"envelope": "log2025-alpha1.rekor.sigstage.dev\n6600\ndkGnJ+1zBeCDPO3w+CMSyZBL30cTl8vfPPO5OJjgpFk=\n\n\u2014 log2025-alpha1.rekor.sigstage.dev 8w1amcTOF4cFBuJnrIMtTVD+a7oPZBzShJDajugc2wuxq/cfw+ImFdwU2mnKf+F334vPvOTWzqiK19Frf4q3F45yegI=\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZHNzZVYwMDIiOnsicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiIxcklKdXAzZU94N2w3ZXU0alJzYmtYdHk3cllVTW81N3BtZjF0NnR3NlljPSJ9LCJzaWduYXR1cmVzIjpbeyJjb250ZW50IjoiTUVZQ0lRRGRXeVBqTUJ4R1YxS1drVURVWm1TR05yVlMzYUN3K3M3S2oxM0tIT1lyaWdJaEFPR2Z4clkyeVhhREpKMUVLQWd0aVdjSEhYY2ZDS09aTHkveDZnYllGYW5KIiwidmVyaWZpZXIiOnsia2V5RGV0YWlscyI6IlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwieDUwOUNlcnRpZmljYXRlIjp7InJhd0J5dGVzIjoiTUlJQ3l6Q0NBbEtnQXdJQkFnSVVLVjkzVlJFOCtnaVI0VTNKbUU0NkZmaldRUEV3Q2dZSUtvWkl6ajBFQXdNd056RVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVI0d0hBWURWUVFERXhWemFXZHpkRzl5WlMxcGJuUmxjbTFsWkdsaGRHVXdIaGNOTWpVd056SXlNVGcwTmpJNFdoY05NalV3TnpJeU1UZzFOakk0V2pBQU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRWliT252N21NVmRDREtHenZrcW5PRzZFZHYyYzMvaUd6WWV6WnN5Uzc1WlV0WVdoMXJuelQ3cm1yck1kcXRldHNaMStsRkFZS204UktZOEZtT205Y0lxT0NBWEV3Z2dGdE1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVV4d1cvakdzSTlWVllGbDhHR0FIalAwQmVWZU13SHdZRFZSMGpCQmd3Rm9BVWNZWXdwaFI4WW0vNTk5YjBCUnAvWC8vcmI2d3dJUVlEVlIwUkFRSC9CQmN3RllFVFlXRnliMjVzWlhkQVoyOXZaMnhsTG1OdmJUQXBCZ29yQmdFRUFZTy9NQUVCQkJ0b2RIUndjem92TDJGalkyOTFiblJ6TG1kdmIyZHNaUzVqYjIwd0t3WUtLd1lCQkFHRHZ6QUJDQVFkREJ0b2RIUndjem92TDJGalkyOTFiblJ6TG1kdmIyZHNaUzVqYjIwd2dZb0dDaXNHQVFRQjFua0NCQUlFZkFSNkFIZ0FkZ0FyTUx6Y2FJako0dUhZSmlsZWRCOUlPVEdXQXZLY004dGVRMEQrc3F5R2VnQUFBWmd6ZFdac0FBQUVBd0JITUVVQ0lFS3VuRnF1OEdkbWhYRHNGd2cveGJUNjdxOTlqUGZBeHNja1BNRlZ3VmdVQWlFQXZIbkZ6Nmg1QkNYbHlUQ2oyMjVGRDBiV0t5RFRtei8zZkcwU2lONTFDMkl3Q2dZSUtvWkl6ajBFQXdNRFp3QXdaQUl3WmVMc3dwS0RETXV4Q3l3S0tNK3BoVFNidkhOKzAyNFllT0dFb0dPZXZvNEdyQk1HY20yUVhhcHlONFUrTUtZMkFqQVk4b3J5TkJsb3RYcUVDcWVZVlVIQ3NCT3UySS9HNDNLalRhZ0ROaFRteFBKYzRvS3NaZUVtWThhekw2SDZRZlE9In19fV19fX0="}], "timestampVerificationData": {"rfc3161Timestamps": [{"signedTimestamp": "MIIE6DADAgEAMIIE3wYJKoZIhvcNAQcCoIIE0DCCBMwCAQMxDTALBglghkgBZQMEAgEwgcIGCyqGSIb3DQEJEAEEoIGyBIGvMIGsAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgLe3+Y0/EGJLgaObiPUd56aqMZHDIPVmcwL4g52XYMmsCFCnmDigcquRsTW0ceewSf7Nu4jatGA8yMDI1MDcyMjE4NDYyOFowAwIBAQIJAO/M+RPO/W6HoDKkMDAuMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxFTATBgNVBAMTDHNpZ3N0b3JlLXRzYaCCAhMwggIPMIIBlqADAgECAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkMB4XDTI1MDMyODA5MTQwNloXDTM1MDMyNjA4MTQwNlowLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATHW/kXcekP16Ae6SekEWVHPtAFEMm7hp5XO33MktFjSW+bHWUXtYEzZz0A3xkY9CyYOoeUk3ZH/v5HEuS+UvORzX0g7Hfy3uYYYRwHtqBQN0IX8rLdFMtIrRej/QCAdB2jajBoMA4GA1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQUqPxk9ijeLuY7c09UjFLE4ZzdU6UwHwYDVR0jBBgwFoAUOyBGWV61Mk1HMM5uY+5zdEfyBH0wFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDZwAwZAIwRK9VLoYa0Xff4nX1N/AQ1YleNG/iLT8dAXAtRKRfpN9XuDScbxWeo0cku8SkC06NAjBQPe7LBNeitA/UOBtXT2sX1h6f4ISqz+ISmJ4lY+y3bzRJI5nk1r53I9WT3/xIWToxggHaMIIB1gIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFAo1oQZh1eJBc8aJlqfyffJ+A3ynMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI1MDcyMjE4NDYyOFowLwYJKoZIhvcNAQkEMSIEIFoIhOeb/JcbKTcAdjaFtJFAJY1EG8InbA7xmYcN4z+mMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCAG9P/gR/6zWZm3M7DXoyNQHPwY5MAzZqhF13U250snRDBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAgRmMGQCMDWotxN6KqroQvcfh9K2D+BAUQu3WhowMAFQYtPpX878/y6s+ingRwDO8773sLoOOAIwWnO0DWUtymNLHKikkq/pr+cKnFry1UMj3udsXHEEkUDpdInnIzlaQi2/re2yPo6o"}]}}, "dsseEnvelope": {"payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS50eHQiLCJkaWdlc3QiOnsic2hhMjU2IjoiYTBjZmM3MTI3MWQ2ZTI3OGU1N2NkMzMyZmY5NTdjM2Y3MDQzZmRkYTM1NGM0Y2JiMTkwYTMwZDU2ZWZhMDFiZiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vYWN0aW9ucy5naXRodWIuaW8vYnVpbGR0eXBlcy93b3JrZmxvdy92MSIsImV4dGVybmFsUGFyYW1ldGVycyI6eyJ3b3JrZmxvdyI6eyJyZWYiOiJyZWZzL2hlYWRzL21haW4iLCJyZXBvc2l0b3J5IjoiaHR0cHM6Ly9naXRodWIuY29tL2xvb3NlYmF6b29rYS9hYS10ZXN0IiwicGF0aCI6Ii5naXRodWIvd29ya2Zsb3dzL3Byb3ZlbmFuY2UueWFtbCJ9fSwiaW50ZXJuYWxQYXJhbWV0ZXJzIjp7ImdpdGh1YiI6eyJldmVudF9uYW1lIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJyZXBvc2l0b3J5X2lkIjoiODkxNzE1NDQ0IiwicmVwb3NpdG9yeV9vd25lcl9pZCI6IjEzMDQ4MjYiLCJydW5uZXJfZW52aXJvbm1lbnQiOiJnaXRodWItaG9zdGVkIn19LCJyZXNvbHZlZERlcGVuZGVuY2llcyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sb29zZWJhem9va2EvYWEtdGVzdEByZWZzL2hlYWRzL21haW4iLCJkaWdlc3QiOnsiZ2l0Q29tbWl0IjoiZWJmZjhkZmJkNjA5YjdiMjIyMzdjNzcxOWNlMDdmMmRjNzkzNGY1ZiJ9fV19LCJydW5EZXRhaWxzIjp7ImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcHJvdmVuYW5jZS55YW1sQHJlZnMvaGVhZHMvbWFpbiJ9LCJtZXRhZGF0YSI6eyJpbnZvY2F0aW9uSWQiOiJodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3QvYWN0aW9ucy9ydW5zLzExOTQxNDI1NDg3L2F0dGVtcHRzLzEifX19fQ==", "payloadType": "application/vnd.in-toto+json", "signatures": [{"sig": "MEYCIQDdWyPjMBxGV1KWkUDUZmSGNrVS3aCw+s7Kj13KHOYrigIhAOGfxrY2yXaDJJ1EKAgtiWcHHXcfCKOZLy/x6gbYFanK"}]}}

0 commit comments

Comments
 (0)