Skip to content

Commit

Permalink
Merge pull request #190 from sigstore/support-multiple-ctfe-keys
Browse files Browse the repository at this point in the history
Support multiple ctfe keys
  • Loading branch information
loosebazooka authored Oct 24, 2022
2 parents 35d8215 + b5798fc commit 2fa972d
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 57 deletions.
28 changes: 10 additions & 18 deletions sigstore-java/src/main/java/dev/sigstore/KeylessSigner.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import com.google.api.client.util.Preconditions;
import com.google.common.hash.Hashing;
import com.google.common.io.Resources;
import dev.sigstore.encryption.certificates.Certificates;
import dev.sigstore.encryption.signers.Signer;
import dev.sigstore.encryption.signers.Signers;
Expand Down Expand Up @@ -113,17 +112,14 @@ public KeylessSigner build() {
public Builder sigstorePublicDefaults()
throws IOException, InvalidAlgorithmParameterException, CertificateException,
InvalidKeySpecException, NoSuchAlgorithmException {
var fulcioCert =
Resources.toByteArray(
Resources.getResource("dev/sigstore/tuf/production/fulcio_v1.crt.pem"));
var ctfePublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/production/ctfe.pub"));
var rekorPublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/production/rekor.pub"));
fulcioClient(
FulcioClient.builder().build(),
FulcioVerifier.newFulcioVerifier(fulcioCert, ctfePublicKey));
rekorClient(RekorClient.builder().build(), RekorVerifier.newRekorVerifier(rekorPublicKey));
FulcioVerifier.newFulcioVerifier(
VerificationMaterial.Production.fulioCert(),
VerificationMaterial.Production.ctfePublicKeys()));
rekorClient(
RekorClient.builder().build(),
RekorVerifier.newRekorVerifier(VerificationMaterial.Production.rekorPublicKey()));
oidcClient(WebOidcClient.builder().build());
signer(Signers.newEcdsaSigner());
return this;
Expand All @@ -132,20 +128,16 @@ public Builder sigstorePublicDefaults()
public Builder sigstoreStagingDefaults()
throws IOException, InvalidAlgorithmParameterException, CertificateException,
InvalidKeySpecException, NoSuchAlgorithmException {
var fulcioCert =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/fulcio.crt.pem"));
var ctfePublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/ctfe.pub"));
var rekorPublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/rekor.pub"));
fulcioClient(
FulcioClient.builder()
.setServerUrl(URI.create(FulcioClient.STAGING_FULCIO_SERVER))
.build(),
FulcioVerifier.newFulcioVerifier(fulcioCert, ctfePublicKey));
FulcioVerifier.newFulcioVerifier(
VerificationMaterial.Staging.fulioCert(),
VerificationMaterial.Staging.ctfePublicKeys()));
rekorClient(
RekorClient.builder().setServerUrl(URI.create(RekorClient.STAGING_REKOR_SERVER)).build(),
RekorVerifier.newRekorVerifier(rekorPublicKey));
RekorVerifier.newRekorVerifier(VerificationMaterial.Staging.rekorPublicKey()));
oidcClient(WebOidcClient.builder().setIssuer(WebOidcClient.STAGING_DEX_ISSUER).build());
signer(Signers.newEcdsaSigner());
return this;
Expand Down
30 changes: 12 additions & 18 deletions sigstore-java/src/main/java/dev/sigstore/KeylessVerifier.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package dev.sigstore;

import com.google.api.client.util.Preconditions;
import com.google.common.io.Resources;
import dev.sigstore.encryption.certificates.Certificates;
import dev.sigstore.encryption.signers.Verifiers;
import dev.sigstore.fulcio.client.FulcioVerificationException;
Expand Down Expand Up @@ -78,31 +77,26 @@ public KeylessVerifier build() {
public Builder sigstorePublicDefaults()
throws IOException, InvalidAlgorithmParameterException, CertificateException,
InvalidKeySpecException, NoSuchAlgorithmException {
var fulcioCert =
Resources.toByteArray(
Resources.getResource("dev/sigstore/tuf/production/fulcio_v1.crt.pem"));
var ctfePublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/production/ctfe.pub"));
var rekorPublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/production/rekor.pub"));
fulcioVerifier(FulcioVerifier.newFulcioVerifier(fulcioCert, ctfePublicKey));
rekorClient(RekorClient.builder().build(), RekorVerifier.newRekorVerifier(rekorPublicKey));
fulcioVerifier(
FulcioVerifier.newFulcioVerifier(
VerificationMaterial.Production.fulioCert(),
VerificationMaterial.Production.ctfePublicKeys()));
rekorClient(
RekorClient.builder().build(),
RekorVerifier.newRekorVerifier(VerificationMaterial.Production.rekorPublicKey()));
return this;
}

public Builder sigstoreStagingDefaults()
throws IOException, InvalidAlgorithmParameterException, CertificateException,
InvalidKeySpecException, NoSuchAlgorithmException {
var fulcioCert =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/fulcio.crt.pem"));
var ctfePublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/ctfe.pub"));
var rekorPublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/rekor.pub"));
fulcioVerifier(FulcioVerifier.newFulcioVerifier(fulcioCert, ctfePublicKey));
fulcioVerifier(
FulcioVerifier.newFulcioVerifier(
VerificationMaterial.Staging.fulioCert(),
VerificationMaterial.Staging.ctfePublicKeys()));
rekorClient(
RekorClient.builder().setServerUrl(URI.create(RekorClient.STAGING_REKOR_SERVER)).build(),
RekorVerifier.newRekorVerifier(rekorPublicKey));
RekorVerifier.newRekorVerifier(VerificationMaterial.Staging.rekorPublicKey()));
return this;
}
}
Expand Down
66 changes: 66 additions & 0 deletions sigstore-java/src/main/java/dev/sigstore/VerificationMaterial.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2022 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 com.google.common.io.Resources;
import java.io.IOException;
import java.util.List;

