Skip to content

Support multiple ctfe keys #190

New issue

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

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

Already on GitHub? Sign in to your account

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is temporary code but why not just parse the pub keys right here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh parse them into keys? I dunno, I guess we could stop sending byte[]s around.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it might be weird for each implementation to have to parse it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lemme handle this is a followup. We'll return certs, and keys instead of just bytes everywhere.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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