diff --git a/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java b/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java index 8c8fa0619..2f57d30fb 100644 --- a/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java +++ b/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java @@ -132,31 +132,30 @@ public Builder trustedRootProvider(TrustedRootProvider trustedRootProvider) { private AlgorithmRegistry.HashAlgorithm findHashAlgorithm(Bundle bundle) throws KeylessVerificationException { try { - var rekorEntry = bundle.getEntries().get(0); - var body = rekorEntry.getBodyDecoded(); - if ("0.0.1".equals(body.getApiVersion())) { - if ("hashedrekord".equals(body.getKind())) { - var entry = RekorTypes.getHashedRekordV001(rekorEntry); - switch (entry.getData().getHash().getAlgorithm()) { - case SHA_256: - return AlgorithmRegistry.HashAlgorithm.SHA2_256; - case SHA_384: - return AlgorithmRegistry.HashAlgorithm.SHA2_384; - case SHA_512: - return AlgorithmRegistry.HashAlgorithm.SHA2_512; + // special case hashedrekord:0.0.1 and dsse:0.0.1 which may contain legacy public key to hash + // algorithm mappings + if (!bundle.getEntries().isEmpty()) { + var rekorEntry = bundle.getEntries().get(0); + var body = rekorEntry.getBodyDecoded(); + if ("0.0.1".equals(body.getApiVersion())) { + if ("hashedrekord".equals(body.getKind())) { + var entry = RekorTypes.getHashedRekordV001(rekorEntry); + switch (entry.getData().getHash().getAlgorithm()) { + case SHA_256: + return AlgorithmRegistry.HashAlgorithm.SHA2_256; + case SHA_384: + return AlgorithmRegistry.HashAlgorithm.SHA2_384; + case SHA_512: + return AlgorithmRegistry.HashAlgorithm.SHA2_512; + } + } else if ("dsse".equals(body.getKind())) { + // dsse:0.0.1 is always sha256 + return AlgorithmRegistry.HashAlgorithm.SHA2_256; } - } else if ("dsse".equals(body.getKind())) { - // dsse:0.0.1 is always sha256 - return AlgorithmRegistry.HashAlgorithm.SHA2_256; } - } else if ("0.0.2".equals(body.getApiVersion())) { - // rekor v2 entries must conform to the Algorithm Registry - var publicKey = Certificates.getLeaf(bundle.getCertPath()).getPublicKey(); - var signingAlgorithm = AlgorithmRegistry.getSigningAlgorithm(publicKey); - return signingAlgorithm.getHashAlgorithm(); } - throw new KeylessVerificationException( - "Unsupported entry type: '" + body.getKind() + ":" + body.getApiVersion() + "'"); + var publicKey = Certificates.getLeaf(bundle.getCertPath()).getPublicKey(); + return AlgorithmRegistry.getSigningAlgorithm(publicKey).getHashAlgorithm(); } catch (JsonParseException | RekorTypeException | UnsupportedAlgorithmException ex) { throw new KeylessVerificationException( "Could not determine hash algorithm from sigstore bundle", ex); @@ -199,7 +198,7 @@ public void verify(byte[] artifactDigest, Bundle bundle, VerificationOptions opt // a trusted CT log try { - fulcioVerifier.verifySigningCertificate(signingCert); + fulcioVerifier.verifySigningCertificate(signingCert, options.getCtLogOptions()); } catch (FulcioVerificationException | IOException ex) { throw new KeylessVerificationException( "Fulcio certificate was not valid: " + ex.getMessage(), ex); @@ -209,7 +208,20 @@ public void verify(byte[] artifactDigest, Bundle bundle, VerificationOptions opt checkCertificateMatchers(leafCert, options.getCertificateMatchers()); var hashAlgorithm = findHashAlgorithm(bundle); - var rekorEntry = bundle.getEntries().get(0); + + // A transparency-log entry is required unless disabled (e.g. a private deployment that verifies + // via a signed timestamp instead). We also refuse to ignore an entry that is present, so a + // disabled policy cannot silently skip verifying a log entry the bundle actually contains. + var entries = bundle.getEntries(); + if (entries.isEmpty() && options.getTLogOptions().isEnabled()) { + throw new KeylessVerificationException( + "No transparency log entry found and transparency-log verification is required"); + } + if (!entries.isEmpty() && !options.getTLogOptions().isEnabled()) { + throw new KeylessVerificationException( + "Bundle contains a transparency log entry but transparency-log verification is disabled"); + } + var rekorEntry = entries.isEmpty() ? null : entries.get(0); byte[] signature; if (bundle.getMessageSignature().isPresent()) { // hashedrekord @@ -222,16 +234,20 @@ public void verify(byte[] artifactDigest, Bundle bundle, VerificationOptions opt signature = dsseEnvelope.getSignature(); } - try { - rekorVerifier.verifyEntry(rekorEntry); - } catch (RekorVerificationException ex) { - throw new KeylessVerificationException("Transparency log entry could not be verified", ex); + // A transparency-log entry that is present is always verified; opting in only relaxes the + // requirement that one exists, never the verification of one that is provided. + Instant entryTime = null; + if (rekorEntry != null) { + try { + rekorVerifier.verifyEntry(rekorEntry); + } catch (RekorVerificationException ex) { + throw new KeylessVerificationException("Transparency log entry could not be verified", ex); + } + // if entry was verified and has a SET, get time from it + var set = rekorEntry.getVerification().getSignedEntryTimestamp(); + entryTime = set != null ? rekorEntry.getIntegratedTimeInstant() : null; } - // if entry was verified and has a SET, get time from it - var set = rekorEntry.getVerification().getSignedEntryTimestamp(); - var entryTime = set != null ? rekorEntry.getIntegratedTimeInstant() : null; - verifyTimestamps(leafCert, bundle.getTimestamps(), entryTime, signature); } @@ -325,6 +341,12 @@ private void checkMessageSignature( "Signature could not be processed: " + ex.getMessage(), ex); } + // No transparency-log entry (allowed via VerificationOptions): the artifact digest and + // signature have been verified above, and there is nothing to cross-check against. + if (rekorEntry == null) { + return; + } + // recreate the log entry and check if it matches what was provided in the entry String version; try { @@ -469,6 +491,12 @@ private void checkDsseEnvelope( throw new KeylessVerificationException("Signature could not be processed", se); } + // No transparency-log entry (allowed via VerificationOptions): the payload subject digest and + // DSSE signature have been verified above, and there is nothing to cross-check against. + if (rekorEntry == null) { + return; + } + RekorEntryBody entryBody; try { entryBody = rekorEntry.getBodyDecoded(); diff --git a/sigstore-java/src/main/java/dev/sigstore/VerificationOptions.java b/sigstore-java/src/main/java/dev/sigstore/VerificationOptions.java index c7b6379e0..0e2f8c404 100644 --- a/sigstore-java/src/main/java/dev/sigstore/VerificationOptions.java +++ b/sigstore-java/src/main/java/dev/sigstore/VerificationOptions.java @@ -20,6 +20,7 @@ import java.security.cert.X509Certificate; import java.util.List; import java.util.function.Predicate; +import org.immutables.value.Value.Default; import org.immutables.value.Value.Immutable; @Immutable(singleton = true) @@ -28,6 +29,40 @@ public interface VerificationOptions { /** An allow list of certificate identities to match with. */ List getCertificateMatchers(); + /** Transparency-log (rekor) verification policy; defaults to requiring an entry. */ + @Default + default TLogOptions getTLogOptions() { + return TLogOptions.builder().isEnabled(true).build(); + } + + /** Certificate-transparency (SCT) verification policy; defaults to requiring an SCT. */ + @Default + default CTLogOptions getCtLogOptions() { + return CTLogOptions.builder().isEnabled(true).build(); + } + + /** Transparency-log verification options. */ + @Immutable + interface TLogOptions { + /** Whether a transparency-log entry is required and verified. */ + boolean isEnabled(); + + static ImmutableTLogOptions.Builder builder() { + return ImmutableTLogOptions.builder(); + } + } + + /** Certificate-transparency verification options. */ + @Immutable + interface CTLogOptions { + /** Whether a certificate-transparency log entry (SCT) is required and verified. */ + boolean isEnabled(); + + static ImmutableCTLogOptions.Builder builder() { + return ImmutableCTLogOptions.builder(); + } + } + /** * An interface for allowing matching of certificates. Use {@link #fulcio()} to instantiate the * default {@link FulcioCertificateMatcher} implementation. Custom implementations may throw diff --git a/sigstore-java/src/main/java/dev/sigstore/bundle/BundleReader.java b/sigstore-java/src/main/java/dev/sigstore/bundle/BundleReader.java index 3bcd184da..8962b6473 100644 --- a/sigstore-java/src/main/java/dev/sigstore/bundle/BundleReader.java +++ b/sigstore-java/src/main/java/dev/sigstore/bundle/BundleReader.java @@ -50,9 +50,6 @@ static Bundle readBundle(Reader jsonReader) throws BundleParseException { bundleBuilder.mediaType(protoBundle.getMediaType()); - if (protoBundle.getVerificationMaterial().getTlogEntriesCount() == 0) { - throw new BundleParseException("Could not find any tlog entries in bundle json"); - } for (var bundleEntry : protoBundle.getVerificationMaterial().getTlogEntriesList()) { if (!bundleEntry.hasInclusionProof()) { // all consumed bundles must have an inclusion proof diff --git a/sigstore-java/src/main/java/dev/sigstore/fulcio/client/FulcioVerifier.java b/sigstore-java/src/main/java/dev/sigstore/fulcio/client/FulcioVerifier.java index bf1812b32..aa0946dbb 100644 --- a/sigstore-java/src/main/java/dev/sigstore/fulcio/client/FulcioVerifier.java +++ b/sigstore-java/src/main/java/dev/sigstore/fulcio/client/FulcioVerifier.java @@ -16,6 +16,7 @@ package dev.sigstore.fulcio.client; import com.google.common.annotations.VisibleForTesting; +import dev.sigstore.VerificationOptions.CTLogOptions; import dev.sigstore.encryption.certificates.Certificates; import dev.sigstore.encryption.certificates.transparency.CTLogInfo; import dev.sigstore.encryption.certificates.transparency.CTVerificationResult; @@ -44,7 +45,7 @@ import java.util.Map; import java.util.stream.Collectors; -/** Verifier for fulcio generated signing cerificates */ +/** Verifier for fulcio generated signing certificates */ public class FulcioVerifier { private final List cas; private final List ctLogs; @@ -94,8 +95,13 @@ private FulcioVerifier( } @VisibleForTesting - void verifySct(CertPath fullCertPath) throws FulcioVerificationException { - if (ctLogs.size() == 0) { + void verifySct(CertPath fullCertPath, CTLogOptions ctLogOptions) + throws FulcioVerificationException { + if (ctLogs.isEmpty()) { + // Only when there are no CT Logs (private deployment) we can skip SCT verification + if (!ctLogOptions.isEnabled()) { + return; + } throw new FulcioVerificationException("No ct logs were provided to verifier"); } @@ -150,8 +156,17 @@ private void verifyEmbeddedScts(CertPath certPath) throws FulcioVerificationExce */ public void verifySigningCertificate(CertPath signingCertificate) throws FulcioVerificationException, IOException { + verifySigningCertificate(signingCertificate, CTLogOptions.builder().isEnabled(true).build()); + } + + /** + * Verify a signing certificate, applying the given certificate-transparency policy (see {@link + * #verifySct(CertPath, CTLogOptions)}). + */ + public void verifySigningCertificate(CertPath signingCertificate, CTLogOptions ctLogOptions) + throws FulcioVerificationException, IOException { CertPath fullCertPath = validateCertPath(signingCertificate); - verifySct(fullCertPath); + verifySct(fullCertPath, ctLogOptions); } public CertPath trimTrustedParent(CertPath signingCertificate) @@ -177,7 +192,8 @@ CertPath validateCertPath(CertPath signingCertificate) throws FulcioVerification } catch (NoSuchAlgorithmException e) { // throw new RuntimeException( - "No PKIX CertPathValidator, we probably shouldn't be here, but this seems to be a system library error not a program control flow issue", + "No PKIX CertPathValidator, we probably shouldn't be here, but this seems to be a system" + + " library error not a program control flow issue", e); } @@ -197,7 +213,8 @@ CertPath validateCertPath(CertPath signingCertificate) throws FulcioVerification pkixParams = new PKIXParameters(Collections.singleton(ca.asTrustAnchor())); } catch (InvalidAlgorithmParameterException | CertificateException e) { throw new RuntimeException( - "Can't create PKIX parameters for fulcioRoot. This should have been checked when generating a verifier instance", + "Can't create PKIX parameters for fulcioRoot. This should have been checked when" + + " generating a verifier instance", e); } pkixParams.setRevocationEnabled(false); diff --git a/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java b/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java index 04ebd68cd..075610582 100644 --- a/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java +++ b/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java @@ -17,9 +17,12 @@ import com.google.common.collect.ImmutableList; import com.google.common.hash.Hashing; +import com.google.common.io.BaseEncoding; import com.google.common.io.Resources; import com.google.gson.JsonParser; +import dev.sigstore.VerificationOptions.CTLogOptions; import dev.sigstore.VerificationOptions.CertificateMatcher; +import dev.sigstore.VerificationOptions.TLogOptions; import dev.sigstore.bundle.Bundle; import dev.sigstore.bundle.ImmutableBundle; import dev.sigstore.encryption.signers.Signers; @@ -38,6 +41,7 @@ import org.hamcrest.MatcherAssert; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -519,9 +523,14 @@ public void testVerify_noTlogEntries_rekorV1() throws Exception { var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath(); var verifier = KeylessVerifier.builder().sigstoreStagingDefaults().build(); - Assertions.assertThrows( - IndexOutOfBoundsException.class, - () -> verifier.verify(Path.of(artifact), testBundle, VerificationOptions.empty())); + // By default a transparency-log entry is required, so a bundle without one is rejected with a + // clear error (rather than the incidental IndexOutOfBoundsException it used to raise). + var ex = + Assertions.assertThrows( + KeylessVerificationException.class, + () -> verifier.verify(Path.of(artifact), testBundle, VerificationOptions.empty())); + MatcherAssert.assertThat( + ex.getMessage(), CoreMatchers.startsWith("No transparency log entry found")); } @Test @@ -549,7 +558,8 @@ public void testVerify_dsseWrongPayloadType_rekorV1() throws Exception { Bundle.from(new StringReader(invalidBundleFile)), VerificationOptions.empty())); Assertions.assertEquals( - "DSSE envelope must have payload type application/vnd.in-toto+json, but found 'application/json'", + "DSSE envelope must have payload type application/vnd.in-toto+json, but found" + + " 'application/json'", ex.getMessage()); } @@ -580,7 +590,7 @@ public void testVerify_unsupportedRekorVersion_rekorV2() throws Exception { Path.of(artifact), Bundle.from(new StringReader(invalidBundleFile)), VerificationOptions.empty())); - Assertions.assertEquals("Unsupported entry type: 'hashedrekord:0.0.3'", ex.getMessage()); + Assertions.assertEquals("Unsupported hashedrekord version: 0.0.3", ex.getMessage()); } @Test @@ -751,7 +761,8 @@ public void testVerify_noRfc3161Timestamps_rekorV2() throws Exception { var validRfc3161Timestamps = "\"rfc3161Timestamps\": [{\n" - + " \"signedTimestamp\": \"MIIC1DADAgEAMIICywYJKoZIhvcNAQcCoIICvDCCArgCAQMxDTALBglghkgBZQMEAgEwgcIGCyqGSIb3DQEJEAEEoIGyBIGvMIGsAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgtF/jtMHzKroX8UjkT/BViNcIlC5Y7za/y4n5cjasXD0CFQCxAdEfFrtmTuy4mcW7QjLeeOAUXhgPMjAyNTA3MDIxODUxNTFaMAMCAQECCE0pZTAXtl1eoDKkMDAuMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxFTATBgNVBAMTDHNpZ3N0b3JlLXRzYaAAMYIB2zCCAdcCAQEwUTA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzALBglghkgBZQMEAgGggfwwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNTA3MDIxODUxNTFaMC8GCSqGSIb3DQEJBDEiBCCiICYObTnM098xx9niiVyPo+gxp4FTvN94z4K6gH/LgjCBjgYLKoZIhvcNAQkQAi8xfzB9MHsweQQgBvT/4Ef+s1mZtzOw16MjUBz8GOTAM2aoRdd1NudLJ0QwVTA9pDswOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUCjWhBmHV4kFzxomWp/J98n4DfKcwCgYIKoZIzj0EAwIEZzBlAjB0/hfB4Hm4GO5SZYuDzCtgnNdXQkETtx/QTtILM09awUdez2kQNmCAkLtPBf8ojB8CMQDfRBy5WNohfrWNDh0o+NBR7Yj67vsUyBS1WK5nT5QatouJQ3PbtSJN3Kk8xsiVxFc=\"\n" + + " \"signedTimestamp\":" + + " \"MIIC1DADAgEAMIICywYJKoZIhvcNAQcCoIICvDCCArgCAQMxDTALBglghkgBZQMEAgEwgcIGCyqGSIb3DQEJEAEEoIGyBIGvMIGsAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgtF/jtMHzKroX8UjkT/BViNcIlC5Y7za/y4n5cjasXD0CFQCxAdEfFrtmTuy4mcW7QjLeeOAUXhgPMjAyNTA3MDIxODUxNTFaMAMCAQECCE0pZTAXtl1eoDKkMDAuMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxFTATBgNVBAMTDHNpZ3N0b3JlLXRzYaAAMYIB2zCCAdcCAQEwUTA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzALBglghkgBZQMEAgGggfwwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNTA3MDIxODUxNTFaMC8GCSqGSIb3DQEJBDEiBCCiICYObTnM098xx9niiVyPo+gxp4FTvN94z4K6gH/LgjCBjgYLKoZIhvcNAQkQAi8xfzB9MHsweQQgBvT/4Ef+s1mZtzOw16MjUBz8GOTAM2aoRdd1NudLJ0QwVTA9pDswOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUCjWhBmHV4kFzxomWp/J98n4DfKcwCgYIKoZIzj0EAwIEZzBlAjB0/hfB4Hm4GO5SZYuDzCtgnNdXQkETtx/QTtILM09awUdez2kQNmCAkLtPBf8ojB8CMQDfRBy5WNohfrWNDh0o+NBR7Yj67vsUyBS1WK5nT5QatouJQ3PbtSJN3Kk8xsiVxFc=\"\n" + " }]"; var noRfc3161Timestamps = "\"rfc3161Timestamps\": []"; var invalidBundleFile = bundleFile.replace(validRfc3161Timestamps, noRfc3161Timestamps); @@ -871,4 +882,110 @@ public void testVerify_wrongArtifactHashAlgorithm() throws Exception { CoreMatchers.startsWith( "Provided artifact digest does not match digest used for verification")); } + + // A real SLSA build-provenance attestation from a GitHub *private* repository: no + // transparency-log entry, no CT log, signed RFC 3161 timestamp only. See the README in the + // fixture directory for provenance and how it was obtained. + private static final String GH_PRIVATE_DIR = + "dev/sigstore/samples/bundles/github-private-no-tlog/"; + private static final String GH_PRIVATE_SIGNER_SAN = + "https://github.com/neverendingsupport/slsa-attestations/.github/workflows/attest.yml@9f6d9dc1bfc02986955721eb15f89ad618f1cedb"; + private static final String GH_PRIVATE_OIDC_ISSUER = + "https://token.actions.githubusercontent.com"; + // sha256 of one of the artifacts recorded as a subject in the attestation. + private static final String GH_PRIVATE_SUBJECT_SHA256 = + "caa015ef69e9bc31a41322d6c71563ed9600c75bb988e4d639b1edc578580551"; + + @Test + public void testVerify_noTransparencyLog_gitHubPrivateInstance(@TempDir Path tempDir) + throws Exception { + var bundle = gitHubPrivateBundle(); + var verifier = gitHubPrivateVerifier(tempDir); + var options = + gitHubPrivateOptions() + .addCertificateMatchers( + CertificateMatcher.fulcio() + .subjectAlternativeName(StringMatcher.string(GH_PRIVATE_SIGNER_SAN)) + .issuer(StringMatcher.string(GH_PRIVATE_OIDC_ISSUER)) + .build()) + .build(); + + Assertions.assertDoesNotThrow( + () -> + verifier.verify( + BaseEncoding.base16().lowerCase().decode(GH_PRIVATE_SUBJECT_SHA256), + bundle, + options)); + } + + @Test + public void testVerify_noTransparencyLog_rejectedWithoutOptIn(@TempDir Path tempDir) + throws Exception { + var bundle = gitHubPrivateBundle(); + var verifier = gitHubPrivateVerifier(tempDir); + + // Default options do not permit skipping the transparency log, so the bundle is rejected. + Assertions.assertThrows( + KeylessVerificationException.class, + () -> + verifier.verify( + BaseEncoding.base16().lowerCase().decode(GH_PRIVATE_SUBJECT_SHA256), + bundle, + VerificationOptions.empty())); + } + + @Test + public void testVerify_noTransparencyLog_optInStillChecksArtifactDigest(@TempDir Path tempDir) + throws Exception { + var bundle = gitHubPrivateBundle(); + var verifier = gitHubPrivateVerifier(tempDir); + var options = gitHubPrivateOptions().build(); + + // Relaxing the tlog/CT requirements does not relax the rest: the artifact digest must still be + // one of the attested subjects. + var badArtifactDigest = + Hashing.sha256().hashString("nonsense", StandardCharsets.UTF_8).asBytes(); + var ex = + Assertions.assertThrows( + KeylessVerificationException.class, + () -> verifier.verify(badArtifactDigest, bundle, options)); + MatcherAssert.assertThat( + ex.getMessage(), + CoreMatchers.startsWith( + "Provided artifact digest does not match any subject sha256 digests in DSSE payload")); + } + + // A private-deployment policy: neither a transparency-log entry nor an SCT is required. + private static ImmutableVerificationOptions.Builder gitHubPrivateOptions() { + return VerificationOptions.builder() + .tLogOptions(TLogOptions.builder().isEnabled(false).build()) + .ctLogOptions(CTLogOptions.builder().isEnabled(false).build()); + } + + private static Bundle gitHubPrivateBundle() throws Exception { + return Bundle.from( + new StringReader( + Resources.toString( + Resources.getResource(GH_PRIVATE_DIR + "attestation.sigstore.json"), + StandardCharsets.UTF_8))); + } + + private static KeylessVerifier gitHubPrivateVerifier(Path tempDir) throws Exception { + var jsonl = + Resources.toString( + Resources.getResource(GH_PRIVATE_DIR + "trusted_root.jsonl"), StandardCharsets.UTF_8); + var gitHubTrustedRoot = + jsonl + .lines() + .filter(line -> line.contains("fulcio.githubapp.com")) + .findFirst() + .orElseThrow( + () -> + new IllegalStateException("no GitHub trust root found in trusted_root.jsonl")); + var trustedRootPath = tempDir.resolve("github-trusted-root.json"); + Files.writeString(trustedRootPath, gitHubTrustedRoot); + return KeylessVerifier.builder() + .trustedRootProvider(TrustedRootProvider.from(trustedRootPath)) + .build(); + } } diff --git a/sigstore-java/src/test/java/dev/sigstore/fulcio/client/FulcioVerifierTest.java b/sigstore-java/src/test/java/dev/sigstore/fulcio/client/FulcioVerifierTest.java index 52deedb40..ffbb0db10 100644 --- a/sigstore-java/src/test/java/dev/sigstore/fulcio/client/FulcioVerifierTest.java +++ b/sigstore-java/src/test/java/dev/sigstore/fulcio/client/FulcioVerifierTest.java @@ -16,6 +16,8 @@ package dev.sigstore.fulcio.client; import com.google.common.io.Resources; +import dev.sigstore.ImmutableCTLogOptions; +import dev.sigstore.VerificationOptions.CTLogOptions; import dev.sigstore.bundle.Bundle; import dev.sigstore.encryption.certificates.Certificates; import dev.sigstore.trustroot.ImmutableLogId; @@ -26,6 +28,7 @@ import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.List; +import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -81,7 +84,7 @@ public void testVerifySct_noSct() throws Exception { var fulcioVerifier = FulcioVerifier.newFulcioVerifier(trustRoot); try { - fulcioVerifier.verifySct(signingCertificate); + fulcioVerifier.verifySct(signingCertificate, enabledCTLog()); Assertions.fail(); } catch (FulcioVerificationException fve) { Assertions.assertEquals("No valid SCTs were found during verification", fve.getMessage()); @@ -122,7 +125,12 @@ public void invalidEmbeddedSct() throws Exception { var fve = Assertions.assertThrows( - FulcioVerificationException.class, () -> fulcioVerifier.verifySct(signingCertificate)); + FulcioVerificationException.class, + () -> fulcioVerifier.verifySct(signingCertificate, enabledCTLog())); Assertions.assertEquals("No valid SCTs were found, all(1) SCTs were invalid", fve.getMessage()); } + + private static @NonNull ImmutableCTLogOptions enabledCTLog() { + return CTLogOptions.builder().isEnabled(true).build(); + } } diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/README.md b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/README.md new file mode 100644 index 000000000..e1cbe34c1 --- /dev/null +++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/README.md @@ -0,0 +1,51 @@ +# GitHub private-repo attestation (no transparency log) + +`attestation.sigstore.json` and `trusted_root.jsonl` are a real SLSA build-provenance +attestation produced by GitHub Actions for a **private** repository. + +Attestations for private repositories are signed by GitHub's own Sigstore instance, +which — unlike the public-good instance — does **not** publish to a transparency log and +does **not** use certificate transparency: + +- the bundle carries **zero** transparency-log entries and relies on a signed RFC 3161 + timestamp for trusted time; +- the trust root GitHub distributes for it contains **zero** CT logs. + +Verifying such a bundle therefore requires a policy that disables both transparency-log +and certificate-transparency checks (`VerificationOptions` with `TLogOptions` / +`CTLogOptions` `isEnabled(false)`). See `KeylessVerifierTest`. + +## Files + +- `attestation.sigstore.json` — the Sigstore bundle (DSSE envelope, in-toto SLSA + provenance predicate). +- `trusted_root.jsonl` — trust roots as JSON Lines. `gh attestation trusted-root` emits + more than one (public-good first, then GitHub). sigstore-java consumes a single trust + root, so the test selects the GitHub one (the line describing the `fulcio.githubapp.com` + CA). + +## How this fixture was obtained + +Both files are the unmodified output of the `gh` CLI, run against a **private** +repository whose build had already produced a SLSA build-provenance attestation for a +released artifact. + +Download the attestation bundle for the built artifact, scoping the lookup to its private +repository: + +```sh +gh attestation download --repo / +``` + +This writes a `sha256-.jsonl` file in the current directory containing the +Sigstore bundle; it is copied verbatim to `attestation.sigstore.json`. + +Fetch the matching trust roots (public-good instance first, then GitHub's instance): + +```sh +gh attestation trusted-root > trusted_root.jsonl +``` + +Any private repository with a build-provenance attestation reproduces an equivalent +fixture: because the repository is private, GitHub signs it with its own Sigstore +instance, so the resulting bundle carries no transparency-log entries. diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/attestation.sigstore.json b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/attestation.sigstore.json new file mode 100644 index 000000000..a4246f5f6 --- /dev/null +++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/attestation.sigstore.json @@ -0,0 +1 @@ +{"mediaType":"application/vnd.dev.sigstore.bundle.v0.3+json","verificationMaterial":{"certificate":{"rawBytes":"MIIHQDCCBsagAwIBAgIUa39WPiLHvriy0BbZ+r6W6E9QoX8wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwyMB4XDTI2MDcyNDE1MzAyN1oXDTI2MDcyNDE1NDAyN1owADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCzR6pDNd61vOrLV+lssLkX83Dw/zNGKEprrEfInxjWcASil70eYKlWm5UdtMpb9rYKMGU2s2mlx56bQZzuJsl2jggXkMIIF4DAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFA5tlV/Yh7mAI5usmY0iLk9s+ErMMB8GA1UdIwQYMBaAFIHjTsG/Xu4ILqbvj2S+p69FoJvPMIGMBgNVHREBAf8EgYEwf4Z9aHR0cHM6Ly9naXRodWIuY29tL25ldmVyZW5kaW5nc3VwcG9ydC9zbHNhLWF0dGVzdGF0aW9ucy8uZ2l0aHViL3dvcmtmbG93cy9hdHRlc3QueW1sQDlmNmQ5ZGMxYmZjMDI5ODY5NTU3MjFlYjE1Zjg5YWQ2MThmMWNlZGIwOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTASBgorBgEEAYO/MAECBARwdXNoMDYGCisGAQQBg78wAQMEKGNhMzQyZTU2Nzg3OTg2Y2Q0ZThkZmMwYzg4MzA2OTY3MTZkM2I0NDEwFQYKKwYBBAGDvzABBAQHUmVsZWFzZTA0BgorBgEEAYO/MAEFBCZuZXZlcmVuZGluZ3N1cHBvcnQvbmVzLWphdmEtdGVzdC1saWItYTAjBgorBgEEAYO/MAEGBBVyZWZzL3RhZ3MvbmVzLXYxLjAuMTIwOwYKKwYBBAGDvzABCAQtDCtodHRwczovL3Rva2VuLmFjdGlvbnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tMIGNBgorBgEEAYO/MAEJBH8MfWh0dHBzOi8vZ2l0aHViLmNvbS9uZXZlcmVuZGluZ3N1cHBvcnQvc2xzYS1hdHRlc3RhdGlvbnMvLmdpdGh1Yi93b3JrZmxvd3MvYXR0ZXN0LnltbEA5ZjZkOWRjMWJmYzAyOTg2OTU1NzIxZWIxNWY4OWFkNjE4ZjFjZWRiMDgGCisGAQQBg78wAQoEKgwoOWY2ZDlkYzFiZmMwMjk4Njk1NTcyMWViMTVmODlhZDYxOGYxY2VkYjAdBgorBgEEAYO/MAELBA8MDWdpdGh1Yi1ob3N0ZWQwSQYKKwYBBAGDvzABDAQ7DDlodHRwczovL2dpdGh1Yi5jb20vbmV2ZXJlbmRpbmdzdXBwb3J0L25lcy1qYXZhLXRlc3QtbGliLWEwOAYKKwYBBAGDvzABDQQqDChjYTM0MmU1Njc4Nzk4NmNkNGU4ZGZjMGM4ODMwNjk2NzE2ZDNiNDQxMCUGCisGAQQBg78wAQ4EFwwVcmVmcy90YWdzL25lcy12MS4wLjEyMBoGCisGAQQBg78wAQ8EDAwKMTI5NjQyODQxNzA1BgorBgEEAYO/MAEQBCcMJWh0dHBzOi8vZ2l0aHViLmNvbS9uZXZlcmVuZGluZ3N1cHBvcnQwGQYKKwYBBAGDvzABEQQLDAkxMTMzOTQzOTYwgYEGCisGAQQBg78wARIEcwxxaHR0cHM6Ly9naXRodWIuY29tL25ldmVyZW5kaW5nc3VwcG9ydC9uZXMtamF2YS10ZXN0LWxpYi1hLy5naXRodWIvd29ya2Zsb3dzL25lcy1yZWxlYXNlLnltbEByZWZzL3RhZ3MvbmVzLXYxLjAuMTIwOAYKKwYBBAGDvzABEwQqDChjYTM0MmU1Njc4Nzk4NmNkNGU4ZGZjMGM4ODMwNjk2NzE2ZDNiNDQxMBQGCisGAQQBg78wARQEBgwEcHVzaDBtBgorBgEEAYO/MAEVBF8MXWh0dHBzOi8vZ2l0aHViLmNvbS9uZXZlcmVuZGluZ3N1cHBvcnQvbmVzLWphdmEtdGVzdC1saWItYS9hY3Rpb25zL3J1bnMvMzAwNjY2OTg5NzUvYXR0ZW1wdHMvMzAXBgorBgEEAYO/MAEWBAkMB3ByaXZhdGUwVQYKKwYBBAGDvzABGARHDEVyZXBvOm5ldmVyZW5kaW5nc3VwcG9ydC9uZXMtamF2YS10ZXN0LWxpYi1hOnJlZjpyZWZzL3RhZ3MvbmVzLXYxLjAuMTIwCgYIKoZIzj0EAwMDaAAwZQIxAJ6aTFDtBXArjgKmtzRRnqGgoPgGG2/0O38NJQtadgIiZebfw188PcS9TeHVUncQgQIwQEyyaxjimHq5q6BWFQeyNholRT4XJ6qyTcyogoy1oIDF8LmH6KfQoQHGUynIcMF/"},"timestampVerificationData":{"rfc3161Timestamps":[{"signedTimestamp":"MIIC0TADAgEAMIICyAYJKoZIhvcNAQcCoIICuTCCArUCAQMxDTALBglghkgBZQMEAgIwgbsGCyqGSIb3DQEJEAEEoIGrBIGoMIGlAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQg9wRSwDiSoN/9BVtwwSPSLO0VhDm7CDR9dC2EqM3UH1oCFFcFv2bliQEgqQF2Vgm7oJaQMxN1GA8yMDI2MDcyNDE1MzAyN1owAwIBAaA2pDQwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5noAAxggHfMIIB2wIBATBKMDIxFTATBgNVBAoTDEdpdEh1YiwgSW5jLjEZMBcGA1UEAxMQVFNBIGludGVybWVkaWF0ZQIUFzPb1un+DvofqFPzAXiB5slHM1IwCwYJYIZIAWUDBAICoIIBBTAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDcyNDE1MzAyN1owPwYJKoZIhvcNAQkEMTIEML0bFLAXQTUhJhhV64ysYiaE+dW8+W9to5DmKcWO+rvX76ZmjMmuwm3OJBi9YKlQGzCBhwYLKoZIhvcNAQkQAi8xeDB2MHQwcgQgRBbIrnMUamOhN8LlW+jecOPJrzBzvzmLqrqo2wgXztcwTjA2pDQwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlAhQXM9vW6f4O+h+oU/MBeIHmyUczUjAKBggqhkjOPQQDAwRoMGYCMQCwdP5T8aUvaO0OUpW5m4gTHVjKe9XfCm0nU+xzBFRuuCclWgGdHVfgL1uEF/7TzoYCMQCr8X65t64LlX6sMFfsmeskPlxglNomGSgiEVTBpiJk91WTgGdM717fc2+u8C83Dko="}]}},"dsseEnvelope":{"payload":"eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS1tb2R1bGUtMS0xLjAuMC1uZXMtamF2YS10ZXN0LWxpYi1hLTEuMC4xMi1zb3VyY2VzLmphciIsImRpZ2VzdCI6eyJzaGEyNTYiOiIxMzgyODBmZDMzMDJiOTcwNjU5NjYyMTc2MTk0NWExYWU5NThmOTNhMTVlNDM3MmRkYWU0ZmMwMGE5M2IwOWEyIn19LHsibmFtZSI6ImEtbW9kdWxlLTEtMS4wLjAtbmVzLWphdmEtdGVzdC1saWItYS0xLjAuMTIuamFyIiwiZGlnZXN0Ijp7InNoYTI1NiI6ImNhYTAxNWVmNjllOWJjMzFhNDEzMjJkNmM3MTU2M2VkOTYwMGM3NWJiOTg4ZTRkNjM5YjFlZGM1Nzg1ODA1NTEifX0seyJuYW1lIjoiYS1tb2R1bGUtMS0xLjAuMC1uZXMtamF2YS10ZXN0LWxpYi1hLTEuMC4xMi5wb20iLCJkaWdlc3QiOnsic2hhMjU2IjoiYWZlOGIxMzZlY2VhZjRkNzgxYWM4MDYwNGRiZTc0OGVlNDZhNDA3NDYyZjNjM2EzOTUyYjFhOGM2MzA3ZGQ0NSJ9fSx7Im5hbWUiOiJhLW1vZHVsZS0yLTEuMC4wLW5lcy1qYXZhLXRlc3QtbGliLWEtMS4wLjEyLXNvdXJjZXMuamFyIiwiZGlnZXN0Ijp7InNoYTI1NiI6Ijk4NzBmZWZlYjE5OWU2ZWVhN2VlNWQ2Yjc5NjNiODg5NzEyZDAzNTk0Y2I4YmYxZDg2NjE1OTczYmIzMWM5YTcifX0seyJuYW1lIjoiYS1tb2R1bGUtMi0xLjAuMC1uZXMtamF2YS10ZXN0LWxpYi1hLTEuMC4xMi5qYXIiLCJkaWdlc3QiOnsic2hhMjU2IjoiMjY3ZmQ1NzUzMjExYzM2MjVhMDA3NWVlODFlMzM5MmI0OWQxNmJkMjNmNTk1OTIyYzQwNDI0OWQ3MWQwMzllMCJ9fSx7Im5hbWUiOiJhLW1vZHVsZS0yLTEuMC4wLW5lcy1qYXZhLXRlc3QtbGliLWEtMS4wLjEyLnBvbSIsImRpZ2VzdCI6eyJzaGEyNTYiOiI0NmQwN2NkOTA2NGI4NzFlMTY2ZjYwMDQ3MmMwMDc1YzEwMzMyNTc5NjlkYjIwODdmODNiYzFiNTRjZGM4NzMzIn19LHsibmFtZSI6ImEtbW9kdWxlLTMtMS4wLjAtbmVzLWphdmEtdGVzdC1saWItYS0xLjAuMTItc291cmNlcy5qYXIiLCJkaWdlc3QiOnsic2hhMjU2IjoiMGQyYzEwNjEwN2ZjM2ViOTdjZTZlMjFjNWVkMTkxMmJmZTY3NzRlNGNkNTc4Yjc0NGFmMzQzNTYxYjVkNTk3MSJ9fSx7Im5hbWUiOiJhLW1vZHVsZS0zLTEuMC4wLW5lcy1qYXZhLXRlc3QtbGliLWEtMS4wLjEyLmphciIsImRpZ2VzdCI6eyJzaGEyNTYiOiI0N2I2ZTA0YTFkYzQ5YjBiMzUzYmNiODA2NjQxMWQwMDE0MWViYWVkMGZhMjA4NmE2NTJjOTUzNDJhOGJiMTRhIn19LHsibmFtZSI6ImEtbW9kdWxlLTMtMS4wLjAtbmVzLWphdmEtdGVzdC1saWItYS0xLjAuMTIucG9tIiwiZGlnZXN0Ijp7InNoYTI1NiI6IjQ4NGNmMzE4ODYwYmUwODFjZDVlNGM4YzkwMmRkNGRmYjlhMWViN2NjZDBhZTliMzQ0MzFlZjEwMGUxNzIxZWIifX0seyJuYW1lIjoibmVzLWphdmEtdGVzdC1saWItYS0xLjAuMC1uZXMtamF2YS10ZXN0LWxpYi1hLTEuMC4xMi5wb20iLCJkaWdlc3QiOnsic2hhMjU2IjoiNWI4NTExNDExNTFkYmM5MzVlMzMyZDQ0ZTMwNTcxOTJkODc5YmNiYWQ3ZTA1Zjc5MjZkMzVlMzdjOTVmOTg0NiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vYWN0aW9ucy5naXRodWIuaW8vYnVpbGR0eXBlcy93b3JrZmxvdy92MSIsImV4dGVybmFsUGFyYW1ldGVycyI6eyJ3b3JrZmxvdyI6eyJyZWYiOiJyZWZzL3RhZ3MvbmVzLXYxLjAuMTIiLCJyZXBvc2l0b3J5IjoiaHR0cHM6Ly9naXRodWIuY29tL25ldmVyZW5kaW5nc3VwcG9ydC9uZXMtamF2YS10ZXN0LWxpYi1hIiwicGF0aCI6Ii5naXRodWIvd29ya2Zsb3dzL25lcy1yZWxlYXNlLnltbCJ9fSwiaW50ZXJuYWxQYXJhbWV0ZXJzIjp7ImdpdGh1YiI6eyJldmVudF9uYW1lIjoicHVzaCIsInJlcG9zaXRvcnlfaWQiOiIxMjk2NDI4NDE3IiwicmVwb3NpdG9yeV9vd25lcl9pZCI6IjExMzM5NDM5NiIsInJ1bm5lcl9lbnZpcm9ubWVudCI6ImdpdGh1Yi1ob3N0ZWQifX0sInJlc29sdmVkRGVwZW5kZW5jaWVzIjpbeyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL25ldmVyZW5kaW5nc3VwcG9ydC9uZXMtamF2YS10ZXN0LWxpYi1hQHJlZnMvdGFncy9uZXMtdjEuMC4xMiIsImRpZ2VzdCI6eyJnaXRDb21taXQiOiJjYTM0MmU1Njc4Nzk4NmNkNGU4ZGZjMGM4ODMwNjk2NzE2ZDNiNDQxIn19XX0sInJ1bkRldGFpbHMiOnsiYnVpbGRlciI6eyJpZCI6Imh0dHBzOi8vZ2l0aHViLmNvbS9uZXZlcmVuZGluZ3N1cHBvcnQvc2xzYS1hdHRlc3RhdGlvbnMvLmdpdGh1Yi93b3JrZmxvd3MvYXR0ZXN0LnltbEA5ZjZkOWRjMWJmYzAyOTg2OTU1NzIxZWIxNWY4OWFkNjE4ZjFjZWRiIn0sIm1ldGFkYXRhIjp7Imludm9jYXRpb25JZCI6Imh0dHBzOi8vZ2l0aHViLmNvbS9uZXZlcmVuZGluZ3N1cHBvcnQvbmVzLWphdmEtdGVzdC1saWItYS9hY3Rpb25zL3J1bnMvMzAwNjY2OTg5NzUvYXR0ZW1wdHMvMyJ9fX19","payloadType":"application/vnd.in-toto+json","signatures":[{"sig":"MEYCIQCdMQAky8sN1kNzf0XmENcKFvUbANBpcUL1Dnx+0nV7NwIhAOz95buyD0Px3atfL85VsJTYehZQAsRC/8HLvTEdAhlL"}]}} diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/trusted_root.jsonl b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/trusted_root.jsonl new file mode 100644 index 000000000..d80ae4489 --- /dev/null +++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/github-private-no-tlog/trusted_root.jsonl @@ -0,0 +1,2 @@ +{"mediaType":"application/vnd.dev.sigstore.trustedroot+json;version=0.1","tlogs":[{"baseUrl":"https://rekor.sigstore.dev","hashAlgorithm":"SHA2_256","publicKey":{"rawBytes":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwrkBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw==","keyDetails":"PKIX_ECDSA_P256_SHA_256","validFor":{"start":"2021-01-12T11:53:27Z"}},"logId":{"keyId":"wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="}},{"baseUrl":"https://log2025-1.rekor.sigstore.dev","hashAlgorithm":"SHA2_256","publicKey":{"rawBytes":"MCowBQYDK2VwAyEAt8rlp1knGwjfbcXAYPYAkn0XiLz1x8O4t0YkEhie244=","keyDetails":"PKIX_ED25519","validFor":{"start":"2025-09-23T00:00:00Z"}},"logId":{"keyId":"zxGZFVvd0FEmjR8WrFwMdcAJ9vtaY/QXf44Y1wUeP6A="}}],"certificateAuthorities":[{"subject":{"organization":"sigstore.dev","commonName":"sigstore"},"uri":"https://fulcio.sigstore.dev","certChain":{"certificates":[{"rawBytes":"MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIxMDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSyA7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0JcastaRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2uSu1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJxVe/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uupHr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ=="}]},"validFor":{"start":"2021-03-07T03:20:29Z","end":"2022-12-31T23:59:59.999Z"}},{"subject":{"organization":"sigstore.dev","commonName":"sigstore"},"uri":"https://fulcio.sigstore.dev","certChain":{"certificates":[{"rawBytes":"MIICGjCCAaGgAwIBAgIUALnViVfnU0brJasmRkHrn/UnfaQwCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMjA0MTMyMDA2MTVaFw0zMTEwMDUxMzU2NThaMDcxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEeMBwGA1UEAxMVc2lnc3RvcmUtaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8RVS/ysH+NOvuDZyPIZtilgUF9NlarYpAd9HP1vBBH1U5CV77LSS7s0ZiH4nE7Hv7ptS6LvvR/STk798LVgMzLlJ4HeIfF3tHSaexLcYpSASr1kS0N/RgBJz/9jWCiXno3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU39Ppz1YkEZb5qNjpKFWixi4YZD8wHwYDVR0jBBgwFoAUWMAeX5FFpWapesyQoZMi0CrFxfowCgYIKoZIzj0EAwMDZwAwZAIwPCsQK4DYiZYDPIaDi5HFKnfxXx6ASSVmERfsynYBiX2X6SJRnZU84/9DZdnFvvxmAjBOt6QpBlc4J/0DxvkTCqpclvziL6BCCPnjdlIB3Pu3BxsPmygUY7Ii2zbdCdliiow="},{"rawBytes":"MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMwKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0yMTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxexX69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92jYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRYwB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQKsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCMWP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ"}]},"validFor":{"start":"2022-04-13T20:06:15Z"}}],"ctlogs":[{"baseUrl":"https://ctfe.sigstore.dev/test","hashAlgorithm":"SHA2_256","publicKey":{"rawBytes":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbfwR+RJudXscgRBRpKX1XFDy3PyudDxz/SfnRi1fT8ekpfBd2O1uoz7jr3Z8nKzxA69EUQ+eFCFI3zeubPWU7w==","keyDetails":"PKIX_ECDSA_P256_SHA_256","validFor":{"start":"2021-03-14T00:00:00Z","end":"2022-10-31T23:59:59.999Z"}},"logId":{"keyId":"CGCS8ChS/2hF0dFrJ4ScRWcYrBY9wzjSbea8IgY2b3I="}},{"baseUrl":"https://ctfe.sigstore.dev/2022","hashAlgorithm":"SHA2_256","publicKey":{"rawBytes":"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEiPSlFi0CmFTfEjCUqF9HuCEcYXNKAaYalIJmBZ8yyezPjTqhxrKBpMnaocVtLJBI1eM3uXnQzQGAJdJ4gs9Fyw==","keyDetails":"PKIX_ECDSA_P256_SHA_256","validFor":{"start":"2022-10-20T00:00:00Z"}},"logId":{"keyId":"3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4="}}],"timestampAuthorities":[{"subject":{"organization":"sigstore.dev","commonName":"sigstore-tsa-selfsigned"},"uri":"https://timestamp.sigstore.dev/api/v1/timestamp","certChain":{"certificates":[{"rawBytes":"MIICEDCCAZagAwIBAgIUOhNULwyQYe68wUMvy4qOiyojiwwwCgYIKoZIzj0EAwMwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZDAeFw0yNTA0MDgwNjU5NDNaFw0zNTA0MDYwNjU5NDNaMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE4ra2Z8hKNig2T9kFjCAToGG30jky+WQv3BzL+mKvh1SKNR/UwuwsfNCg4sryoYAd8E6isovVA3M4aoNdm9QDi50Z8nTEyvqgfDPtTIwXItfiW/AFf1V7uwkbkAoj0xxco2owaDAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0OBBYEFIn9eUOHz9BlRsMCRscsc1t9tOsDMB8GA1UdIwQYMBaAFJjsAe9/u1H/1JUeb4qImFMHic6/MBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMAoGCCqGSM49BAMDA2gAMGUCMDtpsV/6KaO0qyF/UMsX2aSUXKQFdoGTptQGc0ftq1csulHPGG6dsmyMNd3JB+G3EQIxAOajvBcjpJmKb4Nv+2Taoj8Uc5+b6ih6FXCCKraSqupe07zqswMcXJTe1cExvHvvlw=="},{"rawBytes":"MIIB9zCCAXygAwIBAgIUV7f0GLDOoEzIh8LXSW80OJiUp14wCgYIKoZIzj0EAwMwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZDAeFw0yNTA0MDgwNjU5NDNaFw0zNTA0MDYwNjU5NDNaMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQUQNtfRT/ou3YATa6wB/kKTe70cfJwyRIBovMnt8RcJph/COE82uyS6FmppLLL1VBPGcPfpQPYJNXzWwi8icwhKQ6W/Qe2h3oebBb2FHpwNJDqo+TMaC/tdfkv/ElJB72jRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSY7AHvf7tR/9SVHm+KiJhTB4nOvzAKBggqhkjOPQQDAwNpADBmAjEAwGEGrfGZR1cen1R8/DTVMI943LssZmJRtDp/i7SfGHmGRP6gRbuj9vOK3b67Z0QQAjEAuT2H673LQEaHTcyQSZrkp4mX7WwkmF+sVbkYY5mXN+RMH13KUEHHOqASaemYWK/E"}]},"validFor":{"start":"2025-07-04T00:00:00Z"}}]} +{"mediaType":"application/vnd.dev.sigstore.trustedroot+json;version=0.1","certificateAuthorities":[{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"fulcio.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICKjCCAbCgAwIBAgIUW3TJVeOvr+NSvJXdOw8nEEn7HhQwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMB4XDTIzMDkxMjE0MDY1NFoXDTI0MDkxMTE0MDY1NFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEsosodObhuHG6Pr5vp5y+pmnKawS1h2hwv3r3hBwqh3ZHJAw64mhDnDs9fw4jKkZEBYRSVyOHyZppz4day8hgpTIDwdj44Oan4RDb+wmj04jfhVLjLsQ4Q/X4K/ynRgNXo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUm0vkDkQZ29hutYdayJobIRmf/iMwHwYDVR0jBBgwFoAUwOG4UqRLTz7eejgRBs9JjqFFmzMwCgYIKoZIzj0EAwMDaAAwZQIwIBl93E7vkWTvdeIm1WSIM4qNsj0ApE8LCj3k1vrY5x6/7yhAZs7QlO3/FBCoEeaZAjEAlJcNr37uZq9BYHODHBeO/gP+6EfbzsNaLV22ASBlhF/a9y83ESLuqCNN7IxGxmWT"},{"rawBytes":"MIICFTCCAZugAwIBAgIUD3Jlqt4qhrcZI4UnGfPGrEq/pjQwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDkxMTEyMDAwMFoXDTI4MDkwOTEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7X7nK0wC7uEmDjW+on0sXIX3FacL3hhcrhneA+M/kl1OtvQiPmFrH9lbUQqOj/AfspJ8uGY3jaq8WuSg6ghatzYfuuzLAJIK4nGpCBafncF8EynOssPq64/Dz+JUWXqlo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUwOG4UqRLTz7eejgRBs9JjqFFmzMwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAI8HWLrke7uzhOpwlD1cNixPmoX9XFKe7bEPozo0D+vKi0Gt6VlC7xPedFIw4/AypAIwQP+FGRWvfx0IAH5/n0aRiN7/LVpyFA5RkJASZOVOib2Y8pNuhXa9V3ZbWO6v6kW/"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2023-10-27T16:30:00Z","end":"2024-05-25T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"fulcio.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICKzCCAbCgAwIBAgIUOpyw2HaZefsj/4SPXutGof8E2CkwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMB4XDTI0MDUxMzAwMDAwMFoXDTI1MDUxMzAwMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEJNJWvW8fckfk/oQmh+qCeIlFXl9YLEkKSjZCgcVB92Fi1HQnvmpCiyqpvP91SmT1/G6QbrmTGV7MmIQlDnBWHNUT+jwZ3elGu/yfr/v8U0uhZTIli/BMj5Y4ICHK/j4do3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUD0fF3cs+ldPyiWohHJ3JmO91V7gwHwYDVR0jBBgwFoAUwOG4UqRLTz7eejgRBs9JjqFFmzMwCgYIKoZIzj0EAwMDaQAwZgIxAO7BRC9i7oGUHjjlcHU/bfqk2NLy7t6wm3K5W+jBLFbAj6sVjYcY+rrYhop/OjclbQIxALafBKLPIPjoCI29BUHwLBFP6e92ZlyaoFtoqccceXAevRaDjXFvb5+M7wnD6AuAJw=="},{"rawBytes":"MIICFTCCAZugAwIBAgIUD3Jlqt4qhrcZI4UnGfPGrEq/pjQwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDkxMTEyMDAwMFoXDTI4MDkwOTEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7X7nK0wC7uEmDjW+on0sXIX3FacL3hhcrhneA+M/kl1OtvQiPmFrH9lbUQqOj/AfspJ8uGY3jaq8WuSg6ghatzYfuuzLAJIK4nGpCBafncF8EynOssPq64/Dz+JUWXqlo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUwOG4UqRLTz7eejgRBs9JjqFFmzMwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAI8HWLrke7uzhOpwlD1cNixPmoX9XFKe7bEPozo0D+vKi0Gt6VlC7xPedFIw4/AypAIwQP+FGRWvfx0IAH5/n0aRiN7/LVpyFA5RkJASZOVOib2Y8pNuhXa9V3ZbWO6v6kW/"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2024-05-13T00:00:00Z","end":"2024-10-25T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"fulcio.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICKzCCAbCgAwIBAgIUQeyd9UH06yZ63pDuqjgUZ58CnpMwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMB4XDTI0MTAwMzEyMDAwMFoXDTI1MTAwMzEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEwvbET2w+j9j9j50iTInH1gb9GSXkpsCvWz5orX1zgme+/Qh/5gMkpfmgfOSLV2ZRgT1hzujYmnKQvP2mCxYnbwQELAkAf+VhEY/7Uw3zZvguGQSdF1cxzRHiMTOha5eFo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUMib9z4ZYBcQANTVvVCa3KoTGbBUwHwYDVR0jBBgwFoAUwOG4UqRLTz7eejgRBs9JjqFFmzMwCgYIKoZIzj0EAwMDaQAwZgIxAPIU/zlJiJrxn6oTWNdEAD/YBSnhyxcvpq1D2DzFy8E8hbkEfMZPErYL7HyoL/BkdwIxAN9KDEKyktEUBrfHehfcLAzI2kERJx+8DSslXswOIbLaeqYfWsmrQAt5C0X/nOWxXA=="},{"rawBytes":"MIICFTCCAZugAwIBAgIUD3Jlqt4qhrcZI4UnGfPGrEq/pjQwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDkxMTEyMDAwMFoXDTI4MDkwOTEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7X7nK0wC7uEmDjW+on0sXIX3FacL3hhcrhneA+M/kl1OtvQiPmFrH9lbUQqOj/AfspJ8uGY3jaq8WuSg6ghatzYfuuzLAJIK4nGpCBafncF8EynOssPq64/Dz+JUWXqlo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUwOG4UqRLTz7eejgRBs9JjqFFmzMwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAI8HWLrke7uzhOpwlD1cNixPmoX9XFKe7bEPozo0D+vKi0Gt6VlC7xPedFIw4/AypAIwQP+FGRWvfx0IAH5/n0aRiN7/LVpyFA5RkJASZOVOib2Y8pNuhXa9V3ZbWO6v6kW/"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2024-10-07T00:00:00Z","end":"2025-06-19T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"fulcio.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICKTCCAbCgAwIBAgIUU7Y2PESb8FK88XCRQvI2rKDB5skwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMB4XDTI1MDUyNzAwMDAwMFoXDTI2MDUyNzAwMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEevMuOTGccTTXLu65xinRJP4gxkOemyAPCmUXEvhXKtLd+aDgN87PI0QxutOmPuQD2dLZVfxQmt5lvwJpUDIVYkKpH3mDxYbF6MJPMbq+A/EhkMaOS2+mcJRJdY2uam0Vo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU8tE1L3b7FV3qJKzSqy1w97vPt6AwHwYDVR0jBBgwFoAUwOG4UqRLTz7eejgRBs9JjqFFmzMwCgYIKoZIzj0EAwMDZwAwZAIwSIsnfcDIvp+9SGBe9Es4xLDgZ6/B3wtODu+jtNUznQFPw1/WHa3iBMp3vYPkIqZDAjBBD4AKu166Hg7tDd5E8ckSCNNDkXD0Q7Xdl4yujgqv0goVMeOgRA1pKDGszhunjAQ="},{"rawBytes":"MIICFTCCAZugAwIBAgIUD3Jlqt4qhrcZI4UnGfPGrEq/pjQwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDkxMTEyMDAwMFoXDTI4MDkwOTEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7X7nK0wC7uEmDjW+on0sXIX3FacL3hhcrhneA+M/kl1OtvQiPmFrH9lbUQqOj/AfspJ8uGY3jaq8WuSg6ghatzYfuuzLAJIK4nGpCBafncF8EynOssPq64/Dz+JUWXqlo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUwOG4UqRLTz7eejgRBs9JjqFFmzMwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAI8HWLrke7uzhOpwlD1cNixPmoX9XFKe7bEPozo0D+vKi0Gt6VlC7xPedFIw4/AypAIwQP+FGRWvfx0IAH5/n0aRiN7/LVpyFA5RkJASZOVOib2Y8pNuhXa9V3ZbWO6v6kW/"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2025-05-27T00:00:00Z","end":"2025-12-09T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"fulcio.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICKjCCAbCgAwIBAgIUNansGfOzaol+jXgh/wsz0X36zTMwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMB4XDTI1MTExMzAwMDAwMFoXDTI2MTExMzAwMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE24Un0srydTqXkWtrVrNdgPRNa1cCZqBRpFImYqItuVs/mszkn+RSlwcMzg/LwphU84qwA8Xv2z8ZaIETHspoQgMO4dP5zhJ5W8M+9crL1kR4Co2vS3TJZF9Qpsg+HiTro3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUGO6KtZB8c9gbXS2uNF3tXCtFNhEwHwYDVR0jBBgwFoAUwOG4UqRLTz7eejgRBs9JjqFFmzMwCgYIKoZIzj0EAwMDaAAwZQIxALmOdTRy/SiOc+QSf+eAPz24xWGhMryvNpyNvBZDeyqthC9KaMKmX+kHwJ0A6/bTXQIwE1mPbkH6tBXuWxlR/2Bj7UZ3MADlHSYGQUjpHMdQqJk17UVBywad5U6uA/f0pFdU"},{"rawBytes":"MIICFTCCAZugAwIBAgIUD3Jlqt4qhrcZI4UnGfPGrEq/pjQwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDkxMTEyMDAwMFoXDTI4MDkwOTEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7X7nK0wC7uEmDjW+on0sXIX3FacL3hhcrhneA+M/kl1OtvQiPmFrH9lbUQqOj/AfspJ8uGY3jaq8WuSg6ghatzYfuuzLAJIK4nGpCBafncF8EynOssPq64/Dz+JUWXqlo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUwOG4UqRLTz7eejgRBs9JjqFFmzMwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAI8HWLrke7uzhOpwlD1cNixPmoX9XFKe7bEPozo0D+vKi0Gt6VlC7xPedFIw4/AypAIwQP+FGRWvfx0IAH5/n0aRiN7/LVpyFA5RkJASZOVOib2Y8pNuhXa9V3ZbWO6v6kW/"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2025-11-13T00:00:00Z","end":"2026-07-13T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"fulcio.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICKjCCAbCgAwIBAgIUCZdc6761A2K2ny11d+8tvDIlBuAwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMB4XDTI2MDYxMjAwMDAwMFoXDTI3MDYxMjAwMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8K+awztD1Q48OQsI2PzffEwHJxdHoKneYSSRgnG6VCk0RlZWeVHM7EwpsDMgMMz98IrRqVBAjxSt7fs39rz6NUKG3T26Khv0gmzuJ1xG0j0BmK0j0kkfRvzYpQKv108to3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUgeNOwb9e7ggupu+PZL6nr0Wgm88wHwYDVR0jBBgwFoAUwOG4UqRLTz7eejgRBs9JjqFFmzMwCgYIKoZIzj0EAwMDaAAwZQIweEGv0C3qXaA2+oPahLsBzRA2C5+oWNE5Jq1Qpqrn0QeDCSY5eCKzwFjVa5eICks5AjEAsifahLxtAiHc0I2SWHYX3s3sfOLPArgK6oBM0hKbIMCOokEUhss67N06KOuV2rqQ"},{"rawBytes":"MIICFTCCAZugAwIBAgIUD3Jlqt4qhrcZI4UnGfPGrEq/pjQwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDkxMTEyMDAwMFoXDTI4MDkwOTEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZGdWxjaW8gSW50ZXJtZWRpYXRlIGwxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE7X7nK0wC7uEmDjW+on0sXIX3FacL3hhcrhneA+M/kl1OtvQiPmFrH9lbUQqOj/AfspJ8uGY3jaq8WuSg6ghatzYfuuzLAJIK4nGpCBafncF8EynOssPq64/Dz+JUWXqlo2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAdBgNVHQ4EFgQUwOG4UqRLTz7eejgRBs9JjqFFmzMwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAI8HWLrke7uzhOpwlD1cNixPmoX9XFKe7bEPozo0D+vKi0Gt6VlC7xPedFIw4/AypAIwQP+FGRWvfx0IAH5/n0aRiN7/LVpyFA5RkJASZOVOib2Y8pNuhXa9V3ZbWO6v6kW/"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2026-06-12T00:00:00Z"}}],"timestampAuthorities":[{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"timestamp.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICHDCCAaGgAwIBAgIUNDVlmtZuvoujn4KwiC/oxIr8hxAwCgYIKoZIzj0EAwMwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMB4XDTIzMDgzMTEyMDAwMFoXDTI0MDgzMDEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEV/zJhNTdu0Fa9hGCUih/JvqEoE81tEWrAVwUXXhdRgIY9hIFErLhNo6sSOpV9d7Zuy0KWMHhcimCUr41a1732ByVRy3f+Z4QhqpsgFMh5b5J90HJLK7HOyUZjehAnvSno3gwdjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGwE6T5ZIh6lY9wP6vt42UHyVMewwHwYDVR0jBBgwFoAUdh+GTP65aetHLVLs9hdhGgDIKIwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDaQAwZgIxAJo48LtrSsn0UmLtqGiUKg2EUvso+aDN5EyjpvMmobZ/Oq9zjnR7Of369hoABW4/1gIxANg5ZW4FqijhsXnA3md6jM9yLrLCI9QL+KnuZnXq6WgAcNQaAN7PNNjVDKV3iJEklw=="},{"rawBytes":"MIICJDCCAaqgAwIBAgIUckXVHpiw7iJY1V/jY8LYLj5TgqAwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTI4MDgwNTEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEISv96hTQ58QroEzzu4K+o9p8YkwDCBia2U7Y+VBNbOG/w1mLRibve9hSeUE1FSyLBMkiFSSm6MexcsbjyqOoNtRxuMinyYt6DSEox+/It2s/bTPyNAN0QP0DCQQOpnTZo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUdh+GTP65aetHLVLs9hdhGgDIKIwwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAIhf+2E5W2yOb/fCDAjhL/G/jerf74M0tG/zyo32U2keawxkzZosDdwnPaHaGLynAQIwa8nr3en4fZz1AdOZm6nK5hr1qK2F94nifgnAJ/WeT0fZnK/oHan0R28x363qYuYH"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2023-10-27T16:30:00Z","end":"2024-05-25T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"timestamp.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICGzCCAaGgAwIBAgIUPPgn6ner1PU/75CQ+62fdBuazaAwCgYIKoZIzj0EAwMwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMB4XDTI0MDUxMzAwMDAwMFoXDTI1MDUxMzAwMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEA0pG1mAC4qafk1JJuOoIvhnMME9XmBDxjGFreDLnyzaexIzRw+UHUFy8C2gE6Me+0tIGQt4Ftbu66NGmfvBkR6boPMYQSU2O5X5ykZBm/9LR/Aqz0lgmBy/OlXvTJjglo3gwdjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUDa4GVhd97Z2V8kiVl9DB0kC53CMwHwYDVR0jBBgwFoAUdh+GTP65aetHLVLs9hdhGgDIKIwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDaAAwZQIwEQHd++b7IBAAuqT2/1i/wXf1WM2XrkFF6qd1c3kFcBVvdLQyJ5KoyNUHnfCCVJROAjEA+FoASOEcARlU6RqVcif9JthHwzh6nNwz0AfAHvO8xantN/7HjiLmFrFEGR/g0kN/"},{"rawBytes":"MIICJDCCAaqgAwIBAgIUckXVHpiw7iJY1V/jY8LYLj5TgqAwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTI4MDgwNTEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEISv96hTQ58QroEzzu4K+o9p8YkwDCBia2U7Y+VBNbOG/w1mLRibve9hSeUE1FSyLBMkiFSSm6MexcsbjyqOoNtRxuMinyYt6DSEox+/It2s/bTPyNAN0QP0DCQQOpnTZo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUdh+GTP65aetHLVLs9hdhGgDIKIwwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAIhf+2E5W2yOb/fCDAjhL/G/jerf74M0tG/zyo32U2keawxkzZosDdwnPaHaGLynAQIwa8nr3en4fZz1AdOZm6nK5hr1qK2F94nifgnAJ/WeT0fZnK/oHan0R28x363qYuYH"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2024-05-13T00:00:00Z","end":"2024-10-25T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"timestamp.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICGzCCAaGgAwIBAgIUH7swiMTn+svhcDh80OeZccDTj7AwCgYIKoZIzj0EAwMwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMB4XDTI0MTAwNDEyMDAwMFoXDTI1MTAwNDEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEM7jdYNBTeD6hjym2/y73b50u2AFQsf8305Sr1NleOqamH9aWt6obhJQH3NoNUw9iFzHcDvafYWQFMu7SmOxS5n3aqwwfR8oJxKnEl36uCmGB+8TXS3B76SVTHEhG5rzOo3gwdjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUQvz9YbWX3S6a+jruBkhRBiE2RCkwHwYDVR0jBBgwFoAUdh+GTP65aetHLVLs9hdhGgDIKIwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDaAAwZQIxAI4dhu5iyx/g+z1vKAAWvHtebl1ZwsC+Vwgjm6Ttlq5yLNHHvYEnJ/h15Qv2IuXvdgIwZ8H/iy4lXsFJdFYSsB1/zavl24EgxSzxK/pCpihXMetYYDA/lX3xMyquisMx45rN"},{"rawBytes":"MIICJDCCAaqgAwIBAgIUckXVHpiw7iJY1V/jY8LYLj5TgqAwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTI4MDgwNTEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEISv96hTQ58QroEzzu4K+o9p8YkwDCBia2U7Y+VBNbOG/w1mLRibve9hSeUE1FSyLBMkiFSSm6MexcsbjyqOoNtRxuMinyYt6DSEox+/It2s/bTPyNAN0QP0DCQQOpnTZo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUdh+GTP65aetHLVLs9hdhGgDIKIwwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAIhf+2E5W2yOb/fCDAjhL/G/jerf74M0tG/zyo32U2keawxkzZosDdwnPaHaGLynAQIwa8nr3en4fZz1AdOZm6nK5hr1qK2F94nifgnAJ/WeT0fZnK/oHan0R28x363qYuYH"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2024-10-07T00:00:00Z","end":"2025-06-19T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"timestamp.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICGzCCAaGgAwIBAgIUaaAaeAO3NzYXR/muq5YMnGY34IUwCgYIKoZIzj0EAwMwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMB4XDTI1MDUyNzAwMDAwMFoXDTI2MDUyNzAwMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEAjyAb+jWITMjkgbjWC02N05Zf5/kPs73ICf5/8lHSyHnoqqItP2z3fkMpWiRpelX8eIjzCjZ0Zht+DpGxtJUNh5jMa+fFv2qoDLGbnQ17DXKXCr9nWHF4vCMflHZK5JHo3gwdjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUyvAcv8s1s37A/IWZAwdEptzjfWIwHwYDVR0jBBgwFoAUdh+GTP65aetHLVLs9hdhGgDIKIwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDaAAwZQIwMnoHA4qDtR3eRohUIhvHGG70xT9XMfEnuj0kRvi9wu9VumL4pXqz1ktJgTBm6DrYAjEA5SYnRfUm2yAYmGEkJr9RvSCV9O7X+fL8KqfM4TOPrXJLMERQjhRXbWZ4DjxvifnF"},{"rawBytes":"MIICJDCCAaqgAwIBAgIUckXVHpiw7iJY1V/jY8LYLj5TgqAwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTI4MDgwNTEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEISv96hTQ58QroEzzu4K+o9p8YkwDCBia2U7Y+VBNbOG/w1mLRibve9hSeUE1FSyLBMkiFSSm6MexcsbjyqOoNtRxuMinyYt6DSEox+/It2s/bTPyNAN0QP0DCQQOpnTZo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUdh+GTP65aetHLVLs9hdhGgDIKIwwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAIhf+2E5W2yOb/fCDAjhL/G/jerf74M0tG/zyo32U2keawxkzZosDdwnPaHaGLynAQIwa8nr3en4fZz1AdOZm6nK5hr1qK2F94nifgnAJ/WeT0fZnK/oHan0R28x363qYuYH"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2025-05-27T00:00:00Z","end":"2025-12-09T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"timestamp.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICGzCCAaGgAwIBAgIUHiljSG9Nx/Qf/gPpl7V1kyRh/jYwCgYIKoZIzj0EAwMwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMB4XDTI1MTExMzAwMDAwMFoXDTI2MTExMzAwMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEG1ZUJgbtNpInC7jR9hi4OMWK5yF5VeRpmCs6ADS5lx23MEHo3ek32O123e3YwH+J3F9Vbpd7ePQHnpdc6tsBcQ/y/NPw2Vf+VwMI/E35C5/3Y9A5kRXq9CFXC1bU6Fj6o3gwdjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUXa9JaNrcN+1Je5aHEemVnH2XXtMwHwYDVR0jBBgwFoAUdh+GTP65aetHLVLs9hdhGgDIKIwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDaAAwZQIwJyVOay8lriDg4Up0VFWc/o19mzuQeoEItzM2dG50eXF4KbPo9zfdviS3D6StPFRGAjEA5IHCXJ8qP8CsAsQmT3IPimUTAvDNJZI4GFIxs+od/R/EUHGu4NxuwPX3A1ZnJP7z"},{"rawBytes":"MIICJDCCAaqgAwIBAgIUckXVHpiw7iJY1V/jY8LYLj5TgqAwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTI4MDgwNTEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEISv96hTQ58QroEzzu4K+o9p8YkwDCBia2U7Y+VBNbOG/w1mLRibve9hSeUE1FSyLBMkiFSSm6MexcsbjyqOoNtRxuMinyYt6DSEox+/It2s/bTPyNAN0QP0DCQQOpnTZo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUdh+GTP65aetHLVLs9hdhGgDIKIwwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAIhf+2E5W2yOb/fCDAjhL/G/jerf74M0tG/zyo32U2keawxkzZosDdwnPaHaGLynAQIwa8nr3en4fZz1AdOZm6nK5hr1qK2F94nifgnAJ/WeT0fZnK/oHan0R28x363qYuYH"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2025-11-13T00:00:00Z","end":"2026-07-13T00:00:00Z"}},{"subject":{"organization":"GitHub, Inc.","commonName":"Internal Services Root"},"uri":"timestamp.githubapp.com","certChain":{"certificates":[{"rawBytes":"MIICGzCCAaGgAwIBAgIUFzPb1un+DvofqFPzAXiB5slHM1IwCgYIKoZIzj0EAwMwMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMB4XDTI2MDYxMjAwMDAwMFoXDTI3MDYxMjAwMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgVGltZXN0YW1waW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETpok7Tndv57l0YnFjKL+VpcusM8A2xgbTdV353wW8IynvsLTGAjF1BNS4x80TDKHbXxN3jSoSId1u1c3sCWpuEqHB1bbBqCfrlslNn6hyWzhwtiqRLE4LM0T+RPclKQCo3gwdjAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUu/GnSzNLJ4IjG9elW5L5a/W61JMwHwYDVR0jBBgwFoAUdh+GTP65aetHLVLs9hdhGgDIKIwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDaAAwZQIxANGz5WZBgyZqGnuhr0gDhUW2s4ZXkJ1CMUaFzynjsQ0/8WZghN7Jh04vmT4Vl8y9zgIwJeBHIZNDZtjzDQB0UC+7im4snua3zsBrRbsEtWnqQhDzyT580H/uF4EVQN2kUUtZ"},{"rawBytes":"MIICJDCCAaqgAwIBAgIUckXVHpiw7iJY1V/jY8LYLj5TgqAwCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTI4MDgwNTEyMDAwMFowMjEVMBMGA1UEChMMR2l0SHViLCBJbmMuMRkwFwYDVQQDExBUU0EgaW50ZXJtZWRpYXRlMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEISv96hTQ58QroEzzu4K+o9p8YkwDCBia2U7Y+VBNbOG/w1mLRibve9hSeUE1FSyLBMkiFSSm6MexcsbjyqOoNtRxuMinyYt6DSEox+/It2s/bTPyNAN0QP0DCQQOpnTZo3sweTAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUdh+GTP65aetHLVLs9hdhGgDIKIwwHwYDVR0jBBgwFoAUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaAAwZQIxAIhf+2E5W2yOb/fCDAjhL/G/jerf74M0tG/zyo32U2keawxkzZosDdwnPaHaGLynAQIwa8nr3en4fZz1AdOZm6nK5hr1qK2F94nifgnAJ/WeT0fZnK/oHan0R28x363qYuYH"},{"rawBytes":"MIIB9TCCAXqgAwIBAgIUNFryA06EHDIcd5EIbe8swbl9OY4wCgYIKoZIzj0EAwMwODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MB4XDTIzMDgwNzEyMDAwMFoXDTMzMDgwNDEyMDAwMFowODEVMBMGA1UEChMMR2l0SHViLCBJbmMuMR8wHQYDVQQDExZJbnRlcm5hbCBTZXJ2aWNlcyBSb290MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEXYaXx4H0oNuVP/2cfydA3oaafvvkkkgb5hbL8/j/BO25S7uTmDOCA5e4QLLWCKFuc+xp2j14tCH4WmHzMUDvf2tXtInVliY5wZgQMM9L6klo/IwA9x4omdcjnT+kKJAjo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUfFJ5/6rhfHEZPnXAhrQLhGkJJMwwCgYIKoZIzj0EAwMDaQAwZgIxAPzXsV+eokrqOHSQZH/XhhHE1slOscKy3DQpYpYJ1AWmJ2lJu/XOmubBX5s7apllUwIxALw2Ts8CDACiK42UymC8fk6sbNfoXUAWqdyKTVt2Lst+wNdkRniGvx7jT65BKTkcsQ=="}]},"validFor":{"start":"2026-06-12T00:00:00Z"}}]}