/**
* A temporary partial copy of the TUF repos that supplies necessary keys for prod and staging
* environments. This should be replaced with an actual TUF implementation
*/
public class VerificationMaterial {

/** Verification material for *.sigstore.dev */
public static class Production {
public static byte[] fulioCert() throws IOException {
return Resources.toByteArray(
Resources.getResource("dev/sigstore/tuf/production/fulcio_v1.crt.pem"));
}

public static List<byte[]> ctfePublicKeys() throws IOException {
return List.of(
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/production/ctfe.pub")));
}

public static byte[] rekorPublicKey() throws IOException {
return Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/production/rekor.pub"));
}
}

/** Verification material for *.sigstage.dev */
public static class Staging {
public static byte[] fulioCert() throws IOException {
return Resources.toByteArray(
Resources.getResource("dev/sigstore/tuf/staging/fulcio.crt.pem"));
}

public static List<byte[]> ctfePublicKeys() throws IOException {
var ctfePublicKey =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/ctfe.pub"));
var ctfePublicKey2022 =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/ctfe_2022.pub"));
var ctfePublicKey2022_2 =
Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/ctfe_2022_2.pub"));
return List.of(ctfePublicKey, ctfePublicKey2022, ctfePublicKey2022_2);
}

public static byte[] rekorPublicKey() throws IOException {
return Resources.toByteArray(Resources.getResource("dev/sigstore/tuf/staging/rekor.pub"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@
import java.security.PublicKey;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.*;
import org.checkerframework.checker.nullness.qual.Nullable;

/** Verifier for fulcio {@link dev.sigstore.fulcio.client.SigningCertificate}. */
Expand All @@ -38,15 +36,18 @@ public class FulcioVerifier {
* Instantiate a new verifier.
*
* @param fulcioRoot fulcio's root certificate
* @param ctfePublicKey fulcio's certificate transparency log's public key
* @param ctfePublicKeys fulcio's certificate transparency log public keys (for all logs)
*/
public static FulcioVerifier newFulcioVerifier(byte[] fulcioRoot, byte @Nullable [] ctfePublicKey)
public static FulcioVerifier newFulcioVerifier(byte[] fulcioRoot, List<byte[]> ctfePublicKeys)
throws InvalidKeySpecException, NoSuchAlgorithmException, CertificateException, IOException,
InvalidAlgorithmParameterException {

PublicKey ctfePublicKeyObj = null;
if (ctfePublicKey != null) {
ctfePublicKeyObj = Keys.parsePublicKey(ctfePublicKey);
List<PublicKey> ctfePublicKeyObjs = null;
if (ctfePublicKeys != null && ctfePublicKeys.size() != 0) {
ctfePublicKeyObjs = new ArrayList<>();
for (var pk : ctfePublicKeys) {
ctfePublicKeyObjs.add(Keys.parsePublicKey(pk));
}
}

CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Expand All @@ -59,15 +60,25 @@ public static FulcioVerifier newFulcioVerifier(byte[] fulcioRoot, byte @Nullable
// encountered in verifyCertPath
new PKIXParameters(Collections.singleton(fulcioRootTrustAnchor));

return new FulcioVerifier(fulcioRootTrustAnchor, ctfePublicKeyObj);
return new FulcioVerifier(fulcioRootTrustAnchor, ctfePublicKeyObjs);
}

private FulcioVerifier(TrustAnchor fulcioRoot, @Nullable PublicKey ctfePublicKey) {
private FulcioVerifier(TrustAnchor fulcioRoot, @Nullable List<PublicKey> ctfePublicKeys) {
this.fulcioRoot = fulcioRoot;
if (ctfePublicKey != null) {
var ctLogInfo = new CTLogInfo(ctfePublicKey, "fulcio ct log", "unused-url");
if (ctfePublicKeys != null) {
var logInfos = new ArrayList<CTLogInfo>();
for (var pk : ctfePublicKeys) {
var ctLogInfo = new CTLogInfo(pk, "fulcio ct log", "unused-url");
logInfos.add(ctLogInfo);
}
this.ctVerifier =
new CTVerifier(logId -> Arrays.equals(logId, ctLogInfo.getID()) ? ctLogInfo : null);
new CTVerifier(
logId ->
logInfos
.stream()
.filter(ctLogInfo -> Arrays.equals(ctLogInfo.getID(), logId))
.findFirst()
.orElse(null));
} else {
ctVerifier = null;
}
Expand Down
4 changes: 2 additions & 2 deletions sigstore-java/src/main/resources/dev/sigstore/tuf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ We keep copies of the remote tuf repositories locally in
for interfacing with *.sigstage.dev

For this client to function we need the following keys
1. CTFE public key (`ctfe.pub` \
1. CTFE public keys (`ctfe.pub`, `ctfe_*.pub`) \
the public key for the certificate transparency log
2. Fulcio root cert (`fulcio_v1.crt.pem` or `fulcio.crt.pem`)\
2. Fulcio root cert (`fulcio_v1.crt.pem` or `fulcio.crt.pem`) \
the root certificate for fulcio issued certificates
3. Rekor public key (`rekor.pub`) \
the public key for the rekor transparency log
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh99xuRi6slBFd8VUJoK/rLigy4bY
eSYWO/fE6Br7r0D8NpMI94+A63LR/WvLxpUUGBpY8IJA3iU2telag5CRpA==
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8gEDKNme8AnXuPBgHjrtXdS6miHq
c24CRblNEOFpiJRngeq8Ko73Y+K18yRYVf1DXD4AVLwvKyzdNdl5n0jUSQ==
-----END PUBLIC KEY-----
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException;
import java.util.List;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -51,7 +52,7 @@ public static void loadResources() throws IOException {
Resources.getResource("dev/sigstore/samples/fulcio-response/valid/fulcio.crt.pem"));
ctfePub =
Resources.toByteArray(
Resources.getResource("dev/sigstore/samples/fulcio-response/valid/ctfe-ec.pub"));
Resources.getResource("dev/sigstore/samples/fulcio-response/valid/ctfe.pub"));
badCtfePub =
Resources.toByteArray(Resources.getResource("dev/sigstore/samples/keys/test-rsa.pub"));

Expand All @@ -67,7 +68,7 @@ public void validSigningCertAndDetachedSct()
NoSuchAlgorithmException, InvalidAlgorithmParameterException,
FulcioVerificationException {
var signingCertificate = SigningCertificate.newSigningCertificate(certs, sctBase64);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, ctfePub);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, List.of(ctfePub, badCtfePub));

fulcioVerifier.verifyCertChain(signingCertificate);
fulcioVerifier.verifySct(signingCertificate);
Expand All @@ -93,7 +94,7 @@ public void testVerifySct_noSct()
throws SerializationException, CertificateException, IOException,
InvalidAlgorithmParameterException, InvalidKeySpecException, NoSuchAlgorithmException {
var signingCertificate = SigningCertificate.newSigningCertificate(certs, null);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, ctfePub);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, List.of(ctfePub, badCtfePub));

try {
fulcioVerifier.verifySct(signingCertificate);
Expand All @@ -110,7 +111,7 @@ public void validSigningCertAndEmbeddedSct()
NoSuchAlgorithmException, InvalidAlgorithmParameterException,
FulcioVerificationException {
var signingCertificate = SigningCertificate.newSigningCertificate(certsWithEmbeddedSct, null);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, ctfePub);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, List.of(ctfePub, badCtfePub));

fulcioVerifier.verifyCertChain(signingCertificate);
fulcioVerifier.verifySct(signingCertificate);
Expand All @@ -122,7 +123,7 @@ public void invalidEmbeddedSct()
InvalidAlgorithmParameterException, InvalidKeySpecException, NoSuchAlgorithmException,
FulcioVerificationException {
var signingCertificate = SigningCertificate.newSigningCertificate(certsWithEmbeddedSct, null);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, badCtfePub);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, List.of(badCtfePub));

var fve =
Assertions.assertThrows(
Expand All @@ -136,7 +137,7 @@ public void invalidDetachedSct()
throws SerializationException, CertificateException, IOException,
InvalidAlgorithmParameterException, InvalidKeySpecException, NoSuchAlgorithmException {
var signingCertificate = SigningCertificate.newSigningCertificate(certs, sctBase64);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, badCtfePub);
var fulcioVerifier = FulcioVerifier.newFulcioVerifier(fulcioRoot, List.of(badCtfePub));

var fve =
Assertions.assertThrows(
Expand Down

0 comments on commit 2fa972d

Please sign in to comment.