diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 1dc2cb946..25303f08e 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -46,7 +46,7 @@ jobs:
21
distribution: 'temurin'
- name: Setup Go environment
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
+ uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: '1.25.x'
diff --git a/.github/workflows/cifuzz.yaml b/.github/workflows/cifuzz.yaml
index c94799954..5d8b1672f 100644
--- a/.github/workflows/cifuzz.yaml
+++ b/.github/workflows/cifuzz.yaml
@@ -1,5 +1,9 @@
name: CIFuzz
on: [pull_request]
+
+permissions:
+ contents: read
+
jobs:
Fuzzing:
runs-on: ubuntu-latest
diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml
index 9b5993960..73d496641 100644
--- a/.github/workflows/conformance.yml
+++ b/.github/workflows/conformance.yml
@@ -54,7 +54,7 @@ jobs:
distribution: 'temurin'
- name: Run Conformance Tests (production)
- uses: sigstore/sigstore-conformance@4d66ba3cb0c9c95f705c757c0f5e226d3f4d5151 # v0.0.27
+ uses: sigstore/sigstore-conformance@21533cde107c734ebc153c3e3a24d75fc9811a36 # v0.0.29
with:
entrypoint: ${{ github.workspace }}/sigstore-cli/sigstore-cli-server
environment: production
@@ -66,7 +66,7 @@ jobs:
test_sign_verify_dsse
- name: Run Conformance Tests (staging)
- uses: sigstore/sigstore-conformance@4d66ba3cb0c9c95f705c757c0f5e226d3f4d5151 # v0.0.27
+ uses: sigstore/sigstore-conformance@21533cde107c734ebc153c3e3a24d75fc9811a36 # v0.0.29
with:
entrypoint: ${{ github.workspace }}/sigstore-cli/sigstore-cli-server
environment: staging
diff --git a/.github/workflows/examples.yaml b/.github/workflows/examples.yaml
index 7adde2cb4..2fd56b8da 100644
--- a/.github/workflows/examples.yaml
+++ b/.github/workflows/examples.yaml
@@ -56,9 +56,6 @@ jobs:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.os }}-dev
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
- permissions:
- id-token: write
-
steps:
- name: Enable long paths in Git
if: runner.os == 'Windows'
diff --git a/.github/workflows/gradle-wrapper-validation.yaml b/.github/workflows/gradle-wrapper-validation.yaml
index 58c3fb25c..1d82c3b66 100644
--- a/.github/workflows/gradle-wrapper-validation.yaml
+++ b/.github/workflows/gradle-wrapper-validation.yaml
@@ -4,6 +4,9 @@ on:
branches: [main]
pull_request: {}
+permissions:
+ contents: read
+
jobs:
validation:
name: "Validation"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd8614615..6d6ddf350 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,15 @@ All versions prior to 1.0.0 are untracked
## [Unreleased]
+# [2.1.0] - 2026-05-21
+
+## Added
+- Add HTTP Fulcio client: https://github.com/sigstore/sigstore-java/pull/1176
+
+## Fixed
+- Re-add and enhance SET verification in KeylessVerifier: https://github.com/sigstore/sigstore-java/pull/1185
+
+
# [2.0.0] - 2025-11-20
## Added
diff --git a/build-logic/jvm/build.gradle.kts b/build-logic/jvm/build.gradle.kts
index bdd2aa529..f3eec9fd9 100644
--- a/build-logic/jvm/build.gradle.kts
+++ b/build-logic/jvm/build.gradle.kts
@@ -10,7 +10,7 @@ dependencies {
implementation(project(":basics"))
implementation(project(":build-parameters"))
implementation("com.diffplug.spotless:com.diffplug.spotless.gradle.plugin:8.1.0")
- implementation("com.github.vlsi.gradle-extensions:com.github.vlsi.gradle-extensions.gradle.plugin:3.0.1")
+ implementation("com.github.vlsi.gradle-extensions:com.github.vlsi.gradle-extensions.gradle.plugin:3.0.2")
implementation("de.thetaphi.forbiddenapis:de.thetaphi.forbiddenapis.gradle.plugin:3.10")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin")
implementation("org.jetbrains.dokka-javadoc:org.jetbrains.dokka-javadoc.gradle.plugin:2.1.0")
diff --git a/build-logic/publishing/build.gradle.kts b/build-logic/publishing/build.gradle.kts
index 0b3106e12..05607e1d1 100644
--- a/build-logic/publishing/build.gradle.kts
+++ b/build-logic/publishing/build.gradle.kts
@@ -11,7 +11,7 @@ dependencies {
implementation(project(":basics"))
implementation(project(":jvm"))
implementation("dev.sigstore.build-logic:gradle-plugin")
- implementation("dev.sigstore:sigstore-gradle-sign-plugin:2.0.0")
+ implementation("dev.sigstore:sigstore-gradle-sign-plugin:2.1.0")
implementation("com.gradle.plugin-publish:com.gradle.plugin-publish.gradle.plugin:2.0.0")
implementation("com.gradleup.nmcp:com.gradleup.nmcp.gradle.plugin:1.4.0")
}
diff --git a/examples/hello-world/build.gradle.kts b/examples/hello-world/build.gradle.kts
index 01b99c8ad..8acbe090c 100644
--- a/examples/hello-world/build.gradle.kts
+++ b/examples/hello-world/build.gradle.kts
@@ -1,7 +1,7 @@
plugins {
`java-library`
`maven-publish`
- val sigstoreVersion = System.getProperty("sigstore.version") ?: "2.0.0"
+ val sigstoreVersion = System.getProperty("sigstore.version") ?: "2.1.0"
id("dev.sigstore.sign") version "$sigstoreVersion"
signing
}
diff --git a/examples/hello-world/pom.xml b/examples/hello-world/pom.xml
index 3f040e62a..be4659832 100644
--- a/examples/hello-world/pom.xml
+++ b/examples/hello-world/pom.xml
@@ -16,7 +16,7 @@
UTF-8
UTF-8
11
- 2.0.0
+ 2.1.0
diff --git a/examples/hello-world/test.sh b/examples/hello-world/test.sh
index 79e95ab03..966ed02ff 100755
--- a/examples/hello-world/test.sh
+++ b/examples/hello-world/test.sh
@@ -1,9 +1,12 @@
#!/usr/bin/env bash
set -Eeo pipefail
-export MAVEN_GPG_KEY=$(cat ../pgp/private.key)
+MAVEN_GPG_KEY=$(cat ../pgp/private.key)
+export MAVEN_GPG_KEY
export MAVEN_GPG_PASSPHRASE=pass123
export ORG_GRADLE_PROJECT_signingKey=$MAVEN_GPG_KEY
export ORG_GRADLE_PROJECT_signingPassword=$MAVEN_GPG_PASSPHRASE
+SIGSTORE_JAVA_ID_TOKEN=$(curl -f https://storage.googleapis.com/sigstore-conformance-testing-token/untrusted-testing-token.txt)
+export SIGSTORE_JAVA_ID_TOKEN
set -x
# gradle
./gradlew clean publishMavenPublicationToExamplesRepository --stacktrace $@
diff --git a/fuzzing/src/main/java/fuzzing/RekorTypesFuzzer.java b/fuzzing/src/main/java/fuzzing/RekorTypesFuzzer.java
index ff2c12c34..b8b843eb6 100644
--- a/fuzzing/src/main/java/fuzzing/RekorTypesFuzzer.java
+++ b/fuzzing/src/main/java/fuzzing/RekorTypesFuzzer.java
@@ -50,9 +50,6 @@ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
case 2:
RekorTypes.getHashedRekordV002(entry);
break;
- case 3:
- RekorTypes.getDsseV002(entry);
- break;
}
} catch (URISyntaxException | RekorTypeException | RekorParseException e) {
// Known exception
diff --git a/fuzzing/src/main/java/fuzzing/SignerVerifierFuzzer.java b/fuzzing/src/main/java/fuzzing/SignerVerifierFuzzer.java
index 1576fc4e0..a140b4967 100644
--- a/fuzzing/src/main/java/fuzzing/SignerVerifierFuzzer.java
+++ b/fuzzing/src/main/java/fuzzing/SignerVerifierFuzzer.java
@@ -17,6 +17,7 @@
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
import dev.sigstore.encryption.signers.Signer;
import dev.sigstore.encryption.signers.Signers;
import dev.sigstore.encryption.signers.Verifier;
@@ -39,7 +40,10 @@ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
var unused1 = verifier.verify(byteArray, signature1);
var unused2 = verifier.verifyDigest(byteArray, signature2);
- } catch (InvalidKeyException | NoSuchAlgorithmException | SignatureException e) {
+ } catch (InvalidKeyException
+ | NoSuchAlgorithmException
+ | SignatureException
+ | UnsupportedAlgorithmException e) {
// Known exception
}
}
diff --git a/gradle.properties b/gradle.properties
index 289d92593..aacc53311 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,7 +4,7 @@ org.gradle.jvmargs=-XX:MaxMetaspaceSize=768m
group=dev.sigstore
# use the ./scripts/update_version.sh script to update all versions
-version=2.1.0
+version=2.2.0
# Kotlin Dokka is experemental, and we want silence the build warning
org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
diff --git a/scripts/change_version.sh b/scripts/change_version.sh
index 5e5dff152..61300abc0 100755
--- a/scripts/change_version.sh
+++ b/scripts/change_version.sh
@@ -6,6 +6,14 @@
# this script is simple and should work for most usecases, but it may break if we do weird things
set -Eeo pipefail
+sedi() {
+ if [ "$(uname)" = "Darwin" ]; then
+ sed -i "" "$@"
+ else
+ sed -i "$@"
+ fi
+}
+
old_version=$(grep "^version=" gradle.properties | cut -d'=' -f2)
other_old_version=$(grep "sigstoreJavaVersion.convention" sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt | cut -d'"' -f2)
if [[ "$old_version" != "$other_old_version" ]]; then
@@ -20,12 +28,12 @@ echo "old : $old_version"
echo "new : $new_version"
read -r -p "Run update? [y/N]: " yn
go=${yn:-"n"}
-if [ "${go,,}" != "y" ]; then
+if [ "$go" != "y" ] && [ "$go" != "Y" ]; then
echo "aborting"
exit
fi
# update to latest dev version (change update_versions.sh if you change this section)
-sed -i "s/\(sigstoreJavaVersion.convention(\"\)$old_version/\1$new_version/" sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt
-sed -i "s/version=$old_version/version=$new_version/" gradle.properties
+sedi "s/\(sigstoreJavaVersion.convention(\"\)$old_version/\1$new_version/" sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt
+sedi "s/version=$old_version/version=$new_version/" gradle.properties
diff --git a/scripts/update_versions.sh b/scripts/update_versions.sh
index 41d7b67b5..6cabfa8c9 100755
--- a/scripts/update_versions.sh
+++ b/scripts/update_versions.sh
@@ -5,6 +5,14 @@
# this script is simple and should work for most usecases, but it may break if we do weird things
set -Eeo pipefail
+sedi() {
+ if [ "$(uname)" = "Darwin" ]; then
+ sed -i "" "$@"
+ else
+ sed -i "$@"
+ fi
+}
+
calculated_release_version=$(grep "^version=" gradle.properties | cut -d'=' -f2)
read -r -p "Enter released version [${calculated_release_version}]: " vin
release_version=${vin:-${calculated_release_version}}
@@ -23,7 +31,7 @@ echo "latest : $release_version"
echo "next : $next_version"
read -r -p "Run update? [y/N]: " yn
go=${yn:-"n"}
-if [ "${go,,}" != "y" ]; then
+if [ "$go" != "y" ] && [ "$go" != "Y" ]; then
echo "aborting"
exit
fi
@@ -31,13 +39,13 @@ fi
# sed below is probably accepting .'s in versions as regex any chars, but this works for our purposes
# updates to new release version
-sed -i "s/\(sigstore-gradle-sign-plugin:\)$previous_version/\1$release_version/" build-logic/publishing/build.gradle.kts
-sed -i "s/\(\)$previous_version/\1$release_version/" sigstore-maven-plugin/README.md
-sed -i "s/\(dev.sigstore.sign\") version \"\)$previous_version/\1$release_version/" sigstore-gradle/README.md
-sed -i "s/\(sigstore.version.*\)$previous_version/\1$release_version/" examples/hello-world/build.gradle.kts
-sed -i "s/\(\)$previous_version/\1$release_version/" examples/hello-world/pom.xml
+sedi "s/\(sigstore-gradle-sign-plugin:\)$previous_version/\1$release_version/" build-logic/publishing/build.gradle.kts
+sedi "s/\(\)$previous_version/\1$release_version/" sigstore-maven-plugin/README.md
+sedi "s/\(dev.sigstore.sign\") version \"\)$previous_version/\1$release_version/" sigstore-gradle/README.md
+sedi "s/\(sigstore.version.*\)$previous_version/\1$release_version/" examples/hello-world/build.gradle.kts
+sedi "s/\(\)$previous_version/\1$release_version/" examples/hello-world/pom.xml
# update to latest dev version (change change_version.sh if you change this section)
-sed -i "s/\(sigstoreJavaVersion.convention(\"\)$release_version/\1$next_version/" sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt
-sed -i "s/version=$release_version/version=$next_version/" gradle.properties
+sedi "s/\(sigstoreJavaVersion.convention(\"\)$release_version/\1$next_version/" sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt
+sedi "s/version=$release_version/version=$next_version/" gradle.properties
diff --git a/sigstore-cli/build.gradle.kts b/sigstore-cli/build.gradle.kts
index e8d287630..dac90b7ff 100644
--- a/sigstore-cli/build.gradle.kts
+++ b/sigstore-cli/build.gradle.kts
@@ -18,7 +18,7 @@ dependencies {
implementation(platform("com.google.oauth-client:google-oauth-client-bom:1.39.0"))
implementation("com.google.oauth-client:google-oauth-client")
- implementation("org.eclipse.jetty:jetty-server:12.1.5")
+ implementation("org.eclipse.jetty:jetty-server:12.1.10")
implementation("org.slf4j:slf4j-simple:2.0.17")
diff --git a/sigstore-gradle/README.md b/sigstore-gradle/README.md
index 18511446f..508cec132 100644
--- a/sigstore-gradle/README.md
+++ b/sigstore-gradle/README.md
@@ -15,7 +15,7 @@ Signature format uses [Sigstore bundle](https://github.com/sigstore/protobuf-spe
```kotlin
plugins {
- id("dev.sigstore.sign") version "2.0.0"
+ id("dev.sigstore.sign") version "2.1.0"
}
// Automatically sign all Maven publications, using GitHub Actions OIDC when available,
diff --git a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt
index 1dfac133c..5c03a2b3a 100644
--- a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt
+++ b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt
@@ -46,7 +46,7 @@ abstract class SigstoreSignExtension(private val project: Project) {
abstract val sigstoreJavaVersion : Property
init {
- sigstoreJavaVersion.convention("2.1.0")
+ sigstoreJavaVersion.convention("2.2.0")
}
fun sign(publications: DomainObjectCollection) {
diff --git a/sigstore-java/build.gradle.kts b/sigstore-java/build.gradle.kts
index 56a86a49e..2e2f853ea 100644
--- a/sigstore-java/build.gradle.kts
+++ b/sigstore-java/build.gradle.kts
@@ -45,7 +45,7 @@ dependencies {
implementation("com.google.oauth-client:google-oauth-client-java6")
testImplementation(project(":sigstore-testkit"))
- testImplementation(platform("org.junit:junit-bom:5.14.2"))
+ testImplementation(platform("org.junit:junit-bom:5.14.4"))
testImplementation(platform("org.mockito:mockito-bom:5.21.0"))
testImplementation("org.mockito:mockito-core")
diff --git a/sigstore-java/src/main/java/dev/sigstore/AlgorithmRegistry.java b/sigstore-java/src/main/java/dev/sigstore/AlgorithmRegistry.java
index f32ab12e7..89e30a4d2 100644
--- a/sigstore-java/src/main/java/dev/sigstore/AlgorithmRegistry.java
+++ b/sigstore-java/src/main/java/dev/sigstore/AlgorithmRegistry.java
@@ -15,20 +15,77 @@
*/
package dev.sigstore;
-import static com.google.common.hash.Hashing.*;
-
-import com.google.common.hash.HashFunction;
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Map;
public class AlgorithmRegistry {
+
+ // order to differentiate between the various ec curves
+ private static final Map ECDSA_ORDERS =
+ Map.of(
+ new BigInteger(
+ "115792089210356248762697446949407573529996955224135760342422259061068512044369"),
+ SigningAlgorithm.PKIX_ECDSA_P256_SHA_256,
+ new BigInteger(
+ "39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643"),
+ SigningAlgorithm.PKIX_ECDSA_P384_SHA_384,
+ new BigInteger(
+ "6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449"),
+ SigningAlgorithm.PKIX_ECDSA_P521_SHA_512);
+
+ /**
+ * Determine the signing algorithm based on the public key.
+ *
+ * @param publicKey the public key
+ * @return the signing algorithm
+ * @throws UnsupportedAlgorithmException if the key algorithm or curve is not supported
+ * @throws IllegalStateException if the public key cannot be converted into a known type
+ */
+ public static SigningAlgorithm getSigningAlgorithm(PublicKey publicKey)
+ throws UnsupportedAlgorithmException {
+ String algorithm = publicKey.getAlgorithm();
+ if ("RSA".equals(algorithm)) {
+ if (publicKey instanceof RSAPublicKey) {
+ var rsaKey = (RSAPublicKey) publicKey;
+ int bitLength = rsaKey.getModulus().bitLength();
+ if (bitLength == 2048) {
+ return SigningAlgorithm.PKIX_RSA_PKCS1V15_2048_SHA256;
+ } else if (bitLength == 3072) {
+ return SigningAlgorithm.PKIX_RSA_PKCS1V15_3072_SHA256;
+ } else if (bitLength == 4096) {
+ return SigningAlgorithm.PKIX_RSA_PKCS1V15_4096_SHA256;
+ }
+ throw new UnsupportedAlgorithmException("Unsupported RSA bit length: " + bitLength);
+ }
+ throw new IllegalStateException("RSA key must be an instance of RSAPublicKey");
+ }
+ if ("EC".equals(algorithm) || "ECDSA".equals(algorithm)) {
+ if (publicKey instanceof ECPublicKey) {
+ var ecKey = (ECPublicKey) publicKey;
+ var order = ecKey.getParams().getOrder();
+ var signingAlgorithm = ECDSA_ORDERS.get(order);
+ if (signingAlgorithm == null) {
+ throw new UnsupportedAlgorithmException("Unsupported EC key with order: " + order);
+ }
+ return signingAlgorithm;
+ }
+ throw new IllegalStateException("EC/ECDSA key must be an instance of ECPublicKey");
+ }
+ throw new UnsupportedAlgorithmException("Unsupported key algorithm: " + algorithm);
+ }
+
public enum SigningAlgorithm {
PKIX_RSA_PKCS1V15_2048_SHA256(HashAlgorithm.SHA2_256),
PKIX_RSA_PKCS1V15_3072_SHA256(HashAlgorithm.SHA2_256),
PKIX_RSA_PKCS1V15_4096_SHA256(HashAlgorithm.SHA2_256),
// ECDSA
- PKIX_ECDSA_P256_SHA_256(HashAlgorithm.SHA2_256);
- // TODO: PKIX_ECDSA_P384_SHA_384(HashAlgorithm.SHA2_384),
- // TODO: PKIX_ECDSA_P521_SHA_512(HashAlgorithm.SHA2_512);
+ PKIX_ECDSA_P256_SHA_256(HashAlgorithm.SHA2_256),
+ PKIX_ECDSA_P384_SHA_384(HashAlgorithm.SHA2_384),
+ PKIX_ECDSA_P521_SHA_512(HashAlgorithm.SHA2_512);
private final HashAlgorithm hashAlgorithm;
@@ -36,36 +93,36 @@ public enum SigningAlgorithm {
this.hashAlgorithm = hashAlgorithm;
}
- public HashAlgorithm getHashing() {
+ public HashAlgorithm getHashAlgorithm() {
return hashAlgorithm;
}
}
public enum HashAlgorithm {
- SHA2_256("SHA256", 32, sha256());
- // TODO: SHA2_384("SHA384", 48, sha384()),
- // TODO: SHA2_512("SHA512", 64, sha512());
+ SHA2_256("SHA256", "sha256", 32),
+ SHA2_384("SHA384", "sha384", 48),
+ SHA2_512("SHA512", "sha512", 64);
private final String name;
+ private final String lowercase;
private final int length;
- private final HashFunction hashFunction;
- HashAlgorithm(String name, int length, HashFunction hashFunction) {
+ HashAlgorithm(String name, String lowercase, int length) {
this.name = name;
+ this.lowercase = lowercase;
this.length = length;
- this.hashFunction = hashFunction;
}
public String toString() {
return name;
}
- public int getLength() {
- return length;
+ public String toLowercaseString() {
+ return lowercase;
}
- HashFunction getHashFunction() {
- return hashFunction;
+ public int getLength() {
+ return length;
}
}
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/KeylessSigner.java b/sigstore-java/src/main/java/dev/sigstore/KeylessSigner.java
index 5ad03816a..218affb88 100644
--- a/sigstore-java/src/main/java/dev/sigstore/KeylessSigner.java
+++ b/sigstore-java/src/main/java/dev/sigstore/KeylessSigner.java
@@ -18,7 +18,6 @@
import com.google.api.client.util.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.hash.Hashing;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.CheckReturnValue;
import com.google.errorprone.annotations.concurrent.GuardedBy;
@@ -30,6 +29,7 @@
import dev.sigstore.bundle.ImmutableSignature;
import dev.sigstore.bundle.ImmutableTimestamp;
import dev.sigstore.dsse.InTotoPayload;
+import dev.sigstore.encryption.Hashers;
import dev.sigstore.encryption.certificates.Certificates;
import dev.sigstore.encryption.signers.Signer;
import dev.sigstore.encryption.signers.Signers;
@@ -38,7 +38,6 @@
import dev.sigstore.fulcio.client.FulcioClientGrpc;
import dev.sigstore.fulcio.client.FulcioVerificationException;
import dev.sigstore.fulcio.client.FulcioVerifier;
-import dev.sigstore.fulcio.client.UnsupportedAlgorithmException;
import dev.sigstore.json.JsonParseException;
import dev.sigstore.oidc.client.OidcClients;
import dev.sigstore.oidc.client.OidcException;
@@ -46,7 +45,6 @@
import dev.sigstore.oidc.client.OidcTokenMatcher;
import dev.sigstore.proto.ProtoMutators;
import dev.sigstore.proto.common.v1.X509Certificate;
-import dev.sigstore.proto.rekor.v2.DSSERequestV002;
import dev.sigstore.proto.rekor.v2.HashedRekordRequestV002;
import dev.sigstore.proto.rekor.v2.Signature;
import dev.sigstore.proto.rekor.v2.Verifier;
@@ -70,7 +68,6 @@
import dev.sigstore.trustroot.Service;
import dev.sigstore.trustroot.SigstoreConfigurationException;
import dev.sigstore.tuf.SigstoreTufClient;
-import io.intoto.EnvelopeOuterClass;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
@@ -337,7 +334,7 @@ public KeylessSigner build()
oidcClients = OidcClients.from(oidcService.get());
}
- if (!signingAlgorithm.getHashing().equals(AlgorithmRegistry.HashAlgorithm.SHA2_256)) {
+ if (!signingAlgorithm.getHashAlgorithm().equals(AlgorithmRegistry.HashAlgorithm.SHA2_256)) {
throw new SigstoreConfigurationException("Signing algorithm must use sha256");
}
@@ -402,7 +399,7 @@ public List sign(List artifactDigests) throws KeylessSignerExcep
}
for (var digest : artifactDigests) {
- if (signingAlgorithm.getHashing().getLength() != digest.length) {
+ if (signingAlgorithm.getHashAlgorithm().getLength() != digest.length) {
throw new KeylessSignerException(
"Invalid digest length: "
+ digest.length
@@ -453,11 +450,14 @@ public List sign(List artifactDigests) throws KeylessSignerExcep
lock.readLock().unlock();
}
+ var hashFunction = Hashers.from(signingAlgorithm.getHashAlgorithm());
+
var bundleBuilder =
ImmutableBundle.builder()
.certPath(signingCert)
.messageSignature(
- MessageSignature.of(signingAlgorithm.getHashing(), artifactDigest, signature));
+ MessageSignature.of(
+ signingAlgorithm.getHashAlgorithm(), artifactDigest, signature));
if (rekorV2Client != null) { // Using Rekor v2 and a TSA
Preconditions.checkNotNull(
@@ -465,11 +465,11 @@ public List sign(List artifactDigests) throws KeylessSignerExcep
Preconditions.checkNotNull(
timestampVerifier, "Timestamp verifier must be configured for Rekor v2");
- var signatureDigest = Hashing.sha256().hashBytes(signature).asBytes();
+ var signatureDigest = hashFunction.hashBytes(signature).asBytes();
var tsReq =
ImmutableTimestampRequest.builder()
- .hashAlgorithm(dev.sigstore.timestamp.client.HashAlgorithm.SHA256)
+ .hashAlgorithm(signingAlgorithm.getHashAlgorithm())
.hash(signatureDigest)
.build();
@@ -534,7 +534,10 @@ public List sign(List artifactDigests) throws KeylessSignerExcep
} else if (rekorClient != null) { // Using Rekor v1
var rekorRequest =
HashedRekordRequest.newHashedRekordRequest(
- artifactDigest, signingCertPemBytes, signature);
+ artifactDigest,
+ signingAlgorithm.getHashAlgorithm(),
+ signingCertPemBytes,
+ signature);
RekorResponse rekorResponse;
try {
@@ -654,9 +657,9 @@ public Map signFiles(List artifacts) throws KeylessSignerExc
var digests = new ArrayList(artifacts.size());
for (var artifact : artifacts) {
var artifactByteSource = com.google.common.io.Files.asByteSource(artifact.toFile());
+ var hashFunction = Hashers.from(signingAlgorithm);
try {
- digests.add(
- artifactByteSource.hash(signingAlgorithm.getHashing().getHashFunction()).asBytes());
+ digests.add(artifactByteSource.hash(hashFunction).asBytes());
} catch (IOException ex) {
throw new KeylessSignerException("Failed to hash artifact " + artifact);
}
@@ -760,19 +763,21 @@ public Bundle attest(String payload) throws KeylessSignerException {
.build();
var pae = dsse.getPAE();
+ var paeDigest = Hashers.from(signingAlgorithm).hashBytes(pae).asBytes();
+ byte[] signature;
- Bundle.DsseEnvelope dsseSigned;
try {
- var sig = signer.sign(pae);
- dsseSigned =
- ImmutableDsseEnvelope.builder()
- .from(dsse)
- .addSignatures(ImmutableSignature.builder().sig(sig).build())
- .build();
+ signature = signer.signDigest(paeDigest);
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException ex) {
throw new KeylessSignerException("Failed to sign artifact", ex);
}
+ Bundle.DsseEnvelope dsseSigned =
+ ImmutableDsseEnvelope.builder()
+ .from(dsse)
+ .addSignatures(ImmutableSignature.builder().sig(signature).build())
+ .build();
+
var verifier =
Verifier.newBuilder()
.setX509Certificate(
@@ -780,24 +785,24 @@ public Bundle attest(String payload) throws KeylessSignerException {
.setKeyDetails(ProtoMutators.toPublicKeyDetails(signingAlgorithm))
.build();
- var dsseRequest =
- DSSERequestV002.newBuilder()
- .setEnvelope(
- EnvelopeOuterClass.Envelope.newBuilder()
- .setPayload(ByteString.copyFrom(dsseSigned.getPayload()))
- .setPayloadType(dsseSigned.getPayloadType())
- .addSignatures(
- EnvelopeOuterClass.Signature.newBuilder()
- .setSig(ByteString.copyFrom(dsseSigned.getSignature())))
- .build())
- .addVerifiers(verifier)
+ var reqSignature =
+ Signature.newBuilder()
+ .setVerifier(verifier)
+ .setContent(ByteString.copyFrom(dsseSigned.getSignature()))
+ .build();
+
+ var hashedRekordRequest =
+ HashedRekordRequestV002.newBuilder()
+ .setSignature(reqSignature)
+ .setDigest(ByteString.copyFrom(paeDigest))
.build();
- var signatureDigest = Hashing.sha256().hashBytes(dsseSigned.getSignature()).asBytes();
+ var hashFunction = Hashers.from(signingAlgorithm);
+ var signatureDigest = hashFunction.hashBytes(dsseSigned.getSignature()).asBytes();
var tsReq =
ImmutableTimestampRequest.builder()
- .hashAlgorithm(dev.sigstore.timestamp.client.HashAlgorithm.SHA256)
+ .hashAlgorithm(signingAlgorithm.getHashAlgorithm())
.hash(signatureDigest)
.build();
@@ -821,7 +826,7 @@ public Bundle attest(String payload) throws KeylessSignerException {
RekorEntry entry;
try {
- entry = rekorV2Client.putEntry(dsseRequest);
+ entry = rekorV2Client.putEntry(hashedRekordRequest);
} catch (IOException | RekorParseException ex) {
throw new KeylessSignerException("Failed to put entry in rekor", ex);
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java b/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java
index 5e7a99f7c..8c8fa0619 100644
--- a/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java
+++ b/sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java
@@ -17,7 +17,6 @@
import com.google.api.client.util.Preconditions;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import dev.sigstore.VerificationOptions.CertificateMatcher;
import dev.sigstore.VerificationOptions.UncheckedCertificateException;
@@ -25,17 +24,18 @@
import dev.sigstore.bundle.Bundle.DsseEnvelope;
import dev.sigstore.bundle.Bundle.MessageSignature;
import dev.sigstore.dsse.InTotoPayload;
+import dev.sigstore.encryption.Hashers;
import dev.sigstore.encryption.certificates.Certificates;
import dev.sigstore.encryption.signers.Verifiers;
import dev.sigstore.fulcio.client.FulcioVerificationException;
import dev.sigstore.fulcio.client.FulcioVerifier;
import dev.sigstore.json.JsonParseException;
-import dev.sigstore.proto.common.v1.HashAlgorithm;
-import dev.sigstore.proto.rekor.v2.DSSELogEntryV002;
+import dev.sigstore.proto.ProtoMutators;
import dev.sigstore.proto.rekor.v2.HashedRekordLogEntryV002;
import dev.sigstore.proto.rekor.v2.Signature;
import dev.sigstore.rekor.client.HashedRekordRequest;
import dev.sigstore.rekor.client.RekorEntry;
+import dev.sigstore.rekor.client.RekorEntryBody;
import dev.sigstore.rekor.client.RekorTypeException;
import dev.sigstore.rekor.client.RekorTypes;
import dev.sigstore.rekor.client.RekorVerificationException;
@@ -129,15 +129,50 @@ 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;
+ }
+ } 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() + "'");
+ } catch (JsonParseException | RekorTypeException | UnsupportedAlgorithmException ex) {
+ throw new KeylessVerificationException(
+ "Could not determine hash algorithm from sigstore bundle", ex);
+ }
+ }
+
/** Convenience wrapper around {@link #verify(byte[], Bundle, VerificationOptions)}. */
public void verify(Path artifact, Bundle bundle, VerificationOptions options)
throws KeylessVerificationException {
+ var hashAlgorithm = findHashAlgorithm(bundle);
try {
- byte[] artifactDigest =
- Files.asByteSource(artifact.toFile()).hash(Hashing.sha256()).asBytes();
+ var artifactDigest =
+ Files.asByteSource(artifact.toFile()).hash(Hashers.from(hashAlgorithm)).asBytes();
verify(artifactDigest, bundle, options);
- } catch (IOException e) {
- throw new KeylessVerificationException("Could not hash provided artifact path: " + artifact);
+ } catch (IOException ex) {
+ throw new KeylessVerificationException("Could not hash artifact: " + artifact, ex);
}
}
@@ -145,7 +180,8 @@ public void verify(Path artifact, Bundle bundle, VerificationOptions options)
* Verify that the inputs can attest to the validity of a signature using sigstore's keyless
* infrastructure. If no exception is thrown, it should be assumed verification has passed.
*
- * @param artifactDigest the sha256 digest of the artifact that is being verified
+ * @param artifactDigest the digest of the artifact that is being verified, this must match the
+ * scheme used to sign the artifact
* @param bundle the sigstore signature bundle to verify
* @param options the keyless verification data and options
* @throws KeylessVerificationException if the signing information could not be verified
@@ -172,16 +208,17 @@ public void verify(byte[] artifactDigest, Bundle bundle, VerificationOptions opt
// verify the certificate identity if options are present
checkCertificateMatchers(leafCert, options.getCertificateMatchers());
+ var hashAlgorithm = findHashAlgorithm(bundle);
var rekorEntry = bundle.getEntries().get(0);
byte[] signature;
if (bundle.getMessageSignature().isPresent()) { // hashedrekord
var messageSignature = bundle.getMessageSignature().get();
- checkMessageSignature(messageSignature, rekorEntry, artifactDigest, leafCert);
+ checkMessageSignature(messageSignature, rekorEntry, artifactDigest, hashAlgorithm, leafCert);
signature = messageSignature.getSignature();
} else { // dsse
var dsseEnvelope = bundle.getDsseEnvelope().get();
- checkDsseEnvelope(rekorEntry, dsseEnvelope, artifactDigest, leafCert);
+ checkDsseEnvelope(rekorEntry, dsseEnvelope, artifactDigest, hashAlgorithm, leafCert);
signature = dsseEnvelope.getSignature();
}
@@ -257,6 +294,7 @@ private void checkMessageSignature(
MessageSignature messageSignature,
RekorEntry rekorEntry,
byte[] artifactDigest,
+ AlgorithmRegistry.HashAlgorithm hashAlgorithm,
X509Certificate leafCert)
throws KeylessVerificationException {
// this ensures the provided artifact digest matches what may have come from a bundle (in
@@ -276,12 +314,13 @@ private void checkMessageSignature(
// verify the signature over the artifact
var signature = messageSignature.getSignature();
try {
- if (!Verifiers.newVerifier(leafCert.getPublicKey()).verifyDigest(artifactDigest, signature)) {
+ if (!Verifiers.newVerifier(leafCert.getPublicKey(), hashAlgorithm)
+ .verifyDigest(artifactDigest, signature)) {
throw new KeylessVerificationException("Artifact signature was not valid");
}
- } catch (NoSuchAlgorithmException | InvalidKeyException ex) {
- throw new RuntimeException(ex);
- } catch (SignatureException ex) {
+ } catch (NoSuchAlgorithmException | InvalidKeyException e) {
+ throw new RuntimeException(e);
+ } catch (SignatureException | UnsupportedAlgorithmException ex) {
throw new KeylessVerificationException(
"Signature could not be processed: " + ex.getMessage(), ex);
}
@@ -298,7 +337,7 @@ private void checkMessageSignature(
RekorTypes.getHashedRekordV001(rekorEntry);
var calculatedHashedRekord =
HashedRekordRequest.newHashedRekordRequest(
- artifactDigest, Certificates.toPemBytes(leafCert), signature)
+ artifactDigest, hashAlgorithm, Certificates.toPemBytes(leafCert), signature)
.toJsonPayload();
var body =
new String(Base64.getDecoder().decode(rekorEntry.getBody()), StandardCharsets.UTF_8);
@@ -321,9 +360,10 @@ private void checkMessageSignature(
"Could not parse hashedrekord from log entry body", re);
}
- if (!logEntrySpec.getData().getAlgorithm().equals(HashAlgorithm.SHA2_256)) {
- throw new KeylessVerificationException(
- "Unsupported digest algorithm in log entry: " + logEntrySpec.getData().getAlgorithm());
+ try {
+ ProtoMutators.toHashAlgorithm(logEntrySpec.getData().getAlgorithm());
+ } catch (UnsupportedAlgorithmException ex) {
+ throw new KeylessVerificationException("Unsupported digest algorithm in log entry", ex);
}
if (!Arrays.equals(logEntrySpec.getData().getDigest().toByteArray(), artifactDigest)) {
@@ -360,6 +400,7 @@ private void checkDsseEnvelope(
RekorEntry rekorEntry,
DsseEnvelope dsseEnvelope,
byte[] artifactDigest,
+ AlgorithmRegistry.HashAlgorithm hashAlgorithm,
X509Certificate leafCert)
throws KeylessVerificationException {
// verify the artifact is in the subject list of the envelope
@@ -379,13 +420,16 @@ private void checkDsseEnvelope(
throw new KeylessVerificationException("Could not parse DSSE payload", jpe);
}
- // find one sha256 hash in the subject list that matches the artifact hash
+ // find one hash in the subject list that matches the artifact hash
+ var hashName = hashAlgorithm.toLowercaseString();
+ var hashing = Hashers.from(hashAlgorithm);
+
if (payload.getSubject().stream()
.noneMatch(
subject -> {
- if (subject.getDigest().containsKey("sha256")) {
+ if (subject.getDigest().containsKey(hashName)) {
try {
- var digestBytes = Hex.decode(subject.getDigest().get("sha256"));
+ var digestBytes = Hex.decode(subject.getDigest().get(hashName));
return Arrays.equals(artifactDigest, digestBytes);
} catch (DecoderException de) {
// ignore (assume false)
@@ -395,11 +439,13 @@ private void checkDsseEnvelope(
})) {
var providedHashes =
payload.getSubject().stream()
- .map(s -> s.getDigest().getOrDefault("sha256", "no-sha256-hash"))
+ .map(s -> s.getDigest().getOrDefault(hashName, "no-" + hashName + "-hash"))
.collect(Collectors.joining(",", "[", "]"));
throw new KeylessVerificationException(
- "Provided artifact digest does not match any subject sha256 digests in DSSE payload"
+ "Provided artifact digest does not match any subject "
+ + hashName
+ + " digests in DSSE payload"
+ "\nprovided(hex) : "
+ Hex.toHexString(artifactDigest)
+ "\nverification : "
@@ -413,23 +459,25 @@ private void checkDsseEnvelope(
+ dsseEnvelope.getSignatures().size());
}
try {
- if (!Verifiers.newVerifier(leafCert.getPublicKey())
+ if (!Verifiers.newVerifier(leafCert.getPublicKey(), hashAlgorithm)
.verify(dsseEnvelope.getPAE(), dsseEnvelope.getSignature())) {
throw new KeylessVerificationException("DSSE signature was not valid");
}
} catch (NoSuchAlgorithmException | InvalidKeyException ex) {
throw new RuntimeException(ex);
- } catch (SignatureException se) {
+ } catch (SignatureException | UnsupportedAlgorithmException se) {
throw new KeylessVerificationException("Signature could not be processed", se);
}
- String version;
+ RekorEntryBody entryBody;
try {
- version = rekorEntry.getBodyDecoded().getApiVersion();
+ entryBody = rekorEntry.getBodyDecoded();
} catch (JsonParseException ex) {
throw new KeylessVerificationException("Could not extract body from log entry");
}
- if ("0.0.1".equals(version)) {
+ var kind = entryBody.getKind();
+ var version = entryBody.getApiVersion();
+ if ("0.0.1".equals(version) && "dsse".equals(kind)) {
Dsse rekorDsse;
try {
rekorDsse = RekorTypes.getDsseV001(rekorEntry);
@@ -440,7 +488,7 @@ private void checkDsseEnvelope(
var algorithm = rekorDsse.getPayloadHash().getAlgorithm();
if (algorithm != PayloadHash.Algorithm.SHA_256) {
throw new KeylessVerificationException(
- "Cannot process DSSE entry with hashing algorithm " + algorithm.toString());
+ "Cannot process DSSE entry with payload hashing algorithm " + algorithm.toString());
}
// check if the digest over the dsse payload matches the digest in the transparency log entry
@@ -449,10 +497,10 @@ private void checkDsseEnvelope(
payloadDigest = Hex.decode(rekorDsse.getPayloadHash().getValue());
} catch (DecoderException de) {
throw new KeylessVerificationException(
- "Could not decode hex sha256 artifact hash in hashedrekord", de);
+ "Could not decode hex artifact hash in hashedrekord", de);
}
- byte[] calculatedDigest = Hashing.sha256().hashBytes(dsseEnvelope.getPayload()).asBytes();
+ byte[] calculatedDigest = hashing.hashBytes(dsseEnvelope.getPayload()).asBytes();
if (!Arrays.equals(calculatedDigest, payloadDigest)) {
throw new KeylessVerificationException(
"Digest of DSSE payload in bundle does not match DSSE payload digest in log entry");
@@ -471,45 +519,30 @@ private void checkDsseEnvelope(
throw new KeylessVerificationException(
"Provided DSSE signature materials are inconsistent with DSSE log entry");
}
- } else if ("0.0.2".equals(version)) {
- DSSELogEntryV002 logEntrySpec;
+ } else if ("0.0.2".equals(version) && "hashedrekord".equals(kind)) {
+ HashedRekordLogEntryV002 logEntrySpec;
try {
- logEntrySpec = RekorTypes.getDsseV002(rekorEntry);
+ logEntrySpec = RekorTypes.getHashedRekordV002(rekorEntry);
} catch (RekorTypeException re) {
throw new KeylessVerificationException("Could not parse DSSE from log entry body", re);
}
- if (!logEntrySpec.getPayloadHash().getAlgorithm().equals(HashAlgorithm.SHA2_256)) {
+ // check if the digest over the dsse pae matches the digest in the transparency log entry
+ byte[] calculatedDigest = hashing.hashBytes(dsseEnvelope.getPAE()).asBytes();
+ if (!Arrays.equals(logEntrySpec.getData().getDigest().toByteArray(), calculatedDigest)) {
throw new KeylessVerificationException(
- "Unsupported digest algorithm in log entry: "
- + logEntrySpec.getPayloadHash().getAlgorithm());
+ "Digest of DSSE.pae in bundle does not match digest in log entry");
}
- // check if the digest over the dsse payload matches the digest in the transparency log entry
- byte[] calculatedDigest = Hashing.sha256().hashBytes(dsseEnvelope.getPayload()).asBytes();
- if (!Arrays.equals(
- logEntrySpec.getPayloadHash().getDigest().toByteArray(), calculatedDigest)) {
- throw new KeylessVerificationException(
- "Digest of DSSE payload in bundle does not match DSSE payload digest in log entry");
- }
-
- // check if the signature over the dsse payload matches the signature in the rekorEntry
- if (logEntrySpec.getSignaturesCount() != 1) {
- throw new KeylessVerificationException(
- "Log entry spec must have exactly 1 signature, but found: "
- + logEntrySpec.getSignaturesCount());
- }
-
- Signature logSignature = logEntrySpec.getSignatures(0);
+ Signature logSignature = logEntrySpec.getSignature();
if (!Arrays.equals(dsseEnvelope.getSignature(), logSignature.getContent().toByteArray())) {
throw new KeylessVerificationException(
- "Signature in DSSE envelope does not match signature in log entry spec");
+ "Signature in DSSE envelope does not match signature in log entry");
}
var verifier = logSignature.getVerifier();
if (!verifier.hasX509Certificate()) {
- throw new KeylessVerificationException(
- "Rekor entry DSSE verifier is missing X.509 certificate");
+ throw new KeylessVerificationException("Log entry is missing X.509 certificate");
}
try {
byte[] certFromRekor = verifier.getX509Certificate().getRawBytes().toByteArray();
@@ -523,7 +556,8 @@ private void checkDsseEnvelope(
"Could not encode leaf certificate for comparison", e);
}
} else {
- throw new KeylessVerificationException("Unsupported DSSE version: " + version);
+ throw new KeylessVerificationException(
+ "Unsupported entry type: '" + kind + ":" + version + "' for DSSE bundle");
}
}
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/fulcio/client/UnsupportedAlgorithmException.java b/sigstore-java/src/main/java/dev/sigstore/UnsupportedAlgorithmException.java
similarity index 68%
rename from sigstore-java/src/main/java/dev/sigstore/fulcio/client/UnsupportedAlgorithmException.java
rename to sigstore-java/src/main/java/dev/sigstore/UnsupportedAlgorithmException.java
index 8d17b735e..ddf2c2924 100644
--- a/sigstore-java/src/main/java/dev/sigstore/fulcio/client/UnsupportedAlgorithmException.java
+++ b/sigstore-java/src/main/java/dev/sigstore/UnsupportedAlgorithmException.java
@@ -13,16 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package dev.sigstore.fulcio.client;
-
-import java.util.Arrays;
-import java.util.Set;
+package dev.sigstore;
public class UnsupportedAlgorithmException extends Exception {
- public UnsupportedAlgorithmException(Set allowedAlgorithms, String algorithm) {
- super(
- algorithm
- + " is not from supported list of "
- + Arrays.toString(allowedAlgorithms.toArray()));
+ public UnsupportedAlgorithmException(String message) {
+ super(message);
+ }
+
+ public UnsupportedAlgorithmException(String message, Throwable cause) {
+ super(message, cause);
}
}
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 e17757eba..3bcd184da 100644
--- a/sigstore-java/src/main/java/dev/sigstore/bundle/BundleReader.java
+++ b/sigstore-java/src/main/java/dev/sigstore/bundle/BundleReader.java
@@ -19,7 +19,6 @@
import dev.sigstore.AlgorithmRegistry;
import dev.sigstore.json.ProtoJson;
import dev.sigstore.proto.ProtoMutators;
-import dev.sigstore.proto.common.v1.HashAlgorithm;
import dev.sigstore.rekor.client.ImmutableInclusionProof;
import dev.sigstore.rekor.client.ImmutableRekorEntry;
import dev.sigstore.rekor.client.ImmutableVerification;
@@ -115,19 +114,26 @@ static Bundle readBundle(Reader jsonReader) throws BundleParseException {
var signature = protoBundle.getMessageSignature().getSignature().toByteArray();
if (protoBundle.getMessageSignature().hasMessageDigest()) {
var hashAlgorithm = protoBundle.getMessageSignature().getMessageDigest().getAlgorithm();
- if (hashAlgorithm != HashAlgorithm.SHA2_256) {
- throw new BundleParseException(
- "Cannot read message digests of type "
- + hashAlgorithm
- + ", only "
- + HashAlgorithm.SHA2_256
- + " is supported");
+ AlgorithmRegistry.HashAlgorithm alg;
+ switch (hashAlgorithm) {
+ case SHA2_256:
+ alg = AlgorithmRegistry.HashAlgorithm.SHA2_256;
+ break;
+ case SHA2_384:
+ alg = AlgorithmRegistry.HashAlgorithm.SHA2_384;
+ break;
+ case SHA2_512:
+ alg = AlgorithmRegistry.HashAlgorithm.SHA2_512;
+ break;
+ default:
+ throw new BundleParseException(
+ "Cannot read message digests of type " + hashAlgorithm + ", unsupported algorithm");
}
var messageSignature =
ImmutableMessageSignature.builder()
.messageDigest(
ImmutableMessageDigest.builder()
- .hashAlgorithm(AlgorithmRegistry.HashAlgorithm.SHA2_256)
+ .hashAlgorithm(alg)
.digest(
protoBundle
.getMessageSignature()
diff --git a/sigstore-java/src/main/java/dev/sigstore/encryption/Hashers.java b/sigstore-java/src/main/java/dev/sigstore/encryption/Hashers.java
new file mode 100644
index 000000000..c93085751
--- /dev/null
+++ b/sigstore-java/src/main/java/dev/sigstore/encryption/Hashers.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2026 The Sigstore Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.sigstore.encryption;
+
+import com.google.common.hash.HashFunction;
+import com.google.common.hash.Hashing;
+import dev.sigstore.AlgorithmRegistry;
+
+public class Hashers {
+ public static HashFunction from(AlgorithmRegistry.HashAlgorithm hashAlgorithm) {
+ switch (hashAlgorithm) {
+ case SHA2_256:
+ return Hashing.sha256();
+ case SHA2_384:
+ return Hashing.sha384();
+ case SHA2_512:
+ return Hashing.sha512();
+ }
+ throw new IllegalStateException();
+ }
+
+ public static HashFunction from(AlgorithmRegistry.SigningAlgorithm signingAlgorithm) {
+ return from(signingAlgorithm.getHashAlgorithm());
+ }
+}
diff --git a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/EcdsaVerifier.java b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/EcdsaVerifier.java
index b32463b13..50ba30ea1 100644
--- a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/EcdsaVerifier.java
+++ b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/EcdsaVerifier.java
@@ -15,15 +15,18 @@
*/
package dev.sigstore.encryption.signers;
+import dev.sigstore.AlgorithmRegistry;
import java.security.*;
/** ECDSA verifier, instantiated by {@link Verifiers#newVerifier(PublicKey)}. */
public class EcdsaVerifier implements Verifier {
private final PublicKey publicKey;
+ private final AlgorithmRegistry.HashAlgorithm hashAlgorithm;
- EcdsaVerifier(PublicKey publicKey) {
+ EcdsaVerifier(PublicKey publicKey, AlgorithmRegistry.HashAlgorithm hashAlgorithm) {
this.publicKey = publicKey;
+ this.hashAlgorithm = hashAlgorithm;
}
@Override
@@ -34,7 +37,7 @@ public PublicKey getPublicKey() {
@Override
public boolean verify(byte[] artifact, byte[] signature)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- var verifier = Signature.getInstance("SHA256withECDSA");
+ var verifier = Signature.getInstance(hashAlgorithm + "withECDSA");
verifier.initVerify(publicKey);
verifier.update(artifact);
return verifier.verify(signature);
@@ -43,8 +46,9 @@ public boolean verify(byte[] artifact, byte[] signature)
@Override
public boolean verifyDigest(byte[] digest, byte[] signature)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- if (digest.length > 64) {
- throw new SignatureException("Artifact digest cannot be longer than 64 bytes for this mode");
+ if (digest.length != hashAlgorithm.getLength()) {
+ throw new SignatureException(
+ "Artifact digest must be " + hashAlgorithm.getLength() + " bytes");
}
var verifier = Signature.getInstance("NONEwithECDSA");
verifier.initVerify(publicKey);
diff --git a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaSigner.java b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaSigner.java
index b263aad69..e84ee605f 100644
--- a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaSigner.java
+++ b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaSigner.java
@@ -26,11 +26,9 @@ public class RsaSigner implements Signer {
static final byte[] PKCS1_SHA256_PADDING = Hex.decode("3031300d060960864801650304020105000420");
private final KeyPair keyPair;
- private final AlgorithmRegistry.HashAlgorithm hashAlgorithm;
- RsaSigner(KeyPair keyPair, AlgorithmRegistry.HashAlgorithm hashAlgorithm) {
+ RsaSigner(KeyPair keyPair) {
this.keyPair = keyPair;
- this.hashAlgorithm = hashAlgorithm;
}
@Override
@@ -41,7 +39,7 @@ public PublicKey getPublicKey() {
@Override
public byte[] sign(byte[] artifact)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- Signature signature = Signature.getInstance(hashAlgorithm + "withRSA");
+ Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(keyPair.getPrivate());
signature.update(artifact);
return signature.sign();
@@ -50,9 +48,11 @@ public byte[] sign(byte[] artifact)
@Override
public byte[] signDigest(byte[] artifactDigest)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
- if (artifactDigest.length != hashAlgorithm.getLength()) {
+ if (artifactDigest.length != AlgorithmRegistry.HashAlgorithm.SHA2_256.getLength()) {
throw new SignatureException(
- "Artifact digest must be " + hashAlgorithm.getLength() + " bytes");
+ "Artifact digest must be "
+ + AlgorithmRegistry.HashAlgorithm.SHA2_256.getLength()
+ + " bytes");
}
Signature signature = Signature.getInstance("NONEwithRSA");
signature.initSign(keyPair.getPrivate());
diff --git a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaVerifier.java b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaVerifier.java
index cb125ea2c..00593d82f 100644
--- a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaVerifier.java
+++ b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/RsaVerifier.java
@@ -15,9 +15,10 @@
*/
package dev.sigstore.encryption.signers;
+import dev.sigstore.AlgorithmRegistry;
import java.security.*;
-/** RSA verifier, instantiated by {@link Verifiers#newVerifier(PublicKey)}. */
+/** RSA verifier, instantiated by {@link Verifiers}. */
public class RsaVerifier implements Verifier {
private final PublicKey publicKey;
@@ -43,6 +44,12 @@ public boolean verify(byte[] artifact, byte[] signature)
@Override
public boolean verifyDigest(byte[] digest, byte[] signature)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+ if (digest.length != AlgorithmRegistry.HashAlgorithm.SHA2_256.getLength()) {
+ throw new SignatureException(
+ "Artifact digest must be "
+ + AlgorithmRegistry.HashAlgorithm.SHA2_256.getLength()
+ + " bytes");
+ }
var verifier = Signature.getInstance("NONEwithRSA");
verifier.initVerify(publicKey);
verifier.update(RsaSigner.PKCS1_SHA256_PADDING);
diff --git a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Signers.java b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Signers.java
index 77e2abe09..62ef59f05 100644
--- a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Signers.java
+++ b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Signers.java
@@ -28,13 +28,17 @@ public class Signers {
public static Signer from(AlgorithmRegistry.SigningAlgorithm algorithm) {
switch (algorithm) {
case PKIX_RSA_PKCS1V15_2048_SHA256:
- return newRsaSigner(2048, AlgorithmRegistry.HashAlgorithm.SHA2_256);
+ return newRsaSigner(2048);
case PKIX_RSA_PKCS1V15_3072_SHA256:
- return newRsaSigner(3072, AlgorithmRegistry.HashAlgorithm.SHA2_256);
+ return newRsaSigner(3072);
case PKIX_RSA_PKCS1V15_4096_SHA256:
- return newRsaSigner(4096, AlgorithmRegistry.HashAlgorithm.SHA2_256);
+ return newRsaSigner(4096);
case PKIX_ECDSA_P256_SHA_256:
return newEcdsaSigner("secp256r1", AlgorithmRegistry.HashAlgorithm.SHA2_256);
+ case PKIX_ECDSA_P384_SHA_384:
+ return newEcdsaSigner("secp384r1", AlgorithmRegistry.HashAlgorithm.SHA2_384);
+ case PKIX_ECDSA_P521_SHA_512:
+ return newEcdsaSigner("secp521r1", AlgorithmRegistry.HashAlgorithm.SHA2_512);
}
throw new IllegalStateException("Unknown algorithm: " + algorithm);
}
@@ -49,12 +53,12 @@ static EcdsaSigner newEcdsaSigner(String spec, AlgorithmRegistry.HashAlgorithm h
}
}
- /** Create a new RSA signer with 2048 bit keysize. */
- static RsaSigner newRsaSigner(int keysize, AlgorithmRegistry.HashAlgorithm hashAlgorithm) {
+ /** Create a new RSA signer with 2048 bit keysize. Hash Algorithm is always SHA256. */
+ static RsaSigner newRsaSigner(int keysize) {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(keysize);
- return new RsaSigner(keyGen.generateKeyPair(), hashAlgorithm);
+ return new RsaSigner(keyGen.generateKeyPair());
} catch (NoSuchAlgorithmException nse) {
throw new RuntimeException("No RSA algorithm found in Runtime", nse);
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifier.java b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifier.java
index 14b243bc5..40bd21afd 100644
--- a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifier.java
+++ b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifier.java
@@ -25,7 +25,7 @@ public interface Verifier {
PublicKey getPublicKey();
/**
- * Verify an artifact. Implementations will hash the artifact with sha256 before verifying.
+ * Verify an artifact. Implementations will hash the artifact before verifying.
*
* @param artifact the artifact that was signed
* @param signature the signature associated with the artifact
@@ -36,10 +36,10 @@ boolean verify(byte[] artifact, byte[] signature)
throws NoSuchAlgorithmException, InvalidKeyException, SignatureException;
/**
- * Verify an artifact using the artifact's sha256 digest. Implementations do not further hash the
- * input.
+ * Verify an artifact using the artifact's digest. Implementations do not further hash the input,
+ * but may check the hash length is consistent with the Verifier's configuration.
*
- * @param artifactDigest the sha256 digest of the artifact that was signed
+ * @param artifactDigest the digest of the artifact that was signed
* @param signature the signature associated with the artifact
* @return true if the signature is valid, false otherwise
*/
diff --git a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifiers.java b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifiers.java
index 1348b40a9..22591f205 100644
--- a/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifiers.java
+++ b/sigstore-java/src/main/java/dev/sigstore/encryption/signers/Verifiers.java
@@ -15,20 +15,25 @@
*/
package dev.sigstore.encryption.signers;
-import java.security.NoSuchAlgorithmException;
+import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
import java.security.PublicKey;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
/** Autodetection for verification algorithms based on public keys used. */
public class Verifiers {
- /** Returns a new verifier for the provided public key to use during verification. */
- public static Verifier newVerifier(PublicKey publicKey) throws NoSuchAlgorithmException {
+ /**
+ * Returns a new verifier for the provided public key to use during verification. Hash algorithm
+ * is automatically determined from the {@link AlgorithmRegistry}.
+ */
+ public static Verifier newVerifier(PublicKey publicKey) throws UnsupportedAlgorithmException {
if (publicKey.getAlgorithm().equals("RSA")) {
return new RsaVerifier(publicKey);
}
if (publicKey.getAlgorithm().equals("EC") || publicKey.getAlgorithm().equals("ECDSA")) {
- return new EcdsaVerifier(publicKey);
+ return new EcdsaVerifier(
+ publicKey, AlgorithmRegistry.getSigningAlgorithm(publicKey).getHashAlgorithm());
}
if (publicKey.getAlgorithm().equals("Ed25519")) {
return new Ed25519Verifier(publicKey);
@@ -39,12 +44,32 @@ public static Verifier newVerifier(PublicKey publicKey) throws NoSuchAlgorithmEx
&& new ASN1ObjectIdentifier("1.3.101.112").equals(spki.getAlgorithm().getAlgorithm())) {
return new Ed25519Verifier(publicKey);
}
- throw new NoSuchAlgorithmException(
+ throw new UnsupportedAlgorithmException(
"Cannot verify signatures for non-Ed25519 EdDSA key types, this client only supports RSA, ECDSA, and Ed25519 verification");
}
- throw new NoSuchAlgorithmException(
+ throw new UnsupportedAlgorithmException(
"Cannot verify signatures for key type '"
+ publicKey.getAlgorithm()
+ "', this client only supports RSA, ECDSA, and Ed25519 verification");
}
+
+ /**
+ * Returns a verifier that is bound to a specific hash algorithm, useful for legacy signing using
+ * algorithms combinations not available in the {@link AlgorithmRegistry}.
+ */
+ public static Verifier newVerifier(
+ PublicKey publicKey, AlgorithmRegistry.HashAlgorithm hashAlgorithm)
+ throws UnsupportedAlgorithmException {
+ if (publicKey.getAlgorithm().equals("RSA")
+ && AlgorithmRegistry.HashAlgorithm.SHA2_256.equals(hashAlgorithm)) {
+ return new RsaVerifier(publicKey);
+ }
+ if (publicKey.getAlgorithm().equals("EC") || publicKey.getAlgorithm().equals("ECDSA")) {
+ return new EcdsaVerifier(publicKey, hashAlgorithm);
+ }
+ throw new UnsupportedAlgorithmException(
+ "Cannot verify signatures for key type '"
+ + publicKey.getAlgorithm()
+ + "', this client only supports RSA with SHA256 or ECDSA verification when specifying hash algorithm");
+ }
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/fulcio/client/CertificateRequest.java b/sigstore-java/src/main/java/dev/sigstore/fulcio/client/CertificateRequest.java
index 07cb48d15..7d45b347d 100644
--- a/sigstore-java/src/main/java/dev/sigstore/fulcio/client/CertificateRequest.java
+++ b/sigstore-java/src/main/java/dev/sigstore/fulcio/client/CertificateRequest.java
@@ -15,17 +15,15 @@
*/
package dev.sigstore.fulcio.client;
-import com.google.common.collect.ImmutableMap;
+import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
import dev.sigstore.fulcio.v2.PublicKeyAlgorithm;
+import dev.sigstore.proto.ProtoMutators;
import java.security.PublicKey;
-import java.util.Map;
import org.immutables.value.Value;
@Value.Immutable
public interface CertificateRequest {
- Map SUPPORTED_ALGORITHMS =
- ImmutableMap.of("EC", PublicKeyAlgorithm.ECDSA, "RSA", PublicKeyAlgorithm.RSA_PSS);
-
PublicKey getPublicKey();
PublicKeyAlgorithm getPublicKeyAlgorithm();
@@ -37,23 +35,19 @@ public interface CertificateRequest {
/**
* Create a certificate request
*
- * @param publicKey An ECDSA public key
+ * @param publicKey A public key to verify {@code proofOfPossession}
* @param idToken An oidc token obtained from an oauth provider
* @param proofOfPossession The subject or email address from {@code idToken}, signed by the
* private key counterpart of {@code publicKey} in asn1 notation
- * @throws UnsupportedAlgorithmException if key type is not in {@link
- * CertificateRequest#SUPPORTED_ALGORITHMS}
+ * @throws UnsupportedAlgorithmException if key type is not in {@link AlgorithmRegistry}
*/
static CertificateRequest newCertificateRequest(
PublicKey publicKey, String idToken, byte[] proofOfPossession)
throws UnsupportedAlgorithmException {
- if (!SUPPORTED_ALGORITHMS.containsKey(publicKey.getAlgorithm())) {
- throw new UnsupportedAlgorithmException(
- SUPPORTED_ALGORITHMS.keySet(), publicKey.getAlgorithm());
- }
+ var signingAlgorithm = AlgorithmRegistry.getSigningAlgorithm(publicKey);
return ImmutableCertificateRequest.builder()
.publicKey(publicKey)
- .publicKeyAlgorithm(SUPPORTED_ALGORITHMS.get(publicKey.getAlgorithm()))
+ .publicKeyAlgorithm(ProtoMutators.toPublicKeyAlgorithm(signingAlgorithm))
.idToken(idToken)
.proofOfPossession(proofOfPossession)
.build();
diff --git a/sigstore-java/src/main/java/dev/sigstore/oidc/client/EnvTokenProvider.java b/sigstore-java/src/main/java/dev/sigstore/oidc/client/EnvTokenProvider.java
new file mode 100644
index 000000000..933e189db
--- /dev/null
+++ b/sigstore-java/src/main/java/dev/sigstore/oidc/client/EnvTokenProvider.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2026 The Sigstore Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.sigstore.oidc.client;
+
+import java.util.Map;
+
+public class EnvTokenProvider implements TokenStringOidcClient.TokenStringProvider {
+ static final String ENV_VAR_NAME = "SIGSTORE_JAVA_ID_TOKEN";
+
+ static EnvTokenProvider of() {
+ return new EnvTokenProvider();
+ }
+
+ private EnvTokenProvider() {}
+
+ @Override
+ public boolean isEnabled(Map env) {
+ return env.containsKey(ENV_VAR_NAME);
+ }
+
+ @Override
+ public String getTokenString(Map env) throws Exception {
+ var token = env.get(ENV_VAR_NAME);
+ if (token == null) {
+ throw new IllegalStateException(ENV_VAR_NAME + " was not set");
+ }
+ return token;
+ }
+}
diff --git a/sigstore-java/src/main/java/dev/sigstore/oidc/client/OidcClients.java b/sigstore-java/src/main/java/dev/sigstore/oidc/client/OidcClients.java
index 17b1613f2..4e873b893 100644
--- a/sigstore-java/src/main/java/dev/sigstore/oidc/client/OidcClients.java
+++ b/sigstore-java/src/main/java/dev/sigstore/oidc/client/OidcClients.java
@@ -38,6 +38,7 @@ public static OidcClients of(OidcClient... clients) {
*/
public static OidcClients from(Service oidcService) {
return of(
+ TokenStringOidcClient.from(EnvTokenProvider.of()),
GithubActionsOidcClient.builder().build(),
WebOidcClient.builder().setIssuer(oidcService).build());
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/oidc/client/TokenStringOidcClient.java b/sigstore-java/src/main/java/dev/sigstore/oidc/client/TokenStringOidcClient.java
index 3fefd220b..c5fb9e4f0 100644
--- a/sigstore-java/src/main/java/dev/sigstore/oidc/client/TokenStringOidcClient.java
+++ b/sigstore-java/src/main/java/dev/sigstore/oidc/client/TokenStringOidcClient.java
@@ -42,18 +42,29 @@ public static TokenStringOidcClient from(TokenStringProvider provider) {
}
public static TokenStringOidcClient from(String token) {
- return new TokenStringOidcClient(() -> token);
+ return new TokenStringOidcClient(
+ new TokenStringProvider() {
+ @Override
+ public String getTokenString(Map env) throws Exception {
+ return token;
+ }
+
+ @Override
+ public boolean isEnabled(Map env) {
+ return true;
+ }
+ });
}
@Override
public boolean isEnabled(Map env) {
- return true;
+ return idTokenProvider.isEnabled(env);
}
@Override
public OidcToken getIDToken(Map env) throws OidcException {
try {
- var idToken = idTokenProvider.getTokenString();
+ var idToken = idTokenProvider.getTokenString(env);
var jws = JsonWebSignature.parse(new GsonFactory(), idToken);
String email = (String) jws.getPayload().get("email");
String san;
@@ -83,8 +94,9 @@ public OidcToken getIDToken(Map env) throws OidcException {
}
}
- @FunctionalInterface
public interface TokenStringProvider {
- String getTokenString() throws Exception;
+ String getTokenString(Map env) throws Exception;
+
+ boolean isEnabled(Map env);
}
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/proto/ProtoMutators.java b/sigstore-java/src/main/java/dev/sigstore/proto/ProtoMutators.java
index 440a45cc1..e607480ed 100644
--- a/sigstore-java/src/main/java/dev/sigstore/proto/ProtoMutators.java
+++ b/sigstore-java/src/main/java/dev/sigstore/proto/ProtoMutators.java
@@ -15,12 +15,12 @@
*/
package dev.sigstore.proto;
-import static dev.sigstore.proto.common.v1.HashAlgorithm.*;
-
import com.google.protobuf.ByteString;
import com.google.protobuf.Timestamp;
import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
import dev.sigstore.encryption.certificates.Certificates;
+import dev.sigstore.fulcio.v2.PublicKeyAlgorithm;
import dev.sigstore.proto.common.v1.HashAlgorithm;
import dev.sigstore.proto.common.v1.PublicKeyDetails;
import dev.sigstore.proto.common.v1.X509Certificate;
@@ -66,12 +66,30 @@ public static X509Certificate fromCert(java.security.cert.X509Certificate certif
}
public static HashAlgorithm toProtoHashAlgorithm(AlgorithmRegistry.HashAlgorithm algorithm) {
- if (Objects.requireNonNull(algorithm) == AlgorithmRegistry.HashAlgorithm.SHA2_256) {
- return SHA2_256;
+ switch (Objects.requireNonNull(algorithm)) {
+ case SHA2_256:
+ return HashAlgorithm.SHA2_256;
+ case SHA2_384:
+ return HashAlgorithm.SHA2_384;
+ case SHA2_512:
+ return HashAlgorithm.SHA2_512;
}
throw new IllegalStateException("Unknown hash algorithm: " + algorithm);
}
+ public static AlgorithmRegistry.HashAlgorithm toHashAlgorithm(HashAlgorithm hashAlgorithm)
+ throws UnsupportedAlgorithmException {
+ switch (Objects.requireNonNull(hashAlgorithm)) {
+ case SHA2_256:
+ return AlgorithmRegistry.HashAlgorithm.SHA2_256;
+ case SHA2_384:
+ return AlgorithmRegistry.HashAlgorithm.SHA2_384;
+ case SHA2_512:
+ return AlgorithmRegistry.HashAlgorithm.SHA2_512;
+ }
+ throw new UnsupportedAlgorithmException("Unsupported hash algorithm: " + hashAlgorithm);
+ }
+
public static PublicKeyDetails toPublicKeyDetails(AlgorithmRegistry.SigningAlgorithm algorithm) {
switch (algorithm) {
case PKIX_RSA_PKCS1V15_2048_SHA256:
@@ -82,6 +100,23 @@ public static PublicKeyDetails toPublicKeyDetails(AlgorithmRegistry.SigningAlgor
return PublicKeyDetails.PKIX_RSA_PKCS1V15_4096_SHA256;
case PKIX_ECDSA_P256_SHA_256:
return PublicKeyDetails.PKIX_ECDSA_P256_SHA_256;
+ case PKIX_ECDSA_P384_SHA_384:
+ return PublicKeyDetails.PKIX_ECDSA_P384_SHA_384;
+ case PKIX_ECDSA_P521_SHA_512:
+ return PublicKeyDetails.PKIX_ECDSA_P521_SHA_512;
+ }
+ throw new IllegalStateException("Unknown algorithm: " + algorithm);
+ }
+
+ public static PublicKeyAlgorithm toPublicKeyAlgorithm(
+ AlgorithmRegistry.SigningAlgorithm algorithm) {
+ switch (algorithm) {
+ case PKIX_RSA_PKCS1V15_2048_SHA256:
+ case PKIX_RSA_PKCS1V15_3072_SHA256:
+ case PKIX_RSA_PKCS1V15_4096_SHA256:
+ return PublicKeyAlgorithm.RSA_PSS;
+ case PKIX_ECDSA_P256_SHA_256:
+ return PublicKeyAlgorithm.ECDSA;
}
throw new IllegalStateException("Unknown algorithm: " + algorithm);
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/rekor/client/HashedRekordRequest.java b/sigstore-java/src/main/java/dev/sigstore/rekor/client/HashedRekordRequest.java
index a00021f2c..370b6d9b2 100644
--- a/sigstore-java/src/main/java/dev/sigstore/rekor/client/HashedRekordRequest.java
+++ b/sigstore-java/src/main/java/dev/sigstore/rekor/client/HashedRekordRequest.java
@@ -19,6 +19,7 @@
import com.google.common.hash.Hashing;
import com.google.common.primitives.Bytes;
+import dev.sigstore.AlgorithmRegistry;
import dev.sigstore.rekor.hashedRekord.v0_0_1.*;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@@ -38,13 +39,32 @@ private HashedRekordRequest(HashedRekord hashedRekord) {
/**
* Create a new HashedRekorRequest.
*
- * @param artifactDigest the sha256 digest of the artifact (not hex/base64 encoded)
+ * @param artifactDigest the digest of the artifact (not hex/base64 encoded)
+ * @param hashAlgorithm the hash algorithm used to compute the digest
* @param publicKey the pem encoded public key or public key certificate used to verify {@code
* signature}. Certificates in keyless signing are typically obtained from fulcio.
* @param signature the signature over the {@code artifactDigest} (not hex/base64 encoded)
*/
public static HashedRekordRequest newHashedRekordRequest(
- byte[] artifactDigest, byte[] publicKey, byte[] signature) {
+ byte[] artifactDigest,
+ AlgorithmRegistry.HashAlgorithm hashAlgorithm,
+ byte[] publicKey,
+ byte[] signature) {
+
+ Hash.Algorithm rekorAlg;
+ switch (hashAlgorithm) {
+ case SHA2_256:
+ rekorAlg = Hash.Algorithm.SHA_256;
+ break;
+ case SHA2_384:
+ rekorAlg = Hash.Algorithm.SHA_384;
+ break;
+ case SHA2_512:
+ rekorAlg = Hash.Algorithm.SHA_512;
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported hash algorithm: " + hashAlgorithm);
+ }
return new HashedRekordRequest(
new HashedRekord()
@@ -54,7 +74,7 @@ public static HashedRekordRequest newHashedRekordRequest(
new Hash()
.withValue(
new String(Hex.encode(artifactDigest), StandardCharsets.ISO_8859_1))
- .withAlgorithm(Hash.Algorithm.SHA_256)))
+ .withAlgorithm(rekorAlg)))
.withSignature(
new Signature()
.withContent(Base64.getEncoder().encodeToString(signature))
@@ -63,6 +83,20 @@ public static HashedRekordRequest newHashedRekordRequest(
.withContent(Base64.getEncoder().encodeToString(publicKey)))));
}
+ /**
+ * Create a new HashedRekorRequest with SHA-256.
+ *
+ * @param artifactDigest the sha256 digest of the artifact (not hex/base64 encoded)
+ * @param publicKey the pem encoded public key or public key certificate used to verify {@code
+ * signature}. Certificates in keyless signing are typically obtained from fulcio.
+ * @param signature the signature over the {@code artifactDigest} (not hex/base64 encoded)
+ */
+ public static HashedRekordRequest newHashedRekordRequest(
+ byte[] artifactDigest, byte[] publicKey, byte[] signature) {
+ return newHashedRekordRequest(
+ artifactDigest, AlgorithmRegistry.HashAlgorithm.SHA2_256, publicKey, signature);
+ }
+
/** Returned a canonicalized json payload. */
public String toJsonPayload() {
// TODO: use RekorEntryBody type here
diff --git a/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorTypes.java b/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorTypes.java
index d0b196853..f6ac03e1f 100644
--- a/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorTypes.java
+++ b/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorTypes.java
@@ -20,7 +20,6 @@
import com.google.protobuf.InvalidProtocolBufferException;
import dev.sigstore.json.JsonParseException;
import dev.sigstore.json.ProtoJson;
-import dev.sigstore.proto.rekor.v2.DSSELogEntryV002;
import dev.sigstore.proto.rekor.v2.HashedRekordLogEntryV002;
import dev.sigstore.rekor.dsse.v0_0_1.Dsse;
import dev.sigstore.rekor.hashedRekord.v0_0_1.HashedRekord;
@@ -91,32 +90,6 @@ public static Dsse getDsseV001(RekorEntry entry) throws RekorTypeException {
}
}
- /**
- * Parse a dsse from rekor at api version 0.0.2.
- *
- * @param entry the rekor entry obtained from rekor
- * @return the parsed proto
- * @throws RekorTypeException if the dsse:0.0.2 entry could not be parsed
- */
- public static DSSELogEntryV002 getDsseV002(RekorEntry entry) throws RekorTypeException {
- expect(entry, "dsse", "0.0.2");
-
- try {
- DSSELogEntryV002.Builder builder = DSSELogEntryV002.newBuilder();
- ProtoJson.parser()
- .ignoringUnknownFields()
- .merge(
- GSON.get().toJson(entry.getBodyDecoded().getSpec().getAsJsonObject().get("dsseV002")),
- builder);
- return builder.build();
- } catch (InvalidProtocolBufferException
- | JsonParseException
- | NullPointerException
- | IllegalStateException e) {
- throw new RekorTypeException("Could not parse dsse:0.0.2", e);
- }
- }
-
private static void expect(RekorEntry entry, String expectedKind, String expectedApiVersion)
throws RekorTypeException {
try {
diff --git a/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorVerifier.java b/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorVerifier.java
index 4ccb89fe0..932a5471b 100644
--- a/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorVerifier.java
+++ b/sigstore-java/src/main/java/dev/sigstore/rekor/client/RekorVerifier.java
@@ -16,6 +16,7 @@
package dev.sigstore.rekor.client;
import com.google.common.hash.Hashing;
+import dev.sigstore.UnsupportedAlgorithmException;
import dev.sigstore.encryption.signers.Verifiers;
import dev.sigstore.merkle.InclusionProofVerificationException;
import dev.sigstore.merkle.InclusionProofVerifier;
@@ -83,6 +84,7 @@ public void verifyEntry(RekorEntry entry) throws RekorVerificationException {
} catch (InvalidKeySpecException
| InvalidKeyException
| SignatureException
+ | UnsupportedAlgorithmException
| NoSuchAlgorithmException e) {
throw new RekorVerificationException("Entry SET verification failed: " + e.getMessage(), e);
}
@@ -179,6 +181,7 @@ private void verifyCheckpoint(RekorEntry entry, TransparencyLog tlog)
} catch (NoSuchAlgorithmException
| InvalidKeySpecException
| SignatureException
+ | UnsupportedAlgorithmException
| InvalidKeyException ex) {
throw new RekorVerificationException("Could not verify checkpoint signature", ex);
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2Client.java b/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2Client.java
index 46cb03e47..b71c80073 100644
--- a/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2Client.java
+++ b/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2Client.java
@@ -15,7 +15,6 @@
*/
package dev.sigstore.rekor.v2.client;
-import dev.sigstore.proto.rekor.v2.DSSERequestV002;
import dev.sigstore.proto.rekor.v2.HashedRekordRequestV002;
import dev.sigstore.rekor.client.RekorEntry;
import dev.sigstore.rekor.client.RekorParseException;
@@ -31,12 +30,4 @@ public interface RekorV2Client {
*/
RekorEntry putEntry(HashedRekordRequestV002 hashedRekordRequest)
throws IOException, RekorParseException;
-
- /**
- * Put a new dsse entry on the Rekor log.
- *
- * @param dsseRequest the request to send to rekor
- * @return a {@link RekorEntry} with information about the log entry
- */
- RekorEntry putEntry(DSSERequestV002 dsseRequest) throws IOException, RekorParseException;
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttp.java b/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttp.java
index c000ae1c2..2226475f0 100644
--- a/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttp.java
+++ b/sigstore-java/src/main/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttp.java
@@ -26,7 +26,6 @@
import dev.sigstore.http.ImmutableHttpParams;
import dev.sigstore.http.URIFormat;
import dev.sigstore.proto.rekor.v2.CreateEntryRequest;
-import dev.sigstore.proto.rekor.v2.DSSERequestV002;
import dev.sigstore.proto.rekor.v2.HashedRekordRequestV002;
import dev.sigstore.rekor.client.RekorEntry;
import dev.sigstore.rekor.client.RekorParseException;
@@ -83,11 +82,6 @@ public RekorEntry putEntry(HashedRekordRequestV002 hashedRekordRequest)
CreateEntryRequest.newBuilder().setHashedRekordRequestV002(hashedRekordRequest).build());
}
- @Override
- public RekorEntry putEntry(DSSERequestV002 dsseRequest) throws IOException, RekorParseException {
- return putEntry(CreateEntryRequest.newBuilder().setDsseRequestV002(dsseRequest).build());
- }
-
private RekorEntry putEntry(CreateEntryRequest request) throws IOException, RekorParseException {
URI rekorPutEndpoint = URIFormat.appendPath(uri, REKOR_ENTRIES_PATH);
diff --git a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/HashAlgorithm.java b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/HashAlgorithm.java
index 8c730bf2c..2ac654b1f 100644
--- a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/HashAlgorithm.java
+++ b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/HashAlgorithm.java
@@ -15,38 +15,39 @@
*/
package dev.sigstore.timestamp.client;
+import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.tsp.TSPAlgorithms;
/** Supported hash algorithms for timestamp requests. */
-public enum HashAlgorithm {
- SHA256("SHA256", TSPAlgorithms.SHA256),
- SHA384("SHA384", TSPAlgorithms.SHA384),
- SHA512("SHA512", TSPAlgorithms.SHA512);
+public class HashAlgorithm {
+ private HashAlgorithm() {}
- private final String algorithmName;
- private final ASN1ObjectIdentifier oid;
-
- HashAlgorithm(String algorithmName, ASN1ObjectIdentifier oid) {
- this.algorithmName = algorithmName;
- this.oid = oid;
- }
-
- public String getAlgorithmName() {
- return algorithmName;
- }
-
- public ASN1ObjectIdentifier getOid() {
- return oid;
+ public static ASN1ObjectIdentifier toOid(AlgorithmRegistry.HashAlgorithm hashAlgorithm) {
+ switch (hashAlgorithm) {
+ case SHA2_256:
+ return TSPAlgorithms.SHA256;
+ case SHA2_384:
+ return TSPAlgorithms.SHA384;
+ case SHA2_512:
+ return TSPAlgorithms.SHA512;
+ }
+ throw new IllegalArgumentException();
}
- public static HashAlgorithm from(ASN1ObjectIdentifier oid)
- throws UnsupportedHashAlgorithmException {
- for (HashAlgorithm value : values()) {
- if (value.getOid().equals(oid)) {
- return value;
- }
+ public static AlgorithmRegistry.HashAlgorithm fromOid(ASN1ObjectIdentifier oid)
+ throws UnsupportedAlgorithmException {
+ if (oid.equals(TSPAlgorithms.SHA256)) {
+ return AlgorithmRegistry.HashAlgorithm.SHA2_256;
+ }
+ if (oid.equals(TSPAlgorithms.SHA384)) {
+ return AlgorithmRegistry.HashAlgorithm.SHA2_384;
+ }
+ if (oid.equals(TSPAlgorithms.SHA512)) {
+ return AlgorithmRegistry.HashAlgorithm.SHA2_512;
}
- throw new UnsupportedHashAlgorithmException(oid.getId());
+ throw new UnsupportedAlgorithmException(
+ "Unsupported timestamp hashing algorithm oid: " + oid.getId());
}
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampClientHttp.java b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampClientHttp.java
index ca9761d91..c028fc293 100644
--- a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampClientHttp.java
+++ b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampClientHttp.java
@@ -81,7 +81,7 @@ public TimestampResponse timestamp(TimestampRequest tsReq) throws TimestampExcep
TimeStampRequestGenerator bcTsReqGen = new TimeStampRequestGenerator();
// Prepare and send the timestamp request
- var bcAlgorithmOid = tsReq.getHashAlgorithm().getOid();
+ var bcAlgorithmOid = HashAlgorithm.toOid(tsReq.getHashAlgorithm());
var artifactHashBytes = tsReq.getHash();
var nonce = tsReq.getNonce();
bcTsReqGen.setCertReq(tsReq.requestCertificates());
diff --git a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampRequest.java b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampRequest.java
index a067222a0..4c84393cb 100644
--- a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampRequest.java
+++ b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampRequest.java
@@ -15,6 +15,7 @@
*/
package dev.sigstore.timestamp.client;
+import dev.sigstore.AlgorithmRegistry;
import java.math.BigInteger;
import java.security.SecureRandom;
import org.immutables.value.Value;
@@ -23,7 +24,7 @@
@Immutable
public interface TimestampRequest {
/** The hash algorithm used to hash the artifact. */
- HashAlgorithm getHashAlgorithm();
+ AlgorithmRegistry.HashAlgorithm getHashAlgorithm();
/**
* The hash of the artifact to be timestamped. For sigstore-java, this typically refers to the
diff --git a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampVerifier.java b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampVerifier.java
index 0a2c4329c..896016c7e 100644
--- a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampVerifier.java
+++ b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/TimestampVerifier.java
@@ -15,7 +15,9 @@
*/
package dev.sigstore.timestamp.client;
-import com.google.common.hash.Hashing;
+import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
+import dev.sigstore.encryption.Hashers;
import dev.sigstore.encryption.certificates.Certificates;
import dev.sigstore.trustroot.CertificateAuthority;
import dev.sigstore.trustroot.SigstoreTrustedRoot;
@@ -147,26 +149,13 @@ public void verify(TimestampResponse tsResp, byte[] artifact)
// Validate the message imprint digest in the token
var oid = tsToken.getTimeStampInfo().getMessageImprintAlgOID();
- HashAlgorithm hashAlgorithm;
+ AlgorithmRegistry.HashAlgorithm hashAlgorithm;
try {
- hashAlgorithm = HashAlgorithm.from(oid);
- } catch (UnsupportedHashAlgorithmException e) {
+ hashAlgorithm = HashAlgorithm.fromOid(oid);
+ } catch (UnsupportedAlgorithmException e) {
throw new TimestampVerificationException(e);
}
- byte[] artifactDigest;
- switch (hashAlgorithm) {
- case SHA256:
- artifactDigest = Hashing.sha256().hashBytes(artifact).asBytes();
- break;
- case SHA384:
- artifactDigest = Hashing.sha384().hashBytes(artifact).asBytes();
- break;
- case SHA512:
- artifactDigest = Hashing.sha512().hashBytes(artifact).asBytes();
- break;
- default:
- throw new IllegalStateException(); // We shouldn't be here.
- }
+ byte[] artifactDigest = Hashers.from(hashAlgorithm).hashBytes(artifact).asBytes();
validateTokenMessageImprintDigest(tsToken, artifactDigest);
}
diff --git a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/UnsupportedHashAlgorithmException.java b/sigstore-java/src/main/java/dev/sigstore/timestamp/client/UnsupportedHashAlgorithmException.java
deleted file mode 100644
index de7e82df9..000000000
--- a/sigstore-java/src/main/java/dev/sigstore/timestamp/client/UnsupportedHashAlgorithmException.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2025 The Sigstore Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package dev.sigstore.timestamp.client;
-
-public class UnsupportedHashAlgorithmException extends Exception {
- public UnsupportedHashAlgorithmException(String algorithm) {
- super("Unsupported hash algorithm: " + algorithm);
- }
-}
diff --git a/sigstore-java/src/test/java/dev/sigstore/AlgorithmRegistryTest.java b/sigstore-java/src/test/java/dev/sigstore/AlgorithmRegistryTest.java
new file mode 100644
index 000000000..232dfe5a0
--- /dev/null
+++ b/sigstore-java/src/test/java/dev/sigstore/AlgorithmRegistryTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2025 The Sigstore Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.sigstore;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.security.KeyPairGenerator;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.spec.ECGenParameterSpec;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.junit.jupiter.api.Test;
+
+public class AlgorithmRegistryTest {
+
+ @Test
+ public void testGetHashAlgorithm_Unsupported() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("DSA");
+ keyPairGen.initialize(2048);
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertThrows(
+ UnsupportedAlgorithmException.class,
+ () -> AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_RSA_2048() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("RSA");
+ keyPairGen.initialize(2048);
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertEquals(
+ AlgorithmRegistry.SigningAlgorithm.PKIX_RSA_PKCS1V15_2048_SHA256,
+ AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_RSA_3072() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("RSA");
+ keyPairGen.initialize(3072);
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertEquals(
+ AlgorithmRegistry.SigningAlgorithm.PKIX_RSA_PKCS1V15_3072_SHA256,
+ AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_RSA_4096() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("RSA");
+ keyPairGen.initialize(4096);
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertEquals(
+ AlgorithmRegistry.SigningAlgorithm.PKIX_RSA_PKCS1V15_4096_SHA256,
+ AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_EC_P256() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("EC");
+ keyPairGen.initialize(new ECGenParameterSpec("secp256r1"));
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertEquals(
+ AlgorithmRegistry.SigningAlgorithm.PKIX_ECDSA_P256_SHA_256,
+ AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_EC_P384() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("EC");
+ keyPairGen.initialize(new ECGenParameterSpec("secp384r1"));
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertEquals(
+ AlgorithmRegistry.SigningAlgorithm.PKIX_ECDSA_P384_SHA_384,
+ AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_EC_P521() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("EC");
+ keyPairGen.initialize(new ECGenParameterSpec("secp521r1"));
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertEquals(
+ AlgorithmRegistry.SigningAlgorithm.PKIX_ECDSA_P521_SHA_512,
+ AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_RSA_UnsupportedLength() throws Exception {
+ var keyPairGen = KeyPairGenerator.getInstance("RSA");
+ keyPairGen.initialize(1024);
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertThrows(
+ UnsupportedAlgorithmException.class,
+ () -> AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_RSA_NotRsaPublicKey() {
+ PublicKey mockRsaKey =
+ new PublicKey() {
+ @Override
+ public String getAlgorithm() {
+ return "RSA";
+ }
+
+ @Override
+ public String getFormat() {
+ return null;
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ return null;
+ }
+ };
+ assertThrows(
+ IllegalStateException.class, () -> AlgorithmRegistry.getSigningAlgorithm(mockRsaKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_EC_UnsupportedCurve() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+
+ var keyPairGen = KeyPairGenerator.getInstance("EC", "BC");
+ keyPairGen.initialize(new ECGenParameterSpec("secp256k1"));
+ var publicKey = keyPairGen.generateKeyPair().getPublic();
+ assertThrows(
+ UnsupportedAlgorithmException.class,
+ () -> AlgorithmRegistry.getSigningAlgorithm(publicKey));
+ }
+
+ @Test
+ public void testGetHashAlgorithm_EC_NotEcPublicKey() {
+ PublicKey mockEcKey =
+ new PublicKey() {
+ @Override
+ public String getAlgorithm() {
+ return "EC";
+ }
+
+ @Override
+ public String getFormat() {
+ return null;
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ return null;
+ }
+ };
+ assertThrows(
+ IllegalStateException.class, () -> AlgorithmRegistry.getSigningAlgorithm(mockEcKey));
+ }
+}
diff --git a/sigstore-java/src/test/java/dev/sigstore/KeylessTest.java b/sigstore-java/src/test/java/dev/sigstore/KeylessTest.java
index 1b393adf0..77c24f43e 100644
--- a/sigstore-java/src/test/java/dev/sigstore/KeylessTest.java
+++ b/sigstore-java/src/test/java/dev/sigstore/KeylessTest.java
@@ -161,6 +161,7 @@ public void attest_production() throws Exception {
Assertions.assertNotNull(result.getDsseEnvelope().get());
Assertions.assertEquals(payload, result.getDsseEnvelope().get().getPayloadAsString());
Assertions.assertEquals(1, result.getEntries().size());
+ Assertions.assertEquals("hashedrekord", result.getEntries().get(0).getBodyDecoded().getKind());
Assertions.assertEquals("0.0.2", result.getEntries().get(0).getBodyDecoded().getApiVersion());
var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
@@ -190,7 +191,7 @@ public void attest_staging() throws Exception {
}
private void verifySigningResult(List results, boolean enableRekorV2)
- throws IOException, JsonParseException {
+ throws JsonParseException {
Assertions.assertEquals(artifactDigests.size(), results.size());
diff --git a/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java b/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java
index fe8780593..04ebd68cd 100644
--- a/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java
+++ b/sigstore-java/src/test/java/dev/sigstore/KeylessVerifierTest.java
@@ -41,6 +41,7 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
public class KeylessVerifierTest {
@@ -174,7 +175,7 @@ public void testVerify_unsupportedDigestAlgorithm_rekorV2() throws Exception {
var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath();
var verifier = KeylessVerifier.builder().sigstoreStagingDefaults().build();
- var thrown =
+ var ex =
Assertions.assertThrows(
KeylessVerificationException.class,
() ->
@@ -182,8 +183,8 @@ public void testVerify_unsupportedDigestAlgorithm_rekorV2() throws Exception {
Path.of(artifact),
Bundle.from(new StringReader(modifiedBundleFile)),
VerificationOptions.empty()));
- Assertions.assertTrue(
- thrown.getMessage().startsWith("Unsupported digest algorithm in log entry: "));
+ MatcherAssert.assertThat(
+ ex.getMessage(), CoreMatchers.startsWith("Unsupported digest algorithm in log entry"));
}
@Test
@@ -443,16 +444,19 @@ static Stream badDsseProvider() {
Arguments.arguments(
"bundle.dsse.rekor-v2.bad-signature.sigstore", "DSSE signature was not valid"),
Arguments.arguments(
- "bundle.dsse.rekor-v2.mismatched-payload.sigstore",
- "Digest of DSSE payload in bundle does not match DSSE payload digest in log entry"),
+ "bundle.dsse.rekor-v2.mismatched-envelope.sigstore",
+ "Digest of DSSE.pae in bundle does not match digest in log entry"),
Arguments.arguments(
"bundle.dsse.rekor-v2.mismatched-signature.sigstore",
- "Signature in DSSE envelope does not match signature in log entry spec"));
+ "Signature in DSSE envelope does not match signature in log entry"),
+ Arguments.arguments(
+ "bundle.dsse.rekor-v2.bad-entry-type.sigstore",
+ "Unsupported entry type: 'dsse:0.0.2' for DSSE bundle"));
}
@ParameterizedTest
@MethodSource("badDsseProvider")
- public void testVerify_dsseBundleInvalid(String bundleName, String expectedError)
+ public void testVerify_dsseBundleInvalid_rekor(String bundleName, String expectedError)
throws Exception {
var bundleFile =
Resources.toString(
@@ -576,7 +580,7 @@ public void testVerify_unsupportedRekorVersion_rekorV2() throws Exception {
Path.of(artifact),
Bundle.from(new StringReader(invalidBundleFile)),
VerificationOptions.empty()));
- Assertions.assertEquals("Unsupported hashedrekord version: 0.0.3", ex.getMessage());
+ Assertions.assertEquals("Unsupported entry type: 'hashedrekord:0.0.3'", ex.getMessage());
}
@Test
@@ -707,7 +711,7 @@ public void testVerify_dsseBundle_rekorV2() throws Exception {
Resources.getResource("dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.sigstore"),
StandardCharsets.UTF_8);
- var verifier = KeylessVerifier.builder().sigstoreStagingDefaults().build();
+ var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
verifier.verify(
Path.of(artifact), Bundle.from(new StringReader(bundleFile)), VerificationOptions.empty());
}
@@ -720,7 +724,7 @@ public void testVerify_dsseBundleArtifactNotInSubjects_rekorV2() throws Exceptio
StandardCharsets.UTF_8);
var badArtifactDigest =
Hashing.sha256().hashString("nonsense", StandardCharsets.UTF_8).asBytes();
- var verifier = KeylessVerifier.builder().sigstoreStagingDefaults().build();
+ var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
var ex =
Assertions.assertThrows(
@@ -817,4 +821,54 @@ public void testVerify_certificateExpired_rekorV1() throws Exception {
VerificationOptions.empty()));
Assertions.assertEquals("Signing time was after certificate expiry", ex.getMessage());
}
+
+ @ParameterizedTest
+ @ValueSource(
+ strings = {
+ "ECDSA_P256_SHA_256",
+ "ECDSA_P384_SHA_384",
+ "ECDSA_P521_SHA_512",
+ "RSA_PKCS1V15_2048_SHA256",
+ "RSA_PKCS1V15_3072_SHA256",
+ "RSA_PKCS1V15_4096_SHA256"
+ })
+ public void testVerify_algorithmRegistry(String keyAlgorithm) throws Exception {
+ var bundleFile =
+ Resources.toString(
+ Resources.getResource(
+ "dev/sigstore/samples/bundles/PKIX_" + keyAlgorithm + ".sigstore.json"),
+ StandardCharsets.UTF_8);
+
+ var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath();
+ var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
+ verifier.verify(
+ Path.of(artifact), Bundle.from(new StringReader(bundleFile)), VerificationOptions.empty());
+ }
+
+ @Test
+ public void testVerify_wrongArtifactHashAlgorithm() throws Exception {
+ var bundleFile =
+ Resources.toString(
+ Resources.getResource(
+ "dev/sigstore/samples/bundles/PKIX_ECDSA_P256_SHA_256.sigstore.json"),
+ StandardCharsets.UTF_8);
+
+ var artifact = Resources.getResource("dev/sigstore/samples/bundles/artifact.txt").getPath();
+ var verifier = KeylessVerifier.builder().sigstorePublicDefaults().build();
+
+ var sha512 = Hashing.sha512().hashBytes(Files.readAllBytes(Path.of(artifact))).asBytes();
+
+ var ex =
+ Assertions.assertThrows(
+ KeylessVerificationException.class,
+ () ->
+ verifier.verify(
+ sha512,
+ Bundle.from(new StringReader(bundleFile)),
+ VerificationOptions.empty()));
+ MatcherAssert.assertThat(
+ ex.getMessage(),
+ CoreMatchers.startsWith(
+ "Provided artifact digest does not match digest used for verification"));
+ }
}
diff --git a/sigstore-java/src/test/java/dev/sigstore/encryption/signers/SignerTest.java b/sigstore-java/src/test/java/dev/sigstore/encryption/signers/SignerTest.java
index b911504b0..e1c016ba4 100644
--- a/sigstore-java/src/test/java/dev/sigstore/encryption/signers/SignerTest.java
+++ b/sigstore-java/src/test/java/dev/sigstore/encryption/signers/SignerTest.java
@@ -17,8 +17,8 @@
import com.google.common.hash.Hashing;
import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
import java.nio.charset.StandardCharsets;
-import java.security.NoSuchAlgorithmException;
import java.util.stream.Stream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
@@ -30,7 +30,7 @@ public class SignerTest {
private static final byte[] CONTENT = "abcdef".getBytes(StandardCharsets.UTF_8);
private static final byte[] CONTENT_DIGEST = Hashing.sha256().hashBytes(CONTENT).asBytes();
- static Stream signerProvider() throws NoSuchAlgorithmException {
+ static Stream signerProvider() throws UnsupportedAlgorithmException {
var rsaSigner2048 =
Signers.from(AlgorithmRegistry.SigningAlgorithm.PKIX_RSA_PKCS1V15_2048_SHA256);
var rsaSigner3072 =
diff --git a/sigstore-java/src/test/java/dev/sigstore/encryption/signers/VerifiersTest.java b/sigstore-java/src/test/java/dev/sigstore/encryption/signers/VerifiersTest.java
index 3435de415..cb2a72325 100644
--- a/sigstore-java/src/test/java/dev/sigstore/encryption/signers/VerifiersTest.java
+++ b/sigstore-java/src/test/java/dev/sigstore/encryption/signers/VerifiersTest.java
@@ -15,10 +15,10 @@
*/
package dev.sigstore.encryption.signers;
+import dev.sigstore.UnsupportedAlgorithmException;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.Signature;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@@ -53,7 +53,7 @@ public void verify_ed448_withBcProvider() throws Exception {
var signature = genSignature(kp, "ed448");
var exception =
Assertions.assertThrows(
- NoSuchAlgorithmException.class, () -> Verifiers.newVerifier(kp.getPublic()));
+ UnsupportedAlgorithmException.class, () -> Verifiers.newVerifier(kp.getPublic()));
Assertions.assertEquals(
"Cannot verify signatures for key type 'Ed448', this client only supports RSA, ECDSA, and Ed25519 verification",
exception.getMessage());
@@ -66,7 +66,7 @@ public void verify_ed448_withoutBcProvider() throws Exception {
var signature = genSignature(kp, "ed448");
var exception =
Assertions.assertThrows(
- NoSuchAlgorithmException.class, () -> Verifiers.newVerifier(kp.getPublic()));
+ UnsupportedAlgorithmException.class, () -> Verifiers.newVerifier(kp.getPublic()));
Assertions.assertEquals(
"Cannot verify signatures for non-Ed25519 EdDSA key types, this client only supports RSA, ECDSA, and Ed25519 verification",
exception.getMessage());
@@ -77,7 +77,7 @@ public void verify_unknown() throws Exception {
var kp = KeyPairGenerator.getInstance("DSA").generateKeyPair();
var exception =
Assertions.assertThrows(
- NoSuchAlgorithmException.class, () -> Verifiers.newVerifier(kp.getPublic()));
+ UnsupportedAlgorithmException.class, () -> Verifiers.newVerifier(kp.getPublic()));
Assertions.assertEquals(
exception.getMessage(),
"Cannot verify signatures for key type 'DSA', this client only supports RSA, ECDSA, and Ed25519 verification");
diff --git a/sigstore-java/src/test/java/dev/sigstore/oidc/client/EnvTokenProviderTest.java b/sigstore-java/src/test/java/dev/sigstore/oidc/client/EnvTokenProviderTest.java
new file mode 100644
index 000000000..ec49ea12b
--- /dev/null
+++ b/sigstore-java/src/test/java/dev/sigstore/oidc/client/EnvTokenProviderTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2026 The Sigstore Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.sigstore.oidc.client;
+
+import java.util.Map;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class EnvTokenProviderTest {
+
+ @Test
+ public void isEnabled_true() {
+ var provider = EnvTokenProvider.of();
+ var env = Map.of(EnvTokenProvider.ENV_VAR_NAME, "some-token");
+ Assertions.assertTrue(provider.isEnabled(env));
+ }
+
+ @Test
+ public void isEnabled_false() {
+ var provider = EnvTokenProvider.of();
+ Assertions.assertFalse(provider.isEnabled(Map.of()));
+ }
+
+ @Test
+ public void getTokenString_present() throws Exception {
+ var provider = EnvTokenProvider.of();
+ var env = Map.of(EnvTokenProvider.ENV_VAR_NAME, "some-token");
+ Assertions.assertEquals("some-token", provider.getTokenString(env));
+ }
+
+ @Test
+ public void getTokenString_missing() {
+ var provider = EnvTokenProvider.of();
+ var env = Map.of("OTHER_ENV_VAR", "some-token");
+ var exception =
+ Assertions.assertThrows(
+ IllegalStateException.class,
+ () -> {
+ provider.getTokenString(env);
+ });
+ Assertions.assertEquals(EnvTokenProvider.ENV_VAR_NAME + " was not set", exception.getMessage());
+ }
+}
diff --git a/sigstore-java/src/test/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttpTest.java b/sigstore-java/src/test/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttpTest.java
index a624e7b8c..3586f18d2 100644
--- a/sigstore-java/src/test/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttpTest.java
+++ b/sigstore-java/src/test/java/dev/sigstore/rekor/v2/client/RekorV2ClientHttpTest.java
@@ -20,20 +20,15 @@
import com.google.protobuf.ByteString;
import dev.sigstore.AlgorithmRegistry;
-import dev.sigstore.bundle.ImmutableDsseEnvelope;
-import dev.sigstore.bundle.ImmutableSignature;
import dev.sigstore.encryption.signers.Signers;
import dev.sigstore.proto.common.v1.PublicKeyDetails;
import dev.sigstore.proto.common.v1.X509Certificate;
-import dev.sigstore.proto.rekor.v2.DSSERequestV002;
import dev.sigstore.proto.rekor.v2.HashedRekordRequestV002;
import dev.sigstore.proto.rekor.v2.Signature;
import dev.sigstore.proto.rekor.v2.Verifier;
-import dev.sigstore.rekor.client.RekorEntry;
import dev.sigstore.testing.CertGenerator;
import dev.sigstore.trustroot.Service;
import dev.sigstore.tuf.SigstoreTufClient;
-import io.intoto.EnvelopeOuterClass;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
@@ -51,7 +46,6 @@
public class RekorV2ClientHttpTest {
private static RekorV2Client client;
private static HashedRekordRequestV002 req;
- private static RekorEntry entry;
@BeforeAll
public static void setupClient() throws Exception {
@@ -62,7 +56,7 @@ public static void setupClient() throws Exception {
client = RekorV2ClientHttp.builder().setService(rekorService).build();
req = createdRekorRequest();
- entry = client.putEntry(req);
+ client.putEntry(req);
}
@Test
@@ -76,17 +70,6 @@ public void putEntry() throws Exception {
assertNotNull(entry.getLogID());
}
- @Test
- public void putEntry_dsse() throws Exception {
- var req = createDsseRequest();
- var entry = client.putEntry(req);
-
- assertNotNull(entry);
- assertNotNull(entry.getVerification().getInclusionProof());
- assertTrue(entry.getLogIndex() >= 0);
- assertNotNull(entry.getLogID());
- }
-
@NotNull
private static HashedRekordRequestV002 createdRekorRequest()
throws NoSuchAlgorithmException,
@@ -127,53 +110,4 @@ private static HashedRekordRequestV002 createdRekorRequest()
.setSignature(signature)
.build();
}
-
- @NotNull
- private static DSSERequestV002 createDsseRequest()
- throws NoSuchAlgorithmException,
- InvalidKeyException,
- SignatureException,
- OperatorCreationException,
- CertificateException,
- IOException {
- var payload = "{\"foo\":\"bar\"}";
- var payloadType = "application/vnd.in-toto+json";
-
- // sign the full content (these signers do the artifact hashing themselves)
- var signer = Signers.from(AlgorithmRegistry.SigningAlgorithm.PKIX_ECDSA_P256_SHA_256);
-
- // create a fake signing cert (not fulcio/dex)
- var cert = CertGenerator.newCert(signer.getPublicKey()).getEncoded();
-
- var dsse =
- ImmutableDsseEnvelope.builder()
- .payload(payload.getBytes(StandardCharsets.UTF_8))
- .payloadType(payloadType)
- .build();
-
- var pae = dsse.getPAE();
- var sig = signer.sign(pae);
- var dsseSigned =
- ImmutableDsseEnvelope.builder()
- .from(dsse)
- .addSignatures(ImmutableSignature.builder().sig(sig).build())
- .build();
-
- Verifier verifier =
- Verifier.newBuilder()
- .setX509Certificate(
- X509Certificate.newBuilder().setRawBytes(ByteString.copyFrom(cert)).build())
- .setKeyDetails(PublicKeyDetails.PKIX_ECDSA_P256_SHA_256)
- .build();
-
- return DSSERequestV002.newBuilder()
- .setEnvelope(
- EnvelopeOuterClass.Envelope.newBuilder()
- .setPayload(ByteString.copyFrom(dsseSigned.getPayload()))
- .setPayloadType(dsseSigned.getPayloadType())
- .addSignatures(
- EnvelopeOuterClass.Signature.newBuilder().setSig(ByteString.copyFrom(sig))))
- .addVerifiers(verifier)
- .build();
- }
}
diff --git a/sigstore-java/src/test/java/dev/sigstore/timestamp/client/HashAlgorithmTest.java b/sigstore-java/src/test/java/dev/sigstore/timestamp/client/HashAlgorithmTest.java
new file mode 100644
index 000000000..19649fcbb
--- /dev/null
+++ b/sigstore-java/src/test/java/dev/sigstore/timestamp/client/HashAlgorithmTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2026 The Sigstore Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.sigstore.timestamp.client;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import dev.sigstore.AlgorithmRegistry;
+import dev.sigstore.UnsupportedAlgorithmException;
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.tsp.TSPAlgorithms;
+import org.junit.jupiter.api.Test;
+
+public class HashAlgorithmTest {
+
+ @Test
+ public void toOid_success() {
+ assertEquals(
+ TSPAlgorithms.SHA256, HashAlgorithm.toOid(AlgorithmRegistry.HashAlgorithm.SHA2_256));
+ assertEquals(
+ TSPAlgorithms.SHA384, HashAlgorithm.toOid(AlgorithmRegistry.HashAlgorithm.SHA2_384));
+ assertEquals(
+ TSPAlgorithms.SHA512, HashAlgorithm.toOid(AlgorithmRegistry.HashAlgorithm.SHA2_512));
+ }
+
+ @Test
+ public void fromOid_success() throws Exception {
+ assertEquals(
+ AlgorithmRegistry.HashAlgorithm.SHA2_256, HashAlgorithm.fromOid(TSPAlgorithms.SHA256));
+ assertEquals(
+ AlgorithmRegistry.HashAlgorithm.SHA2_384, HashAlgorithm.fromOid(TSPAlgorithms.SHA384));
+ assertEquals(
+ AlgorithmRegistry.HashAlgorithm.SHA2_512, HashAlgorithm.fromOid(TSPAlgorithms.SHA512));
+ }
+
+ @Test
+ public void fromOid_unsupported() {
+ ASN1ObjectIdentifier unsupportedOid = new ASN1ObjectIdentifier("1.2.840.113549.2.5"); // MD5 OID
+ UnsupportedAlgorithmException exception =
+ assertThrows(
+ UnsupportedAlgorithmException.class, () -> HashAlgorithm.fromOid(unsupportedOid));
+ assertEquals(
+ "Unsupported timestamp hashing algorithm oid: 1.2.840.113549.2.5", exception.getMessage());
+ }
+}
diff --git a/sigstore-java/src/test/java/dev/sigstore/timestamp/client/TimestampClientHttpTest.java b/sigstore-java/src/test/java/dev/sigstore/timestamp/client/TimestampClientHttpTest.java
index a82de6f13..14cba6df2 100644
--- a/sigstore-java/src/test/java/dev/sigstore/timestamp/client/TimestampClientHttpTest.java
+++ b/sigstore-java/src/test/java/dev/sigstore/timestamp/client/TimestampClientHttpTest.java
@@ -21,6 +21,7 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import dev.sigstore.AlgorithmRegistry;
import dev.sigstore.trustroot.Service;
import dev.sigstore.tuf.SigstoreTufClient;
import java.nio.charset.StandardCharsets;
@@ -45,7 +46,7 @@ public static void setup() throws Exception {
tsReq =
ImmutableTimestampRequest.builder()
.hash(artifactHashBytes)
- .hashAlgorithm(HashAlgorithm.SHA256)
+ .hashAlgorithm(AlgorithmRegistry.HashAlgorithm.SHA2_256)
.build();
}
@@ -74,7 +75,7 @@ public void timestamp_success() throws Exception {
assertEquals(tsReq.getNonce(), tsInfo.getNonce());
- var expectedOid = tsReq.getHashAlgorithm().getOid();
+ var expectedOid = HashAlgorithm.toOid(tsReq.getHashAlgorithm());
assertEquals(expectedOid, tsInfo.getMessageImprintAlgOID());
}
@@ -83,7 +84,7 @@ public void timestamp_failure_badResponse_incorrectDigestLength() throws Excepti
var tsReqWithIncorrectDigestLength =
ImmutableTimestampRequest.builder()
.hash(tsReq.getHash())
- .hashAlgorithm(HashAlgorithm.SHA512)
+ .hashAlgorithm(AlgorithmRegistry.HashAlgorithm.SHA2_512)
.nonce(tsReq.getNonce())
.build();
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P256_SHA_256.sigstore.json b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P256_SHA_256.sigstore.json
new file mode 100644
index 000000000..2811e03e0
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P256_SHA_256.sigstore.json
@@ -0,0 +1,39 @@
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "tlogEntries": [{
+ "logIndex": "1633569114",
+ "logId": {
+ "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.1"
+ },
+ "integratedTime": "1779805321",
+ "inclusionPromise": {
+ "signedEntryTimestamp": "MEUCIBa25WosjOZkivuTxMfNb096gOBt715KB7GiD7SZ5BphAiEAkZvzXhOb6DTsB4utXIlOCmwhYTx2wJfHvglpR3U25c0="
+ },
+ "inclusionProof": {
+ "logIndex": "1511664852",
+ "rootHash": "+OMiRtEi0Fk67u3QLC7OjcMaDwRSfibjw0jmcPsLMww=",
+ "treeSize": "1511664856",
+ "hashes": ["uaf+ewAfwTnPv6aC2yue7mDrzwgUeYjjl5pG0X+1j2E=", "z0TNjG4glTKjh/MR2HINxvRxtjsMoW309xfS4iyLM1w=", "8obflnH4s34ntg2xE3mxT5mCKQFXF0UJqERA6Iicy6k=", "C547ULJy/3SPvHBRkgOxie1AJJMOvU/UPNyWTdnUnzs=", "8SMQ0w1Uk5ufeAHI59kjEho9nEZZl/aZXCVl/QzWdIM=", "XmNJtj66PRtWfesOdLtl2wG9Nobsej1YNqv9JxVI+Es=", "pX58u/0w68oJS7qRP4+77lddPGxcVMT0d/Snp4FCqbY=", "2FvdzBMfv489BLEkgJC+yWb4gSp/47E315qOjOzHTZI=", "ABU28Mr2tF+9hnqOGwSAlabYkP6grvZMoM7oesu/L6g=", "REVcPsjUwNz5y9ZezFOmhc5jS5qbXafRs0h0VXC31RU=", "PuM3CasxXEHFjDo5J0ekAcFZIFVhA7jFiUUCiPtlkzQ=", "20Rm754Do/BWEhP8pav1J4ARfPD0r+Jd7mEf5DE4eqk=", "Nq4SYV9bcP17fOZqrjs6GE6Ed73nTtmZCLg2CI+M+Ro=", "r5nn9+mbgUQL4m8neTg/XjYkdf2hD/cvZMsNR/v0cBU=", "eT+F471g2HJfd43U4j4L1PIBkt4rLbHQd/pOR/rllO0=", "DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="],
+ "checkpoint": {
+ "envelope": "rekor.sigstore.dev - 1193050959916656506\n1511664856\n+OMiRtEi0Fk67u3QLC7OjcMaDwRSfibjw0jmcPsLMww\u003d\n\n— rekor.sigstore.dev wNI9ajBEAiA5Zz+topxrulXbq02w1YhEg2sqCTVcv5/KK7tOiWnnXAIgJ2ic48DpdKMBdHuBXXE2MvSDKs5gK/6ucaP1REr8Wjs\u003d\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJhMGNmYzcxMjcxZDZlMjc4ZTU3Y2QzMzJmZjk1N2MzZjcwNDNmZGRhMzU0YzRjYmIxOTBhMzBkNTZlZmEwMWJmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJSFdFei9jZ3I1bGtIYmJ6aml2ZTlLemd6bXdVa254T1BZT1M5WWF4a1d5dUFpRUF5QUZyR1l6ekdBQ2RLR2tHU3k3bFZNeS9Hek5lNnF2MlAyVHBJTEFGdXFjPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVTTRWRU5EUVc1bFowRjNTVUpCWjBsVlJ6Tm9kSGd3TlhSQmRscFdjVWcyUlhKbllraFFWREJYT1UxSmQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDVVU1RKTlZGRjVUV3BCZUZkb1kwNU5hbGwzVGxSSk1rMVVVWHBOYWtGNFYycEJRVTFHYTNkRmQxbElDa3R2V2tsNmFqQkRRVkZaU1V0dldrbDZhakJFUVZGalJGRm5RVVZEVUdoNlFuVldNbGRCV1RkV1ZqTlZja054WnpSdVNtVTBjRWxxVlM5eFJYVTRka0VLU0VGSFpXRjJPVTl2VVVsU1dsRlRVVVpCTkhoUk1HZHhkblp5ZDNsUU5WSmpaekp4VkV3MGFFRmtiMlp1ZDJ0SmRuRlBRMEZhV1hkblowZFRUVUUwUndwQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRlJFUkJTMEpuWjNKQ1owVkdRbEZqUkVGNlFXUkNaMDVXU0ZFMFJVWm5VVlZHYTFkVkNtTm1WRWMwVmpGU1FXeHNSRFpaWjBkdVIwODRaM1E0ZDBoM1dVUldVakJxUWtKbmQwWnZRVlV6T1ZCd2VqRlphMFZhWWpWeFRtcHdTMFpYYVhocE5Ga0tXa1E0ZDFKM1dVUldVakJTUVZGSUwwSkVNSGRQTkVVMVpGYzFNR051Vm5wa1IxWnJURmhPYUZGSVRuQmFNMDR3WWpOS2JFeFhUblppYlZwMlkyMHhhQXBpYlU1c1RHMXNhR0pUTlc1ak1sWjVaRzFzYWxwWFJtcFpNamt4WW01UmRWa3lPWFJOUTJ0SFEybHpSMEZSVVVKbk56aDNRVkZGUlVjeWFEQmtTRUo2Q2s5cE9IWlpWMDVxWWpOV2RXUklUWFZhTWpsMldqSjRiRXh0VG5aaVZFRnlRbWR2Y2tKblJVVkJXVTh2VFVGRlNVSkNNRTFITW1nd1pFaENlazlwT0hZS1dWZE9hbUl6Vm5Wa1NFMTFXakk1ZGxveWVHeE1iVTUyWWxSRFFtbFJXVXRMZDFsQ1FrRklWMlZSU1VWQloxSTNRa2hyUVdSM1FqRkJUakE1VFVkeVJ3cDRlRVY1V1hoclpVaEtiRzVPZDB0cFUydzJORE5xZVhRdk5HVkxZMjlCZGt0bE5rOUJRVUZDYm0xVGNDdENVVUZCUVZGRVFVVlpkMUpCU1dkamFpdE1DbVlyV21sVWREUnNRVU00VjNZd1QyTndlR3hIT0M5d1VWZ3ZSMHRhUTBoTVpHaEhhMXBXUVVOSlJIZEpiaXN5YlUxUlkwNXFjWFZaWVVVd2FsRjFkM1VLYTFCSFNXaHhhbmRIY1hseFQwVlBXR0YwTVM5TlFXOUhRME54UjFOTk5EbENRVTFFUVRKblFVMUhWVU5OUlU0eGVtRllhR0U1S3k5S1UydDNRa1J2WmdvM2NraDBaWHBOVERGQk5VSkJPVXgzU25SdWJFMHhkVkF4ZFVoWGVUUjFhVU15YmtKc1lUVXhWalp3YUVSUlNYaEJUMkZyZUhWMGQwVTJUVTUyYWxkM0NrVndUMkZIWXpaR1JVNXBUMWx4YVV0TlRsZG1SM0ZUUzFGclUxUXdaV0kxTUVvelRrMHdjRGxrZUZCME5FaFVhMlIzUFQwS0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX19"
+ }],
+ "certificate": {
+ "rawBytes": "MIIC8TCCAnegAwIBAgIUG3htx05tAvZVqH6ErgbHPT0W9MIwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTI2MTQyMjAxWhcNMjYwNTI2MTQzMjAxWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAECPhzBuV2WAY7VV3UrCqg4nJe4pIjU/qEu8vAHAGeav9OoQIRZQSQFA4xQ0gqvvrwyP5Rcg2qTL4hAdofnwkIvqOCAZYwggGSMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUFkWUcfTG4V1RAllD6YgGnGO8gt8wHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wRwYDVR0RAQH/BD0wO4E5dW50cnVzdGVkLXNhQHNpZ3N0b3JlLWNvbmZvcm1hbmNlLmlhbS5nc2VydmljZWFjY291bnQuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTCBiQYKKwYBBAHWeQIEAgR7BHkAdwB1AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABnmSp+BQAAAQDAEYwRAIgcj+Lf+ZiTt4lAC8Wv0OcpxlG8/pQX/GKZCHLdhGkZVACIDwIn+2mMQcNjquYaE0jQuwukPGIhqjwGqyqOEOXat1/MAoGCCqGSM49BAMDA2gAMGUCMEN1zaXha9+/JSkwBDof7rHtezML1A5BA9LwJtnlM1uP1uHWy4uiC2nBla51V6phDQIxAOakxutwE6MNvjWwEpOaGc6FENiOYqiKMNWfGqSKQkST0eb50J3NM0p9dxPt4HTkdw=="
+ }
+ },
+ "messageSignature": {
+ "messageDigest": {
+ "algorithm": "SHA2_256",
+ "digest": "oM/HEnHW4njlfNMy/5V8P3BD/do1TEy7GQow1W76Ab8="
+ },
+ "signature": "MEUCIHWEz/cgr5lkHbbzjive9KzgzmwUknxOPYOS9YaxkWyuAiEAyAFrGYzzGACdKGkGSy7lVMy/GzNe6qv2P2TpILAFuqc="
+ }
+}
\ No newline at end of file
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P384_SHA_384.sigstore.json b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P384_SHA_384.sigstore.json
new file mode 100644
index 000000000..d33d6f9bd
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P384_SHA_384.sigstore.json
@@ -0,0 +1,39 @@
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "tlogEntries": [{
+ "logIndex": "1633569217",
+ "logId": {
+ "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.1"
+ },
+ "integratedTime": "1779805323",
+ "inclusionPromise": {
+ "signedEntryTimestamp": "MEQCICHfmvBfmngrnpzeHuaCSpFxmmoRGAL5NrDClOkFHr3oAiBqdTudkNwkyZ7ujT7TfGu/ShjW+GuweIjNt32hCYlFkw=="
+ },
+ "inclusionProof": {
+ "logIndex": "1511664955",
+ "rootHash": "6O6n4PC07k+eiHDpCN5nsyhdF6RD8b/Le9gczBdR8BU=",
+ "treeSize": "1511664956",
+ "hashes": ["GeEqzhzKNKf65DVTlO32cIK4TMSBDq40ZggwNp22Cxc=", "GP1zW1+a/zuzuFFw54hzcRAxcbAQW961vky8M/SsH6Q=", "2rnm2pGLRYqNl8m0KNlJlODjY9JYkFw5C6elb17+01E=", "qYjm8/KMw260FMLub/L0cmq8nEbAKLAyZBtML1AolPY=", "eHQlAVoQ4Lskco3SL4iv6bylJQ/fkRoxSWk2KV2nQTk=", "sbWCavuxbmjnYYHbmcC6N2VDwuJLnPFNIP/hXftVP0c=", "pX58u/0w68oJS7qRP4+77lddPGxcVMT0d/Snp4FCqbY=", "2FvdzBMfv489BLEkgJC+yWb4gSp/47E315qOjOzHTZI=", "ABU28Mr2tF+9hnqOGwSAlabYkP6grvZMoM7oesu/L6g=", "REVcPsjUwNz5y9ZezFOmhc5jS5qbXafRs0h0VXC31RU=", "PuM3CasxXEHFjDo5J0ekAcFZIFVhA7jFiUUCiPtlkzQ=", "20Rm754Do/BWEhP8pav1J4ARfPD0r+Jd7mEf5DE4eqk=", "Nq4SYV9bcP17fOZqrjs6GE6Ed73nTtmZCLg2CI+M+Ro=", "r5nn9+mbgUQL4m8neTg/XjYkdf2hD/cvZMsNR/v0cBU=", "eT+F471g2HJfd43U4j4L1PIBkt4rLbHQd/pOR/rllO0=", "DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="],
+ "checkpoint": {
+ "envelope": "rekor.sigstore.dev - 1193050959916656506\n1511664956\n6O6n4PC07k+eiHDpCN5nsyhdF6RD8b/Le9gczBdR8BU\u003d\n\n— rekor.sigstore.dev wNI9ajBFAiBdS7K1iDv2NElhospJljqP4bY4fMjL3TB34CGTCuWBwwIhAM84bjg1Ka/CppTYpOtMRLk48TooYRiazwlsep6GBtVz\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMzg0IiwidmFsdWUiOiIzZTdmOGZhNmI3Njg4NTU5MDk1ZDRhOGNhNGZlNDQ5ZGNhYjNmOTk3ZDkwMGFlMDFjNTRlYTU3NzM3ZDVlNjNhOGVmMzQ1NzM4NTk0N2NmMTk5NTMzZTY2NWNmZWEzN2IifX0sInNpZ25hdHVyZSI6eyJjb250ZW50IjoiTUdVQ01IMi9ibDhsbVlCYzB0Ym5tRWh5bDlUaFA3Z0JNZWo0UnZnbkJXZTEvZ200MDVkTXNBWmlqaFc2UVphQ3k5ZW5JUUl4QU5KYkZEZFNZZGI1VVRkMGcvcGNnb1dteXNPSjhqVlMzdTJ4QzRhTWxrUGhiMEI0S0FINXhodHJvZVFkS1RiTTFBPT0iLCJwdWJsaWNLZXkiOnsiY29udGVudCI6IkxTMHRMUzFDUlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJFZWtORFFYQmhaMEYzU1VKQlowbFZVR1owUjJGdmRtcHRlSEZUVVVscFNrazJNR3h0TURsaWFGRTRkME5uV1VsTGIxcEplbW93UlVGM1RYY0tUbnBGVmsxQ1RVZEJNVlZGUTJoTlRXTXliRzVqTTFKMlkyMVZkVnBIVmpKTlVqUjNTRUZaUkZaUlVVUkZlRlo2WVZka2VtUkhPWGxhVXpGd1ltNVNiQXBqYlRGc1drZHNhR1JIVlhkSWFHTk9UV3BaZDA1VVNUSk5WRkY1VFdwQmVWZG9ZMDVOYWxsM1RsUkpNazFVVVhwTmFrRjVWMnBCUVUxSVdYZEZRVmxJQ2t0dldrbDZhakJEUVZGWlJrczBSVVZCUTBsRVdXZEJSWGxGVTJZd2QyRlBXbWR5U2pZNFZHOTFhMnAySzNCcmRtdG9UekJpT1dad05YUm9Oa0pPYVVrS2VuUkdlV0ZoVEdFdmJHbGljbXN3TWprNVJuQkhhRUpCY0hGNFdFbG9USE5YYlVSQmMyUnZPV2xFZEZCWmFsSldWV3BSS3pkVllXODFlVVZqZDBsSVp3cFVaM1pPVjJjM2JsQjRWM1ZTTkVSdFZVZElhbFpxVmxadk5FbENiVVJEUTBGYVVYZEVaMWxFVmxJd1VFRlJTQzlDUVZGRVFXZGxRVTFDVFVkQk1WVmtDa3BSVVUxTlFXOUhRME56UjBGUlZVWkNkMDFFVFVJd1IwRXhWV1JFWjFGWFFrSlNkMWRoYWtObU5HSkdOa2M0Vm5GVFp6ZGhRVEIzVVVsNFluTkVRV1lLUW1kT1ZraFRUVVZIUkVGWFowSlVaakFyYmxCV2FWRlNiSFp0YnpKUGEyOVdZVXhIVEdob2ExQjZRa2hDWjA1V1NGSkZRa0ZtT0VWUVZFRTNaMVJzTVFwaWJsSjVaRmhPTUZwWFVYUmpNa1pCWXpKc2JtTXpVblpqYlZWMFdUSTVkVnB0T1hsaVYwWjFXVEpWZFdGWFJuUk1iV1I2V2xoS01tRlhUbXhaVjA1cUNtSXpWblZrUXpWcVlqSXdkMHRSV1V0TGQxbENRa0ZIUkhaNlFVSkJVVkZpWVVoU01HTklUVFpNZVRsb1dUSk9kbVJYTlRCamVUVnVZakk1Ym1KSFZYVUtXVEk1ZEUxRGMwZERhWE5IUVZGUlFtYzNPSGRCVVdkRlNGRjNZbUZJVWpCalNFMDJUSGs1YUZreVRuWmtWelV3WTNrMWJtSXlPVzVpUjFWMVdUSTVkQXBOU1VkTVFtZHZja0puUlVWQlpGbzFRV2RSUTBKSU1FVmxkMEkxUVVoalFUTlVNSGRoYzJKSVJWUktha2RTTkdOdFYyTXpRWEZLUzFoeWFtVlFTek12Q21nMGNIbG5Remh3TjI4MFFVRkJSMlZhUzI0cldVRkJRVUpCVFVGVFJFSkhRV2xGUVhRMFkwbGlPV0p1ZGpSMFN6WTJUREJzYlhad01YTjZRbTB4VG04S1MxVm5VblJqVERKTFJrRlViSEkwUTBsUlEwVnpTR3hPZG5OeFNtZzRjRXBpY2pKVVFVWk9SV2h4ZGxKdE5WTlNRbTh3T0ZaMGRURlNRMEY1YmtSQlN3cENaMmR4YUd0cVQxQlJVVVJCZDA1dVFVUkNhMEZxUVVJMWJHZzJibUpHWlVoM2EzQnFZelJhYkdKVFp5OHlUMDVTWjNKVWJHZEpjVlpQVm1sV2NsSkpDbVZ2UTI5TFpqZEphak15WlhCWWJrNHlWVk15YUhoQlEwMUZPVzFOUlRFM2FtNVZRbUpSSzBVMFR6WXJOVGh0YW5nM1owRmhRVUowWTNrdlYxSm9iSFFLVWpGUGNrbDRNek5QUlhWeE9VUmtVM2hKVTFwVmJtWTNVMmM5UFFvdExTMHRMVVZPUkNCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2c9PSJ9fX19"
+ }],
+ "certificate": {
+ "rawBytes": "MIIDDzCCApagAwIBAgIUPftGaovjmxqSQIiJI60lm09bhQ8wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTI2MTQyMjAyWhcNMjYwNTI2MTQzMjAyWjAAMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEyESf0waOZgrJ68Toukjv+pkvkhO0b9fp5th6BNiIztFyaaLa/librk0299FpGhBApqxXIhLsWmDAsdo9iDtPYjRVUjQ+7Uao5yEcwIHgTgvNWg7nPxWuR4DmUGHjVjVVo4IBmDCCAZQwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBRwWajCf4bF6G8VqSg7aA0wQIxbsDAfBgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzBHBgNVHREBAf8EPTA7gTl1bnRydXN0ZWQtc2FAc2lnc3RvcmUtY29uZm9ybWFuY2UuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20wKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGLBgorBgEEAdZ5AgQCBH0EewB5AHcA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGeZKn+YAAABAMASDBGAiEAt4cIb9bnv4tK66L0lmvp1szBm1NoKUgRtcL2KFATlr4CIQCEsHlNvsqJh8pJbr2TAFNEhqvRm5SRBo08Vtu1RCAynDAKBggqhkjOPQQDAwNnADBkAjAB5lh6nbFeHwkpjc4ZlbSg/2ONRgrTlgIqVOViVrRIeoCoKf7Ij32epXnN2US2hxACME9mME17jnUBbQ+E4O6+58mjx7gAaABtcy/WRhltR1OrIx33OEuq9DdSxISZUnf7Sg=="
+ }
+ },
+ "messageSignature": {
+ "messageDigest": {
+ "algorithm": "SHA2_384",
+ "digest": "Pn+PprdohVkJXUqMpP5Encqz+ZfZAK4BxU6ldzfV5jqO80VzhZR88ZlTPmZc/qN7"
+ },
+ "signature": "MGUCMH2/bl8lmYBc0tbnmEhyl9ThP7gBMej4RvgnBWe1/gm405dMsAZijhW6QZaCy9enIQIxANJbFDdSYdb5UTd0g/pcgoWmysOJ8jVS3u2xC4aMlkPhb0B4KAH5xhtroeQdKTbM1A=="
+ }
+}
\ No newline at end of file
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P521_SHA_512.sigstore.json b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P521_SHA_512.sigstore.json
new file mode 100644
index 000000000..41f0657e4
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_ECDSA_P521_SHA_512.sigstore.json
@@ -0,0 +1,39 @@
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "tlogEntries": [{
+ "logIndex": "1633569325",
+ "logId": {
+ "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.1"
+ },
+ "integratedTime": "1779805324",
+ "inclusionPromise": {
+ "signedEntryTimestamp": "MEYCIQCpcBBeLarwqBkHo4f4EsaB9ZG5IPXNugO8LoG9KDhPSwIhAJ6faF6Qbfgl4kuUX9Erbbw4To/7CQnj6Ppsmy8n8mt2"
+ },
+ "inclusionProof": {
+ "logIndex": "1511665063",
+ "rootHash": "OG0nIG3AvtuixXataAYGzSBL9MEL5FZGZibuVapXMkg=",
+ "treeSize": "1511665068",
+ "hashes": ["/fR1ioWVvMrUvNt1DVs3NWODFxBFIROLn4VkUAwu3lI=", "t8m2tH1LtHf+0mA6H6il80aWpWVINUye2x5w+g62luo=", "fQaSctgrZm39JqrIojf6llElCOcn9n1p9uKLolaiGAw=", "7FydKdmxprpvtqXL75w9v+baIB2DP7XfIOMu/D60tlE=", "+u0ggcxJXZ+w3y9Azn/OR/bv1uOSVbRgRG06Ua1q1KY=", "5TFd672x6P+omz0enrjWhPLDPt2mIEZW7jVkXTvuQxs=", "sbWCavuxbmjnYYHbmcC6N2VDwuJLnPFNIP/hXftVP0c=", "pX58u/0w68oJS7qRP4+77lddPGxcVMT0d/Snp4FCqbY=", "2FvdzBMfv489BLEkgJC+yWb4gSp/47E315qOjOzHTZI=", "ABU28Mr2tF+9hnqOGwSAlabYkP6grvZMoM7oesu/L6g=", "REVcPsjUwNz5y9ZezFOmhc5jS5qbXafRs0h0VXC31RU=", "PuM3CasxXEHFjDo5J0ekAcFZIFVhA7jFiUUCiPtlkzQ=", "20Rm754Do/BWEhP8pav1J4ARfPD0r+Jd7mEf5DE4eqk=", "Nq4SYV9bcP17fOZqrjs6GE6Ed73nTtmZCLg2CI+M+Ro=", "r5nn9+mbgUQL4m8neTg/XjYkdf2hD/cvZMsNR/v0cBU=", "eT+F471g2HJfd43U4j4L1PIBkt4rLbHQd/pOR/rllO0=", "DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="],
+ "checkpoint": {
+ "envelope": "rekor.sigstore.dev - 1193050959916656506\n1511665068\nOG0nIG3AvtuixXataAYGzSBL9MEL5FZGZibuVapXMkg\u003d\n\n— rekor.sigstore.dev wNI9ajBFAiBXdkcrA8j3ini2P8MWEipDGkkrCuulqR1mIeVvC0t/CwIhAO9N0h6e1rhE/6t0Hu5wg3sFzhjGRd97yKePg9CuUvh4\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhNTEyIiwidmFsdWUiOiJkMmUyMTY1NzA0NmJmZjEwOGVmZTM5NjNjNzc4ZWQyYTgwMzM4Njc5ODhmYzI0ZDlmMWEyZmE5ZTk2NDhmZTE5ODdjMGY5YzVjYzY3Mzk2ZWFiM2VlNzM2NTRjY2RiZmRmZWNmZmFiYTEzMzkwYjkwZTMxN2MwMDM4Nzg3NDdmYSJ9fSwic2lnbmF0dXJlIjp7ImNvbnRlbnQiOiJNSUdJQWtJQkZCZngrSHNqYVFZVEVPR1RWYVVBckJ1eDVnTzVnODU3VzZUMHoyL2cyc2NhRWZxc3FrTHl5aytINCtwZDZCT0VIWkk5Nk5LMmJpaHR2ektQOGlGSllrc0NRZ0hvc09wUGwxSDFpbDRYR1NtVC9KQzFWbkkxWHcrQmxlL1ZFR1cxSktmQTdTVFlxRnZBY1l5ZnpJVDNuNWVrQVZBbDZNYUhvOG5pWldNejRlSlE3UGNheWc9PSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVUk9WRU5EUVhKNVowRjNTVUpCWjBsVlNIcFNkMmh2SzBKYVJEUjFTMDFPU25GalVtbElOVEJVVHpoamQwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDVVU1RKTlZGRjVUV3BCTUZkb1kwNU5hbGwzVGxSSk1rMVVVWHBOYWtFd1YycEJRVTFKUjJKTlFrRkhDa0o1Y1VkVFRUUTVRV2RGUjBKVGRVSkNRVUZxUVRSSFIwRkJVVUYwTTNwQ2QwVTJWMHh2T1VkVldqQmhhR2hwVlZkR2JteEdiR05hVEdodU1FeG1hMU1LTjJvd2RXUmlXR051UW5KNE9WbGtlakZVWjJRNFV5czJWM1pPTlhsaVJYSlFSa0o1UmpoWE5IZG9LMGRxTlVVMU9FSlJRVkZWS3pFNGFrWkhMME5PV2dwdGFFWnpjbk0zVFdoeE9WTkxlazFaUlhWT1pESm9iMEUzUkVGRE1FZEtZWFlyU0RKd2RTOVNaR1V5TUdWcWVtdFBOazR6TVRoWWJVRTBZMVpGY0dSeENqVXZSbXhrWWs5dlVVbDVhbWRuUjFsTlNVbENiRVJCVDBKblRsWklVVGhDUVdZNFJVSkJUVU5DTkVGM1JYZFpSRlpTTUd4Q1FYZDNRMmRaU1V0M1dVSUtRbEZWU0VGM1RYZElVVmxFVmxJd1QwSkNXVVZHVGxVM1QweHdTMHRVZUV4bU1USnBhM1YwU25oV1ZVZHNVVzlHVFVJNFIwRXhWV1JKZDFGWlRVSmhRUXBHVGk5VU5tTTVWMHBDUjFjcllXcFpObE5vVm05eldYVkhSMUV2VFVWalIwRXhWV1JGVVVWQ0wzZFJPVTFFZFVKUFdGWjFaRWhLTVdNelVteGFRekY2Q2xsVlFucGhWMlI2WkVjNWVWcFRNV3BpTWpWdFlqTktkRmxYTldwYVV6VndXVmN3ZFZvelRteGpibHB3V1RKV2FGa3lUblprVnpVd1RHMU9kbUpVUVhBS1FtZHZja0puUlVWQldVOHZUVUZGUWtKQ2RHOWtTRkozWTNwdmRrd3lSbXBaTWpreFltNVNla3h0WkhaaU1tUnpXbE0xYW1JeU1IZExkMWxMUzNkWlFncENRVWRFZG5wQlFrTkJVV1JFUW5SdlpFaFNkMk42YjNaTU1rWnFXVEk1TVdKdVVucE1iV1IyWWpKa2MxcFROV3BpTWpCM1oxbHpSME5wYzBkQlVWRkNDakZ1YTBOQ1FVbEZabEZTTjBGSWEwRmtkMFJrVUZSQ2NYaHpZMUpOYlUxYVNHaDVXbHA2WTBOdmEzQmxkVTQwT0hKbUswaHBia3RCVEhsdWRXcG5RVUVLUVZvMWEzRm5VVkJCUVVGRlFYZENTVTFGV1VOSlVVUkZSbUZGYVdobk0wOWxaWFpZUXpWRUx6RXZhRTByV1RSa01raExkMjlPY2pVMVNtazVlV2N3S3dvMlVVbG9RVXBXYURWUVRqWklXalZ6ZVhjd1RrNWtPRWx6UTAweFpGZ3JabkF6Yldvd1dHRnlaa2hrY25aSlZuWk5RVzlIUTBOeFIxTk5ORGxDUVUxRUNrRXlZMEZOUjFGRFRVTkliamx1WjFoS2VuaFFNVU5ETUVSS1VVMUpVVXRpT1hGSFNWQjJVblpoUWpOelNVNHJZMjFxV2pSdlMzSm9PVWxzUm5GdEwxSUtNMEZLV0ZVd1JWVlZkMGwzVVVGemFVeDNTVEk1VkVWM1JGTTBXVFoxT0VZeE1rRmhlRFFyVFRKRWEwTnVWRkZTTTFkcmMyUkdaRzV2WlVwdlVFUkdOUXA2T0UxalFWRTJRMVpaVG5vS0xTMHRMUzFGVGtRZ1EwVlNWRWxHU1VOQlZFVXRMUzB0TFFvPSJ9fX19"
+ }],
+ "certificate": {
+ "rawBytes": "MIIDNTCCArygAwIBAgIUHzRwho+BZD4uKMNJqcRiH50TO8cwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTI2MTQyMjA0WhcNMjYwNTI2MTQzMjA0WjAAMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAt3zBwE6WLo9GUZ0ahhiUWFnlFlcZLhn0LfkS7j0udbXcnBrx9Ydz1Tgd8S+6WvN5ybErPFByF8W4wh+Gj5E58BQAQU+18jFG/CNZmhFsrs7Mhq9SKzMYEuNd2hoA7DAC0GJav+H2pu/Rde20ejzkO6N318XmA4cVEpdq5/FldbOoQIyjggGYMIIBlDAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFNU7OLpKKTxLf12ikutJxVUGlQoFMB8GA1UdIwQYMBaAFN/T6c9WJBGW+ajY6ShVosYuGGQ/MEcGA1UdEQEB/wQ9MDuBOXVudHJ1c3RlZC1zYUBzaWdzdG9yZS1jb25mb3JtYW5jZS5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbTApBgorBgEEAYO/MAEBBBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wKwYKKwYBBAGDvzABCAQdDBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wgYsGCisGAQQB1nkCBAIEfQR7AHkAdwDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynujgAAAZ5kqgQPAAAEAwBIMEYCIQDEFaEihg3OeevXC5D/1/hM+Y4d2HKwoNr55Ji9yg0+6QIhAJVh5PN6HZ5syw0NNd8IsCM1dX+fp3mj0XarfHdrvIVvMAoGCCqGSM49BAMDA2cAMGQCMCHn9ngXJzxP1CC0DJQMIQKb9qGIPvRvaB3sIN+cmjZ4oKrh9IlFqm/R3AJXU0EUUwIwQAsiLwI29TEwDS4Y6u8F12Aax4+M2DkCnTQR3WksdFdnoeJoPDF5z8McAQ6CVYNz"
+ }
+ },
+ "messageSignature": {
+ "messageDigest": {
+ "algorithm": "SHA2_512",
+ "digest": "0uIWVwRr/xCO/jljx3jtKoAzhnmI/CTZ8aL6npZI/hmHwPnFzGc5bqs+5zZUzNv9/s/6uhM5C5DjF8ADh4dH+g=="
+ },
+ "signature": "MIGIAkIBFBfx+HsjaQYTEOGTVaUArBux5gO5g857W6T0z2/g2scaEfqsqkLyyk+H4+pd6BOEHZI96NK2bihtvzKP8iFJYksCQgHosOpPl1H1il4XGSmT/JC1VnI1Xw+Ble/VEGW1JKfA7STYqFvAcYyfzIT3n5ekAVAl6MaHo8niZWMz4eJQ7Pcayg=="
+ }
+}
\ No newline at end of file
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_2048_SHA256.sigstore.json b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_2048_SHA256.sigstore.json
new file mode 100644
index 000000000..b65ece4b7
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_2048_SHA256.sigstore.json
@@ -0,0 +1,39 @@
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "tlogEntries": [{
+ "logIndex": "1633568801",
+ "logId": {
+ "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.1"
+ },
+ "integratedTime": "1779805315",
+ "inclusionPromise": {
+ "signedEntryTimestamp": "MEUCIQDos+IAkMZ/jnqUSpGb6N2nh4950ifb3aIxn+twMOhxzwIgfbS2Vu/iDPJMatkgaBJyKwmlXWhoTMiyJqloaUOsSt8="
+ },
+ "inclusionProof": {
+ "logIndex": "1511664539",
+ "rootHash": "RUgZIzsqWcdFQB/fbniVkUuw3Usx5BB6MF2UZTKD+qI=",
+ "treeSize": "1511664556",
+ "hashes": ["xGwAW8gNvSGxzhqnGYZpaNfwA1KLf1+2J9jEti/4YRY=", "Ey8aAoKa3zjqJVaqNSNkCbmd10JnEi7IvUAilW7meyY=", "RdvCbuKK9Lqp4BCiK+VQJFMXUMjKsC17oW3i0HIrBJA=", "++nShmo+yz0BPaT8dC5HMMV6wu/2kU8QbHjhdI2iGSA=", "T7WHDjSSKy+ZcKFDwZALlwU6bBZP9467irAS/oIWD9s=", "wb9fodqw8pJjNmQ95w4UVbGx0Fg6Xi3n3Xz1jgeEwzc=", "xSu0qHv/64wkk02iJvDkJnxGy2loA5vpkONwD2HjhhU=", "dUrhanpHa77Uv+Mo/S3+YA9TatQnhJL7njbNjwzSECY=", "6LkSiUGhQ8/HjNUHxFQInxFnaD/+e/VwVwnRUFCrESg=", "2FvdzBMfv489BLEkgJC+yWb4gSp/47E315qOjOzHTZI=", "ABU28Mr2tF+9hnqOGwSAlabYkP6grvZMoM7oesu/L6g=", "REVcPsjUwNz5y9ZezFOmhc5jS5qbXafRs0h0VXC31RU=", "PuM3CasxXEHFjDo5J0ekAcFZIFVhA7jFiUUCiPtlkzQ=", "20Rm754Do/BWEhP8pav1J4ARfPD0r+Jd7mEf5DE4eqk=", "Nq4SYV9bcP17fOZqrjs6GE6Ed73nTtmZCLg2CI+M+Ro=", "r5nn9+mbgUQL4m8neTg/XjYkdf2hD/cvZMsNR/v0cBU=", "eT+F471g2HJfd43U4j4L1PIBkt4rLbHQd/pOR/rllO0=", "DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="],
+ "checkpoint": {
+ "envelope": "rekor.sigstore.dev - 1193050959916656506\n1511664556\nRUgZIzsqWcdFQB/fbniVkUuw3Usx5BB6MF2UZTKD+qI\u003d\n\n— rekor.sigstore.dev wNI9ajBFAiBdzTyvKlf5WXgpVRdVlMVCeNUWQleCkNLg0UvtfSRf0AIhAPqrrk7wIrHB6ggjb9zgVdz0ZpNivlb2I/J/lu4A2DeD\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJhMGNmYzcxMjcxZDZlMjc4ZTU3Y2QzMzJmZjk1N2MzZjcwNDNmZGRhMzU0YzRjYmIxOTBhMzBkNTZlZmEwMWJmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6IkhJMmxMNjV4ZmZ4cnpsS3Fvc0g2aGFmRStPQXNSdi93bmxqNFFSMVBYVFQrS2JjZjdmY0NLZXBQd09waU5ZbW12V0NqYmcxdzRiRmwwWEZFOVdpandaVWhIcGt1b2prQkJVWVJPUUdYWkFIZ0VSNE5XMnFRVUlZemI3TjlqaVJ4NSszcFltSnU1RXNaNmV5ajRjV2tVSnBLeW9zeVFnVjl1MFlqbzlIRGZ6eHljbklPQ0JYSm5YL1RON0JDUXhXM0xLMFc5ajBkUWZFOTN5K2VKc3M5WEowK0xXNnVnKzMzdEljbzNmaGpzOUEreWVFeDZaRkZJQ2FXY3dSNUluUlRYNUdlOWxyUnNYSDRwS1poVWJLNCtmR2MzaEZHMjNnSzF6SWRBTVVvZXM1dG8yQTk1ekhva2c4Q2JuMVBoVHBGVmtDbU9iMmlBUjRoWXM1VXoxMG9VUT09IiwicHVibGljS2V5Ijp7ImNvbnRlbnQiOiJMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VSMlZFTkRRVEJQWjBGM1NVSkJaMGxWVFZZMlZpdEpkWGgwZEZjNFYzQnRRekJwYVhCQ1luTm9UbUUwZDBObldVbExiMXBKZW1vd1JVRjNUWGNLVG5wRlZrMUNUVWRCTVZWRlEyaE5UV015Ykc1ak0xSjJZMjFWZFZwSFZqSk5ValIzU0VGWlJGWlJVVVJGZUZaNllWZGtlbVJIT1hsYVV6RndZbTVTYkFwamJURnNXa2RzYUdSSFZYZElhR05PVFdwWmQwNVVTVEpOVkZGNVRWUlZNRmRvWTA1TmFsbDNUbFJKTWsxVVVYcE5WRlV3VjJwQlFVMUpTVUpKYWtGT0NrSm5hM0ZvYTJsSE9YY3dRa0ZSUlVaQlFVOURRVkU0UVUxSlNVSkRaMHREUVZGRlFUQlRORGRVWm5jeFFqQnBhemxtUzBwTk0xcHRRM1ZUUzJsc2FtNEtRVk5aY0RGU1FYZzNkeXRKWXl0bmEycFRObmt6T0M4MWJEaEhTRWs1TkRGdVoxQnhjV3BMT0ROaFJ6UjNZMFkzUlVZek5qWllkbEEwZGtaRVExbGFXQXBsYm5wT1MyZzNNbGxsVjJWTVIySkRhVmRFYjFRNGJXYzRWRUV4V2xsUVNXTkJWMGgzTWxRNFZ5dG5iaThyY21oMlMzWnBNazlITnpCTlptNDRMMVJJQ2s1S1FYVkphRkl4VEVkd1dIUlhiREJQVm1WeU5HSlBOR2QxTjB0QlNGRlpXVEJ5VUV0bU5YUlFOVTFPVVVnNFRXOU9RV3hIV1VRdlpGRnZSRlpZVm1JS1N5dHliRzVtTTJ4VVNISjRSMWROTjJ0S1EyeHVXREJ4ZG14dlJ6VTJTRlpxSzNKQlRuQllkV0l4YXpJeFRFcGlSSEJFYW5ZM1kzZHlWbkZWYjNKd2RRcHRSbWxhUlVSS016aFljVGxwTWtoV1JWTnpVSFZxYkhkdFpFOTRSa1l6VG1KdldWcFhaV1pCZGpkeVdIaHZhbFpyVFVOT1dEVlhiVE5SU1VSQlVVRkNDbTgwU1VKc2VrTkRRVnBOZDBSbldVUldVakJRUVZGSUwwSkJVVVJCWjJWQlRVSk5SMEV4VldSS1VWRk5UVUZ2UjBORGMwZEJVVlZHUW5kTlJFMUNNRWNLUVRGVlpFUm5VVmRDUWxOamRVc3hOa0psVGpGek5XVnhWSFpzUms1dFJsZ3ZWV2RCUVhwQlprSm5UbFpJVTAxRlIwUkJWMmRDVkdZd0syNVFWbWxSVWdwc2RtMXZNazlyYjFaaFRFZE1hR2hyVUhwQ1NFSm5UbFpJVWtWQ1FXWTRSVkJVUVRkblZHd3hZbTVTZVdSWVRqQmFWMUYwWXpKR1FXTXliRzVqTTFKMkNtTnRWWFJaTWpsMVdtMDVlV0pYUm5WWk1sVjFZVmRHZEV4dFpIcGFXRW95WVZkT2JGbFhUbXBpTTFaMVpFTTFhbUl5TUhkTFVWbExTM2RaUWtKQlIwUUtkbnBCUWtGUlVXSmhTRkl3WTBoTk5reDVPV2haTWs1MlpGYzFNR041Tlc1aU1qbHVZa2RWZFZreU9YUk5RM05IUTJselIwRlJVVUpuTnpoM1FWRm5SUXBJVVhkaVlVaFNNR05JVFRaTWVUbG9XVEpPZG1SWE5UQmplVFZ1WWpJNWJtSkhWWFZaTWpsMFRVbEhTMEpuYjNKQ1owVkZRV1JhTlVGblVVTkNTSGRGQ21WblFqUkJTRmxCTTFRd2QyRnpZa2hGVkVwcVIxSTBZMjFYWXpOQmNVcExXSEpxWlZCTE15OW9OSEI1WjBNNGNEZHZORUZCUVVkbFdrdHVaa0ZSUVVFS1FrRk5RVko2UWtaQmFVVkJjR2hIVjNWb2RURlRNVU00TkdaT1MxUnZSMGQyTTFsbFFsQXlRMFVyZHpaMVRtSmlXSE5WTUZkYVVVTkpRM0pzUmt4RWFRbzBhSHBDZHpOcFZucElPRkJIVG1sM1l6ZDJURmsyZFRNd2VWVnhSa0pXVUhvNVR6Tk5RVzlIUTBOeFIxTk5ORGxDUVUxRVFUSm5RVTFIVlVOTlVVUlhDblZtZEd4TldIcGhRbmh5VGxCbVltTXhXVEZ2UWtvMGJrVnJVemhhZDA1Qk1FcGxVRVpIV0hSMWFXcHZiMlJLWVZWRE9YUTBPV0lyWjBSeFluVndSVU1LVFVSWmRIRk9jV1ZNVVZKd1YwcHZNRzV4VERkdGJ6TjZhR1Z5ZGsxbWNVRjFNVFJZZDJWdFYyZHZRVGR0TldZM1QwTm1RVkJTVEV0SFJrNW9ZWHBpTXdwM1p6MDlDaTB0TFMwdFJVNUVJRU5GVWxSSlJrbERRVlJGTFMwdExTMEsifX19fQ=="
+ }],
+ "certificate": {
+ "rawBytes": "MIIDvTCCA0OgAwIBAgIUMV6V+IuxttW8WpmC0iipBbshNa4wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTI2MTQyMTU0WhcNMjYwNTI2MTQzMTU0WjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0S47Tfw1B0ik9fKJM3ZmCuSKiljnASYp1RAx7w+Ic+gkjS6y38/5l8GHI941ngPqqjK83aG4wcF7EF366XvP4vFDCYZXenzNKh72YeWeLGbCiWDoT8mg8TA1ZYPIcAWHw2T8W+gn/+rhvKvi2OG70Mfn8/THNJAuIhR1LGpXtWl0OVer4bO4gu7KAHQYY0rPKf5tP5MNQH8MoNAlGYD/dQoDVXVbK+rlnf3lTHrxGWM7kJClnX0qvloG56HVj+rANpXub1k21LJbDpDjv7cwrVqUorpumFiZEDJ38Xq9i2HVESsPujlwmdOxFF3NboYZWefAv7rXxojVkMCNX5Wm3QIDAQABo4IBlzCCAZMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMB0GA1UdDgQWBBScuK16BeN1s5eqTvlFNmFX/UgAAzAfBgNVHSMEGDAWgBTf0+nPViQRlvmo2OkoVaLGLhhkPzBHBgNVHREBAf8EPTA7gTl1bnRydXN0ZWQtc2FAc2lnc3RvcmUtY29uZm9ybWFuY2UuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20wKQYKKwYBBAGDvzABAQQbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMCsGCisGAQQBg78wAQgEHQwbaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tMIGKBgorBgEEAdZ5AgQCBHwEegB4AHYA3T0wasbHETJjGR4cmWc3AqJKXrjePK3/h4pygC8p7o4AAAGeZKnfAQAABAMARzBFAiEAphGWuhu1S1C84fNKToGGv3YeBP2CE+w6uNbbXsU0WZQCICrlFLDi4hzBw3iVzH8PGNiwc7vLY6u30yUqFBVPz9O3MAoGCCqGSM49BAMDA2gAMGUCMQDWuftlMXzaBxrNPfbc1Y1oBJ4nEkS8ZwNA0JePFGXtuijoodJaUC9t49b+gDqbupECMDYtqNqeLQRpWJo0nqL7mo3zhervMfqAu14XwemWgoA7m5f7OCfAPRLKGFNhazb3wg=="
+ }
+ },
+ "messageSignature": {
+ "messageDigest": {
+ "algorithm": "SHA2_256",
+ "digest": "oM/HEnHW4njlfNMy/5V8P3BD/do1TEy7GQow1W76Ab8="
+ },
+ "signature": "HI2lL65xffxrzlKqosH6hafE+OAsRv/wnlj4QR1PXTT+Kbcf7fcCKepPwOpiNYmmvWCjbg1w4bFl0XFE9WijwZUhHpkuojkBBUYROQGXZAHgER4NW2qQUIYzb7N9jiRx5+3pYmJu5EsZ6eyj4cWkUJpKyosyQgV9u0Yjo9HDfzxycnIOCBXJnX/TN7BCQxW3LK0W9j0dQfE93y+eJss9XJ0+LW6ug+33tIco3fhjs9A+yeEx6ZFFICaWcwR5InRTX5Ge9lrRsXH4pKZhUbK4+fGc3hFG23gK1zIdAMUoes5to2A95zHokg8Cbn1PhTpFVkCmOb2iAR4hYs5Uz10oUQ=="
+ }
+}
\ No newline at end of file
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_3072_SHA256.sigstore.json b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_3072_SHA256.sigstore.json
new file mode 100644
index 000000000..6c47b9884
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_3072_SHA256.sigstore.json
@@ -0,0 +1,39 @@
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "tlogEntries": [{
+ "logIndex": "1633568932",
+ "logId": {
+ "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.1"
+ },
+ "integratedTime": "1779805317",
+ "inclusionPromise": {
+ "signedEntryTimestamp": "MEUCICeoXyF59i4iuCpz92HBUlCzOYohOWjSpf8gDXYMiad9AiEAzA+pNj62pEEtDgJ9COdKmd6wEWpNQFr7UhQq/U5GsS0="
+ },
+ "inclusionProof": {
+ "logIndex": "1511664670",
+ "rootHash": "I7RLY64RqlzDoC0jMgLHX5zQ++gjjCyY1xmS3jEjnGM=",
+ "treeSize": "1511664676",
+ "hashes": ["y77oCrIcSDAWfDelTyL1sro0acC/ihDVwQhZbeJsFFs=", "G8c+QPcZ0l8gIqLASogj2GNGjckLNjwytoxwlnOr7Ag=", "Mm3ph0cRll/9nqHzdKM1+TfGaZxEh1cCyOy7JVel2Us=", "hyR9lpqD1dYXN2MOHq7LTM+sk4Za5owdPYwreVZ8jMg=", "jcYflOQae53LHTS7kfonyYWYzAv279gBrLg0WCAcigQ=", "l7xjJLFraHqkE+m/iFLLmicphG2AAEBmRCn3Zbfmiyw=", "pX58u/0w68oJS7qRP4+77lddPGxcVMT0d/Snp4FCqbY=", "2FvdzBMfv489BLEkgJC+yWb4gSp/47E315qOjOzHTZI=", "ABU28Mr2tF+9hnqOGwSAlabYkP6grvZMoM7oesu/L6g=", "REVcPsjUwNz5y9ZezFOmhc5jS5qbXafRs0h0VXC31RU=", "PuM3CasxXEHFjDo5J0ekAcFZIFVhA7jFiUUCiPtlkzQ=", "20Rm754Do/BWEhP8pav1J4ARfPD0r+Jd7mEf5DE4eqk=", "Nq4SYV9bcP17fOZqrjs6GE6Ed73nTtmZCLg2CI+M+Ro=", "r5nn9+mbgUQL4m8neTg/XjYkdf2hD/cvZMsNR/v0cBU=", "eT+F471g2HJfd43U4j4L1PIBkt4rLbHQd/pOR/rllO0=", "DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="],
+ "checkpoint": {
+ "envelope": "rekor.sigstore.dev - 1193050959916656506\n1511664676\nI7RLY64RqlzDoC0jMgLHX5zQ++gjjCyY1xmS3jEjnGM\u003d\n\n— rekor.sigstore.dev wNI9ajBGAiEAixJOUs07kNNSDLL55TknfJSJu6OIP9L2GfTA/Qx2o34CIQDkhN5cN4gcDK4TDvC9dAjo0kNB4w1zfq00VaJWpyxIhA\u003d\u003d\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJhMGNmYzcxMjcxZDZlMjc4ZTU3Y2QzMzJmZjk1N2MzZjcwNDNmZGRhMzU0YzRjYmIxOTBhMzBkNTZlZmEwMWJmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6ImgzYk0zc1NJeWw5ZHh0L3Nnc0psaEhSUGJhdE1MaGFSbkh5SEVCdHVLVm55UmVoZVRsNE9OU2hOakszTXQ5MFgyazYwQTZmMzBIRVdmRkJYM1J2Zm84aVYxTlB2S3BlYUJ2SitreVhBYmNwQm43MWJuRjZkQ3lPeWZHL0FZVlE0UFZ5bndGRFo1bGtzVGxoRkh4U3ZBWVF0QVpTVk5nRTg3ZHZZblRIaHRjbFM3MXJYbjkralBKRTRmbmVldjVIQWQrLytZbGJ0Qm9IUFI4R3E4dUNqS0JsUnk0REF1dkZadUdHcHFQT2FSUzgwenNkNUNEV0t0dC9EYWJFdVQvM1dUYkp5ZEtKOFhmK0hGRTQzR3djMWxNUjJMZ2dUeUttOGJJWVlxVzdXRTgxMXBJWGRBOWl2Um84RkJZd1V1Z01wQlNPYi9KY09xOTg5dDdIT3UrQWZEaFNkNmorNHBqUHlzeHJ1a1dkKzdzTUo0RTRHZS9ia3dDSnhsT1M2NG90UXBtWmR3eGVNYS9CT1ovMm1lNFJDUVNLVVBCUEtuVHR3VHpNbmkySnRlUXlvZDVBRGIxQTBHelNLZDkva01rTUo0M0ZxNmtrNDZmWTRDRittKzNxb0k1SUZGTmNoaS83eEJYcDdhSG9WV0Z0NE84MjJORVhxTm1KclUvS1VNMGRnIiwicHVibGljS2V5Ijp7ImNvbnRlbnQiOiJMUzB0TFMxQ1JVZEpUaUJEUlZKVVNVWkpRMEZVUlMwdExTMHRDazFKU1VWUVZFTkRRVGhQWjBGM1NVSkJaMGxWVUdRNFFYZEJiMGxWVm1sMFdWUm5kMGRuYVRGM1YwSjFTV3RCZDBObldVbExiMXBKZW1vd1JVRjNUWGNLVG5wRlZrMUNUVWRCTVZWRlEyaE5UV015Ykc1ak0xSjJZMjFWZFZwSFZqSk5ValIzU0VGWlJGWlJVVVJGZUZaNllWZGtlbVJIT1hsYVV6RndZbTVTYkFwamJURnNXa2RzYUdSSFZYZElhR05PVFdwWmQwNVVTVEpOVkZGNVRWUlZNbGRvWTA1TmFsbDNUbFJKTWsxVVVYcE5WRlV5VjJwQlFVMUpTVUp2YWtGT0NrSm5hM0ZvYTJsSE9YY3dRa0ZSUlVaQlFVOURRVms0UVUxSlNVSnBaMHREUVZsRlFYSjBNVTE0UlVveFpUWmFWMDV0Y1ZCV1NEbGpRblZvTUZoelVtd0tibTFSTkRaS1JFaFhPVWxrUVUweFZFTk9UM0ZQWW1aR1kzUlJPRTgzWW1aUWRqQlhZV2xuWkRVNVZGcHBXaTh2Tm5CSFFtMVVTeTlxVm1jdksydG5hd3BtVXpCVE1qWmFUVTV0VGs0NWQwRXZVMkozZVhoV1VWcE9iVTEwVDBwQk9VbDVXVWRwYVhwdVVHaEdSVFJPY2tSTlRVZEtla2xzVkhkUkwyRm9NVk5qQ2xoQ2RHSkxOV1JTVTBOd2FFbFZOWEZPTVVwSGFqWkdMMEZNZDFGcE4zcHpXRUpQUjBKRlpqZ3pkMVpPTDA0MU9HTllUa1I0YjNBNU9HcG9OMFI0VXpFS1ZFdHBRVkV3ZFVJMGQwMUlhV3BaY1VJMlZEbDBka2RWUlROVlNEUkRja2szYVZkek5Ya3JabXcwWjBkclpFOVVaMlpoZGpCUFFVTTVjMjFzYW1kU01RcFFkRkUwYW13dmNWQjZlbVI1ZUhCck9VYzFWbEp0Y0RSWFIwNW5aSGR4YkhacGNsRkphbXBtSzJSdk5VTXhMM1ZMTmxSU1J5OWhlbEI2U0RKR0swWTRDakJKTUcxUE4xaHlWazFhZW1OS0szTTVkVE5XWjJoUlNrWmFhVlF6V25oeVFtcDJPRlZtV1VobU1XMTNabG80WVRkemExUlZTR0oyWldOamRrTlNlWGtLWmpaMU1uQnhTR1E1YlU5MmQyVnFUMkl4T0N0R1JrTlpNVFZwVkdKQlVrczJXWGhyV1Vwa2FUWXdZa3hTTjA1SVdHbFJZM0ZaY2xaWVRtMWlTamhtZUFwSGMyWlFMek5CYkhkaFNucHBkMlJyVEU1WlNDOXVTelJyWm5kVGNrUkJSRXMzYzNKQlowMUNRVUZIYW1kblIxaE5TVWxDYTNwQlQwSm5UbFpJVVRoQ0NrRm1PRVZDUVUxRFFqUkJkMFYzV1VSV1VqQnNRa0YzZDBObldVbExkMWxDUWxGVlNFRjNUWGRJVVZsRVZsSXdUMEpDV1VWR1JqWk9ZMVpOYlcxRGFHZ0tNbTVCTnk5ek9WaEZlblZTU1dsQldFMUNPRWRCTVZWa1NYZFJXVTFDWVVGR1RpOVVObU01VjBwQ1IxY3JZV3BaTmxOb1ZtOXpXWFZIUjFFdlRVVmpSd3BCTVZWa1JWRkZRaTkzVVRsTlJIVkNUMWhXZFdSSVNqRmpNMUpzV2tNeGVsbFZRbnBoVjJSNlpFYzVlVnBUTVdwaU1qVnRZak5LZEZsWE5XcGFVelZ3Q2xsWE1IVmFNMDVzWTI1YWNGa3lWbWhaTWs1MlpGYzFNRXh0VG5aaVZFRndRbWR2Y2tKblJVVkJXVTh2VFVGRlFrSkNkRzlrU0ZKM1kzcHZka3d5Um1vS1dUSTVNV0p1VW5wTWJXUjJZakprYzFwVE5XcGlNakIzUzNkWlMwdDNXVUpDUVVkRWRucEJRa05CVVdSRVFuUnZaRWhTZDJONmIzWk1Na1pxV1RJNU1RcGlibEo2VEcxa2RtSXlaSE5hVXpWcVlqSXdkMmRaYjBkRGFYTkhRVkZSUWpGdWEwTkNRVWxGWmtGU05rRklaMEZrWjBSa1VGUkNjWGh6WTFKTmJVMWFDa2hvZVZwYWVtTkRiMnR3WlhWT05EaHlaaXRJYVc1TFFVeDViblZxWjBGQlFWbzFhM0ZsWkRkQlFVRkZRWGRDU0UxRlZVTkpSbVJ3WjJkdGN6UnNjbklLZVdab1dtRXhkRVZLYjJacFZXTndTVVEwTVd0VVVYWlNaVzVWTlZOTFdVNUJhVVZCYmt0emNHODVhalIzUzNaallWcGtUVXhRUVhWbkt6ZExVVGhHV0FwaFpVeE9hVmxaVWtRMlVIcDBWMjkzUTJkWlNVdHZXa2w2YWpCRlFYZE5SR0ZCUVhkYVVVbDRRVXN6TkRRMFEybDZZWEJhYnpsalUzRjNlVlJUUkdGUENrNU9VVXh6ZWtKb1RtbHNMMkZ6ZG1obWExcHJUa3BzVGxWTlpURnBPVWhSUmtGV2QxTlBSeko2ZDBsM1pIYzJNMlJTYTJrMmVqazJVbXRsWW5kbFVTOEtlbnBTVUZRd1ZsUmxXamRHUjNaWmMyWXhTMmhhUW5KYU1rWldTWFJWYXpWbGMzaFBVRWhvV25wdVZHa0tMUzB0TFMxRlRrUWdRMFZTVkVsR1NVTkJWRVV0TFMwdExRbz0ifX19fQ=="
+ }],
+ "certificate": {
+ "rawBytes": "MIIEPTCCA8OgAwIBAgIUPd8AwAoIUVitYTgwGgi1wWBuIkAwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTI2MTQyMTU2WhcNMjYwNTI2MTQzMTU2WjAAMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEArt1MxEJ1e6ZWNmqPVH9cBuh0XsRlnmQ46JDHW9IdAM1TCNOqObfFctQ8O7bfPv0Waigd59TZiZ//6pGBmTK/jVg/+kgkfS0S26ZMNmNN9wA/SbwyxVQZNmMtOJA9IyYGiiznPhFE4NrDMMGJzIlTwQ/ah1ScXBtbK5dRSCphIU5qN1JGj6F/ALwQi7zsXBOGBEf83wVN/N58cXNDxop98jh7DxS1TKiAQ0uB4wMHijYqB6T9tvGUE3UH4CrI7iWs5y+fl4gGkdOTgfav0OAC9smljgR1PtQ4jl/qPzzdyxpk9G5VRmp4WGNgdwqlvirQIjjf+do5C1/uK6TRG/azPzH2F+F80I0mO7XrVMZzcJ+s9u3VghQJFZiT3ZxrBjv8UfYHf1mwfZ8a7skTUHbveccvCRyyf6u2pqHd9mOvwejOb18+FFCY15iTbARK6YxkYJdi60bLR7NHXiQcqYrVXNmbJ8fxGsfP/3AlwaJziwdkLNYH/nK4kfwSrDADK7srAgMBAAGjggGXMIIBkzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwHQYDVR0OBBYEFF6NcVMmmChh2nA7/s9XEzuRIiAXMB8GA1UdIwQYMBaAFN/T6c9WJBGW+ajY6ShVosYuGGQ/MEcGA1UdEQEB/wQ9MDuBOXVudHJ1c3RlZC1zYUBzaWdzdG9yZS1jb25mb3JtYW5jZS5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbTApBgorBgEEAYO/MAEBBBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wKwYKKwYBBAGDvzABCAQdDBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wgYoGCisGAQQB1nkCBAIEfAR6AHgAdgDdPTBqxscRMmMZHhyZZzcCokpeuN48rf+HinKALynujgAAAZ5kqed7AAAEAwBHMEUCIFdpggms4lrryfhZa1tEJofiUcpID41kTQvRenU5SKYNAiEAnKspo9j4wKvcaZdMLPAug+7KQ8FXaeLNiYYRD6PztWowCgYIKoZIzj0EAwMDaAAwZQIxAK3444CizapZo9cSqwyTSDaONNQLszBhNil/asvhfkZkNJlNUMe1i9HQFAVwSOG2zwIwdw63dRki6z96RkebweQ/zzRPT0VTeZ7FGvYsf1KhZBrZ2FVItUk5esxOPHhZznTi"
+ }
+ },
+ "messageSignature": {
+ "messageDigest": {
+ "algorithm": "SHA2_256",
+ "digest": "oM/HEnHW4njlfNMy/5V8P3BD/do1TEy7GQow1W76Ab8="
+ },
+ "signature": "h3bM3sSIyl9dxt/sgsJlhHRPbatMLhaRnHyHEBtuKVnyReheTl4ONShNjK3Mt90X2k60A6f30HEWfFBX3Rvfo8iV1NPvKpeaBvJ+kyXAbcpBn71bnF6dCyOyfG/AYVQ4PVynwFDZ5lksTlhFHxSvAYQtAZSVNgE87dvYnTHhtclS71rXn9+jPJE4fneev5HAd+/+YlbtBoHPR8Gq8uCjKBlRy4DAuvFZuGGpqPOaRS80zsd5CDWKtt/DabEuT/3WTbJydKJ8Xf+HFE43Gwc1lMR2LggTyKm8bIYYqW7WE811pIXdA9ivRo8FBYwUugMpBSOb/JcOq989t7HOu+AfDhSd6j+4pjPysxrukWd+7sMJ4E4Ge/bkwCJxlOS64otQpmZdwxeMa/BOZ/2me4RCQSKUPBPKnTtwTzMni2JteQyod5ADb1A0GzSKd9/kMkMJ43Fq6kk46fY4CF+m+3qoI5IFFNchi/7xBXp7aHoVWFt4O822NEXqNmJrU/KUM0dg"
+ }
+}
\ No newline at end of file
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_4096_SHA256.sigstore.json b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_4096_SHA256.sigstore.json
new file mode 100644
index 000000000..bd0e9792d
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/PKIX_RSA_PKCS1V15_4096_SHA256.sigstore.json
@@ -0,0 +1,39 @@
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "tlogEntries": [{
+ "logIndex": "1633569045",
+ "logId": {
+ "keyId": "wNI9atQGlz+VWfO6LRygH4QUfY/8W4RFwiT5i5WRgB0="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.1"
+ },
+ "integratedTime": "1779805319",
+ "inclusionPromise": {
+ "signedEntryTimestamp": "MEQCIHSVeaPzaqwIm3vyQouqQc4LGKE3pYmvq4CqlF/ZxOrcAiBdmos25t5tie6miVxT1WpZBMslTxrHx9k9UTz71WVw3g=="
+ },
+ "inclusionProof": {
+ "logIndex": "1511664783",
+ "rootHash": "7WDxLLLno9QiXssb9FC8T6i9/wcYcdqQcqBe9pxCaC8=",
+ "treeSize": "1511664795",
+ "hashes": ["VoNyfoWqpALTUfvoDxmajNBleejN7oSqSWaKRUl/cok=", "77PIsRX6qzlTv5eQviHo2eUOwcuROZLGJ2MGwlInEHA=", "x2SVVtvPuAlb+C+v8uXOW7616CXLkfGb5Tk0BkmLQII=", "aeft8rG57jMaQzNqfj3Ofvmt3L698MBl2A0+JkV+bQw=", "40rn+sA8aNaD9X6A975djnhQgdLdgg3EY5mO24me/gs=", "XmNJtj66PRtWfesOdLtl2wG9Nobsej1YNqv9JxVI+Es=", "pX58u/0w68oJS7qRP4+77lddPGxcVMT0d/Snp4FCqbY=", "2FvdzBMfv489BLEkgJC+yWb4gSp/47E315qOjOzHTZI=", "ABU28Mr2tF+9hnqOGwSAlabYkP6grvZMoM7oesu/L6g=", "REVcPsjUwNz5y9ZezFOmhc5jS5qbXafRs0h0VXC31RU=", "PuM3CasxXEHFjDo5J0ekAcFZIFVhA7jFiUUCiPtlkzQ=", "20Rm754Do/BWEhP8pav1J4ARfPD0r+Jd7mEf5DE4eqk=", "Nq4SYV9bcP17fOZqrjs6GE6Ed73nTtmZCLg2CI+M+Ro=", "r5nn9+mbgUQL4m8neTg/XjYkdf2hD/cvZMsNR/v0cBU=", "eT+F471g2HJfd43U4j4L1PIBkt4rLbHQd/pOR/rllO0=", "DOCeoSMovIvLExkhIvisow9AuNXgeWs4ECkyR6EcqYU="],
+ "checkpoint": {
+ "envelope": "rekor.sigstore.dev - 1193050959916656506\n1511664795\n7WDxLLLno9QiXssb9FC8T6i9/wcYcdqQcqBe9pxCaC8\u003d\n\n— rekor.sigstore.dev wNI9ajBFAiEAh756dTGoV4qJ3+3dv1KzUtJRH9YdQ5xqirDO8g8rVToCIG8Tzv3aX1K/uhr2rQ9xYwEzelzHPtCpU1UYnES0xQF4\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjEiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJkYXRhIjp7Imhhc2giOnsiYWxnb3JpdGhtIjoic2hhMjU2IiwidmFsdWUiOiJhMGNmYzcxMjcxZDZlMjc4ZTU3Y2QzMzJmZjk1N2MzZjcwNDNmZGRhMzU0YzRjYmIxOTBhMzBkNTZlZmEwMWJmIn19LCJzaWduYXR1cmUiOnsiY29udGVudCI6IlplOUJzbzE1Y0JUSklwUndlNlQ4aFdrWUtOTkxzQVl4OWdnQjY4cmZwZCtrTk9mK28vMnVCUlZ0Wmo1ZXUrZm1DVnlLWTFKZC9ZQUFRR21FcUc0N2ROOEh4U1lKWWlscEtXMktOQUVWTW9ZcURod1Blb09SSzFTdnlxc2FxMDIxVTZkWWdnQ2VVZ2RZQkx2YzhsUEJtMHltUU9ad2ZzeTA0MlRpQ2h4bUNGRW9JTTFiM0hNQ2Q2WTZzMjU4eFBubUNIMFB1eGZPL2tmbmhvNEcvMDBKaWpkUlNJazBackZQZWFFY2JiVXFBMWRzTnYzZWpJQitabGs3NmI2M3JFOXY2eTRhb1kzTW1RU1VzSCtYUXNveVFWUWlJWVprbDBrZmQ0aUZDU0lWUGJHc2EzL2JPbCs2OGlhREtxSlQvdFExZFVaMnJPMGpRUS9RNzd4SGNpWklhb3d1Z3QyelRSQVdYQjIzL3Z5eEpCeW5KUXBTcFIvUFdTMFZRQ0JrT2M5VXoxSDR0SERvaWx0SlZmSFZQOWxPVTdUUmFTa3V2K0NMUTE4QVBYL2RqdU04VEg2K1lXTit5NUJPczBCZDNjT2RIMU9CVWlncGgydWV3KzJ3VzBjRlNqR0VzMGlxL3VyNlJ1UEwxaXpxZ2tnNkFKS3kwQW45UkNXN2pQYXJ2d21PMTB0UXFNeGxkV1pjTDlUVHhFYmtGd1U5M0JJTU1tSlpjTmloV2p3QS8yZVpPVzdtVXg2Q3l3N0FvM2xRK25aczhza3JJMDdaS2xLdWQ3cmJzTGt2K1M5RG5hSlR5U1p2MkRwNjZjWU5XNkRjYm4yS21nMTlDZldkak5WMUplb0tLSlROMUtDNUFjNFZFQTc2OU9RcmtNKzdjNkVQSFlQaHdUVUxXQTJPVFRrPSIsInB1YmxpY0tleSI6eyJjb250ZW50IjoiTFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzB0Q2sxSlNVVjJSRU5EUWtWVFowRjNTVUpCWjBsVlMydG9hMFZOVUZoVWREbHpiMkpETDBaU1REZHplVlpESzJFd2QwTm5XVWxMYjFwSmVtb3dSVUYzVFhjS1RucEZWazFDVFVkQk1WVkZRMmhOVFdNeWJHNWpNMUoyWTIxVmRWcEhWakpOVWpSM1NFRlpSRlpSVVVSRmVGWjZZVmRrZW1SSE9YbGFVekZ3WW01U2JBcGpiVEZzV2tkc2FHUkhWWGRJYUdOT1RXcFpkMDVVU1RKTlZGRjVUVlJWTlZkb1kwNU5hbGwzVGxSSk1rMVVVWHBOVkZVMVYycEJRVTFKU1VOSmFrRk9Da0puYTNGb2EybEhPWGN3UWtGUlJVWkJRVTlEUVdjNFFVMUpTVU5EWjB0RFFXZEZRVEJzVDJ0Q1pXZDZTVkJyTW5oVU1EWjNVVTlSY0dkYWRVdDRNMndLU3poRWFuazVjV2RxYjNKMVNVWTNlV04yT0hVdlZVNHdaelJPZG5OYVdFRnpRelpuVFhkVlpVaHBiM0E0YTNwWmRrcEJRVEozTjB4a2MzWjBaR3BNU1FwUlMwWlNlbW94TlhGQ2FYZHhXRFF3YzFvek1rRnFUVGM1UnpOM1pTczViM0ZMU0ZZMmJFWXpiVTh3TVd0SldqTnFiME53VEdkR2RHcFhhbGxHZG5vM0NuTjJMMmRxTm1sb1lqaFhZVUZGVGtkd2JEQldkMDUwYmpRMFNIQnhiVkJ1ZURCR2NEWmtOalZWYmtKQllraFdZbkZFYVV4WlJsbHROM1JsWW5OVGRHTUtMM05XVFdkSWNIbEdjbFoxVEZKNWMwTkVWeTl1VURGeFZuVm5UVlZwVGtreU5GTlJVbVYzVlV4WU5uTjNSRmxsVG01UmMzaERkM1paVEhBelJETkRZZ3BEU21ScGRFaFRSMFprY3pFMk56ZExOSEphZDJFd1FtdGFMMVF4Um1OeWREVXdURTk2TVRoVmQwUTJjVWRCS3pjM2FVbFhTR05NYlhsTFRqZzJTVVp4Q21wU1RVaHJUMGhXYURGek4wVnRSazVwYW5OV1FuYzVSa1ptY0ZrNVVXWmtORWhEWjJsa1FrUlBVMUo1T0ZaeVZqZGFURnBKUmsxd1RGQjFMMXBCZEdjS1VqQlRZbWg1VVdsYU1ISlNjRkZrVVRSQlVYUlJielo2ZVdGWk5qaFhTMnhDYVVGSlRDOVhOM3BNVEZkbVVYZ3lWMmd5YVhCdlUzRTNNemxZYUhjMWNncFVlbFkwVkhsUWFrOURRWFZOYVZoUVVVeHZRVTloTUZreVVFZE9ablZxVFVZd1N6UXhXa0oxTkRGeWJHeDBVVXRwVXpsUVJtTjVjRVZFVTI1blMzTktDaTlpUWtOVGJsbG1SMHhJUkRBeFdVeEVNbU00TTFKNFlYbEhXamQzYWxGaGRFbG1OVmRXU1hWdVNIRkhZa3A2Y0ZkQk56bHdiSEJRYVdkemR6RnhRVU1LZG5OV2VHbzJTMU53V0hrNE4zcEpkM01yUVRKbmJtNTFhQzlhYTBFeVNrczVhbmRqWm5SaVMwdHNhRGhLT0VvclZWSmxlR3MyVG5sSGMzVkxVeXRVY0Fvd2IzRlVjVXRpT1RoMlF6VlBkRlZEUVhkRlFVRmhUME5CV21kM1oyZEhWVTFCTkVkQk1WVmtSSGRGUWk5M1VVVkJkMGxJWjBSQlZFSm5UbFpJVTFWRkNrUkVRVXRDWjJkeVFtZEZSa0pSWTBSQmVrRmtRbWRPVmtoUk5FVkdaMUZWU3k5WlRuZDRhV2g2TDFabkt5dEhhbUpPV1habVFYWXZXaXRWZDBoM1dVUUtWbEl3YWtKQ1ozZEdiMEZWTXpsUWNIb3hXV3RGV21JMWNVNXFjRXRHVjJsNGFUUlpXa1E0ZDFKM1dVUldVakJTUVZGSUwwSkVNSGRQTkVVMVpGYzFNQXBqYmxaNlpFZFdhMHhZVG1oUlNFNXdXak5PTUdJelNteE1WMDUyWW0xYWRtTnRNV2hpYlU1c1RHMXNhR0pUTlc1ak1sWjVaRzFzYWxwWFJtcFpNamt4Q21KdVVYVlpNamwwVFVOclIwTnBjMGRCVVZGQ1p6YzRkMEZSUlVWSE1tZ3daRWhDZWs5cE9IWlpWMDVxWWpOV2RXUklUWFZhTWpsMldqSjRiRXh0VG5ZS1lsUkJja0puYjNKQ1owVkZRVmxQTDAxQlJVbENRakJOUnpKb01HUklRbnBQYVRoMldWZE9hbUl6Vm5Wa1NFMTFXakk1ZGxveWVHeE1iVTUyWWxSRFFncHBkMWxMUzNkWlFrSkJTRmRsVVVsRlFXZFNPVUpJYzBGbFVVSXpRVTR3T1UxSGNrZDRlRVY1V1hoclpVaEtiRzVPZDB0cFUydzJORE5xZVhRdk5HVkxDbU52UVhaTFpUWlBRVUZCUW01dFUzQTRaRzlCUVVGUlJFRkZaM2RTWjBsb1FVdzFOVGxZUmtOM1NGTjZWMmMwTjNWV2FVUmpkbUZDUVZGUFpHRlZRMkVLYldsa2VVUkJOMnAwYmk5MlFXbEZRVzl5YWxwMGFrUklhMnh0Tm5wVVVFeHRNQzlRWVZBMGVFMUljbTVFWkcxM09WaG5Ta1I2TUZaUFlrbDNRMmRaU1FwTGIxcEplbW93UlVGM1RVUmFaMEYzV1hkSmRtVlZaRE4yWlVKTk4zTjNjbVJhVjNadFdVMUNZV3BuVHpSdmNYUnpXR3B5Wkhad05VbFBLelExZWtsWUNrMXZlakJMTjBabk1GUm1iRVZ5VGtreU5IZERUVUZHVXpOcFNsaEVhbXN4VVRKeVUyNVhiVlJYZEdNMlZrVnlPVlpxVld4eE9GWmtTWEpNTTJwa05IVUtSbXR5TjBSVmRsQnphVEJXWlRCWFJUVktiSEY0WnowOUNpMHRMUzB0UlU1RUlFTkZVbFJKUmtsRFFWUkZMUzB0TFMwSyJ9fX19"
+ }],
+ "certificate": {
+ "rawBytes": "MIIEvDCCBESgAwIBAgIUKkhkEMPXTt9sobC/FRL7syVC+a0wCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTI2MTQyMTU5WhcNMjYwNTI2MTQzMTU5WjAAMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0lOkBegzIPk2xT06wQOQpgZuKx3lK8Djy9qgjoruIF7ycv8u/UN0g4NvsZXAsC6gMwUeHiop8kzYvJAA2w7LdsvtdjLIQKFRzj15qBiwqX40sZ32AjM79G3we+9oqKHV6lF3mO01kIZ3joCpLgFtjWjYFvz7sv/gj6ihb8WaAENGpl0VwNtn44HpqmPnx0Fp6d65UnBAbHVbqDiLYFYm7tebsStc/sVMgHpyFrVuLRysCDW/nP1qVugMUiNI24SQRewULX6swDYeNnQsxCwvYLp3D3CbCJditHSGFds1677K4rZwa0BkZ/T1Fcrt50LOz18UwD6qGA+77iIWHcLmyKN86IFqjRMHkOHVh1s7EmFNijsVBw9FFfpY9Qfd4HCgidBDOSRy8VrV7ZLZIFMpLPu/ZAtgR0SbhyQiZ0rRpQdQ4AQtQo6zyaY68WKlBiAIL/W7zLLWfQx2Wh2ipoSq739Xhw5rTzV4TyPjOCAuMiXPQLoAOa0Y2PGNfujMF0K41ZBu41rlltQKiS9PFcypEDSngKsJ/bBCSnYfGLHD01YLD2c83RxayGZ7wjQatIf5WVIunHqGbJzpWA79plpPigsw1qACvsVxj6KSpXy87zIws+A2gnnuh/ZkA2JK9jwcftbKKlh8J8J+URexk6NyGsuKS+Tp0oqTqKb98vC5OtUCAwEAAaOCAZgwggGUMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUK/YNwxihz/Vg++GjbNYvfAv/Z+UwHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wRwYDVR0RAQH/BD0wO4E5dW50cnVzdGVkLXNhQHNpZ3N0b3JlLWNvbmZvcm1hbmNlLmlhbS5nc2VydmljZWFjY291bnQuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTCBiwYKKwYBBAHWeQIEAgR9BHsAeQB3AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABnmSp8doAAAQDAEgwRgIhAL559XFCwHSzWg47uViDcvaBAQOdaUCamidyDA7jtn/vAiEAorjZtjDHklm6zTPLm0/PaP4xMHrnDdmw9XgJDz0VObIwCgYIKoZIzj0EAwMDZgAwYwIveUd3veBM7swrdZWvmYMBajgO4oqtsXjrdvp5IO+45zIXMoz0K7Fg0TflErNI24wCMAFS3iJXDjk1Q2rSnWmTWtc6VEr9VjUlq8VdIrL3jd4uFkr7DUvPsi0Ve0WE5Jlqxg=="
+ }
+ },
+ "messageSignature": {
+ "messageDigest": {
+ "algorithm": "SHA2_256",
+ "digest": "oM/HEnHW4njlfNMy/5V8P3BD/do1TEy7GQow1W76Ab8="
+ },
+ "signature": "Ze9Bso15cBTJIpRwe6T8hWkYKNNLsAYx9ggB68rfpd+kNOf+o/2uBRVtZj5eu+fmCVyKY1Jd/YAAQGmEqG47dN8HxSYJYilpKW2KNAEVMoYqDhwPeoORK1Svyqsaq021U6dYggCeUgdYBLvc8lPBm0ymQOZwfsy042TiChxmCFEoIM1b3HMCd6Y6s258xPnmCH0PuxfO/kfnho4G/00JijdRSIk0ZrFPeaEcbbUqA1dsNv3ejIB+Zlk76b63rE9v6y4aoY3MmQSUsH+XQsoyQVQiIYZkl0kfd4iFCSIVPbGsa3/bOl+68iaDKqJT/tQ1dUZ2rO0jQQ/Q77xHciZIaowugt2zTRAWXB23/vyxJBynJQpSpR/PWS0VQCBkOc9Uz1H4tHDoiltJVfHVP9lOU7TRaSkuv+CLQ18APX/djuM8TH6+YWN+y5BOs0Bd3cOdH1OBUigph2uew+2wW0cFSjGEs0iq/ur6RuPL1izqgkg6AJKy0An9RCW7jParvwmO10tQqMxldWZcL9TTxEbkFwU93BIMMmJZcNihWjwA/2eZOW7mUx6Cyw7Ao3lQ+nZs8skrI07ZKlKud7rbsLkv+S9DnaJTySZv2Dp66cYNW6Dcbn2Kmg19CfWdjNV1JeoKKJTN1KC5Ac4VEA769OQrkM+7c6EPHYPhwTULWA2OTTk="
+ }
+}
\ No newline at end of file
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.bad-entry-type.sigstore b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.bad-entry-type.sigstore
new file mode 100644
index 000000000..2b6b6d028
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.bad-entry-type.sigstore
@@ -0,0 +1 @@
+{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICyzCCAlKgAwIBAgIUMjDNrL/ZpriwSc+lM+0mnq5EFyIwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNzIzMTk1MDIyWhcNMjUwNzIzMjAwMDIyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEE9LbVCgJscxGQF0RtZZWmIbJvkMEKuqQqg1eQsJ/qQK1Nh2VMDjZqfWBoc1u1cBFeBpChVHY83edhztO8Jx52aOCAXEwggFtMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUJvm5ncCyW6avs3RqBIXXtrMRGEswHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwIQYDVR0RAQH/BBcwFYETYWFyb25sZXdAZ29vZ2xlLmNvbTApBgorBgEEAYO/MAEBBBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wKwYKKwYBBAGDvzABCAQdDBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wgYoGCisGAQQB1nkCBAIEfAR6AHgAdgArMLzcaIjJ4uHYJiledB9IOTGWAvKcM8teQ0D+sqyGegAAAZg41kFVAAAEAwBHMEUCIEENnFN8ER4UNtH/nSBTirhvUZr7ICsOIBBN9vYAjz4pAiEArtD1UwqX5s5GB2eEFj4K/01Eh2K0wzQIGDa2YeS+hTwwCgYIKoZIzj0EAwMDZwAwZAIwYPr0dXtDc1iEraYMm1FemlXVH2o84E6kz1/RgQ623kyMFQR0XxXWavwCB89k6oecAjAcMKRHly449ScmfECUwUQ+gLxaJkrj4tGkWKIoUJm1J4jyfN6+7GT5T4n1iJLDBVM="}, "tlogEntries": [{"logIndex": "6883", "logId": {"keyId": "8w1amZ2S5mJIQkQmPxdMuOrL/oJkvFg9MnQXmeOCXck="}, "kindVersion": {"kind": "dsse", "version": "0.0.2"}, "inclusionProof": {"logIndex": "6883", "rootHash": "3PBfVgP7khx41FlnyPpz8uHwHgOwAy9eUaEGoJEpWS4=", "treeSize": "6884", "hashes": ["vG3789z3en7YY3+8TOMH3EoNH0l3Z+nEafcCSQla9ac=", "pUx4FWhp5snrjfhiDBFRZn5Ib3Om9PmIJKR/X8FKt6o=", "rul+526SZeq9WeyupR6VYddH+cFHJnCpolYwl1Akbx4=", "/WSx54v3EqBwQlFEzk+ovLearmtjbNDfjNyHfAL0iHk=", "Ezo3FTVCd4Kzk1oPeT3rNLZhvRsGZN/66ONX81DrJ0M=", "tnv06iEfRP1UrMtn7D7v4lA+1VfpdI3ioGcQRJLMoP0=", "Ag03a73jphtOkMBVhp+MkrJwDkx2NE69NESHMFcwcfI=", "xbDsGnxf1siByWHEuiK85p0reQCaKKWUjf8YNl9s/Vo="], "checkpoint": {"envelope": "log2025-alpha1.rekor.sigstage.dev\n6884\n3PBfVgP7khx41FlnyPpz8uHwHgOwAy9eUaEGoJEpWS4=\n\n\u2014 log2025-alpha1.rekor.sigstage.dev 8w1amd9Jy5UcYJbfxsSogkHmrj1wbtv3g4IWtZ4rspPxgWyDUrbQI7W0T4gHrjLM5IUbkoTmKRQoZsXTgmMgZ8B8ywk=\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZHNzZVYwMDIiOnsicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiI5VmpkVnVPcGN5SEtnOFlsbWhuRjZXWXhrOHVvRXRSWHplS0FmcSt0WnIwPSJ9LCJzaWduYXR1cmVzIjpbeyJjb250ZW50IjoiTUVZQ0lRQ1psOS9laWVMOXdDUVhRY01uSmJYMis2cko5RTF0dm5EZTZPbkFwUFhLMGdJaEFKeUxiek1pZXFiY0o0VWZ6RkxKeG1GNUc3Y1FhRjhKTDZUZFFVd3JpdXY0IiwidmVyaWZpZXIiOnsia2V5RGV0YWlscyI6IlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwieDUwOUNlcnRpZmljYXRlIjp7InJhd0J5dGVzIjoiTUlJQ3l6Q0NBbEtnQXdJQkFnSVVNakROckwvWnByaXdTYytsTSswbW5xNUVGeUl3Q2dZSUtvWkl6ajBFQXdNd056RVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVI0d0hBWURWUVFERXhWemFXZHpkRzl5WlMxcGJuUmxjbTFsWkdsaGRHVXdIaGNOTWpVd056SXpNVGsxTURJeVdoY05NalV3TnpJek1qQXdNREl5V2pBQU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUU5TGJWQ2dKc2N4R1FGMFJ0WlpXbUliSnZrTUVLdXFRcWcxZVFzSi9xUUsxTmgyVk1EalpxZldCb2MxdTFjQkZlQnBDaFZIWTgzZWRoenRPOEp4NTJhT0NBWEV3Z2dGdE1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVKdm01bmNDeVc2YXZzM1JxQklYWHRyTVJHRXN3SHdZRFZSMGpCQmd3Rm9BVWNZWXdwaFI4WW0vNTk5YjBCUnAvWC8vcmI2d3dJUVlEVlIwUkFRSC9CQmN3RllFVFlXRnliMjVzWlhkQVoyOXZaMnhsTG1OdmJUQXBCZ29yQmdFRUFZTy9NQUVCQkJ0b2RIUndjem92TDJGalkyOTFiblJ6TG1kdmIyZHNaUzVqYjIwd0t3WUtLd1lCQkFHRHZ6QUJDQVFkREJ0b2RIUndjem92TDJGalkyOTFiblJ6TG1kdmIyZHNaUzVqYjIwd2dZb0dDaXNHQVFRQjFua0NCQUlFZkFSNkFIZ0FkZ0FyTUx6Y2FJako0dUhZSmlsZWRCOUlPVEdXQXZLY004dGVRMEQrc3F5R2VnQUFBWmc0MWtGVkFBQUVBd0JITUVVQ0lFRU5uRk44RVI0VU50SC9uU0JUaXJodlVacjdJQ3NPSUJCTjl2WUFqejRwQWlFQXJ0RDFVd3FYNXM1R0IyZUVGajRLLzAxRWgySzB3elFJR0RhMlllUytoVHd3Q2dZSUtvWkl6ajBFQXdNRFp3QXdaQUl3WVByMGRYdERjMWlFcmFZTW0xRmVtbFhWSDJvODRFNmt6MS9SZ1E2MjNreU1GUVIwWHhYV2F2d0NCODlrNm9lY0FqQWNNS1JIbHk0NDlTY21mRUNVd1VRK2dMeGFKa3JqNHRHa1dLSW9VSm0xSjRqeWZONis3R1Q1VDRuMWlKTERCVk09In19fV19fX0="}], "timestampVerificationData": {"rfc3161Timestamps": [{"signedTimestamp": "MIIE6TADAgEAMIIE4AYJKoZIhvcNAQcCoIIE0TCCBM0CAQMxDTALBglghkgBZQMEAgEwgcIGCyqGSIb3DQEJEAEEoIGyBIGvMIGsAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgGHLmT/+u6DojuoqF81X1QeqgdFuIF0j7UYmOrfaqgiUCFBGYrUgXErfzFv7+j+Caoe5Uagg4GA8yMDI1MDcyMzE5NTAyMlowAwIBAQIJAOa3xjMvK5GjoDKkMDAuMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxFTATBgNVBAMTDHNpZ3N0b3JlLXRzYaCCAhMwggIPMIIBlqADAgECAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkMB4XDTI1MDMyODA5MTQwNloXDTM1MDMyNjA4MTQwNlowLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATHW/kXcekP16Ae6SekEWVHPtAFEMm7hp5XO33MktFjSW+bHWUXtYEzZz0A3xkY9CyYOoeUk3ZH/v5HEuS+UvORzX0g7Hfy3uYYYRwHtqBQN0IX8rLdFMtIrRej/QCAdB2jajBoMA4GA1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQUqPxk9ijeLuY7c09UjFLE4ZzdU6UwHwYDVR0jBBgwFoAUOyBGWV61Mk1HMM5uY+5zdEfyBH0wFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDZwAwZAIwRK9VLoYa0Xff4nX1N/AQ1YleNG/iLT8dAXAtRKRfpN9XuDScbxWeo0cku8SkC06NAjBQPe7LBNeitA/UOBtXT2sX1h6f4ISqz+ISmJ4lY+y3bzRJI5nk1r53I9WT3/xIWToxggHbMIIB1wIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFAo1oQZh1eJBc8aJlqfyffJ+A3ynMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI1MDcyMzE5NTAyMlowLwYJKoZIhvcNAQkEMSIEIOM5iKgzY5WzDUaZZCfd+WqilYB3hPNR5dedubOhel9XMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCAG9P/gR/6zWZm3M7DXoyNQHPwY5MAzZqhF13U250snRDBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAgRnMGUCMQCpzZZXVqicWuWohrGEoJqnxlI56up1QspAzfNwVecr6Kb/WIJpc5thx2/YHlEJMcACMHTGqJy4jBbYWP+vxkzT7smvrTf93MSNvWVuvujkSr+rLau6cLYVjAzK4y6chE0LkA=="}]}}, "dsseEnvelope": {"payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYXJ0aWZhY3QudHh0IiwiZGlnZXN0Ijp7InNoYTI1NiI6ImEwY2ZjNzEyNzFkNmUyNzhlNTdjZDMzMmZmOTU3YzNmNzA0M2ZkZGEzNTRjNGNiYjE5MGEzMGQ1NmVmYTAxYmYifX1dLCJwcmVkaWNhdGVUeXBlIjoiaHR0cHM6Ly9zbHNhLmRldi9wcm92ZW5hbmNlL3YxIiwicHJlZGljYXRlIjp7ImJ1aWxkRGVmaW5pdGlvbiI6eyJidWlsZFR5cGUiOiJodHRwczovL2FjdGlvbnMuZ2l0aHViLmlvL2J1aWxkdHlwZXMvd29ya2Zsb3cvdjEiLCJleHRlcm5hbFBhcmFtZXRlcnMiOnsid29ya2Zsb3ciOnsicmVmIjoicmVmcy9oZWFkcy9tYWluIiwicmVwb3NpdG9yeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9sb29zZWJhem9va2EvYWEtdGVzdCIsInBhdGgiOiIuZ2l0aHViL3dvcmtmbG93cy9wcm92ZW5hbmNlLnlhbWwifX0sImludGVybmFsUGFyYW1ldGVycyI6eyJnaXRodWIiOnsiZXZlbnRfbmFtZSI6IndvcmtmbG93X2Rpc3BhdGNoIiwicmVwb3NpdG9yeV9pZCI6Ijg5MTcxNTQ0NCIsInJlcG9zaXRvcnlfb3duZXJfaWQiOiIxMzA0ODI2IiwicnVubmVyX2Vudmlyb25tZW50IjoiZ2l0aHViLWhvc3RlZCJ9fSwicmVzb2x2ZWREZXBlbmRlbmNpZXMiOlt7InVyaSI6ImdpdCtodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3RAcmVmcy9oZWFkcy9tYWluIiwiZGlnZXN0Ijp7ImdpdENvbW1pdCI6ImViZmY4ZGZiZDYwOWI3YjIyMjM3Yzc3MTljZTA3ZjJkYzc5MzRmNWYifX1dfSwicnVuRGV0YWlscyI6eyJidWlsZGVyIjp7ImlkIjoiaHR0cHM6Ly9naXRodWIuY29tL2xvb3NlYmF6b29rYS9hYS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3Byb3ZlbmFuY2UueWFtbEByZWZzL2hlYWRzL21haW4ifSwibWV0YWRhdGEiOnsiaW52b2NhdGlvbklkIjoiaHR0cHM6Ly9naXRodWIuY29tL2xvb3NlYmF6b29rYS9hYS10ZXN0L2FjdGlvbnMvcnVucy8xMTk0MTQyNTQ4Ny9hdHRlbXB0cy8xIn19fX0=", "payloadType": "application/vnd.in-toto+json", "signatures": [{"sig": "MEYCIQCZl9/eieL9wCQXQcMnJbX2+6rJ9E1tvnDe6OnApPXK0gIhAJyLbzMieqbcJ4UfzFLJxmF5G7cQaF8JL6TdQUwriuv4"}]}}
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.bad-signature.sigstore b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.bad-signature.sigstore
index 284fcd6b3..2c2b99ef6 100644
--- a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.bad-signature.sigstore
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.bad-signature.sigstore
@@ -1 +1,60 @@
-{"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"}]}}
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "certificate": {
+ "rawBytes": "MIIIPjCCB8OgAwIBAgIUeM3NlSziGqyL9eZI60oZxLb9zagwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTEzMTkyMzMyWhcNMjYwNTEzMTkzMzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1QyGuXvW6qw/A8ZGhPMkTgNtuI5KD78Melrj2MiRes4Q/35YI+tC14XKYjQDQDgIOVODYXt948sJw9zG7gXMkKOCBuIwggbeMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUMz1orfizj2bmeTSSIKuK9zh5iPcwHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwgaUGA1UdEQEB/wSBmjCBl4aBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAfBgorBgEEAYO/MAECBBF3b3JrZmxvd19kaXNwYXRjaDA2BgorBgEEAYO/MAEDBCg5NzdlOGQwODU1NGNhOWJkYTI3OWM5NmU5MWJlMjExOWZiNjdjNzMwMC0GCisGAQQBg78wAQQEH0V4dHJlbWVseSBkYW5nZXJvdXMgT0lEQyBiZWFjb24wSQYKKwYBBAGDvzABBQQ7c2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24wHQYKKwYBBAGDvzABBgQPcmVmcy9oZWFkcy9tYWluMDsGCisGAQQBg78wAQgELQwraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTCBpgYKKwYBBAGDvzABCQSBlwyBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABCgQqDCg5NzdlOGQwODU1NGNhOWJkYTI3OWM5NmU5MWJlMjExOWZiNjdjNzMwMB0GCisGAQQBg78wAQsEDwwNZ2l0aHViLWhvc3RlZDBeBgorBgEEAYO/MAEMBFAMTmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbjA4BgorBgEEAYO/MAENBCoMKDk3N2U4ZDA4NTU0Y2E5YmRhMjc5Yzk2ZTkxYmUyMTE5ZmI2N2M3MzAwHwYKKwYBBAGDvzABDgQRDA9yZWZzL2hlYWRzL21haW4wGQYKKwYBBAGDvzABDwQLDAk2MzI1OTY4OTcwNwYKKwYBBAGDvzABEAQpDCdodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UwGQYKKwYBBAGDvzABEQQLDAkxMzE4MDQ1NjMwgaYGCisGAQQBg78wARIEgZcMgZRodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24vLmdpdGh1Yi93b3JrZmxvd3MvZXh0cmVtZWx5LWRhbmdlcm91cy1vaWRjLWJlYWNvbi55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wARMEKgwoOTc3ZThkMDg1NTRjYTliZGEyNzljOTZlOTFiZTIxMTlmYjY3YzczMDAhBgorBgEEAYO/MAEUBBMMEXdvcmtmbG93X2Rpc3BhdGNoMIGCBgorBgEEAYO/MAEVBHQMcmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi9hY3Rpb25zL3J1bnMvMjU4MjEyODIwNTkvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzCBlQYKKwYBBAHWeQIEAgSBhgSBgwCBAH8APmBxU3RuGJLgkLI2sUl2Jy9ntE1vks5vdxFKtyKgprYAAAGeIstZkAAIAAAFAAAN3hQEAwBIMEYCIQC21zfS/kOLTPP8uvSrAJ286X4dw5beF3pgCtHp3FsvbAIhAMR7wwTWf9++dtLPpMlRmvzOC2gwgS4j9f7eRLw2txXMMAoGCCqGSM49BAMDA2kAMGYCMQDoTVmOTK23t5eE/1BMr7GPxiyvF3+D8XJ/Okx7TRHuizJjlNF5dNRWLXRkp9okFrcCMQDQppyt8F1tbFc8mQqirwA90eyEJfBVjG4D0loN6t7JwKrO+K/QuoE8B1mozTZixIc="
+ },
+ "tlogEntries": [
+ {
+ "logIndex": "4026478",
+ "logId": {
+ "keyId": "09OnDKEw7/hpZiYVPoTRzRbglHk0sylsUovegnRUlJY="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.2"
+ },
+ "inclusionProof": {
+ "logIndex": "4026478",
+ "rootHash": "5iaX4xK6PMnp4ZFTP4iywMcwLgaTjzgRTkrTOUFIrfY=",
+ "treeSize": "4026479",
+ "hashes": [
+ "y9eH/Cl/glEuLMKtwV0bgZ+a1P/AjoPyvu/iUeanaIM=",
+ "nrNQ2vb5JM2No6zELZt05onTYzqQOwDUcs24jAa6lzk=",
+ "HfZO2uZZbokwORUD/0dMRpBEouo33Ab2nQ2N6r4v688=",
+ "grMdYn8tE73JvJU8Ixk4hl8/fKu06hUdgpPNsuAfb7o=",
+ "i1gQ61xe3f9MP09y2e9Z4n5ZnDiFuqQmTK/u7Gji4Ws=",
+ "TkPA4Mv4plM3c6oejf5r+PqVxfMPk0x+QAjumzaswsU=",
+ "wGq46RfkA9tCYZ2CCOOMGQttyhHIqMksBAl+soDBgRw=",
+ "WPWftR+8Qjv3qiIBp48n3PiweejcpuHjokhaSIJaUOo=",
+ "kgGccNZjCDNKiQBUSPorZcTXoy9T0OIygUNX2V9tF7s=",
+ "7vMeapYqpjDZc8itt3uF6dGxL5qkbFsQ18jBiblH/5g=",
+ "ma8nVjhpJ0JmgSzaxhxP7bvHXtiZC6nJXIBmDV8kNAI=",
+ "CZJWJtYZFYWwC+DsEiCMnWled/ED66viI0Wz/L+9vxk=",
+ "Y8Q9QaTpqRAlSoWnNwyYGDerVLL1f6b8osmbDYEF6og="
+ ],
+ "checkpoint": {
+ "envelope": "log2025-alpha3.rekor.sigstage.dev\n4026479\n5iaX4xK6PMnp4ZFTP4iywMcwLgaTjzgRTkrTOUFIrfY=\n\n— log2025-alpha3.rekor.sigstage.dev 09OnDHwVrKeXjBYQ4NJ5EoENdtpBwZcV3X8n+cAZFIk+8LBPKEpZcKqoN2CfjGw0zlQwt+U2pLt5UyYEFv+STPHPmQg=\n— witness.stagemole.eu Z/euoAAAAABqBM+21mV7JbHwWmLP20ZSpNWneHMkITOPopt+Vj1MoJSILqOIPpx93pbRfA0U+Eq5IiJjEUhG1JwGhPCJEUT5yDcFDg==\n— staging.witness.transparency.goog/ring-any-bells LhqNyQAAAABqBM+2Ob9EtpF9h6IUMXc/LTRkkXiNAgbbohBxHekby1oASdDtPLkgZLmBHH73DF25f2L8xGgp/qVwoZK5thKXc6XnCw==\n— witness.navigli.sunlight.geomys.org o+AP4gAAAABqBM+2NoYlK4g3lkC5QltDB6f2F9U8yF6+8kXKjLKHAYvSDJ3u5dZufSU3bz+AtJMdOoMixoFJBkQ397WY/mE0i9tlCg==\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJoYXNoZWRSZWtvcmRWMDAyIjp7ImRhdGEiOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiJWL0lUWEZsTWY1Tmc1NXBVSXNLUitJZU5TdVhGT2J3RTNLUmRwajE4TGhFPSJ9LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNRUTExbnNvVGFPNTIvTUM0OGcwN21qQVRkeEQ4Nnl3ZHUzTnhKVWpIN3lBSWdXR2MrTVIzZUlBb1d1OEpFMVFNMllEc2xwb0ZBek1WV3BOMTE1ZkNLdXFnPSIsInZlcmlmaWVyIjp7ImtleURldGFpbHMiOiJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsIng1MDlDZXJ0aWZpY2F0ZSI6eyJyYXdCeXRlcyI6Ik1JSUlQakNDQjhPZ0F3SUJBZ0lVZU0zTmxTemlHcXlMOWVaSTYwb1p4TGI5emFnd0NnWUlLb1pJemowRUF3TXdOekVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SNHdIQVlEVlFRREV4VnphV2R6ZEc5eVpTMXBiblJsY20xbFpHbGhkR1V3SGhjTk1qWXdOVEV6TVRreU16TXlXaGNOTWpZd05URXpNVGt6TXpNeVdqQUFNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUxUXlHdVh2VzZxdy9BOFpHaFBNa1RnTnR1STVLRDc4TWVscmoyTWlSZXM0US8zNVlJK3RDMTRYS1lqUURRRGdJT1ZPRFlYdDk0OHNKdzl6RzdnWE1rS09DQnVJd2dnYmVNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBekFkQmdOVkhRNEVGZ1FVTXoxb3JmaXpqMmJtZVRTU0lLdUs5emg1aVBjd0h3WURWUjBqQkJnd0ZvQVVjWVl3cGhSOFltLzU5OWIwQlJwL1gvL3JiNnd3Z2FVR0ExVWRFUUVCL3dTQm1qQ0JsNGFCbEdoMGRIQnpPaTh2WjJsMGFIVmlMbU52YlM5emFXZHpkRzl5WlMxamIyNW1iM0p0WVc1alpTOWxlSFJ5WlcxbGJIa3RaR0Z1WjJWeWIzVnpMWEIxWW14cFl5MXZhV1JqTFdKbFlXTnZiaTh1WjJsMGFIVmlMM2R2Y210bWJHOTNjeTlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFc5cFpHTXRZbVZoWTI5dUxubHRiRUJ5WldaekwyaGxZV1J6TDIxaGFXNHdPUVlLS3dZQkJBR0R2ekFCQVFRcmFIUjBjSE02THk5MGIydGxiaTVoWTNScGIyNXpMbWRwZEdoMVluVnpaWEpqYjI1MFpXNTBMbU52YlRBZkJnb3JCZ0VFQVlPL01BRUNCQkYzYjNKclpteHZkMTlrYVhOd1lYUmphREEyQmdvckJnRUVBWU8vTUFFREJDZzVOemRsT0dRd09EVTFOR05oT1dKa1lUSTNPV001Tm1VNU1XSmxNakV4T1daaU5qZGpOek13TUMwR0Npc0dBUVFCZzc4d0FRUUVIMFY0ZEhKbGJXVnNlU0JrWVc1blpYSnZkWE1nVDBsRVF5QmlaV0ZqYjI0d1NRWUtLd1lCQkFHRHZ6QUJCUVE3YzJsbmMzUnZjbVV0WTI5dVptOXliV0Z1WTJVdlpYaDBjbVZ0Wld4NUxXUmhibWRsY205MWN5MXdkV0pzYVdNdGIybGtZeTFpWldGamIyNHdIUVlLS3dZQkJBR0R2ekFCQmdRUGNtVm1jeTlvWldGa2N5OXRZV2x1TURzR0Npc0dBUVFCZzc4d0FRZ0VMUXdyYUhSMGNITTZMeTkwYjJ0bGJpNWhZM1JwYjI1ekxtZHBkR2gxWW5WelpYSmpiMjUwWlc1MExtTnZiVENCcGdZS0t3WUJCQUdEdnpBQkNRU0Jsd3lCbEdoMGRIQnpPaTh2WjJsMGFIVmlMbU52YlM5emFXZHpkRzl5WlMxamIyNW1iM0p0WVc1alpTOWxlSFJ5WlcxbGJIa3RaR0Z1WjJWeWIzVnpMWEIxWW14cFl5MXZhV1JqTFdKbFlXTnZiaTh1WjJsMGFIVmlMM2R2Y210bWJHOTNjeTlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFc5cFpHTXRZbVZoWTI5dUxubHRiRUJ5WldaekwyaGxZV1J6TDIxaGFXNHdPQVlLS3dZQkJBR0R2ekFCQ2dRcURDZzVOemRsT0dRd09EVTFOR05oT1dKa1lUSTNPV001Tm1VNU1XSmxNakV4T1daaU5qZGpOek13TUIwR0Npc0dBUVFCZzc4d0FRc0VEd3dOWjJsMGFIVmlMV2h2YzNSbFpEQmVCZ29yQmdFRUFZTy9NQUVNQkZBTVRtaDBkSEJ6T2k4dloybDBhSFZpTG1OdmJTOXphV2R6ZEc5eVpTMWpiMjVtYjNKdFlXNWpaUzlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFhCMVlteHBZeTF2YVdSakxXSmxZV052YmpBNEJnb3JCZ0VFQVlPL01BRU5CQ29NS0RrM04yVTRaREE0TlRVMFkyRTVZbVJoTWpjNVl6azJaVGt4WW1VeU1URTVabUkyTjJNM016QXdId1lLS3dZQkJBR0R2ekFCRGdRUkRBOXlaV1p6TDJobFlXUnpMMjFoYVc0d0dRWUtLd1lCQkFHRHZ6QUJEd1FMREFrMk16STFPVFk0T1Rjd053WUtLd1lCQkFHRHZ6QUJFQVFwRENkb2RIUndjem92TDJkcGRHaDFZaTVqYjIwdmMybG5jM1J2Y21VdFkyOXVabTl5YldGdVkyVXdHUVlLS3dZQkJBR0R2ekFCRVFRTERBa3hNekU0TURRMU5qTXdnYVlHQ2lzR0FRUUJnNzh3QVJJRWdaY01nWlJvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2YzJsbmMzUnZjbVV0WTI5dVptOXliV0Z1WTJVdlpYaDBjbVZ0Wld4NUxXUmhibWRsY205MWN5MXdkV0pzYVdNdGIybGtZeTFpWldGamIyNHZMbWRwZEdoMVlpOTNiM0pyWm14dmQzTXZaWGgwY21WdFpXeDVMV1JoYm1kbGNtOTFjeTF2YVdSakxXSmxZV052Ymk1NWJXeEFjbVZtY3k5b1pXRmtjeTl0WVdsdU1EZ0dDaXNHQVFRQmc3OHdBUk1FS2d3b09UYzNaVGhrTURnMU5UUmpZVGxpWkdFeU56bGpPVFpsT1RGaVpUSXhNVGxtWWpZM1l6Y3pNREFoQmdvckJnRUVBWU8vTUFFVUJCTU1FWGR2Y210bWJHOTNYMlJwYzNCaGRHTm9NSUdDQmdvckJnRUVBWU8vTUFFVkJIUU1jbWgwZEhCek9pOHZaMmwwYUhWaUxtTnZiUzl6YVdkemRHOXlaUzFqYjI1bWIzSnRZVzVqWlM5bGVIUnlaVzFsYkhrdFpHRnVaMlZ5YjNWekxYQjFZbXhwWXkxdmFXUmpMV0psWVdOdmJpOWhZM1JwYjI1ekwzSjFibk12TWpVNE1qRXlPREl3TlRrdllYUjBaVzF3ZEhNdk1UQVdCZ29yQmdFRUFZTy9NQUVXQkFnTUJuQjFZbXhwWXpDQmxRWUtLd1lCQkFIV2VRSUVBZ1NCaGdTQmd3Q0JBSDhBUG1CeFUzUnVHSkxna0xJMnNVbDJKeTludEUxdmtzNXZkeEZLdHlLZ3ByWUFBQUdlSXN0WmtBQUlBQUFGQUFBTjNoUUVBd0JJTUVZQ0lRQzIxemZTL2tPTFRQUDh1dlNyQUoyODZYNGR3NWJlRjNwZ0N0SHAzRnN2YkFJaEFNUjd3d1RXZjkrK2R0TFBwTWxSbXZ6T0MyZ3dnUzRqOWY3ZVJMdzJ0eFhNTUFvR0NDcUdTTTQ5QkFNREEya0FNR1lDTVFEb1RWbU9USzIzdDVlRS8xQk1yN0dQeGl5dkYzK0Q4WEovT2t4N1RSSHVpekpqbE5GNWROUldMWFJrcDlva0ZyY0NNUURRcHB5dDhGMXRiRmM4bVFxaXJ3QTkwZXlFSmZCVmpHNEQwbG9ONnQ3SndLck8rSy9RdW9FOEIxbW96VFppeEljPSJ9fX19fX0="
+ }
+ ],
+ "timestampVerificationData": {
+ "rfc3161Timestamps": [
+ {
+ "signedTimestamp": "MIICyjADAgEAMIICwQYJKoZIhvcNAQcCoIICsjCCAq4CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgRXW8rbjklsWKDcJFbuknkfjvdFIBMi3ojw4H29CcgdkCFQDtkvBN6hnmJO23oMzmDmX9yOwfaxgPMjAyNjA1MTMxOTIzNDNaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHbMIIB1wIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFAo1oQZh1eJBc8aJlqfyffJ+A3ynMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDUxMzE5MjM0M1owLwYJKoZIhvcNAQkEMSIEIOjra37uRbFEfJnttmmwbM8Uh0T8xn+yfCHefVJZjyIAMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCAG9P/gR/6zWZm3M7DXoyNQHPwY5MAzZqhF13U250snRDBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAgRnMGUCMBxMhzj+c5RIcHrbXaop+KaE7U/YLqHZL8Qq7de9raDZ2nSFtMHgx48CiWomLoFJuQIxAN5vzm+NlmN2hYUPL6MT81bzmlfLWsG1NIcpqZ+KqXNhZD6ZV5cfT9wfUBmRf19zpQ=="
+ }
+ ]
+ }
+ },
+ "dsseEnvelope": {
+ "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS50eHQiLCJkaWdlc3QiOnsic2hhMjU2IjoiYTBjZmM3MTI3MWQ2ZTI3OGU1N2NkMzMyZmY5NTdjM2Y3MDQzZmRkYTM1NGM0Y2JiMTkwYTMwZDU2ZWZhMDFiZiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9yZWtvcjItZHNzZS1oYXNoZWRyZWtvcmQtcmVnZW4ifSwicnVuRGV0YWlscyI6eyJidWlsZGVyIjp7ImlkIjoiaHR0cHM6Ly9naXRodWIuY29tL3NpZ3N0b3JlLWNvbmZvcm1hbmNlL3Jla29yMi1kc3NlLWhhc2hlZHJla29yZC1yZWdlbiJ9fX19",
+ "payloadType": "application/vnd.in-toto+json",
+ "signatures": [
+ {
+ "sig": "MEYCIQC1Xqle9kbwDnYSMqcu9lmyN6zaEL2t8NusgbK/I8SoDgIhANBJ99vGP6KJ4zUBtGEFiw3E7a0AbX3okUKmLUkyKBpZ"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-envelope.sigstore b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-envelope.sigstore
new file mode 100644
index 000000000..b4f8ee611
--- /dev/null
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-envelope.sigstore
@@ -0,0 +1,60 @@
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "certificate": {
+ "rawBytes": "MIIIPjCCB8OgAwIBAgIUeM3NlSziGqyL9eZI60oZxLb9zagwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTEzMTkyMzMyWhcNMjYwNTEzMTkzMzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1QyGuXvW6qw/A8ZGhPMkTgNtuI5KD78Melrj2MiRes4Q/35YI+tC14XKYjQDQDgIOVODYXt948sJw9zG7gXMkKOCBuIwggbeMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUMz1orfizj2bmeTSSIKuK9zh5iPcwHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwgaUGA1UdEQEB/wSBmjCBl4aBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAfBgorBgEEAYO/MAECBBF3b3JrZmxvd19kaXNwYXRjaDA2BgorBgEEAYO/MAEDBCg5NzdlOGQwODU1NGNhOWJkYTI3OWM5NmU5MWJlMjExOWZiNjdjNzMwMC0GCisGAQQBg78wAQQEH0V4dHJlbWVseSBkYW5nZXJvdXMgT0lEQyBiZWFjb24wSQYKKwYBBAGDvzABBQQ7c2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24wHQYKKwYBBAGDvzABBgQPcmVmcy9oZWFkcy9tYWluMDsGCisGAQQBg78wAQgELQwraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTCBpgYKKwYBBAGDvzABCQSBlwyBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABCgQqDCg5NzdlOGQwODU1NGNhOWJkYTI3OWM5NmU5MWJlMjExOWZiNjdjNzMwMB0GCisGAQQBg78wAQsEDwwNZ2l0aHViLWhvc3RlZDBeBgorBgEEAYO/MAEMBFAMTmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbjA4BgorBgEEAYO/MAENBCoMKDk3N2U4ZDA4NTU0Y2E5YmRhMjc5Yzk2ZTkxYmUyMTE5ZmI2N2M3MzAwHwYKKwYBBAGDvzABDgQRDA9yZWZzL2hlYWRzL21haW4wGQYKKwYBBAGDvzABDwQLDAk2MzI1OTY4OTcwNwYKKwYBBAGDvzABEAQpDCdodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UwGQYKKwYBBAGDvzABEQQLDAkxMzE4MDQ1NjMwgaYGCisGAQQBg78wARIEgZcMgZRodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24vLmdpdGh1Yi93b3JrZmxvd3MvZXh0cmVtZWx5LWRhbmdlcm91cy1vaWRjLWJlYWNvbi55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wARMEKgwoOTc3ZThkMDg1NTRjYTliZGEyNzljOTZlOTFiZTIxMTlmYjY3YzczMDAhBgorBgEEAYO/MAEUBBMMEXdvcmtmbG93X2Rpc3BhdGNoMIGCBgorBgEEAYO/MAEVBHQMcmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi9hY3Rpb25zL3J1bnMvMjU4MjEyODIwNTkvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzCBlQYKKwYBBAHWeQIEAgSBhgSBgwCBAH8APmBxU3RuGJLgkLI2sUl2Jy9ntE1vks5vdxFKtyKgprYAAAGeIstZkAAIAAAFAAAN3hQEAwBIMEYCIQC21zfS/kOLTPP8uvSrAJ286X4dw5beF3pgCtHp3FsvbAIhAMR7wwTWf9++dtLPpMlRmvzOC2gwgS4j9f7eRLw2txXMMAoGCCqGSM49BAMDA2kAMGYCMQDoTVmOTK23t5eE/1BMr7GPxiyvF3+D8XJ/Okx7TRHuizJjlNF5dNRWLXRkp9okFrcCMQDQppyt8F1tbFc8mQqirwA90eyEJfBVjG4D0loN6t7JwKrO+K/QuoE8B1mozTZixIc="
+ },
+ "tlogEntries": [
+ {
+ "logIndex": "4026478",
+ "logId": {
+ "keyId": "09OnDKEw7/hpZiYVPoTRzRbglHk0sylsUovegnRUlJY="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.2"
+ },
+ "inclusionProof": {
+ "logIndex": "4026478",
+ "rootHash": "5iaX4xK6PMnp4ZFTP4iywMcwLgaTjzgRTkrTOUFIrfY=",
+ "treeSize": "4026479",
+ "hashes": [
+ "y9eH/Cl/glEuLMKtwV0bgZ+a1P/AjoPyvu/iUeanaIM=",
+ "nrNQ2vb5JM2No6zELZt05onTYzqQOwDUcs24jAa6lzk=",
+ "HfZO2uZZbokwORUD/0dMRpBEouo33Ab2nQ2N6r4v688=",
+ "grMdYn8tE73JvJU8Ixk4hl8/fKu06hUdgpPNsuAfb7o=",
+ "i1gQ61xe3f9MP09y2e9Z4n5ZnDiFuqQmTK/u7Gji4Ws=",
+ "TkPA4Mv4plM3c6oejf5r+PqVxfMPk0x+QAjumzaswsU=",
+ "wGq46RfkA9tCYZ2CCOOMGQttyhHIqMksBAl+soDBgRw=",
+ "WPWftR+8Qjv3qiIBp48n3PiweejcpuHjokhaSIJaUOo=",
+ "kgGccNZjCDNKiQBUSPorZcTXoy9T0OIygUNX2V9tF7s=",
+ "7vMeapYqpjDZc8itt3uF6dGxL5qkbFsQ18jBiblH/5g=",
+ "ma8nVjhpJ0JmgSzaxhxP7bvHXtiZC6nJXIBmDV8kNAI=",
+ "CZJWJtYZFYWwC+DsEiCMnWled/ED66viI0Wz/L+9vxk=",
+ "Y8Q9QaTpqRAlSoWnNwyYGDerVLL1f6b8osmbDYEF6og="
+ ],
+ "checkpoint": {
+ "envelope": "log2025-alpha3.rekor.sigstage.dev\n4026479\n5iaX4xK6PMnp4ZFTP4iywMcwLgaTjzgRTkrTOUFIrfY=\n\n— log2025-alpha3.rekor.sigstage.dev 09OnDHwVrKeXjBYQ4NJ5EoENdtpBwZcV3X8n+cAZFIk+8LBPKEpZcKqoN2CfjGw0zlQwt+U2pLt5UyYEFv+STPHPmQg=\n— witness.stagemole.eu Z/euoAAAAABqBM+21mV7JbHwWmLP20ZSpNWneHMkITOPopt+Vj1MoJSILqOIPpx93pbRfA0U+Eq5IiJjEUhG1JwGhPCJEUT5yDcFDg==\n— staging.witness.transparency.goog/ring-any-bells LhqNyQAAAABqBM+2Ob9EtpF9h6IUMXc/LTRkkXiNAgbbohBxHekby1oASdDtPLkgZLmBHH73DF25f2L8xGgp/qVwoZK5thKXc6XnCw==\n— witness.navigli.sunlight.geomys.org o+AP4gAAAABqBM+2NoYlK4g3lkC5QltDB6f2F9U8yF6+8kXKjLKHAYvSDJ3u5dZufSU3bz+AtJMdOoMixoFJBkQ397WY/mE0i9tlCg==\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJoYXNoZWRSZWtvcmRWMDAyIjp7ImRhdGEiOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiJWL0lUWEZsTWY1Tmc1NXBVSXNLUitJZU5TdVhGT2J3RTNLUmRwajE4TGhFPSJ9LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNRUTExbnNvVGFPNTIvTUM0OGcwN21qQVRkeEQ4Nnl3ZHUzTnhKVWpIN3lBSWdXR2MrTVIzZUlBb1d1OEpFMVFNMllEc2xwb0ZBek1WV3BOMTE1ZkNLdXFnPSIsInZlcmlmaWVyIjp7ImtleURldGFpbHMiOiJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsIng1MDlDZXJ0aWZpY2F0ZSI6eyJyYXdCeXRlcyI6Ik1JSUlQakNDQjhPZ0F3SUJBZ0lVZU0zTmxTemlHcXlMOWVaSTYwb1p4TGI5emFnd0NnWUlLb1pJemowRUF3TXdOekVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SNHdIQVlEVlFRREV4VnphV2R6ZEc5eVpTMXBiblJsY20xbFpHbGhkR1V3SGhjTk1qWXdOVEV6TVRreU16TXlXaGNOTWpZd05URXpNVGt6TXpNeVdqQUFNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUxUXlHdVh2VzZxdy9BOFpHaFBNa1RnTnR1STVLRDc4TWVscmoyTWlSZXM0US8zNVlJK3RDMTRYS1lqUURRRGdJT1ZPRFlYdDk0OHNKdzl6RzdnWE1rS09DQnVJd2dnYmVNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBekFkQmdOVkhRNEVGZ1FVTXoxb3JmaXpqMmJtZVRTU0lLdUs5emg1aVBjd0h3WURWUjBqQkJnd0ZvQVVjWVl3cGhSOFltLzU5OWIwQlJwL1gvL3JiNnd3Z2FVR0ExVWRFUUVCL3dTQm1qQ0JsNGFCbEdoMGRIQnpPaTh2WjJsMGFIVmlMbU52YlM5emFXZHpkRzl5WlMxamIyNW1iM0p0WVc1alpTOWxlSFJ5WlcxbGJIa3RaR0Z1WjJWeWIzVnpMWEIxWW14cFl5MXZhV1JqTFdKbFlXTnZiaTh1WjJsMGFIVmlMM2R2Y210bWJHOTNjeTlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFc5cFpHTXRZbVZoWTI5dUxubHRiRUJ5WldaekwyaGxZV1J6TDIxaGFXNHdPUVlLS3dZQkJBR0R2ekFCQVFRcmFIUjBjSE02THk5MGIydGxiaTVoWTNScGIyNXpMbWRwZEdoMVluVnpaWEpqYjI1MFpXNTBMbU52YlRBZkJnb3JCZ0VFQVlPL01BRUNCQkYzYjNKclpteHZkMTlrYVhOd1lYUmphREEyQmdvckJnRUVBWU8vTUFFREJDZzVOemRsT0dRd09EVTFOR05oT1dKa1lUSTNPV001Tm1VNU1XSmxNakV4T1daaU5qZGpOek13TUMwR0Npc0dBUVFCZzc4d0FRUUVIMFY0ZEhKbGJXVnNlU0JrWVc1blpYSnZkWE1nVDBsRVF5QmlaV0ZqYjI0d1NRWUtLd1lCQkFHRHZ6QUJCUVE3YzJsbmMzUnZjbVV0WTI5dVptOXliV0Z1WTJVdlpYaDBjbVZ0Wld4NUxXUmhibWRsY205MWN5MXdkV0pzYVdNdGIybGtZeTFpWldGamIyNHdIUVlLS3dZQkJBR0R2ekFCQmdRUGNtVm1jeTlvWldGa2N5OXRZV2x1TURzR0Npc0dBUVFCZzc4d0FRZ0VMUXdyYUhSMGNITTZMeTkwYjJ0bGJpNWhZM1JwYjI1ekxtZHBkR2gxWW5WelpYSmpiMjUwWlc1MExtTnZiVENCcGdZS0t3WUJCQUdEdnpBQkNRU0Jsd3lCbEdoMGRIQnpPaTh2WjJsMGFIVmlMbU52YlM5emFXZHpkRzl5WlMxamIyNW1iM0p0WVc1alpTOWxlSFJ5WlcxbGJIa3RaR0Z1WjJWeWIzVnpMWEIxWW14cFl5MXZhV1JqTFdKbFlXTnZiaTh1WjJsMGFIVmlMM2R2Y210bWJHOTNjeTlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFc5cFpHTXRZbVZoWTI5dUxubHRiRUJ5WldaekwyaGxZV1J6TDIxaGFXNHdPQVlLS3dZQkJBR0R2ekFCQ2dRcURDZzVOemRsT0dRd09EVTFOR05oT1dKa1lUSTNPV001Tm1VNU1XSmxNakV4T1daaU5qZGpOek13TUIwR0Npc0dBUVFCZzc4d0FRc0VEd3dOWjJsMGFIVmlMV2h2YzNSbFpEQmVCZ29yQmdFRUFZTy9NQUVNQkZBTVRtaDBkSEJ6T2k4dloybDBhSFZpTG1OdmJTOXphV2R6ZEc5eVpTMWpiMjVtYjNKdFlXNWpaUzlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFhCMVlteHBZeTF2YVdSakxXSmxZV052YmpBNEJnb3JCZ0VFQVlPL01BRU5CQ29NS0RrM04yVTRaREE0TlRVMFkyRTVZbVJoTWpjNVl6azJaVGt4WW1VeU1URTVabUkyTjJNM016QXdId1lLS3dZQkJBR0R2ekFCRGdRUkRBOXlaV1p6TDJobFlXUnpMMjFoYVc0d0dRWUtLd1lCQkFHRHZ6QUJEd1FMREFrMk16STFPVFk0T1Rjd053WUtLd1lCQkFHRHZ6QUJFQVFwRENkb2RIUndjem92TDJkcGRHaDFZaTVqYjIwdmMybG5jM1J2Y21VdFkyOXVabTl5YldGdVkyVXdHUVlLS3dZQkJBR0R2ekFCRVFRTERBa3hNekU0TURRMU5qTXdnYVlHQ2lzR0FRUUJnNzh3QVJJRWdaY01nWlJvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2YzJsbmMzUnZjbVV0WTI5dVptOXliV0Z1WTJVdlpYaDBjbVZ0Wld4NUxXUmhibWRsY205MWN5MXdkV0pzYVdNdGIybGtZeTFpWldGamIyNHZMbWRwZEdoMVlpOTNiM0pyWm14dmQzTXZaWGgwY21WdFpXeDVMV1JoYm1kbGNtOTFjeTF2YVdSakxXSmxZV052Ymk1NWJXeEFjbVZtY3k5b1pXRmtjeTl0WVdsdU1EZ0dDaXNHQVFRQmc3OHdBUk1FS2d3b09UYzNaVGhrTURnMU5UUmpZVGxpWkdFeU56bGpPVFpsT1RGaVpUSXhNVGxtWWpZM1l6Y3pNREFoQmdvckJnRUVBWU8vTUFFVUJCTU1FWGR2Y210bWJHOTNYMlJwYzNCaGRHTm9NSUdDQmdvckJnRUVBWU8vTUFFVkJIUU1jbWgwZEhCek9pOHZaMmwwYUhWaUxtTnZiUzl6YVdkemRHOXlaUzFqYjI1bWIzSnRZVzVqWlM5bGVIUnlaVzFsYkhrdFpHRnVaMlZ5YjNWekxYQjFZbXhwWXkxdmFXUmpMV0psWVdOdmJpOWhZM1JwYjI1ekwzSjFibk12TWpVNE1qRXlPREl3TlRrdllYUjBaVzF3ZEhNdk1UQVdCZ29yQmdFRUFZTy9NQUVXQkFnTUJuQjFZbXhwWXpDQmxRWUtLd1lCQkFIV2VRSUVBZ1NCaGdTQmd3Q0JBSDhBUG1CeFUzUnVHSkxna0xJMnNVbDJKeTludEUxdmtzNXZkeEZLdHlLZ3ByWUFBQUdlSXN0WmtBQUlBQUFGQUFBTjNoUUVBd0JJTUVZQ0lRQzIxemZTL2tPTFRQUDh1dlNyQUoyODZYNGR3NWJlRjNwZ0N0SHAzRnN2YkFJaEFNUjd3d1RXZjkrK2R0TFBwTWxSbXZ6T0MyZ3dnUzRqOWY3ZVJMdzJ0eFhNTUFvR0NDcUdTTTQ5QkFNREEya0FNR1lDTVFEb1RWbU9USzIzdDVlRS8xQk1yN0dQeGl5dkYzK0Q4WEovT2t4N1RSSHVpekpqbE5GNWROUldMWFJrcDlva0ZyY0NNUURRcHB5dDhGMXRiRmM4bVFxaXJ3QTkwZXlFSmZCVmpHNEQwbG9ONnQ3SndLck8rSy9RdW9FOEIxbW96VFppeEljPSJ9fX19fX0="
+ }
+ ],
+ "timestampVerificationData": {
+ "rfc3161Timestamps": [
+ {
+ "signedTimestamp": "MIICyTADAgEAMIICwAYJKoZIhvcNAQcCoIICsTCCAq0CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgazE7B5EcUMfVP4g7Py0R0KJ/cIqcv2ssos6rgpgS3icCFQDldn1hrfcIdQRDSGoP/Jyh3ZnBBRgPMjAyNjA1MTMxOTIzMzhaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHaMIIB1gIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFAo1oQZh1eJBc8aJlqfyffJ+A3ynMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDUxMzE5MjMzOFowLwYJKoZIhvcNAQkEMSIEIN8PIhiZjXlEP6q7W/1AbeAoVV4jl2k3w2EKbWFmV1HNMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCAG9P/gR/6zWZm3M7DXoyNQHPwY5MAzZqhF13U250snRDBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAgRmMGQCMGdHU26L2sHhFr0usPG/nKSi1e4y8n7qDO+ArBAXZde3MxTv4DdqzmpFTwRHBaM9/wIwM3LCOaWjFkycUkGCxdrjl5qJAYSR31fWv2kiZnKJJ2Dy1p4SY2M5UGUeQ1K8jaay"
+ }
+ ]
+ }
+ },
+ "dsseEnvelope": {
+ "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS50eHQiLCJkaWdlc3QiOnsic2hhMjU2IjoiYTBjZmM3MTI3MWQ2ZTI3OGU1N2NkMzMyZmY5NTdjM2Y3MDQzZmRkYTM1NGM0Y2JiMTkwYTMwZDU2ZWZhMDFiZiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9yZWtvcjItZHNzZS1oYXNoZWRyZWtvcmQtcmVnZW4tQiJ9LCJydW5EZXRhaWxzIjp7ImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UvcmVrb3IyLWRzc2UtaGFzaGVkcmVrb3JkLXJlZ2VuIn19fX0=",
+ "payloadType": "application/vnd.in-toto+json",
+ "signatures": [
+ {
+ "sig": "MEUCIDwMaP7ZdDdswggkkaJPJpaBqURbByINZX6rYpHNXcWcAiEA/LkKHLTdb2ZUgL4S2mE9+kP7MO63YRNgqBgQXrk3N1s="
+ }
+ ]
+ }
+}
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-payload.sigstore b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-payload.sigstore
deleted file mode 100644
index e3a9cd6a8..000000000
--- a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-payload.sigstore
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
- "verificationMaterial": {
- "tlogEntries": [{
- "logIndex": "6844",
- "logId": {
- "keyId": "8w1amZ2S5mJIQkQmPxdMuOrL/oJkvFg9MnQXmeOCXck="
- },
- "kindVersion": {
- "kind": "dsse",
- "version": "0.0.2"
- },
- "inclusionProof": {
- "logIndex": "6844",
- "rootHash": "02OB8dyqde5plQxRi5YRH9W0oGck5q7ARK2iN5SXrGU=",
- "treeSize": "6845",
- "hashes": ["kBUUZhLrBMTZCfNozIBd2DA+9CnTkE9PBRP0Ld9nDFA=", "D2vBCcgnwglrjVnkLUM8/t1kqEGubtgUU97+EVQUZ28=", "nMiUUOA/Lv/1lgcBYft53KwJdHo/MR2p+M3DSRWr/cY=", "ihByrS/Xgl0QEHjv6rp/AxV6uk+E7c9ncM04J7zbqbU=", "Ezo3FTVCd4Kzk1oPeT3rNLZhvRsGZN/66ONX81DrJ0M=", "tnv06iEfRP1UrMtn7D7v4lA+1VfpdI3ioGcQRJLMoP0=", "Ag03a73jphtOkMBVhp+MkrJwDkx2NE69NESHMFcwcfI=", "xbDsGnxf1siByWHEuiK85p0reQCaKKWUjf8YNl9s/Vo="],
- "checkpoint": {
- "envelope": "log2025-alpha1.rekor.sigstage.dev\n6845\n02OB8dyqde5plQxRi5YRH9W0oGck5q7ARK2iN5SXrGU\u003d\n\n— log2025-alpha1.rekor.sigstage.dev 8w1amY7vnN7S7KnCOLVV5AJvz1iL+GjoOCh3Gd+CfJbsof5wp+REsZBBygM01BEtvCWLN/HXaWrFAfHCodvFdrIVHA8\u003d\n"
- }
- },
- "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZHNzZVYwMDIiOnsicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiIxcklKdXAzZU94N2w3ZXU0alJzYmtYdHk3cllVTW81N3BtZjF0NnR3NlljPSJ9LCJzaWduYXR1cmVzIjpbeyJjb250ZW50IjoiTUVZQ0lRQ0dSYU9OV3FsNlFyUWgvTGVjS3Q0TE5tRVdVc3huWmU2RXprVEthTVRmUVFJaEFOZDk2SWw3S1RFTkFFMHFITSsxK3hvamZaSmY4Z3hoWFFPcHhleGNYY0huIiwidmVyaWZpZXIiOnsia2V5RGV0YWlscyI6IlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwieDUwOUNlcnRpZmljYXRlIjp7InJhd0J5dGVzIjoiTUlJQ3lEQ0NBazZnQXdJQkFnSVVhc0FseW53bmc2aktPelFUVEU1b1J0QzhnQ2t3Q2dZSUtvWkl6ajBFQXdNd056RVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVI0d0hBWURWUVFERXhWemFXZHpkRzl5WlMxcGJuUmxjbTFsWkdsaGRHVXdIaGNOTWpVd056SXpNVGcxTnpNNFdoY05NalV3TnpJek1Ua3dOek00V2pBQU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVpwaDM3TmR0c3p0cHcwK2tCWUJnVXZhbkFZalUvem5wREM4ZHpQV2h4WTR5emthbXFRUjlSWGR5TVZOV2JtZktMMHBuTHNzM244K09URWxrYTFJUk02T0NBVzB3Z2dGcE1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVPLzdsWEg5MWhEcnNtUnFLVG1nSUlXVWRiU013SHdZRFZSMGpCQmd3Rm9BVWNZWXdwaFI4WW0vNTk5YjBCUnAvWC8vcmI2d3dIUVlEVlIwUkFRSC9CQk13RVlFUFlYQndkVUJuYjI5bmJHVXVZMjl0TUNrR0Npc0dBUVFCZzc4d0FRRUVHMmgwZEhCek9pOHZZV05qYjNWdWRITXVaMjl2WjJ4bExtTnZiVEFyQmdvckJnRUVBWU8vTUFFSUJCME1HMmgwZEhCek9pOHZZV05qYjNWdWRITXVaMjl2WjJ4bExtTnZiVENCaWdZS0t3WUJCQUhXZVFJRUFnUjhCSG9BZUFCMkFDc3d2TnhvaU1uaTRkZ21LVjUwSDBnNU1aWUM4cHd6eTE1RFFQNnlySVo2QUFBQm1EaWwrdElBQUFRREFFY3dSUUloQU12a3NTejFlTHFjNktWSGFUVTkyR2l2ZzU2NnNBMUdUZ0ZmdGVNNmtXcmhBaUJUWHhLOUQyTStjam45VlI0V2hvQlBMa3N4MmRYZTFaMGRFMkhnTnBSUkVUQUtCZ2dxaGtqT1BRUURBd05vQURCbEFqQjVtNlgwT1k2TVRBdjhYaWVWaXdRZENKWXdqZ1VmQmtvWk9aL0NNdisvL1BKamw3UlRSZDh5a3NyVUNDMEFHNEFDTVFDalE3WWF5TzlGVXdXOStvTFNHS0s2OXRHZFZabjNaMFBuUllqdDlwRDgvRWFEY2RKZm9iU0ZOVlNiQXUyRVQ5UT0ifX19XX19fQ=="
- }],
- "timestampVerificationData": {
- "rfc3161Timestamps": [{
- "signedTimestamp": "MIIC0zADAgEAMIICygYJKoZIhvcNAQcCoIICuzCCArcCAQMxDTALBglghkgBZQMEAgEwgcEGCyqGSIb3DQEJEAEEoIGxBIGuMIGrAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgLoG+mJBA8vAFUybo77C/c7vI/tcNIa2/n0mHtZwvrHkCFC90Y/kHxo5PJlnJITAPKPt3idPVGA8yMDI1MDcyMzE4NTczOFowAwIBAQIIcRfeeghrEbKgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHbMIIB1wIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFAo1oQZh1eJBc8aJlqfyffJ+A3ynMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI1MDcyMzE4NTczOFowLwYJKoZIhvcNAQkEMSIEIBLMMNhxlXRVMZtKNbfWDXQW4niE731b9NjYfFVUD9/8MIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCAG9P/gR/6zWZm3M7DXoyNQHPwY5MAzZqhF13U250snRDBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAgRnMGUCMBT7UThGRiJKbEvz3MPs3/Gmn9vN+liXlIO2KmzW5zF8QXeze1fyD5kP5+Pwnlf1pgIxAL/qP5C6GKGlPT2ako7yY7kgpEWa8HiL+Q39u8W2vgS3tDSlLrntEzQGU0s0NmJ/zw=="
- }]
- },
- "certificate": {
- "rawBytes": "MIICyDCCAk6gAwIBAgIUasAlynwng6jKOzQTTE5oRtC8gCkwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNzIzMTg1NzM4WhcNMjUwNzIzMTkwNzM4WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZph37Ndtsztpw0+kBYBgUvanAYjU/znpDC8dzPWhxY4yzkamqQR9RXdyMVNWbmfKL0pnLss3n8+OTElka1IRM6OCAW0wggFpMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUO/7lXH91hDrsmRqKTmgIIWUdbSMwHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwHQYDVR0RAQH/BBMwEYEPYXBwdUBnb29nbGUuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTCBigYKKwYBBAHWeQIEAgR8BHoAeAB2ACswvNxoiMni4dgmKV50H0g5MZYC8pwzy15DQP6yrIZ6AAABmDil+tIAAAQDAEcwRQIhAMvksSz1eLqc6KVHaTU92Givg566sA1GTgFfteM6kWrhAiBTXxK9D2M+cjn9VR4WhoBPLksx2dXe1Z0dE2HgNpRRETAKBggqhkjOPQQDAwNoADBlAjB5m6X0OY6MTAv8XieViwQdCJYwjgUfBkoZOZ/CMv+//PJjl7RTRd8yksrUCC0AG4ACMQCjQ7YayO9FUwW9+oLSGKK69tGdVZn3Z0PnRYjt9pD8/EaDcdJfobSFNVSbAu2ET9Q="
- }
- },
- "dsseEnvelope": {
- "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS50eHQiLCJkaWdlc3QiOnsic2hhMjU2IjoiYTBjZmM3MTI3MWQ2ZTI3OGU1N2NkMzMyZmY5NTdjM2Y3MDQzZmRkYTM1NGM0Y2JiMTkwYTMwZDU2ZWZhMDFiZiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vYWN0aW9ucy5naXRodWIuaW8vYnVpbGR0eXBlcy93b3JrZmxvdy92MSIsImV4dGVybmFsUGFyYW1ldGVycyI6eyJ3b3JrZmxvdyI6eyJyZWYiOiJyZWZzL2hlYWRzL21haW4iLCJyZXBvc2l0b3J5IjoiaHR0cHM6Ly9naXRodWIuY29tL21vb3NlL2FhLXRlc3QiLCJwYXRoIjoiLmdpdGh1Yi93b3JrZmxvd3MvcHJvdmVuYW5jZS55YW1sIn19LCJpbnRlcm5hbFBhcmFtZXRlcnMiOnsiZ2l0aHViIjp7ImV2ZW50X25hbWUiOiJ3b3JrZmxvd19kaXNwYXRjaCIsInJlcG9zaXRvcnlfaWQiOiI4OTE3MTU0NDQiLCJyZXBvc2l0b3J5X293bmVyX2lkIjoiMTMwNDgyNiIsInJ1bm5lcl9lbnZpcm9ubWVudCI6ImdpdGh1Yi1ob3N0ZWQifX0sInJlc29sdmVkRGVwZW5kZW5jaWVzIjpbeyJ1cmkiOiJnaXQraHR0cHM6Ly9naXRodWIuY29tL21vb3NlL2FhLXRlc3RAcmVmcy9oZWFkcy9tYWluIiwiZGlnZXN0Ijp7ImdpdENvbW1pdCI6ImViZmY4ZGZiZDYwOWI3YjIyMjM3Yzc3MTljZTA3ZjJkYzc5MzRmNWYifX1dfSwicnVuRGV0YWlscyI6eyJidWlsZGVyIjp7ImlkIjoiaHR0cHM6Ly9naXRodWIuY29tL21vb3NlL2FhLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcHJvdmVuYW5jZS55YW1sQHJlZnMvaGVhZHMvbWFpbiJ9LCJtZXRhZGF0YSI6eyJpbnZvY2F0aW9uSWQiOiJodHRwczovL2dpdGh1Yi5jb20vbW9vc2UvYWEtdGVzdC9hY3Rpb25zL3J1bnMvMTE5NDE0MjU0ODcvYXR0ZW1wdHMvMSJ9fX19Cg==",
- "payloadType": "application/vnd.in-toto+json",
- "signatures": [{
- "sig": "MEUCIAClWd1w/CSq1ztmu0LCVMaymV1udltXXIHn27xGsWj1AiEAuz0pr2mhAyrDyzojHwOfHtR2n95zhHFlxgUv3fQ2MMs="
- }]
- }
-}
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-signature.sigstore b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-signature.sigstore
index d60c16a07..12295d512 100644
--- a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-signature.sigstore
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.mismatched-signature.sigstore
@@ -1,40 +1,60 @@
{
"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
"verificationMaterial": {
- "tlogEntries": [{
- "logIndex": "6610",
- "logId": {
- "keyId": "8w1amZ2S5mJIQkQmPxdMuOrL/oJkvFg9MnQXmeOCXck="
- },
- "kindVersion": {
- "kind": "dsse",
- "version": "0.0.2"
- },
- "inclusionProof": {
- "logIndex": "6610",
- "rootHash": "oAIwoOiwvcPNs87ZrwYZnoe2nFt4Cei0eyCdvMDyPTI=",
- "treeSize": "6611",
- "hashes": ["OvbsUnEZXSqqN0viZZwzQIFZZOaez8S/y4s728HMtYE=", "BJfz0qlmgfv4T3PWEdaQDsRGoofPEgoCXCmmLPLaIsY=", "A+VlB+XR92aS2txcqdoEfCb3QqZ89UHRDE87bcK7JiU=", "HhgSw1jzUj25LbExsCl8FbDRO6eJnxb9iGu259pM3ms=", "gpAC2IEHOQH0Mluo3QTOJzs2KTswWJ+2JiODSInqpyg=", "Ag03a73jphtOkMBVhp+MkrJwDkx2NE69NESHMFcwcfI=", "xbDsGnxf1siByWHEuiK85p0reQCaKKWUjf8YNl9s/Vo="],
- "checkpoint": {
- "envelope": "log2025-alpha1.rekor.sigstage.dev\n6611\noAIwoOiwvcPNs87ZrwYZnoe2nFt4Cei0eyCdvMDyPTI\u003d\n\n— log2025-alpha1.rekor.sigstage.dev 8w1amVKLn3ccD2kYYAyungw1LTii2Cj0aEjUM5XME1qwBLgT46SMOQgbcUcPNjgrrjgKNdYUHnw7gHCok2+vkx0+Xgw\u003d\n"
- }
- },
- "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZHNzZVYwMDIiOnsicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiIxcklKdXAzZU94N2w3ZXU0alJzYmtYdHk3cllVTW81N3BtZjF0NnR3NlljPSJ9LCJzaWduYXR1cmVzIjpbeyJjb250ZW50IjoiTUVVQ0lRQ1FkNUdwVkNlZGdld3BjMkpEakdmV2pIYmYycDl4dEEzRWlvWWIvQTVvWHdJZ0RiazdCN3Z0YkNucDl2MStiL3JxeTdhb3NVYXUxODJZZzBlUHJOUG1oRnc9IiwidmVyaWZpZXIiOnsia2V5RGV0YWlscyI6IlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwieDUwOUNlcnRpZmljYXRlIjp7InJhd0J5dGVzIjoiTUlJQ3h6Q0NBa3lnQXdJQkFnSVVYSXQ1RjNJUlRKYXdaQThJaW02am5PWXBtRmd3Q2dZSUtvWkl6ajBFQXdNd056RVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVI0d0hBWURWUVFERXhWemFXZHpkRzl5WlMxcGJuUmxjbTFsWkdsaGRHVXdIaGNOTWpVd056SXpNREUxTmpNM1doY05NalV3TnpJek1ESXdOak0zV2pBQU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXo4WWFwb0FOQmRWUGFaeHBzMUVaS1d4RFVnL2dST1F4RDBtVlcxUU9iVTJKVEU3N1JvWDR3U2pIRnE3aDBXUDFDYUd4YktCS0NaUXFjTVlDd0xTc1pxT0NBV3N3Z2dGbk1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVV0UkFIS1Znak9vV3k3UVNBeHJQZFRFQUF2MEl3SHdZRFZSMGpCQmd3Rm9BVWNZWXdwaFI4WW0vNTk5YjBCUnAvWC8vcmI2d3dIUVlEVlIwUkFRSC9CQk13RVlFUFlYQndkVUJuYjI5bmJHVXVZMjl0TUNrR0Npc0dBUVFCZzc4d0FRRUVHMmgwZEhCek9pOHZZV05qYjNWdWRITXVaMjl2WjJ4bExtTnZiVEFyQmdvckJnRUVBWU8vTUFFSUJCME1HMmgwZEhCek9pOHZZV05qYjNWdWRITXVaMjl2WjJ4bExtTnZiVENCaUFZS0t3WUJCQUhXZVFJRUFnUjZCSGdBZGdCMEFDc3d2TnhvaU1uaTRkZ21LVjUwSDBnNU1aWUM4cHd6eTE1RFFQNnlySVo2QUFBQm1EVC9PSDRBQUFRREFFVXdRd0lnWFVzcnJNL05qU2pkOG1pYU5hQmUyeFkweGo2MFBtN1BWQmZPck5COCtUUUNIMWJ1WFBVNnpvWlhieFJFNXcyemZwbWhvK0Y3WjVnQnVxZkt4dUhMc1hrd0NnWUlLb1pJemowRUF3TURhUUF3WmdJeEFJajZiOCswdzQ0b1B2ZmhxUUlQT3p2UWxKWTRBUGt4MlJlNUkzYmxyRFhIMUVzTVA2L0E1dkZueTh6dW1pd2o1Z0l4QUxvU1M4L2tPbXd3cnpINUllZktZd3VNUkNQSkhrajF1QUg3aERxaE4yaTFXSzZUM2NUYWxYaEhDR1dvRXl2NjB3PT0ifX19XX19fQ=="
- }],
- "timestampVerificationData": {
- "rfc3161Timestamps": [{
- "signedTimestamp": "MIIC0zADAgEAMIICygYJKoZIhvcNAQcCoIICuzCCArcCAQMxDTALBglghkgBZQMEAgEwgcIGCyqGSIb3DQEJEAEEoIGyBIGvMIGsAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgoH07w11OUpHxP7JvbvGdbbHVUZOs6Io72DvhZwPiqkUCFEIVSsJGdW4IRQl/Gfuzm+xlPZ32GA8yMDI1MDcyMzAxNTYzOFowAwIBAQIJALUNS91gOUJyoDKkMDAuMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxFTATBgNVBAMTDHNpZ3N0b3JlLXRzYaAAMYIB2jCCAdYCAQEwUTA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzALBglghkgBZQMEAgGggfwwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNTA3MjMwMTU2MzhaMC8GCSqGSIb3DQEJBDEiBCA9rWes2hX785eWIhdYgCs/c9RM9m6wVfVQRNzZzvhcrzCBjgYLKoZIhvcNAQkQAi8xfzB9MHsweQQgBvT/4Ef+s1mZtzOw16MjUBz8GOTAM2aoRdd1NudLJ0QwVTA9pDswOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUCjWhBmHV4kFzxomWp/J98n4DfKcwCgYIKoZIzj0EAwIEZjBkAjB4LnECzOgwVRxF1ne0ZzwZF2hatQkQrzBOjQvZmo5z+urmpG0MR+3idz/EfgDlNUkCMHD0igjYHO4T5XcVoyiIYd9Frkpl1hZfUX7QgQb0WyJLxQcZFgV8r+46bdTowCRb8A=="
- }]
- },
"certificate": {
- "rawBytes": "MIICxzCCAkygAwIBAgIUXIt5F3IRTJawZA8Iim6jnOYpmFgwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNzIzMDE1NjM3WhcNMjUwNzIzMDIwNjM3WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEz8YapoANBdVPaZxps1EZKWxDUg/gROQxD0mVW1QObU2JTE77RoX4wSjHFq7h0WP1CaGxbKBKCZQqcMYCwLSsZqOCAWswggFnMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUtRAHKVgjOoWy7QSAxrPdTEAAv0IwHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwHQYDVR0RAQH/BBMwEYEPYXBwdUBnb29nbGUuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTCBiAYKKwYBBAHWeQIEAgR6BHgAdgB0ACswvNxoiMni4dgmKV50H0g5MZYC8pwzy15DQP6yrIZ6AAABmDT/OH4AAAQDAEUwQwIgXUsrrM/NjSjd8miaNaBe2xY0xj60Pm7PVBfOrNB8+TQCH1buXPU6zoZXbxRE5w2zfpmho+F7Z5gBuqfKxuHLsXkwCgYIKoZIzj0EAwMDaQAwZgIxAIj6b8+0w44oPvfhqQIPOzvQlJY4APkx2Re5I3blrDXH1EsMP6/A5vFny8zumiwj5gIxALoSS8/kOmwwrzH5IefKYwuMRCPJHkj1uAH7hDqhN2i1WK6T3cTalXhHCGWoEyv60w=="
+ "rawBytes": "MIIIPjCCB8OgAwIBAgIUeM3NlSziGqyL9eZI60oZxLb9zagwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNTEzMTkyMzMyWhcNMjYwNTEzMTkzMzMyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1QyGuXvW6qw/A8ZGhPMkTgNtuI5KD78Melrj2MiRes4Q/35YI+tC14XKYjQDQDgIOVODYXt948sJw9zG7gXMkKOCBuIwggbeMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUMz1orfizj2bmeTSSIKuK9zh5iPcwHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwgaUGA1UdEQEB/wSBmjCBl4aBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOQYKKwYBBAGDvzABAQQraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTAfBgorBgEEAYO/MAECBBF3b3JrZmxvd19kaXNwYXRjaDA2BgorBgEEAYO/MAEDBCg5NzdlOGQwODU1NGNhOWJkYTI3OWM5NmU5MWJlMjExOWZiNjdjNzMwMC0GCisGAQQBg78wAQQEH0V4dHJlbWVseSBkYW5nZXJvdXMgT0lEQyBiZWFjb24wSQYKKwYBBAGDvzABBQQ7c2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24wHQYKKwYBBAGDvzABBgQPcmVmcy9oZWFkcy9tYWluMDsGCisGAQQBg78wAQgELQwraHR0cHM6Ly90b2tlbi5hY3Rpb25zLmdpdGh1YnVzZXJjb250ZW50LmNvbTCBpgYKKwYBBAGDvzABCQSBlwyBlGh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi8uZ2l0aHViL3dvcmtmbG93cy9leHRyZW1lbHktZGFuZ2Vyb3VzLW9pZGMtYmVhY29uLnltbEByZWZzL2hlYWRzL21haW4wOAYKKwYBBAGDvzABCgQqDCg5NzdlOGQwODU1NGNhOWJkYTI3OWM5NmU5MWJlMjExOWZiNjdjNzMwMB0GCisGAQQBg78wAQsEDwwNZ2l0aHViLWhvc3RlZDBeBgorBgEEAYO/MAEMBFAMTmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbjA4BgorBgEEAYO/MAENBCoMKDk3N2U4ZDA4NTU0Y2E5YmRhMjc5Yzk2ZTkxYmUyMTE5ZmI2N2M3MzAwHwYKKwYBBAGDvzABDgQRDA9yZWZzL2hlYWRzL21haW4wGQYKKwYBBAGDvzABDwQLDAk2MzI1OTY4OTcwNwYKKwYBBAGDvzABEAQpDCdodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UwGQYKKwYBBAGDvzABEQQLDAkxMzE4MDQ1NjMwgaYGCisGAQQBg78wARIEgZcMgZRodHRwczovL2dpdGh1Yi5jb20vc2lnc3RvcmUtY29uZm9ybWFuY2UvZXh0cmVtZWx5LWRhbmdlcm91cy1wdWJsaWMtb2lkYy1iZWFjb24vLmdpdGh1Yi93b3JrZmxvd3MvZXh0cmVtZWx5LWRhbmdlcm91cy1vaWRjLWJlYWNvbi55bWxAcmVmcy9oZWFkcy9tYWluMDgGCisGAQQBg78wARMEKgwoOTc3ZThkMDg1NTRjYTliZGEyNzljOTZlOTFiZTIxMTlmYjY3YzczMDAhBgorBgEEAYO/MAEUBBMMEXdvcmtmbG93X2Rpc3BhdGNoMIGCBgorBgEEAYO/MAEVBHQMcmh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9leHRyZW1lbHktZGFuZ2Vyb3VzLXB1YmxpYy1vaWRjLWJlYWNvbi9hY3Rpb25zL3J1bnMvMjU4MjEyODIwNTkvYXR0ZW1wdHMvMTAWBgorBgEEAYO/MAEWBAgMBnB1YmxpYzCBlQYKKwYBBAHWeQIEAgSBhgSBgwCBAH8APmBxU3RuGJLgkLI2sUl2Jy9ntE1vks5vdxFKtyKgprYAAAGeIstZkAAIAAAFAAAN3hQEAwBIMEYCIQC21zfS/kOLTPP8uvSrAJ286X4dw5beF3pgCtHp3FsvbAIhAMR7wwTWf9++dtLPpMlRmvzOC2gwgS4j9f7eRLw2txXMMAoGCCqGSM49BAMDA2kAMGYCMQDoTVmOTK23t5eE/1BMr7GPxiyvF3+D8XJ/Okx7TRHuizJjlNF5dNRWLXRkp9okFrcCMQDQppyt8F1tbFc8mQqirwA90eyEJfBVjG4D0loN6t7JwKrO+K/QuoE8B1mozTZixIc="
+ },
+ "tlogEntries": [
+ {
+ "logIndex": "4026478",
+ "logId": {
+ "keyId": "09OnDKEw7/hpZiYVPoTRzRbglHk0sylsUovegnRUlJY="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.2"
+ },
+ "inclusionProof": {
+ "logIndex": "4026478",
+ "rootHash": "5iaX4xK6PMnp4ZFTP4iywMcwLgaTjzgRTkrTOUFIrfY=",
+ "treeSize": "4026479",
+ "hashes": [
+ "y9eH/Cl/glEuLMKtwV0bgZ+a1P/AjoPyvu/iUeanaIM=",
+ "nrNQ2vb5JM2No6zELZt05onTYzqQOwDUcs24jAa6lzk=",
+ "HfZO2uZZbokwORUD/0dMRpBEouo33Ab2nQ2N6r4v688=",
+ "grMdYn8tE73JvJU8Ixk4hl8/fKu06hUdgpPNsuAfb7o=",
+ "i1gQ61xe3f9MP09y2e9Z4n5ZnDiFuqQmTK/u7Gji4Ws=",
+ "TkPA4Mv4plM3c6oejf5r+PqVxfMPk0x+QAjumzaswsU=",
+ "wGq46RfkA9tCYZ2CCOOMGQttyhHIqMksBAl+soDBgRw=",
+ "WPWftR+8Qjv3qiIBp48n3PiweejcpuHjokhaSIJaUOo=",
+ "kgGccNZjCDNKiQBUSPorZcTXoy9T0OIygUNX2V9tF7s=",
+ "7vMeapYqpjDZc8itt3uF6dGxL5qkbFsQ18jBiblH/5g=",
+ "ma8nVjhpJ0JmgSzaxhxP7bvHXtiZC6nJXIBmDV8kNAI=",
+ "CZJWJtYZFYWwC+DsEiCMnWled/ED66viI0Wz/L+9vxk=",
+ "Y8Q9QaTpqRAlSoWnNwyYGDerVLL1f6b8osmbDYEF6og="
+ ],
+ "checkpoint": {
+ "envelope": "log2025-alpha3.rekor.sigstage.dev\n4026479\n5iaX4xK6PMnp4ZFTP4iywMcwLgaTjzgRTkrTOUFIrfY=\n\n— log2025-alpha3.rekor.sigstage.dev 09OnDHwVrKeXjBYQ4NJ5EoENdtpBwZcV3X8n+cAZFIk+8LBPKEpZcKqoN2CfjGw0zlQwt+U2pLt5UyYEFv+STPHPmQg=\n— witness.stagemole.eu Z/euoAAAAABqBM+21mV7JbHwWmLP20ZSpNWneHMkITOPopt+Vj1MoJSILqOIPpx93pbRfA0U+Eq5IiJjEUhG1JwGhPCJEUT5yDcFDg==\n— staging.witness.transparency.goog/ring-any-bells LhqNyQAAAABqBM+2Ob9EtpF9h6IUMXc/LTRkkXiNAgbbohBxHekby1oASdDtPLkgZLmBHH73DF25f2L8xGgp/qVwoZK5thKXc6XnCw==\n— witness.navigli.sunlight.geomys.org o+AP4gAAAABqBM+2NoYlK4g3lkC5QltDB6f2F9U8yF6+8kXKjLKHAYvSDJ3u5dZufSU3bz+AtJMdOoMixoFJBkQ397WY/mE0i9tlCg==\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJoYXNoZWRSZWtvcmRWMDAyIjp7ImRhdGEiOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiJWL0lUWEZsTWY1Tmc1NXBVSXNLUitJZU5TdVhGT2J3RTNLUmRwajE4TGhFPSJ9LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FVUNJUUNRUTExbnNvVGFPNTIvTUM0OGcwN21qQVRkeEQ4Nnl3ZHUzTnhKVWpIN3lBSWdXR2MrTVIzZUlBb1d1OEpFMVFNMllEc2xwb0ZBek1WV3BOMTE1ZkNLdXFnPSIsInZlcmlmaWVyIjp7ImtleURldGFpbHMiOiJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsIng1MDlDZXJ0aWZpY2F0ZSI6eyJyYXdCeXRlcyI6Ik1JSUlQakNDQjhPZ0F3SUJBZ0lVZU0zTmxTemlHcXlMOWVaSTYwb1p4TGI5emFnd0NnWUlLb1pJemowRUF3TXdOekVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SNHdIQVlEVlFRREV4VnphV2R6ZEc5eVpTMXBiblJsY20xbFpHbGhkR1V3SGhjTk1qWXdOVEV6TVRreU16TXlXaGNOTWpZd05URXpNVGt6TXpNeVdqQUFNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUxUXlHdVh2VzZxdy9BOFpHaFBNa1RnTnR1STVLRDc4TWVscmoyTWlSZXM0US8zNVlJK3RDMTRYS1lqUURRRGdJT1ZPRFlYdDk0OHNKdzl6RzdnWE1rS09DQnVJd2dnYmVNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBekFkQmdOVkhRNEVGZ1FVTXoxb3JmaXpqMmJtZVRTU0lLdUs5emg1aVBjd0h3WURWUjBqQkJnd0ZvQVVjWVl3cGhSOFltLzU5OWIwQlJwL1gvL3JiNnd3Z2FVR0ExVWRFUUVCL3dTQm1qQ0JsNGFCbEdoMGRIQnpPaTh2WjJsMGFIVmlMbU52YlM5emFXZHpkRzl5WlMxamIyNW1iM0p0WVc1alpTOWxlSFJ5WlcxbGJIa3RaR0Z1WjJWeWIzVnpMWEIxWW14cFl5MXZhV1JqTFdKbFlXTnZiaTh1WjJsMGFIVmlMM2R2Y210bWJHOTNjeTlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFc5cFpHTXRZbVZoWTI5dUxubHRiRUJ5WldaekwyaGxZV1J6TDIxaGFXNHdPUVlLS3dZQkJBR0R2ekFCQVFRcmFIUjBjSE02THk5MGIydGxiaTVoWTNScGIyNXpMbWRwZEdoMVluVnpaWEpqYjI1MFpXNTBMbU52YlRBZkJnb3JCZ0VFQVlPL01BRUNCQkYzYjNKclpteHZkMTlrYVhOd1lYUmphREEyQmdvckJnRUVBWU8vTUFFREJDZzVOemRsT0dRd09EVTFOR05oT1dKa1lUSTNPV001Tm1VNU1XSmxNakV4T1daaU5qZGpOek13TUMwR0Npc0dBUVFCZzc4d0FRUUVIMFY0ZEhKbGJXVnNlU0JrWVc1blpYSnZkWE1nVDBsRVF5QmlaV0ZqYjI0d1NRWUtLd1lCQkFHRHZ6QUJCUVE3YzJsbmMzUnZjbVV0WTI5dVptOXliV0Z1WTJVdlpYaDBjbVZ0Wld4NUxXUmhibWRsY205MWN5MXdkV0pzYVdNdGIybGtZeTFpWldGamIyNHdIUVlLS3dZQkJBR0R2ekFCQmdRUGNtVm1jeTlvWldGa2N5OXRZV2x1TURzR0Npc0dBUVFCZzc4d0FRZ0VMUXdyYUhSMGNITTZMeTkwYjJ0bGJpNWhZM1JwYjI1ekxtZHBkR2gxWW5WelpYSmpiMjUwWlc1MExtTnZiVENCcGdZS0t3WUJCQUdEdnpBQkNRU0Jsd3lCbEdoMGRIQnpPaTh2WjJsMGFIVmlMbU52YlM5emFXZHpkRzl5WlMxamIyNW1iM0p0WVc1alpTOWxlSFJ5WlcxbGJIa3RaR0Z1WjJWeWIzVnpMWEIxWW14cFl5MXZhV1JqTFdKbFlXTnZiaTh1WjJsMGFIVmlMM2R2Y210bWJHOTNjeTlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFc5cFpHTXRZbVZoWTI5dUxubHRiRUJ5WldaekwyaGxZV1J6TDIxaGFXNHdPQVlLS3dZQkJBR0R2ekFCQ2dRcURDZzVOemRsT0dRd09EVTFOR05oT1dKa1lUSTNPV001Tm1VNU1XSmxNakV4T1daaU5qZGpOek13TUIwR0Npc0dBUVFCZzc4d0FRc0VEd3dOWjJsMGFIVmlMV2h2YzNSbFpEQmVCZ29yQmdFRUFZTy9NQUVNQkZBTVRtaDBkSEJ6T2k4dloybDBhSFZpTG1OdmJTOXphV2R6ZEc5eVpTMWpiMjVtYjNKdFlXNWpaUzlsZUhSeVpXMWxiSGt0WkdGdVoyVnliM1Z6TFhCMVlteHBZeTF2YVdSakxXSmxZV052YmpBNEJnb3JCZ0VFQVlPL01BRU5CQ29NS0RrM04yVTRaREE0TlRVMFkyRTVZbVJoTWpjNVl6azJaVGt4WW1VeU1URTVabUkyTjJNM016QXdId1lLS3dZQkJBR0R2ekFCRGdRUkRBOXlaV1p6TDJobFlXUnpMMjFoYVc0d0dRWUtLd1lCQkFHRHZ6QUJEd1FMREFrMk16STFPVFk0T1Rjd053WUtLd1lCQkFHRHZ6QUJFQVFwRENkb2RIUndjem92TDJkcGRHaDFZaTVqYjIwdmMybG5jM1J2Y21VdFkyOXVabTl5YldGdVkyVXdHUVlLS3dZQkJBR0R2ekFCRVFRTERBa3hNekU0TURRMU5qTXdnYVlHQ2lzR0FRUUJnNzh3QVJJRWdaY01nWlJvZEhSd2N6b3ZMMmRwZEdoMVlpNWpiMjB2YzJsbmMzUnZjbVV0WTI5dVptOXliV0Z1WTJVdlpYaDBjbVZ0Wld4NUxXUmhibWRsY205MWN5MXdkV0pzYVdNdGIybGtZeTFpWldGamIyNHZMbWRwZEdoMVlpOTNiM0pyWm14dmQzTXZaWGgwY21WdFpXeDVMV1JoYm1kbGNtOTFjeTF2YVdSakxXSmxZV052Ymk1NWJXeEFjbVZtY3k5b1pXRmtjeTl0WVdsdU1EZ0dDaXNHQVFRQmc3OHdBUk1FS2d3b09UYzNaVGhrTURnMU5UUmpZVGxpWkdFeU56bGpPVFpsT1RGaVpUSXhNVGxtWWpZM1l6Y3pNREFoQmdvckJnRUVBWU8vTUFFVUJCTU1FWGR2Y210bWJHOTNYMlJwYzNCaGRHTm9NSUdDQmdvckJnRUVBWU8vTUFFVkJIUU1jbWgwZEhCek9pOHZaMmwwYUhWaUxtTnZiUzl6YVdkemRHOXlaUzFqYjI1bWIzSnRZVzVqWlM5bGVIUnlaVzFsYkhrdFpHRnVaMlZ5YjNWekxYQjFZbXhwWXkxdmFXUmpMV0psWVdOdmJpOWhZM1JwYjI1ekwzSjFibk12TWpVNE1qRXlPREl3TlRrdllYUjBaVzF3ZEhNdk1UQVdCZ29yQmdFRUFZTy9NQUVXQkFnTUJuQjFZbXhwWXpDQmxRWUtLd1lCQkFIV2VRSUVBZ1NCaGdTQmd3Q0JBSDhBUG1CeFUzUnVHSkxna0xJMnNVbDJKeTludEUxdmtzNXZkeEZLdHlLZ3ByWUFBQUdlSXN0WmtBQUlBQUFGQUFBTjNoUUVBd0JJTUVZQ0lRQzIxemZTL2tPTFRQUDh1dlNyQUoyODZYNGR3NWJlRjNwZ0N0SHAzRnN2YkFJaEFNUjd3d1RXZjkrK2R0TFBwTWxSbXZ6T0MyZ3dnUzRqOWY3ZVJMdzJ0eFhNTUFvR0NDcUdTTTQ5QkFNREEya0FNR1lDTVFEb1RWbU9USzIzdDVlRS8xQk1yN0dQeGl5dkYzK0Q4WEovT2t4N1RSSHVpekpqbE5GNWROUldMWFJrcDlva0ZyY0NNUURRcHB5dDhGMXRiRmM4bVFxaXJ3QTkwZXlFSmZCVmpHNEQwbG9ONnQ3SndLck8rSy9RdW9FOEIxbW96VFppeEljPSJ9fX19fX0="
+ }
+ ],
+ "timestampVerificationData": {
+ "rfc3161Timestamps": [
+ {
+ "signedTimestamp": "MIICyzADAgEAMIICwgYJKoZIhvcNAQcCoIICszCCAq8CAQMxDTALBglghkgBZQMEAgEwgbgGCyqGSIb3DQEJEAEEoIGoBIGlMIGiAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgWD/kdb0X6i1+GgKjU90CUYSfx1d7REuAvHJRjTz9hVECFQDl+Rm4z9uwI6k6kxhHO7k3oZ+T3BgPMjAyNjA1MTMxOTIzMzZaMAMCAQGgMqQwMC4xFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEVMBMGA1UEAxMMc2lnc3RvcmUtdHNhoAAxggHcMIIB2AIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFAo1oQZh1eJBc8aJlqfyffJ+A3ynMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MDUxMzE5MjMzNlowLwYJKoZIhvcNAQkEMSIEIJwLGQJ8dEmSY92i0AkhXwpJ5J66dYbEr2f5jtQlKrEKMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCAG9P/gR/6zWZm3M7DXoyNQHPwY5MAzZqhF13U250snRDBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAgRoMGYCMQCdtq6trvjr9zZb27XykDqOhSCqBUt5+TtfKkfV50t2AWeJC6bh5oX6D+owAXswT4QCMQCMAY+vbUacSlSjgwyZe5LHk3H19/G4twkIT+1sUY0ZzLZ7mw1Oydm/015e4HkFD3w="
+ }
+ ]
}
},
"dsseEnvelope": {
- "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS50eHQiLCJkaWdlc3QiOnsic2hhMjU2IjoiYTBjZmM3MTI3MWQ2ZTI3OGU1N2NkMzMyZmY5NTdjM2Y3MDQzZmRkYTM1NGM0Y2JiMTkwYTMwZDU2ZWZhMDFiZiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vYWN0aW9ucy5naXRodWIuaW8vYnVpbGR0eXBlcy93b3JrZmxvdy92MSIsImV4dGVybmFsUGFyYW1ldGVycyI6eyJ3b3JrZmxvdyI6eyJyZWYiOiJyZWZzL2hlYWRzL21haW4iLCJyZXBvc2l0b3J5IjoiaHR0cHM6Ly9naXRodWIuY29tL2xvb3NlYmF6b29rYS9hYS10ZXN0IiwicGF0aCI6Ii5naXRodWIvd29ya2Zsb3dzL3Byb3ZlbmFuY2UueWFtbCJ9fSwiaW50ZXJuYWxQYXJhbWV0ZXJzIjp7ImdpdGh1YiI6eyJldmVudF9uYW1lIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJyZXBvc2l0b3J5X2lkIjoiODkxNzE1NDQ0IiwicmVwb3NpdG9yeV9vd25lcl9pZCI6IjEzMDQ4MjYiLCJydW5uZXJfZW52aXJvbm1lbnQiOiJnaXRodWItaG9zdGVkIn19LCJyZXNvbHZlZERlcGVuZGVuY2llcyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sb29zZWJhem9va2EvYWEtdGVzdEByZWZzL2hlYWRzL21haW4iLCJkaWdlc3QiOnsiZ2l0Q29tbWl0IjoiZWJmZjhkZmJkNjA5YjdiMjIyMzdjNzcxOWNlMDdmMmRjNzkzNGY1ZiJ9fV19LCJydW5EZXRhaWxzIjp7ImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcHJvdmVuYW5jZS55YW1sQHJlZnMvaGVhZHMvbWFpbiJ9LCJtZXRhZGF0YSI6eyJpbnZvY2F0aW9uSWQiOiJodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3QvYWN0aW9ucy9ydW5zLzExOTQxNDI1NDg3L2F0dGVtcHRzLzEifX19fQ==",
+ "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS50eHQiLCJkaWdlc3QiOnsic2hhMjU2IjoiYTBjZmM3MTI3MWQ2ZTI3OGU1N2NkMzMyZmY5NTdjM2Y3MDQzZmRkYTM1NGM0Y2JiMTkwYTMwZDU2ZWZhMDFiZiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9zaWdzdG9yZS1jb25mb3JtYW5jZS9yZWtvcjItZHNzZS1oYXNoZWRyZWtvcmQtcmVnZW4ifSwicnVuRGV0YWlscyI6eyJidWlsZGVyIjp7ImlkIjoiaHR0cHM6Ly9naXRodWIuY29tL3NpZ3N0b3JlLWNvbmZvcm1hbmNlL3Jla29yMi1kc3NlLWhhc2hlZHJla29yZC1yZWdlbiJ9fX19",
"payloadType": "application/vnd.in-toto+json",
- "signatures": [{
- "sig": "MEYCIQCkNCQpMWfAbq+tIwicACgKN+BR+GleQNvdQXB137b+gwIhANp0c1JC8gCSylSG6UFkEXzUwU/Y7Ba0rBrAZAT2yqoe"
- }]
+ "signatures": [
+ {
+ "sig": "MEUCIQCgdnmnfji2dSYZ5Bk/9i6aXcuIRj5uaf9v1WRTD5bsUAIgU206JXzdef4+LtEGMsv2Q3ZyWxykmRY5t/4EbQodlX4="
+ }
+ ]
}
}
diff --git a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.sigstore b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.sigstore
index 2b6b6d028..ab4ef3449 100644
--- a/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.sigstore
+++ b/sigstore-java/src/test/resources/dev/sigstore/samples/bundles/bundle.dsse.rekor-v2.sigstore
@@ -1 +1,40 @@
-{"mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json", "verificationMaterial": {"certificate": {"rawBytes": "MIICyzCCAlKgAwIBAgIUMjDNrL/ZpriwSc+lM+0mnq5EFyIwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjUwNzIzMTk1MDIyWhcNMjUwNzIzMjAwMDIyWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEE9LbVCgJscxGQF0RtZZWmIbJvkMEKuqQqg1eQsJ/qQK1Nh2VMDjZqfWBoc1u1cBFeBpChVHY83edhztO8Jx52aOCAXEwggFtMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUJvm5ncCyW6avs3RqBIXXtrMRGEswHwYDVR0jBBgwFoAUcYYwphR8Ym/599b0BRp/X//rb6wwIQYDVR0RAQH/BBcwFYETYWFyb25sZXdAZ29vZ2xlLmNvbTApBgorBgEEAYO/MAEBBBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wKwYKKwYBBAGDvzABCAQdDBtodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20wgYoGCisGAQQB1nkCBAIEfAR6AHgAdgArMLzcaIjJ4uHYJiledB9IOTGWAvKcM8teQ0D+sqyGegAAAZg41kFVAAAEAwBHMEUCIEENnFN8ER4UNtH/nSBTirhvUZr7ICsOIBBN9vYAjz4pAiEArtD1UwqX5s5GB2eEFj4K/01Eh2K0wzQIGDa2YeS+hTwwCgYIKoZIzj0EAwMDZwAwZAIwYPr0dXtDc1iEraYMm1FemlXVH2o84E6kz1/RgQ623kyMFQR0XxXWavwCB89k6oecAjAcMKRHly449ScmfECUwUQ+gLxaJkrj4tGkWKIoUJm1J4jyfN6+7GT5T4n1iJLDBVM="}, "tlogEntries": [{"logIndex": "6883", "logId": {"keyId": "8w1amZ2S5mJIQkQmPxdMuOrL/oJkvFg9MnQXmeOCXck="}, "kindVersion": {"kind": "dsse", "version": "0.0.2"}, "inclusionProof": {"logIndex": "6883", "rootHash": "3PBfVgP7khx41FlnyPpz8uHwHgOwAy9eUaEGoJEpWS4=", "treeSize": "6884", "hashes": ["vG3789z3en7YY3+8TOMH3EoNH0l3Z+nEafcCSQla9ac=", "pUx4FWhp5snrjfhiDBFRZn5Ib3Om9PmIJKR/X8FKt6o=", "rul+526SZeq9WeyupR6VYddH+cFHJnCpolYwl1Akbx4=", "/WSx54v3EqBwQlFEzk+ovLearmtjbNDfjNyHfAL0iHk=", "Ezo3FTVCd4Kzk1oPeT3rNLZhvRsGZN/66ONX81DrJ0M=", "tnv06iEfRP1UrMtn7D7v4lA+1VfpdI3ioGcQRJLMoP0=", "Ag03a73jphtOkMBVhp+MkrJwDkx2NE69NESHMFcwcfI=", "xbDsGnxf1siByWHEuiK85p0reQCaKKWUjf8YNl9s/Vo="], "checkpoint": {"envelope": "log2025-alpha1.rekor.sigstage.dev\n6884\n3PBfVgP7khx41FlnyPpz8uHwHgOwAy9eUaEGoJEpWS4=\n\n\u2014 log2025-alpha1.rekor.sigstage.dev 8w1amd9Jy5UcYJbfxsSogkHmrj1wbtv3g4IWtZ4rspPxgWyDUrbQI7W0T4gHrjLM5IUbkoTmKRQoZsXTgmMgZ8B8ywk=\n"}}, "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiZHNzZSIsInNwZWMiOnsiZHNzZVYwMDIiOnsicGF5bG9hZEhhc2giOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiI5VmpkVnVPcGN5SEtnOFlsbWhuRjZXWXhrOHVvRXRSWHplS0FmcSt0WnIwPSJ9LCJzaWduYXR1cmVzIjpbeyJjb250ZW50IjoiTUVZQ0lRQ1psOS9laWVMOXdDUVhRY01uSmJYMis2cko5RTF0dm5EZTZPbkFwUFhLMGdJaEFKeUxiek1pZXFiY0o0VWZ6RkxKeG1GNUc3Y1FhRjhKTDZUZFFVd3JpdXY0IiwidmVyaWZpZXIiOnsia2V5RGV0YWlscyI6IlBLSVhfRUNEU0FfUDI1Nl9TSEFfMjU2IiwieDUwOUNlcnRpZmljYXRlIjp7InJhd0J5dGVzIjoiTUlJQ3l6Q0NBbEtnQXdJQkFnSVVNakROckwvWnByaXdTYytsTSswbW5xNUVGeUl3Q2dZSUtvWkl6ajBFQXdNd056RVZNQk1HQTFVRUNoTU1jMmxuYzNSdmNtVXVaR1YyTVI0d0hBWURWUVFERXhWemFXZHpkRzl5WlMxcGJuUmxjbTFsWkdsaGRHVXdIaGNOTWpVd056SXpNVGsxTURJeVdoY05NalV3TnpJek1qQXdNREl5V2pBQU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUU5TGJWQ2dKc2N4R1FGMFJ0WlpXbUliSnZrTUVLdXFRcWcxZVFzSi9xUUsxTmgyVk1EalpxZldCb2MxdTFjQkZlQnBDaFZIWTgzZWRoenRPOEp4NTJhT0NBWEV3Z2dGdE1BNEdBMVVkRHdFQi93UUVBd0lIZ0RBVEJnTlZIU1VFRERBS0JnZ3JCZ0VGQlFjREF6QWRCZ05WSFE0RUZnUVVKdm01bmNDeVc2YXZzM1JxQklYWHRyTVJHRXN3SHdZRFZSMGpCQmd3Rm9BVWNZWXdwaFI4WW0vNTk5YjBCUnAvWC8vcmI2d3dJUVlEVlIwUkFRSC9CQmN3RllFVFlXRnliMjVzWlhkQVoyOXZaMnhsTG1OdmJUQXBCZ29yQmdFRUFZTy9NQUVCQkJ0b2RIUndjem92TDJGalkyOTFiblJ6TG1kdmIyZHNaUzVqYjIwd0t3WUtLd1lCQkFHRHZ6QUJDQVFkREJ0b2RIUndjem92TDJGalkyOTFiblJ6TG1kdmIyZHNaUzVqYjIwd2dZb0dDaXNHQVFRQjFua0NCQUlFZkFSNkFIZ0FkZ0FyTUx6Y2FJako0dUhZSmlsZWRCOUlPVEdXQXZLY004dGVRMEQrc3F5R2VnQUFBWmc0MWtGVkFBQUVBd0JITUVVQ0lFRU5uRk44RVI0VU50SC9uU0JUaXJodlVacjdJQ3NPSUJCTjl2WUFqejRwQWlFQXJ0RDFVd3FYNXM1R0IyZUVGajRLLzAxRWgySzB3elFJR0RhMlllUytoVHd3Q2dZSUtvWkl6ajBFQXdNRFp3QXdaQUl3WVByMGRYdERjMWlFcmFZTW0xRmVtbFhWSDJvODRFNmt6MS9SZ1E2MjNreU1GUVIwWHhYV2F2d0NCODlrNm9lY0FqQWNNS1JIbHk0NDlTY21mRUNVd1VRK2dMeGFKa3JqNHRHa1dLSW9VSm0xSjRqeWZONis3R1Q1VDRuMWlKTERCVk09In19fV19fX0="}], "timestampVerificationData": {"rfc3161Timestamps": [{"signedTimestamp": "MIIE6TADAgEAMIIE4AYJKoZIhvcNAQcCoIIE0TCCBM0CAQMxDTALBglghkgBZQMEAgEwgcIGCyqGSIb3DQEJEAEEoIGyBIGvMIGsAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgGHLmT/+u6DojuoqF81X1QeqgdFuIF0j7UYmOrfaqgiUCFBGYrUgXErfzFv7+j+Caoe5Uagg4GA8yMDI1MDcyMzE5NTAyMlowAwIBAQIJAOa3xjMvK5GjoDKkMDAuMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxFTATBgNVBAMTDHNpZ3N0b3JlLXRzYaCCAhMwggIPMIIBlqADAgECAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkMB4XDTI1MDMyODA5MTQwNloXDTM1MDMyNjA4MTQwNlowLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATHW/kXcekP16Ae6SekEWVHPtAFEMm7hp5XO33MktFjSW+bHWUXtYEzZz0A3xkY9CyYOoeUk3ZH/v5HEuS+UvORzX0g7Hfy3uYYYRwHtqBQN0IX8rLdFMtIrRej/QCAdB2jajBoMA4GA1UdDwEB/wQEAwIHgDAdBgNVHQ4EFgQUqPxk9ijeLuY7c09UjFLE4ZzdU6UwHwYDVR0jBBgwFoAUOyBGWV61Mk1HMM5uY+5zdEfyBH0wFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwCgYIKoZIzj0EAwMDZwAwZAIwRK9VLoYa0Xff4nX1N/AQ1YleNG/iLT8dAXAtRKRfpN9XuDScbxWeo0cku8SkC06NAjBQPe7LBNeitA/UOBtXT2sX1h6f4ISqz+ISmJ4lY+y3bzRJI5nk1r53I9WT3/xIWToxggHbMIIB1wIBATBRMDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFAo1oQZh1eJBc8aJlqfyffJ+A3ynMAsGCWCGSAFlAwQCAaCB/DAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI1MDcyMzE5NTAyMlowLwYJKoZIhvcNAQkEMSIEIOM5iKgzY5WzDUaZZCfd+WqilYB3hPNR5dedubOhel9XMIGOBgsqhkiG9w0BCRACLzF/MH0wezB5BCAG9P/gR/6zWZm3M7DXoyNQHPwY5MAzZqhF13U250snRDBVMD2kOzA5MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxIDAeBgNVBAMTF3NpZ3N0b3JlLXRzYS1zZWxmc2lnbmVkAhQKNaEGYdXiQXPGiZan8n3yfgN8pzAKBggqhkjOPQQDAgRnMGUCMQCpzZZXVqicWuWohrGEoJqnxlI56up1QspAzfNwVecr6Kb/WIJpc5thx2/YHlEJMcACMHTGqJy4jBbYWP+vxkzT7smvrTf93MSNvWVuvujkSr+rLau6cLYVjAzK4y6chE0LkA=="}]}}, "dsseEnvelope": {"payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYXJ0aWZhY3QudHh0IiwiZGlnZXN0Ijp7InNoYTI1NiI6ImEwY2ZjNzEyNzFkNmUyNzhlNTdjZDMzMmZmOTU3YzNmNzA0M2ZkZGEzNTRjNGNiYjE5MGEzMGQ1NmVmYTAxYmYifX1dLCJwcmVkaWNhdGVUeXBlIjoiaHR0cHM6Ly9zbHNhLmRldi9wcm92ZW5hbmNlL3YxIiwicHJlZGljYXRlIjp7ImJ1aWxkRGVmaW5pdGlvbiI6eyJidWlsZFR5cGUiOiJodHRwczovL2FjdGlvbnMuZ2l0aHViLmlvL2J1aWxkdHlwZXMvd29ya2Zsb3cvdjEiLCJleHRlcm5hbFBhcmFtZXRlcnMiOnsid29ya2Zsb3ciOnsicmVmIjoicmVmcy9oZWFkcy9tYWluIiwicmVwb3NpdG9yeSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9sb29zZWJhem9va2EvYWEtdGVzdCIsInBhdGgiOiIuZ2l0aHViL3dvcmtmbG93cy9wcm92ZW5hbmNlLnlhbWwifX0sImludGVybmFsUGFyYW1ldGVycyI6eyJnaXRodWIiOnsiZXZlbnRfbmFtZSI6IndvcmtmbG93X2Rpc3BhdGNoIiwicmVwb3NpdG9yeV9pZCI6Ijg5MTcxNTQ0NCIsInJlcG9zaXRvcnlfb3duZXJfaWQiOiIxMzA0ODI2IiwicnVubmVyX2Vudmlyb25tZW50IjoiZ2l0aHViLWhvc3RlZCJ9fSwicmVzb2x2ZWREZXBlbmRlbmNpZXMiOlt7InVyaSI6ImdpdCtodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3RAcmVmcy9oZWFkcy9tYWluIiwiZGlnZXN0Ijp7ImdpdENvbW1pdCI6ImViZmY4ZGZiZDYwOWI3YjIyMjM3Yzc3MTljZTA3ZjJkYzc5MzRmNWYifX1dfSwicnVuRGV0YWlscyI6eyJidWlsZGVyIjp7ImlkIjoiaHR0cHM6Ly9naXRodWIuY29tL2xvb3NlYmF6b29rYS9hYS10ZXN0Ly5naXRodWIvd29ya2Zsb3dzL3Byb3ZlbmFuY2UueWFtbEByZWZzL2hlYWRzL21haW4ifSwibWV0YWRhdGEiOnsiaW52b2NhdGlvbklkIjoiaHR0cHM6Ly9naXRodWIuY29tL2xvb3NlYmF6b29rYS9hYS10ZXN0L2FjdGlvbnMvcnVucy8xMTk0MTQyNTQ4Ny9hdHRlbXB0cy8xIn19fX0=", "payloadType": "application/vnd.in-toto+json", "signatures": [{"sig": "MEYCIQCZl9/eieL9wCQXQcMnJbX2+6rJ9E1tvnDe6OnApPXK0gIhAJyLbzMieqbcJ4UfzFLJxmF5G7cQaF8JL6TdQUwriuv4"}]}}
+{
+ "mediaType": "application/vnd.dev.sigstore.bundle.v0.3+json",
+ "verificationMaterial": {
+ "tlogEntries": [{
+ "logIndex": "4855114",
+ "logId": {
+ "keyId": "zxGZFVvd0FEmjR8WrFwMdcAJ9vtaY/QXf44Y1wUeP6A="
+ },
+ "kindVersion": {
+ "kind": "hashedrekord",
+ "version": "0.0.2"
+ },
+ "inclusionProof": {
+ "logIndex": "4855114",
+ "rootHash": "gDfQHcPSkLDVUd/xeZWPsqSB7RTR0ho07k15jgzLOpw=",
+ "treeSize": "4855115",
+ "hashes": ["aRZL/szw4ux5Z1bkEzjHOFvc0ZZViI2IkA7OTwYpEcM=", "kR4us392eg3w0hRqRnexneIv62Nn36bew88TGoKQD9w=", "zBgMHKQebztMpP9eR2jHuxhkzxMna+vebKTmGZiBjiQ=", "+iue0VkI7SZLyxnVEhBMG8s0J3JVIQU1l3DXbM8L0oI=", "82eSFCN2O3dP0jFRfn+3FucCiP3/fecKSnyOJ0hUCEc=", "ls8yhkXw2PgEuL24MH7kkNhVCOZjQqXU36uPc27hYiI=", "u2qY+l+Ndm3d9uQ/1KcKYeXlTK+jktofNB6nMnFkb2o=", "Rg1QTxC1Ag1H1bj1+44xJ3YzU3+DBayNGdzbbzixNKA=", "9Qzg8F3rbivd2Qo+aEdiFHlxyQZNgXWbIo5JFAUKqA4="],
+ "checkpoint": {
+ "envelope": "log2025-1.rekor.sigstore.dev\n4855115\ngDfQHcPSkLDVUd/xeZWPsqSB7RTR0ho07k15jgzLOpw\u003d\n\n— log2025-1.rekor.sigstore.dev zxGZFXYHvtV6cW22YJx1dWx9IiuUHw4BuXZ3X81JAgK8sWX/HBQH2QdlDapqjMkp9GcrITop7jUG979FyKaY7C7VvQM\u003d\n"
+ }
+ },
+ "canonicalizedBody": "eyJhcGlWZXJzaW9uIjoiMC4wLjIiLCJraW5kIjoiaGFzaGVkcmVrb3JkIiwic3BlYyI6eyJoYXNoZWRSZWtvcmRWMDAyIjp7ImRhdGEiOnsiYWxnb3JpdGhtIjoiU0hBMl8yNTYiLCJkaWdlc3QiOiJma1BYSnd0Tm51NHJ6cWZZa1N1ZExrSDRqU3ZldCtKM2dxOUhySHhHY2I0PSJ9LCJzaWduYXR1cmUiOnsiY29udGVudCI6Ik1FUUNJRURDSzJyRXNXTmt4L2tPTzMySHBiZDNvczZ3QkFsS3QxczBWNys3cW1xeEFpQkFmK29rdnluYmZmYVZMcG1nWUlUUHEyeStWQm9RT0NIUWxiVjJjaC9SQmc9PSIsInZlcmlmaWVyIjp7ImtleURldGFpbHMiOiJQS0lYX0VDRFNBX1AyNTZfU0hBXzI1NiIsIng1MDlDZXJ0aWZpY2F0ZSI6eyJyYXdCeXRlcyI6Ik1JSURHVENDQXArZ0F3SUJBZ0lVQjErcXJ5Mjg3S1RyZmVhRlJhanFpbyt5OWZ3d0NnWUlLb1pJemowRUF3TXdOekVWTUJNR0ExVUVDaE1NYzJsbmMzUnZjbVV1WkdWMk1SNHdIQVlEVlFRREV4VnphV2R6ZEc5eVpTMXBiblJsY20xbFpHbGhkR1V3SGhjTk1qWXdOakF6TVRreU16STJXaGNOTWpZd05qQXpNVGt6TXpJMldqQUFNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVERjBZOHRjbTJxOGZUelNvN1FBd0RzbTlQUTFPbmYxeWF3QXhIWEU5RXQzZmFYdGNvb3J2VVlQR2dKZ3RsNTRvb1lHWldvUFozdkRGL3FmczhOaVJQcU9DQWI0d2dnRzZNQTRHQTFVZER3RUIvd1FFQXdJSGdEQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBekFkQmdOVkhRNEVGZ1FVcTduY05uMC9yYUw0dWh1VkQ1QnZubDlJVW9vd0h3WURWUjBqQkJnd0ZvQVUzOVBwejFZa0VaYjVxTmpwS0ZXaXhpNFlaRDh3UndZRFZSMFJBUUgvQkQwd080RTVkVzUwY25WemRHVmtMWE5oUUhOcFozTjBiM0psTFdOdmJtWnZjbTFoYm1ObExtbGhiUzVuYzJWeWRtbGpaV0ZqWTI5MWJuUXVZMjl0TUNrR0Npc0dBUVFCZzc4d0FRRUVHMmgwZEhCek9pOHZZV05qYjNWdWRITXVaMjl2WjJ4bExtTnZiVEFyQmdvckJnRUVBWU8vTUFFSUJCME1HMmgwZEhCek9pOHZZV05qYjNWdWRITXVaMjl2WjJ4bExtTnZiVEFsQmdvckJnRUVBWU8vTUFFWUJCY01GVEV3TlRFME5EWXhPREEwT1RJME9EazJOakUzTnpDQmlnWUtLd1lCQkFIV2VRSUVBZ1I4QkhvQWVBQjJBTjA5TUdyR3h4RXlZeGtlSEpsbk53S2lTbDY0M2p5dC80ZUtjb0F2S2U2T0FBQUJubzd3ekVVQUFBUURBRWN3UlFJaEFKTzVIc1daNnZCU0haazdlWlJsSkJkL3BYVnlocE1zb3IyNnFpWDU4U2pIQWlCNUdqL1hqL3RzeEpNblVEWkxZejFoUVB1akJLYldsbExNM3ZKakQvM0lJakFLQmdncWhrak9QUVFEQXdOb0FEQmxBakJqVk1iVWs2ZTZ1dHcxR1I4LzkrK0JDTmxiQ1kxR01IKzFVOWZpQVZpc3VpSTZGVklIYTVSNTdHUDlkT1V1QzRZQ01RRExEQkdFMURlTG5reEwrN25wcGRmZU1rR0dZOE9OZHRvRGJ0SXpFRHVvZ0xkaURzZ1NxbFVBT1VUY1A2a0t5MWc9In19fX19fQ=="
+ }],
+ "timestampVerificationData": {
+ "rfc3161Timestamps": [{
+ "signedTimestamp": "MIIC1jADAgEAMIICzQYJKoZIhvcNAQcCoIICvjCCAroCAQMxDTALBglghkgBZQMEAgEwgcMGCyqGSIb3DQEJEAEEoIGzBIGwMIGtAgEBBgkrBgEEAYO/MAIwMTANBglghkgBZQMEAgEFAAQgvraobS2GVwDcuhIBJmFhc8Ls46OCw3urr+EiVqAbZaACFQChspT9FIXsr4Cewk9LfyWQdbSSaxgPMjAyNjA2MDMxOTIzMjZaMAMCAQECCQDRvg++0VJYZaAypDAwLjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MRUwEwYDVQQDEwxzaWdzdG9yZS10c2GgADGCAdwwggHYAgEBMFEwOTEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MSAwHgYDVQQDExdzaWdzdG9yZS10c2Etc2VsZnNpZ25lZAIUOhNULwyQYe68wUMvy4qOiyojiwwwCwYJYIZIAWUDBAIBoIH8MBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjYwNjAzMTkyMzI2WjAvBgkqhkiG9w0BCQQxIgQgUdUi6vUAyFZ4xMmjXmdIo/Ff1zCzsS1ihwGCEhf5JdkwgY4GCyqGSIb3DQEJEAIvMX8wfTB7MHkEIIX5J7wHq2LKw7RDVsEO/IGyxog/2nq55thw2dE6zQW3MFUwPaQ7MDkxFTATBgNVBAoTDHNpZ3N0b3JlLmRldjEgMB4GA1UEAxMXc2lnc3RvcmUtdHNhLXNlbGZzaWduZWQCFDoTVC8MkGHuvMFDL8uKjosqI4sMMAoGCCqGSM49BAMCBGgwZgIxAMlnScf/BqEXZlb5SvPdTKCKH9Ys1qK3I3obY3t/C3jmVM2SN7He7sGyBt/2JMdxfwIxANuIZRt25TQN1RopM4R2Lf9VYccaDxMm7kzUYk9QlV1FmZdJrspDSMxarvpOE6W2ag=="
+ }]
+ },
+ "certificate": {
+ "rawBytes": "MIIDGTCCAp+gAwIBAgIUB1+qry287KTrfeaFRajqio+y9fwwCgYIKoZIzj0EAwMwNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwHhcNMjYwNjAzMTkyMzI2WhcNMjYwNjAzMTkzMzI2WjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDF0Y8tcm2q8fTzSo7QAwDsm9PQ1Onf1yawAxHXE9Et3faXtcoorvUYPGgJgtl54ooYGZWoPZ3vDF/qfs8NiRPqOCAb4wggG6MA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNVHQ4EFgQUq7ncNn0/raL4uhuVD5Bvnl9IUoowHwYDVR0jBBgwFoAU39Ppz1YkEZb5qNjpKFWixi4YZD8wRwYDVR0RAQH/BD0wO4E5dW50cnVzdGVkLXNhQHNpZ3N0b3JlLWNvbmZvcm1hbmNlLmlhbS5nc2VydmljZWFjY291bnQuY29tMCkGCisGAQQBg78wAQEEG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTArBgorBgEEAYO/MAEIBB0MG2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbTAlBgorBgEEAYO/MAEYBBcMFTEwNTE0NDYxODA0OTI0ODk2NjE3NzCBigYKKwYBBAHWeQIEAgR8BHoAeAB2AN09MGrGxxEyYxkeHJlnNwKiSl643jyt/4eKcoAvKe6OAAABno7wzEUAAAQDAEcwRQIhAJO5HsWZ6vBSHZk7eZRlJBd/pXVyhpMsor26qiX58SjHAiB5Gj/Xj/tsxJMnUDZLYz1hQPujBKbWllLM3vJjD/3IIjAKBggqhkjOPQQDAwNoADBlAjBjVMbUk6e6utw1GR8/9++BCNlbCY1GMH+1U9fiAVisuiI6FVIHa5R57GP9dOUuC4YCMQDLDBGE1DeLnkxL+7nppdfeMkGGY8ONdtoDbtIzEDuogLdiDsgSqlUAOUTcP6kKy1g="
+ }
+ },
+ "dsseEnvelope": {
+ "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoiYS50eHQiLCJkaWdlc3QiOnsic2hhMjU2IjoiYTBjZmM3MTI3MWQ2ZTI3OGU1N2NkMzMyZmY5NTdjM2Y3MDQzZmRkYTM1NGM0Y2JiMTkwYTMwZDU2ZWZhMDFiZiJ9fV0sInByZWRpY2F0ZVR5cGUiOiJodHRwczovL3Nsc2EuZGV2L3Byb3ZlbmFuY2UvdjEiLCJwcmVkaWNhdGUiOnsiYnVpbGREZWZpbml0aW9uIjp7ImJ1aWxkVHlwZSI6Imh0dHBzOi8vYWN0aW9ucy5naXRodWIuaW8vYnVpbGR0eXBlcy93b3JrZmxvdy92MSIsImV4dGVybmFsUGFyYW1ldGVycyI6eyJ3b3JrZmxvdyI6eyJyZWYiOiJyZWZzL2hlYWRzL21haW4iLCJyZXBvc2l0b3J5IjoiaHR0cHM6Ly9naXRodWIuY29tL2xvb3NlYmF6b29rYS9hYS10ZXN0IiwicGF0aCI6Ii5naXRodWIvd29ya2Zsb3dzL3Byb3ZlbmFuY2UueWFtbCJ9fSwiaW50ZXJuYWxQYXJhbWV0ZXJzIjp7ImdpdGh1YiI6eyJldmVudF9uYW1lIjoid29ya2Zsb3dfZGlzcGF0Y2giLCJyZXBvc2l0b3J5X2lkIjoiODkxNzE1NDQ0IiwicmVwb3NpdG9yeV9vd25lcl9pZCI6IjEzMDQ4MjYiLCJydW5uZXJfZW52aXJvbm1lbnQiOiJnaXRodWItaG9zdGVkIn19LCJyZXNvbHZlZERlcGVuZGVuY2llcyI6W3sidXJpIjoiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9sb29zZWJhem9va2EvYWEtdGVzdEByZWZzL2hlYWRzL21haW4iLCJkaWdlc3QiOnsiZ2l0Q29tbWl0IjoiZWJmZjhkZmJkNjA5YjdiMjIyMzdjNzcxOWNlMDdmMmRjNzkzNGY1ZiJ9fV19LCJydW5EZXRhaWxzIjp7ImJ1aWxkZXIiOnsiaWQiOiJodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3QvLmdpdGh1Yi93b3JrZmxvd3MvcHJvdmVuYW5jZS55YW1sQHJlZnMvaGVhZHMvbWFpbiJ9LCJtZXRhZGF0YSI6eyJpbnZvY2F0aW9uSWQiOiJodHRwczovL2dpdGh1Yi5jb20vbG9vc2ViYXpvb2thL2FhLXRlc3QvYWN0aW9ucy9ydW5zLzExOTQxNDI1NDg3L2F0dGVtcHRzLzEifX19fQ==",
+ "payloadType": "application/vnd.in-toto+json",
+ "signatures": [{
+ "sig": "MEQCIEDCK2rEsWNkx/kOO32Hpbd3os6wBAlKt1s0V7+7qmqxAiBAf+okvynbffaVLpmgYITPq2y+VBoQOCHQlbV2ch/RBg=="
+ }]
+ }
+}
diff --git a/sigstore-maven-plugin/README.md b/sigstore-maven-plugin/README.md
index 7c62c98a0..b7622faa7 100644
--- a/sigstore-maven-plugin/README.md
+++ b/sigstore-maven-plugin/README.md
@@ -17,7 +17,7 @@ Signature format uses [Sigstore bundle](https://github.com/sigstore/protobuf-spe
dev.sigstore
sigstore-maven-plugin
- 2.0.0
+ 2.1.0
sign
diff --git a/sigstore-testkit/build.gradle.kts b/sigstore-testkit/build.gradle.kts
index a077ad92a..0abc29903 100644
--- a/sigstore-testkit/build.gradle.kts
+++ b/sigstore-testkit/build.gradle.kts
@@ -11,7 +11,7 @@ dependencies {
// This is different from typical "testImplementation" dependencies, because
// testkit exposes junit5 dependencies in its API (e.g. annotations)
- api(platform("org.junit:junit-bom:5.14.2"))
+ api(platform("org.junit:junit-bom:5.14.4"))
api("org.junit.jupiter:junit-jupiter-api")
api("org.junit.jupiter:junit-jupiter-params")
implementation("org.junit.jupiter:junit-jupiter")
diff --git a/sigstore-testkit/src/main/java/dev/sigstore/testkit/oidc/ConformanceTestingTokenProvider.java b/sigstore-testkit/src/main/java/dev/sigstore/testkit/oidc/ConformanceTestingTokenProvider.java
index ca757966b..afa6ea817 100644
--- a/sigstore-testkit/src/main/java/dev/sigstore/testkit/oidc/ConformanceTestingTokenProvider.java
+++ b/sigstore-testkit/src/main/java/dev/sigstore/testkit/oidc/ConformanceTestingTokenProvider.java
@@ -22,6 +22,7 @@
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
+import java.util.Map;
/**
* A token provider that will grab the "unsafe" token from sigstore github conformance testing. This
@@ -30,18 +31,31 @@
*/
public class ConformanceTestingTokenProvider implements TokenStringOidcClient.TokenStringProvider {
- public static ConformanceTestingTokenProvider newProvider() {
- return new ConformanceTestingTokenProvider();
+ public static ConformanceTestingTokenProvider newProviderFromGithub() {
+ return new ConformanceTestingTokenProvider(
+ "https://raw.githubusercontent.com/sigstore-conformance/extremely-dangerous-public-oidc-beacon/refs/heads/current-token/oidc-token.txt");
}
- private ConformanceTestingTokenProvider() {}
+ public static ConformanceTestingTokenProvider newProviderFromGcp() {
+ return new ConformanceTestingTokenProvider(
+ "https://storage.googleapis.com/sigstore-conformance-testing-token/untrusted-testing-token.txt");
+ }
+
+ private final String tokenUrl;
+
+ private ConformanceTestingTokenProvider(String tokenUrl) {
+ this.tokenUrl = tokenUrl;
+ }
+
+ @Override
+ public boolean isEnabled(Map env) {
+ return true;
+ }
@Override
- public String getTokenString() throws Exception {
+ public String getTokenString(Map env) throws Exception {
HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build();
- URI fileUri =
- new URI(
- "https://raw.githubusercontent.com/sigstore-conformance/extremely-dangerous-public-oidc-beacon/refs/heads/current-token/oidc-token.txt");
+ URI fileUri = new URI(tokenUrl);
HttpRequest request =
HttpRequest.newBuilder()
.uri(fileUri)
diff --git a/tuf-cli/build.gradle.kts b/tuf-cli/build.gradle.kts
index 5b89d49a3..edc9a8bac 100644
--- a/tuf-cli/build.gradle.kts
+++ b/tuf-cli/build.gradle.kts
@@ -18,7 +18,7 @@ dependencies {
implementation(platform("com.google.oauth-client:google-oauth-client-bom:1.39.0"))
implementation("com.google.oauth-client:google-oauth-client")
- implementation("org.eclipse.jetty:jetty-server:12.1.5")
+ implementation("org.eclipse.jetty:jetty-server:12.1.10")
implementation("org.slf4j:slf4j-simple:2.0.17")