From dfecc1359b88fb84c15777afa3a20caba11ed25c Mon Sep 17 00:00:00 2001 From: Jack Leightcap Date: Wed, 3 Jan 2024 13:12:02 -0500 Subject: [PATCH] verify: init Signed-off-by: Jack Leightcap --- Cargo.toml | 3 +- src/bundle/mod.rs | 28 +- src/crypto/certificate.rs | 143 ++++++++- src/crypto/mod.rs | 2 + src/crypto/verification.rs | 8 + src/crypto/verification_key.rs | 64 +++- src/errors.rs | 3 + src/lib.rs | 3 + src/tuf/constants.rs | 1 + src/verify/mod.rs | 24 ++ src/verify/models.rs | 222 ++++++++++++++ src/verify/policy.rs | 284 ++++++++++++++++++ src/verify/verifier.rs | 197 ++++++++++++ tests/conformance/Cargo.toml | 2 + tests/conformance/conformance.rs | 67 +++++ .../data/repository/1.registry.npmjs.org.json | 23 ++ tests/data/repository/1.root.json | 119 ++------ tests/data/repository/1.snapshot.json | 32 ++ tests/data/repository/1.targets.json | 148 +++++++++ .../data/repository/2.registry.npmjs.org.json | 23 ++ tests/data/repository/2.root.json | 129 ++------ tests/data/repository/2.snapshot.json | 32 ++ tests/data/repository/2.targets.json | 135 +++++++++ tests/data/repository/registry.npmjs.org.json | 23 ++ tests/data/repository/rekor.json | 23 -- tests/data/repository/root.json | 129 ++------ tests/data/repository/snapshot.json | 52 ++-- tests/data/repository/staging.json | 15 - tests/data/repository/targets.json | 202 +++++++------ ...67072b6f89ddf1032273a78b.trusted_root.json | 86 ++++++ tests/data/repository/targets/artifact.pub | 4 - tests/data/repository/targets/ctfe.pub | 4 - ...40ca812d8ac47a128bf84963.trusted_root.json | 86 ++++++ tests/data/repository/targets/fulcio.crt.pem | 13 - .../data/repository/targets/fulcio_v1.crt.pem | 13 - ...8f8df61bc7274189122c123446248426.keys.json | 26 ++ ...2551fcaa870a30d4601ba1caf6f63699.keys.json | 26 ++ tests/data/repository/targets/rekor.0.pub | 4 - tests/data/repository/targets/rekor.json | 23 -- tests/data/repository/targets/rekor.pub | 4 - tests/data/repository/timestamp.json | 30 +- 41 files changed, 1906 insertions(+), 549 deletions(-) create mode 100644 src/crypto/verification.rs create mode 100644 src/verify/mod.rs create mode 100644 src/verify/models.rs create mode 100644 src/verify/policy.rs create mode 100644 src/verify/verifier.rs create mode 100644 tests/data/repository/1.registry.npmjs.org.json create mode 100644 tests/data/repository/1.snapshot.json create mode 100644 tests/data/repository/1.targets.json create mode 100644 tests/data/repository/2.registry.npmjs.org.json create mode 100644 tests/data/repository/2.snapshot.json create mode 100644 tests/data/repository/2.targets.json create mode 100644 tests/data/repository/registry.npmjs.org.json delete mode 100644 tests/data/repository/rekor.json delete mode 100644 tests/data/repository/staging.json create mode 100644 tests/data/repository/targets/6494317303d0e04509a30b239bf8290057164fba67072b6f89ddf1032273a78b.trusted_root.json delete mode 100644 tests/data/repository/targets/artifact.pub delete mode 100644 tests/data/repository/targets/ctfe.pub create mode 100644 tests/data/repository/targets/fa2ca05656176f993fd616fa8586f3deeaacfb891dfb6f58e02b26073cb0233a52b7e66338d0053c8549f551485581141094c2de40ca812d8ac47a128bf84963.trusted_root.json delete mode 100644 tests/data/repository/targets/fulcio.crt.pem delete mode 100644 tests/data/repository/targets/fulcio_v1.crt.pem create mode 100644 tests/data/repository/targets/registry.npmjs.org/7a8ec9678ad824cdccaa7a6dc0961caf8f8df61bc7274189122c123446248426.keys.json create mode 100644 tests/data/repository/targets/registry.npmjs.org/881a853ee92d8cf513b07c164fea36b22a7305c256125bdfffdc5c65a4205c4c3fc2b5bcc98964349167ea68d40b8cd02551fcaa870a30d4601ba1caf6f63699.keys.json delete mode 100644 tests/data/repository/targets/rekor.0.pub delete mode 100644 tests/data/repository/targets/rekor.json delete mode 100644 tests/data/repository/targets/rekor.pub diff --git a/Cargo.toml b/Cargo.toml index 6a6422c2e9..81feaf108d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ readme = "README.md" repository = "https://github.com/sigstore/sigstore-rs" [features] -default = ["full-native-tls", "cached-client", "tuf", "sign"] +default = ["full-native-tls", "cached-client", "tuf", "sign", "verify"] wasm = ["getrandom/js"] full-native-tls = [ @@ -43,6 +43,7 @@ rekor = ["reqwest"] tuf = ["tough", "regex"] sign = [] +verify = [] cosign-native-tls = [ "oci-distribution/native-tls", diff --git a/src/bundle/mod.rs b/src/bundle/mod.rs index 2b9b9cb73c..1bf8e8d840 100644 --- a/src/bundle/mod.rs +++ b/src/bundle/mod.rs @@ -15,21 +15,45 @@ //! Useful types for Sigstore bundles. use std::fmt::Display; +use std::str::FromStr; pub use sigstore_protobuf_specs::Bundle; +macro_rules! required { + ($($base:expr )? ; $first_attr:ident $( . $rest_attrs:ident)* $( , $else_err:expr)?) => { + $( $base . )? $first_attr.as_ref() + $( + .and_then(|v| v.$rest_attrs.as_ref()) + )* + $( .ok_or($else_err) )? + } +} +pub(crate) use required; + // Known Sigstore bundle media types. #[derive(Clone, Copy, Debug)] pub enum Version { - _Bundle0_1, + Bundle0_1, Bundle0_2, } impl Display for Version { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.write_str(match &self { - Version::_Bundle0_1 => "application/vnd.dev.sigstore.bundle+json;version=0.1", + Version::Bundle0_1 => "application/vnd.dev.sigstore.bundle+json;version=0.1", Version::Bundle0_2 => "application/vnd.dev.sigstore.bundle+json;version=0.2", }) } } + +impl FromStr for Version { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "application/vnd.dev.sigstore.bundle+json;version=0.1" => Ok(Version::Bundle0_1), + "application/vnd.dev.sigstore.bundle+json;version=0.2" => Ok(Version::Bundle0_2), + _ => Err(()), + } + } +} diff --git a/src/crypto/certificate.rs b/src/crypto/certificate.rs index 943df12923..9310efbfbc 100644 --- a/src/crypto/certificate.rs +++ b/src/crypto/certificate.rs @@ -16,7 +16,7 @@ use chrono::{DateTime, NaiveDateTime, Utc}; use const_oid::db::rfc5912::ID_KP_CODE_SIGNING; use x509_cert::{ - ext::pkix::{ExtendedKeyUsage, KeyUsage, KeyUsages, SubjectAltName}, + ext::pkix::{constraints, ExtendedKeyUsage, KeyUsage, KeyUsages, SubjectAltName}, Certificate, }; @@ -120,6 +120,147 @@ fn verify_expiration(certificate: &Certificate, integrated_time: i64) -> Result< Ok(()) } +/// Check if the given certificate is a leaf in the context of the Sigstore profile. +/// +/// * It is not a root or intermediate CA; +/// * It has `keyUsage.digitalSignature` +/// * It has `CODE_SIGNING` as an `ExtendedKeyUsage`. +/// +/// This function does not evaluate the trustworthiness of the certificate. +pub(crate) fn is_leaf(certificate: &Certificate) -> Result { + // NOTE(jl): following structure of sigstore-python over the slightly different handling found + // in `verify_key_usages`. + let tbs = &certificate.tbs_certificate; + + // Only V3 certificates should appear in the context of Sigstore; earlier versions of X.509 lack + // extensions and have ambiguous CA behavior. + if tbs.version != x509_cert::Version::V3 { + return Err(SigstoreError::CertificateUnsupportedVersionError); + } + + if is_ca(certificate)? { + return Ok(false); + }; + + let digital_signature = match tbs.get::()? { + None => { + return Err(SigstoreError::InvalidCertError( + "invalid X.509 certificate: missing KeyUsage".to_string(), + )) + } + Some((_, key_usage)) => key_usage.digital_signature(), + }; + + if !digital_signature { + return Err(SigstoreError::InvalidCertError( + "invalid certificate for Sigstore purposes: missing digital signature usage" + .to_string(), + )); + } + + // Finally, we check to make sure the leaf has an `ExtendedKeyUsages` + // extension that includes a codesigning entitlement. Sigstore should + // never issue a leaf that doesn't have this extended usage. + + let extended_key_usage = match tbs.get::()? { + None => { + return Err(SigstoreError::InvalidCertError( + "invalid X.509 certificate: missing ExtendedKeyUsage".to_string(), + )) + } + Some((_, extended_key_usage)) => extended_key_usage, + }; + + return Ok(extended_key_usage.0.contains(&ID_KP_CODE_SIGNING)); +} + +/// Checks if the given `certificate` is a CA certificate. +/// +/// This does **not** indicate trustworthiness of the given `certificate`, only if it has the +/// appropriate interior state. +/// +/// This function is **not** naively invertible: users **must** use the dedicated `is_leaf` +/// utility function to determine whether a particular leaf upholds Sigstore's invariants. +pub(crate) fn is_ca(certificate: &Certificate) -> Result { + let tbs = &certificate.tbs_certificate; + + // Only V3 certificates should appear in the context of Sigstore; earlier versions of X.509 lack + // extensions and have ambiguous CA behavior. + if tbs.version != x509_cert::Version::V3 { + return Err(SigstoreError::CertificateUnsupportedVersionError); + } + + // Valid CA certificates must have the following set: + // + // - `BasicKeyUsage.keyCertSign` + // - `BasicConstraints.ca` + // + // Any other combination of states is inconsistent and invalid, meaning + // that we won't consider the certificate a valid non-CA leaf. + + let ca = match tbs.get::()? { + None => return Ok(false), + Some((false, _)) => { + // BasicConstraints must be marked as critical, per RFC 5280 4.2.1.9. + return Err(SigstoreError::InvalidCertError( + "invalid X.509 certificate: non-critical BasicConstraints in CA".to_string(), + )); + } + Some((true, v)) => v.ca, + }; + + let key_cert_sign = match tbs.get::()? { + None => { + return Err(SigstoreError::InvalidCertError( + "invalid X.509 certificate: missing KeyUsage".to_string(), + )) + } + Some((_, v)) => v.key_cert_sign(), + }; + + // both states set, this is a CA. + if ca && key_cert_sign { + return Ok(true); + } + + if !(ca || key_cert_sign) { + return Ok(false); + } + + // Anything else is an invalid state that should never occur. + return Err(SigstoreError::InvalidCertError(format!( + "invalid certificate states: KeyUsage.keyCertSign={}, BasicConstraints.ca={}", + key_cert_sign, ca + ))); +} + +/// Returns `True` if and only if the given `Certificate` indicates +/// that it's a root CA. +/// +/// This is **not** a verification function, and it does not establish +/// the trustworthiness of the given certificate. +pub(crate) fn is_root_ca(certificate: &Certificate) -> Result { + // NOTE(ww): This function is obnoxiously long to make the different + // states explicit. + + let tbs = &certificate.tbs_certificate; + + // Only V3 certificates should appear in the context of Sigstore; earlier versions of X.509 lack + // extensions and have ambiguous CA behavior. + if tbs.version != x509_cert::Version::V3 { + return Err(SigstoreError::CertificateUnsupportedVersionError); + } + + // Non-CAs can't possibly be root CAs. + if !is_ca(certificate)? { + return Ok(false); + } + + // A certificate that is its own issuer and signer is considered a root CA. + // TODO(jl): verify_directly_issued_by + todo!() +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/crypto/mod.rs b/src/crypto/mod.rs index c8a35e22bf..adfa82ba5e 100644 --- a/src/crypto/mod.rs +++ b/src/crypto/mod.rs @@ -177,6 +177,8 @@ pub enum Signature<'a> { pub(crate) mod certificate; #[cfg(feature = "cert")] pub(crate) mod certificate_pool; +#[cfg(feature = "cert")] +pub(crate) use certificate_pool::CertificatePool; pub mod verification_key; diff --git a/src/crypto/verification.rs b/src/crypto/verification.rs new file mode 100644 index 0000000000..a0a6ddcf2d --- /dev/null +++ b/src/crypto/verification.rs @@ -0,0 +1,8 @@ +use rustls_pki_types::CertificateDer; +use webpki::TrustAnchor; + +/// Machinery for Sigstore end entity certificate verification. +struct CertificateVerificationContext<'a> { + pub trust_anchors: Vec>, + pub intermediate_certs: Vec>, +} diff --git a/src/crypto/verification_key.rs b/src/crypto/verification_key.rs index 1cf40d7eed..f6881f2574 100644 --- a/src/crypto/verification_key.rs +++ b/src/crypto/verification_key.rs @@ -18,7 +18,7 @@ use const_oid::db::rfc5912::{ID_EC_PUBLIC_KEY, RSA_ENCRYPTION}; use ed25519::pkcs8::DecodePublicKey as ED25519DecodePublicKey; use rsa::{pkcs1v15, pss}; use sha2::{Digest, Sha256, Sha384}; -use signature::{DigestVerifier, Verifier}; +use signature::{hazmat::PrehashVerifier, DigestVerifier, Verifier}; use std::convert::TryFrom; use x509_cert::{der::referenced::OwnedToRef, spki::SubjectPublicKeyInfoOwned}; @@ -329,6 +329,68 @@ impl CosignVerificationKey { } } } + + /// Verify the signature provided has been actually generated by the given key + /// when signing the provided prehashed message. + pub fn verify_prehash(&self, signature: Signature, msg: &[u8]) -> Result<()> { + let sig = match signature { + Signature::Raw(data) => data.to_owned(), + Signature::Base64Encoded(data) => BASE64_STD_ENGINE.decode(data)?, + }; + + match self { + CosignVerificationKey::RSA_PSS_SHA256(inner) => { + let sig = pss::Signature::try_from(sig.as_slice())?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + CosignVerificationKey::RSA_PSS_SHA384(inner) => { + let sig = pss::Signature::try_from(sig.as_slice())?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + CosignVerificationKey::RSA_PSS_SHA512(inner) => { + let sig = pss::Signature::try_from(sig.as_slice())?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + CosignVerificationKey::RSA_PKCS1_SHA256(inner) => { + let sig = pkcs1v15::Signature::try_from(sig.as_slice())?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + CosignVerificationKey::RSA_PKCS1_SHA384(inner) => { + let sig = pkcs1v15::Signature::try_from(sig.as_slice())?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + CosignVerificationKey::RSA_PKCS1_SHA512(inner) => { + let sig = pkcs1v15::Signature::try_from(sig.as_slice())?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + // ECDSA signatures are encoded in der. + CosignVerificationKey::ECDSA_P256_SHA256_ASN1(inner) => { + let sig = ecdsa::Signature::from_der(&sig)?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + CosignVerificationKey::ECDSA_P384_SHA384_ASN1(inner) => { + let sig = ecdsa::Signature::from_der(&sig)?; + inner + .verify_prehash(msg, &sig) + .map_err(|_| SigstoreError::PublicKeyVerificationError) + } + _ => unimplemented!("Ed25519 doesn't implement verify_prehash"), + } + } } #[cfg(test)] diff --git a/src/errors.rs b/src/errors.rs index 22b87e95cb..e6b6b723ff 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -109,6 +109,9 @@ pub enum SigstoreError { #[error("Certificate pool error: {0}")] CertificatePoolError(String), + #[error("Certificate invalid: {0}")] + InvalidCertError(String), + #[error("Signing session expired")] ExpiredSigningSession(), diff --git a/src/lib.rs b/src/lib.rs index 0c648b5f62..3346d8d57e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -288,5 +288,8 @@ pub mod tuf; mod bundle; pub use bundle::Bundle; +#[cfg(feature = "verify")] +pub mod verify; + #[cfg(feature = "sign")] pub mod sign; diff --git a/src/tuf/constants.rs b/src/tuf/constants.rs index 325989706c..0529d1128b 100644 --- a/src/tuf/constants.rs +++ b/src/tuf/constants.rs @@ -23,3 +23,4 @@ macro_rules! tuf_resource { } pub(crate) const SIGSTORE_ROOT: &[u8] = tuf_resource!("prod/root.json"); +pub(crate) const _SIGSTORE_TRUST_BUNDLE: &[u8] = tuf_resource!("prod/trusted_root.json"); diff --git a/src/verify/mod.rs b/src/verify/mod.rs new file mode 100644 index 0000000000..5954d45bd6 --- /dev/null +++ b/src/verify/mod.rs @@ -0,0 +1,24 @@ +// +// Copyright 2023 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. + +//! Verifier for Sigstore bundles and associated types and policies. +mod models; +pub use models::{VerificationError, VerificationMaterials, VerificationResult}; + +pub mod policy; +pub use policy::VerificationPolicy; + +mod verifier; +pub use verifier::Verifier; diff --git a/src/verify/models.rs b/src/verify/models.rs new file mode 100644 index 0000000000..dcf6e39b68 --- /dev/null +++ b/src/verify/models.rs @@ -0,0 +1,222 @@ +// +// Copyright 2023 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. + +use std::{ + cell::OnceCell, + io::{self, Read}, + str::FromStr, +}; + +use crate::{ + bundle::required, + bundle::Version as BundleVersion, + crypto::certificate::{is_leaf, is_root_ca}, + errors::SigstoreError, + rekor::models::log_entry, + rekor::models::{ + log_entry::{InclusionProof, Verification}, + LogEntry, + }, +}; + +use base64::{engine::general_purpose::STANDARD as base64, Engine as _}; +use pkcs8::der::Decode; +use sha2::{Digest, Sha256}; +use sigstore_protobuf_specs::Bundle; +use thiserror::Error; +use x509_cert::Certificate; + +#[derive(Error, Debug)] +pub enum VerificationError { + #[error("Certificate expired before time of signing")] + CertificateExpired, + + #[error("Certificate malformed")] + CertificateMalformed, + + #[error("Failed to verify certificate")] + CertificateVerificationFailure, + + #[error("Certificate cannot be used for verification: {0}")] + CertificateTypeError(String), + + #[error("Failed to verify that the signature corresponds to the input")] + SignatureVerificationFailure, + + #[error("{0}")] + PolicyFailure(String), +} +pub type VerificationResult = Result<(), VerificationError>; + +pub struct VerificationMaterials { + pub input_digest: Vec, + pub certificate: Certificate, + pub signature: Vec, + rekor_entry: OnceCell, +} + +impl VerificationMaterials { + pub fn new( + input: &mut R, + certificate: Certificate, + signature: Vec, + offline: bool, + rekor_entry: Option, + ) -> Option { + let mut hasher = Sha256::new(); + io::copy(input, &mut hasher).ok()?; + + if offline && rekor_entry.is_none() { + // offline verification requires a Rekor entry + return None; + } + + let rekor_entry = if let Some(rekor_entry) = rekor_entry { + let cell = OnceCell::new(); + + // TODO(tnytown): Switch to setting if offline when Rekor fetching is implemented. + #[allow(clippy::unwrap_used)] + cell.set(rekor_entry).unwrap(); + + cell + } else { + Default::default() + }; + + Some(Self { + input_digest: hasher.finalize().to_vec(), + rekor_entry, + certificate, + signature, + }) + } + + /// Constructs a VerificationMaterials from the given Bundle. + /// + /// For details on bundle semantics, please refer to [VerificationMaterial]. + /// + /// [VerificationMaterial]: sigstore_protobuf_specs::DevSigstoreBundleV1VerificationMaterial + /// + /// TODO(tnytown): Determine if this type should yield SigstoreResult. + pub fn from_bundle(input: &mut R, bundle: Bundle, offline: bool) -> Option { + fn certificate_from_base64(encoded: &str) -> Option { + Certificate::from_der(&base64.decode(encoded).ok()?).ok() + } + + let certs = required!( + bundle; + verification_material.x_509_certificate_chain.certificates, + SigstoreError::SigstoreBundleMalformedError("Cannot find required field in bundle".to_string()) + ).ok()?; + + // Parse the certificates. The first entry in the chain MUST be a leaf certificate, and the + // rest of the chain MUST NOT include a root CA or any intermediate CAs that appear in an + // independent root of trust. + let certs = certs + .iter() + .map(|cert| certificate_from_base64(cert.raw_bytes.as_ref()?)) + .collect::>>()?; + let [leaf_cert, chain_certs @ ..] = &certs[..] else { + return None; + }; + + if is_leaf(leaf_cert).is_err() { + return None; + } + + for chain_cert in chain_certs { + if is_root_ca(chain_cert).is_ok() { + return None; + } + } + + let signature = base64 + .decode(required!(bundle; message_signature.signature)?) + .ok()?; + let tlog_entries = required!(bundle; verification_material.tlog_entries)?; + if tlog_entries.len() != 1 { + // Expected exactly one tlog entry. + return None; + } + let tlog_entry = &tlog_entries[0]; + + let inclusion_promise = &tlog_entry.inclusion_promise; + let inclusion_proof = tlog_entry.inclusion_proof.as_ref(); + + let has_checkpoint = required!(; inclusion_proof.checkpoint.envelope).is_some(); + match BundleVersion::from_str(&bundle.media_type?).ok()? { + BundleVersion::Bundle0_1 => { + if inclusion_promise.is_none() { + // 0.1 bundle must contain inclusion promise + return None; + } + + if inclusion_proof.is_some() && !has_checkpoint { + // TODO(tnytown): Act here. + // NOTE(jl): in sigstore-python, this is a no-op that prints a warning log. + } + } + BundleVersion::Bundle0_2 => { + inclusion_proof?; + if !has_checkpoint { + // inclusion proofs must contain checkpoints + return None; // FIXME(jl): this raises an error in sigstore-python. + } + } + } + + let parsed_inclusion_proof = if inclusion_proof.is_some() && has_checkpoint { + Some(InclusionProof { + checkpoint: required!(; inclusion_proof.checkpoint.envelope)?.clone(), + hashes: required!(; inclusion_proof.hashes)?.clone(), + log_index: required!(; inclusion_proof.log_index)?.parse().ok()?, + root_hash: required!(; inclusion_proof.log_index)?.clone(), + tree_size: required!(; inclusion_proof.tree_size)?.parse().ok()?, + }) + } else { + None + }; + + let canonicalized_body = { + let decoded = base64 + .decode(tlog_entry.canonicalized_body.as_ref()?) + .ok()?; + serde_json::from_slice(&decoded).ok()? + }; + // required!(tlog_entry; log_id.key_id)?.clone(); + let entry = LogEntry { + uuid: "".to_string(), + body: log_entry::Body::hashedrekord(canonicalized_body), + attestation: None, + integrated_time: required!(tlog_entry; integrated_time)?.parse().ok()?, + log_i_d: "".into(), + log_index: required!(tlog_entry; log_index)?.parse().ok()?, + verification: Verification { + inclusion_proof: parsed_inclusion_proof, + signed_entry_timestamp: required!(; inclusion_promise.signed_entry_timestamp)? + .clone(), + }, + }; + + Self::new(input, leaf_cert.clone(), signature, offline, Some(entry)) + } + + /// Retrieves the [LogEntry] for the materials. + pub fn rekor_entry(&self) -> &LogEntry { + // TODO(tnytown): Fetch online Rekor entry, confirm consistency, and get_or_init here. + #[allow(clippy::unwrap_used)] + self.rekor_entry.get().unwrap() + } +} diff --git a/src/verify/policy.rs b/src/verify/policy.rs new file mode 100644 index 0000000000..8f0791c50f --- /dev/null +++ b/src/verify/policy.rs @@ -0,0 +1,284 @@ +// Copyright 2023 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. + +//! Verifiers for certificate metadata. +//! +//! + +use const_oid::ObjectIdentifier; +use x509_cert::ext::pkix::{name::GeneralName, SubjectAltName}; + +use crate::verify::VerificationError; + +use super::models::VerificationResult; + +macro_rules! oids { + ($($name:ident = $value:literal),+) => { + $(const $name: ObjectIdentifier = ObjectIdentifier::new_unwrap($value);)+ + }; +} + +macro_rules! impl_policy { + ($policy:ident, $oid:expr, $doc:literal) => { + #[doc = $doc] + pub struct $policy(pub String); + + impl const_oid::AssociatedOid for $policy { + const OID: ObjectIdentifier = $oid; + } + + impl SingleX509ExtPolicy for $policy { + fn new>(val: S) -> Self { + Self(val.as_ref().to_owned()) + } + + fn name() -> &'static str { + stringify!($policy) + } + + fn value(&self) -> &str { + &self.0 + } + } + }; +} + +oids! { + OIDC_ISSUER_OID = "1.3.6.1.4.1.57264.1.1", + OIDC_GITHUB_WORKFLOW_TRIGGER_OID = "1.3.6.1.4.1.57264.1.2", + OIDC_GITHUB_WORKFLOW_SHA_OID = "1.3.6.1.4.1.57264.1.3", + OIDC_GITHUB_WORKFLOW_NAME_OID = "1.3.6.1.4.1.57264.1.4", + OIDC_GITHUB_WORKFLOW_REPOSITORY_OID = "1.3.6.1.4.1.57264.1.5", + OIDC_GITHUB_WORKFLOW_REF_OID = "1.3.6.1.4.1.57264.1.6", + OTHERNAME_OID = "1.3.6.1.4.1.57264.1.7" + +} + +/// A trait for policies that check a single textual value against a X.509 extension. +pub trait SingleX509ExtPolicy { + fn new>(val: S) -> Self; + fn name() -> &'static str; + fn value(&self) -> &str; +} + +impl VerificationPolicy for T { + fn verify(&self, cert: &x509_cert::Certificate) -> VerificationResult { + let extensions = cert.tbs_certificate.extensions.as_deref().unwrap_or(&[]); + let mut extensions = extensions.iter().filter(|ext| ext.extn_id == T::OID); + + // Check for exactly one extension. + let (Some(ext), None) = (extensions.next(), extensions.next()) else { + return Err(VerificationError::PolicyFailure( + "Cannot get policy extensions from certificate".into(), + )); + }; + + // Parse raw string without DER encoding. + let val = std::str::from_utf8(ext.extn_value.as_bytes()) + .expect("failed to parse constructed Extension!"); + + if val != self.value() { + Err(VerificationError::PolicyFailure(format!( + "Certificate's {} does not match (got {}, expected {})", + T::name(), + val, + self.value() + ))) + } else { + Ok(()) + } + } +} + +impl_policy!( + OIDCIssuer, + OIDC_ISSUER_OID, + "Checks the certificate's OIDC issuer." +); + +impl_policy!( + GitHubWorkflowTrigger, + OIDC_GITHUB_WORKFLOW_TRIGGER_OID, + "Checks the certificate's GitHub Actions workflow trigger." +); + +impl_policy!( + GitHubWorkflowSHA, + OIDC_GITHUB_WORKFLOW_SHA_OID, + "Checks the certificate's GitHub Actions workflow commit SHA." +); + +impl_policy!( + GitHubWorkflowName, + OIDC_GITHUB_WORKFLOW_NAME_OID, + "Checks the certificate's GitHub Actions workflow name." +); + +impl_policy!( + GitHubWorkflowRepository, + OIDC_GITHUB_WORKFLOW_REPOSITORY_OID, + "Checks the certificate's GitHub Actions workflow repository." +); + +impl_policy!( + GitHubWorkflowRef, + OIDC_GITHUB_WORKFLOW_REF_OID, + "Checks the certificate's GitHub Actions workflow ref." +); + +/// An interface that all policies must conform to. +pub trait VerificationPolicy { + fn verify(&self, cert: &x509_cert::Certificate) -> VerificationResult; +} + +/// The "any of" policy, corresponding to a logical OR between child policies. +/// +/// An empty list of child policies is considered trivially invalid. +pub struct AnyOf<'a> { + children: Vec<&'a dyn VerificationPolicy>, +} + +impl<'a> AnyOf<'a> { + pub fn new>(policies: I) -> Self { + Self { + children: policies.into_iter().collect(), + } + } +} + +impl VerificationPolicy for AnyOf<'_> { + fn verify(&self, cert: &x509_cert::Certificate) -> VerificationResult { + self.children + .iter() + .find(|policy| policy.verify(cert).is_ok()) + .ok_or(VerificationError::PolicyFailure(format!( + "0 of {} policies succeeded", + self.children.len() + ))) + .map(|_| ()) + } +} + +/// The "all of" policy, corresponding to a logical AND between child policies. +/// +/// An empty list of child policies is considered trivially invalid. +pub struct AllOf<'a> { + children: Vec<&'a dyn VerificationPolicy>, +} + +impl<'a> AllOf<'a> { + pub fn new>(policies: I) -> Self { + Self { + children: policies.into_iter().collect(), + } + } +} + +impl VerificationPolicy for AllOf<'_> { + fn verify(&self, cert: &x509_cert::Certificate) -> VerificationResult { + // Without this, we'd consider empty lists of child policies trivially valid. + // This is almost certainly not what the user wants and is a potential + // source of API misuse, so we explicitly disallow it. + if self.children.is_empty() { + return Err(VerificationError::PolicyFailure( + "no child policies to verify".into(), + )); + } + + let results = self.children.iter().map(|policy| policy.verify(cert)); + let failures: Vec<_> = results + .filter_map(|result| result.err()) + .map(|err| err.to_string()) + .collect(); + + if failures.is_empty() { + Ok(()) + } else { + Err(VerificationError::PolicyFailure(format!( + "{} of {} policies failed:\n- {}", + failures.len(), + self.children.len(), + failures.join("\n- ") + ))) + } + } +} + +pub(crate) struct UnsafeNoOp; + +impl VerificationPolicy for UnsafeNoOp { + fn verify(&self, _cert: &x509_cert::Certificate) -> VerificationResult { + eprintln!("unsafe (no-op) verification policy used! no verification performed!"); + VerificationResult::Ok(()) + } +} + +/// Verifies the certificate's "identity", corresponding to the X.509v3 SAN. +/// Identities are verified modulo an OIDC issuer, so the issuer's URI +/// is also required. +/// +/// Supported SAN types include emails, URIs, and Sigstore-specific "other names". +pub struct Identity { + identity: String, + issuer: OIDCIssuer, +} + +impl Identity { + pub fn new(identity: A, issuer: B) -> Self + where + A: AsRef, + B: AsRef, + { + Self { + identity: identity.as_ref().to_owned(), + issuer: OIDCIssuer::new(issuer), + } + } +} + +impl VerificationPolicy for Identity { + fn verify(&self, cert: &x509_cert::Certificate) -> VerificationResult { + if let err @ Err(_) = self.issuer.verify(cert) { + return err; + } + + let (_, san): (bool, SubjectAltName) = match cert.tbs_certificate.get() { + Ok(Some(result)) => result, + _ => return Err(VerificationError::CertificateMalformed), + }; + + let names: Vec<_> = san + .0 + .iter() + .filter_map(|name| match name { + GeneralName::Rfc822Name(name) => Some(name.as_str()), + GeneralName::UniformResourceIdentifier(name) => Some(name.as_str()), + GeneralName::OtherName(name) if name.type_id == OTHERNAME_OID => { + std::str::from_utf8(name.value.value()).ok() + } + _ => None, + }) + .collect(); + + if names.contains(&self.identity.as_str()) { + Ok(()) + } else { + Err(VerificationError::PolicyFailure(format!( + "Certificate's SANs do not match {}; actual SANs: {}", + self.identity, + names.join(", ") + ))) + } + } +} diff --git a/src/verify/verifier.rs b/src/verify/verifier.rs new file mode 100644 index 0000000000..dd70b195cd --- /dev/null +++ b/src/verify/verifier.rs @@ -0,0 +1,197 @@ +// Copyright 2023 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. + +use std::cell::OnceCell; + +use const_oid::db::rfc5280::ID_KP_CODE_SIGNING; +use pkcs8::der::Encode; +use rustls_pki_types::UnixTime; +use x509_cert::ext::pkix::{ExtendedKeyUsage, KeyUsage}; + +use crate::{ + crypto::{CertificatePool, CosignVerificationKey, Signature}, + errors::Result as SigstoreResult, + rekor::apis::configuration::Configuration as RekorConfiguration, + tuf::{Repository, SigstoreRepository}, + verify::VerificationError, +}; + +use super::{models::VerificationMaterials, policy::VerificationPolicy, VerificationResult}; + +pub struct Verifier<'a, R: Repository> { + #[allow(dead_code)] + rekor_config: RekorConfiguration, + trust_repo: R, + cert_pool: OnceCell>, +} + +impl<'a, R: Repository> Verifier<'a, R> { + pub fn new(rekor_config: RekorConfiguration, trust_repo: R) -> SigstoreResult { + Ok(Self { + rekor_config, + cert_pool: Default::default(), + trust_repo, + }) + } + + /// TODO(tnytown): Evil (?) interior mutability hack to work around lifetime issues. + fn cert_pool(&'a self) -> SigstoreResult<&CertificatePool<'a>> { + let init_cert_pool = || { + let certs = self.trust_repo.fulcio_certs()?; + CertificatePool::from_certificates(certs, []) + }; + + let cert_pool = init_cert_pool()?; + Ok(self.cert_pool.get_or_init(|| cert_pool)) + } + + pub fn verify( + &'a self, + materials: VerificationMaterials, + policy: &impl VerificationPolicy, + ) -> VerificationResult { + let store = self + .cert_pool() + .expect("Failed to construct certificate pool"); + + // In order to verify an artifact, we need to achieve the following: + // + // 1) Verify that the signing certificate is signed by the certificate + // chain and that the signing certificate was valid at the time + // of signing. + // 2) Verify that the signing certificate belongs to the signer. + // 3) Verify that the artifact signature was signed by the public key in the + // signing certificate. + // 4) Verify that the Rekor entry is consistent with the other signing + // materials (preventing CVE-2022-36056) + // 5) Verify the inclusion proof supplied by Rekor for this artifact, + // if we're doing online verification. + // 6) Verify the Signed Entry Timestamp (SET) supplied by Rekor for this + // artifact. + // 7) Verify that the signing certificate was valid at the time of + // signing by comparing the expiry against the integrated timestamp. + + // 1) Verify that the signing certificate is signed by the root certificate and that the + // signing certificate was valid at the time of signing. + + // 1) Verify that the signing certificate is signed by the certificate + // chain and that the signing certificate was valid at the time + // of signing. + let issued_at = materials + .certificate + .tbs_certificate + .validity + .not_before + .to_unix_duration(); + let cert_der = &materials + .certificate + .to_der() + .expect("failed to DER-encode constructed Certificate!"); + store + .verify_cert_with_time(cert_der, UnixTime::since_unix_epoch(issued_at)) + .or(Err(VerificationError::CertificateVerificationFailure))?; + + // 2) Verify that the signing certificate belongs to the signer. + + // TODO(tnytown): How likely is a malformed certificate in this position? Do we want to + // account for it and create an error type as opposed to unwrapping? + let (_, key_usage_ext): (bool, KeyUsage) = materials + .certificate + .tbs_certificate + .get() + .expect("Malformed certificate") + .expect("Malformed certificate"); + + if !key_usage_ext.digital_signature() { + return Err(VerificationError::CertificateTypeError( + "Key usage is not of type `digital signature`".into(), + )); + } + + let (_, extended_key_usage_ext): (bool, ExtendedKeyUsage) = materials + .certificate + .tbs_certificate + .get() + .expect("Malformed certificate") + .expect("Malformed certificate"); + + if !extended_key_usage_ext.0.contains(&ID_KP_CODE_SIGNING) { + return Err(VerificationError::CertificateTypeError( + "Extended key usage does not contain `code signing`".into(), + )); + } + + policy.verify(&materials.certificate)?; + + // 3) Verify that the signature was signed by the public key in the signing certificate + let signing_key: SigstoreResult = (&materials + .certificate + .tbs_certificate + .subject_public_key_info) + .try_into(); + + let signing_key = + signing_key.expect("Malformed certificate (cannot deserialize public key)"); + + signing_key + .verify_prehash( + Signature::Raw(&materials.signature), + &materials.input_digest, + ) + .or(Err(VerificationError::SignatureVerificationFailure))?; + + // 4) Verify that the Rekor entry is consistent with the other signing + // materials + let log_entry = materials.rekor_entry(); + + // 5) Verify the inclusion proof supplied by Rekor for this artifact, + // if we're doing online verification. + // TODO(tnytown): Merkle inclusion + + // 6) Verify the Signed Entry Timestamp (SET) supplied by Rekor for this + // artifact. + // TODO(tnytown) SET verification + + // 7) Verify that the signing certificate was valid at the time of + // signing by comparing the expiry against the integrated timestamp. + let integrated_time = log_entry.integrated_time as u64; + let not_before = materials + .certificate + .tbs_certificate + .validity + .not_before + .to_unix_duration() + .as_secs(); + let not_after = materials + .certificate + .tbs_certificate + .validity + .not_after + .to_unix_duration() + .as_secs(); + if !(not_before <= integrated_time && integrated_time <= not_after) { + return Err(VerificationError::CertificateExpired); + } + + Ok(()) + } +} + +impl<'a> Verifier<'a, SigstoreRepository> { + pub fn production() -> SigstoreResult> { + let updater = SigstoreRepository::new(None)?; + + Verifier::<'a, SigstoreRepository>::new(Default::default(), updater) + } +} diff --git a/tests/conformance/Cargo.toml b/tests/conformance/Cargo.toml index 6c0c5d16a9..b5d896c3e3 100644 --- a/tests/conformance/Cargo.toml +++ b/tests/conformance/Cargo.toml @@ -8,6 +8,8 @@ license = "Apache-2.0" [dependencies] clap = { version = "4.0.8", features = ["derive"] } +anyhow = "1.0.75" +serde_json = "1.0.107" sigstore = { path = "../../" } [[bin]] diff --git a/tests/conformance/conformance.rs b/tests/conformance/conformance.rs index c52c822fe1..801cc6b064 100644 --- a/tests/conformance/conformance.rs +++ b/tests/conformance/conformance.rs @@ -16,7 +16,16 @@ // CLI implemented to specification: // https://github.com/sigstore/sigstore-conformance/blob/main/docs/cli_protocol.md +use std::{fs, process::exit}; + +use anyhow::anyhow; use clap::{Parser, Subcommand}; +use sigstore::{ + oauth::IdentityToken, + sign::SigningContext, + verify::VerificationMaterials, + verify::{policy, Verifier}, +}; #[derive(Parser, Debug)] struct Cli { @@ -106,4 +115,62 @@ struct VerifyBundle { fn main() { let cli = Cli::parse(); + + let result = match cli.command { + Commands::SignBundle(args) => sign_bundle(args), + Commands::VerifyBundle(args) => verify_bundle(args), + _ => unimplemented!("sig/cert commands"), + }; + + if let Err(error) = result { + eprintln!("Operation failed:\n{error:?}"); + exit(-1); + } + + eprintln!("Operation succeeded!"); +} + +fn sign_bundle(args: SignBundle) -> anyhow::Result<()> { + let SignBundle { + identity_token, + bundle, + artifact, + } = args; + let identity_token = IdentityToken::try_from(identity_token.as_str())?; + let bundle = fs::File::create(bundle)?; + let mut artifact = fs::File::open(artifact)?; + + let context = SigningContext::production(); + let signer = context.signer(identity_token); + + let signing_artifact = signer.sign(&mut artifact)?; + let bundle_data = signing_artifact.to_bundle(); + + serde_json::to_writer(bundle, &bundle_data)?; + + Ok(()) +} + +fn verify_bundle(args: VerifyBundle) -> anyhow::Result<()> { + let VerifyBundle { + bundle, + certificate_identity, + certificate_oidc_issuer, + artifact, + } = args; + let bundle = fs::File::open(bundle)?; + let mut artifact = fs::File::open(artifact)?; + + let bundle: sigstore::Bundle = serde_json::from_reader(bundle)?; + let materials = VerificationMaterials::from_bundle(&mut artifact, bundle, true) + .ok_or(anyhow!("Unable to construct VerificationMaterials"))?; + + let verifier = Verifier::production()?; + + verifier.verify( + materials, + &policy::Identity::new(certificate_identity, certificate_oidc_issuer), + )?; + + Ok(()) } diff --git a/tests/data/repository/1.registry.npmjs.org.json b/tests/data/repository/1.registry.npmjs.org.json new file mode 100644 index 0000000000..1c8ec2165b --- /dev/null +++ b/tests/data/repository/1.registry.npmjs.org.json @@ -0,0 +1,23 @@ +{ + "signed": { + "_type": "targets", + "spec_version": "1.0", + "version": 1, + "expires": "2024-09-29T16:47:20Z", + "targets": { + "registry.npmjs.org/keys.json": { + "length": 1017, + "hashes": { + "sha256": "7a8ec9678ad824cdccaa7a6dc0961caf8f8df61bc7274189122c123446248426", + "sha512": "881a853ee92d8cf513b07c164fea36b22a7305c256125bdfffdc5c65a4205c4c3fc2b5bcc98964349167ea68d40b8cd02551fcaa870a30d4601ba1caf6f63699" + } + } + } + }, + "signatures": [ + { + "keyid": "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600", + "sig": "3044022059bf01a64dd2793d5b630e26d7b6e455b0d6d8b47c23049ae856a122e5cec2ab022068b99b8bb39457e53d500f698cb43f9e640958ed26e5d3a47c29619df61889bc" + } + ] +} \ No newline at end of file diff --git a/tests/data/repository/1.root.json b/tests/data/repository/1.root.json index dcc71f963a..4ca0da87fe 100644 --- a/tests/data/repository/1.root.json +++ b/tests/data/repository/1.root.json @@ -1,130 +1,65 @@ { - "signatures": [ - { - "keyid": "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "sig": "30450221008a35d51da0f845301a5eac98ad0df00a934f59b709c1eaf81c86be734d9356f80220742942325599749800f52675f6efe124345980a2a636c0dc76f9caf9fc3123b0" - }, - { - "keyid": "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "sig": "3045022100ef9157ece2a09baec1eab80adfc00b04da20b1f9a0d1b47c5dabc4506719ef2c022074f72acd57398e4ddc8c2a5040df902961e9615dca48f3fbe38cbb506e500066" - }, - { - "keyid": "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "sig": "30450220420fdc9a09cd069b8b15fd8db9cedf7d0dee75871bd1cfee77c926d4120a770002210097553b5ad0d6b4a13902ed37509638bb63a9009f78230cd56c802909ffbfead7" - }, - { - "keyid": "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "sig": "304502202aaf32e66f90752f658672b085ecfe45cc1ad31ee6cf5c9ad05f3267685f8d88022100b5df02acdaa371123db9d7a42219553fe079b230b168833e951be7ee56ded347" - }, - { - "keyid": "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209", - "sig": "304402205d420c7d05c58980c1c9f7d221f53b5334aae27a447d2a91c2ceddd685269749022039ec83e51f8e1779d7f0142dfa4a5bbecfe327fc0b91b7416090fea2416fd53a" - } - ], "signed": { "_type": "root", - "consistent_snapshot": false, - "expires": "2021-12-18T13:28:12.99008-06:00", + "spec_version": "1.0", + "version": 1, + "expires": "2024-09-29T16:47:17Z", "keys": { - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": { "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04cbc5cab2684160323c25cd06c3307178a6b1d1c9b949328453ae473c5ba7527e35b13f298b41633382241f3fd8526c262d43b45adee5c618fa0642c82b8a9803" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62": { + "scheme": "ecdsa-sha2-nistp256", "keyid_hash_algorithms": [ "sha256", "sha512" ], - "keytype": "ecdsa-sha2-nistp256", "keyval": { - "public": "04a71aacd835dc170ba6db3fa33a1a33dee751d4f8b0217b805b9bd3242921ee93672fdcfd840576c5bb0dc0ed815edf394c1ee48c2b5e02485e59bfc512f3adc7" - }, - "scheme": "ecdsa-sha2-nistp256" + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n" + } }, - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04117b33dd265715bf23315e368faa499728db8d1f0a377070a1c7b1aba2cc21be6ab1628e42f2cdd7a35479f2dce07b303a8ba646c55569a8d2a504ba7e86e447" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda": { "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04cc1cd53a61c23e88cc54b488dfae168a257c34fac3e88811c55962b24cffbfecb724447999c54670e365883716302e49da57c79a33cd3e16f81fbc66f0bcdf48" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209": { + "scheme": "ecdsa-sha2-nistp256", "keyid_hash_algorithms": [ "sha256", "sha512" ], - "keytype": "ecdsa-sha2-nistp256", "keyval": { - "public": "048a78a44ac01099890d787e5e62afc29c8ccb69a70ec6549a6b04033b0a8acbfb42ab1ab9c713d225cdb52b858886cf46c8e90a7f3b9e6371882f370c259e1c5b" - }, - "scheme": "ecdsa-sha2-nistp256" + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL3vL/VeaH6nBbo4rekyO4cc/QthS\n+nlyJXCXSnyIMAtLmVTa8Pf0qG6YIVaR0TmLkyk9YoSVsZakxuMTuaEwrg==\n-----END PUBLIC KEY-----\n" + } } }, "roles": { "root": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda" ], - "threshold": 3 + "threshold": 1 }, "snapshot": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" ], - "threshold": 3 + "threshold": 1 }, "targets": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda" ], - "threshold": 3 + "threshold": 1 }, "timestamp": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" ], - "threshold": 3 + "threshold": 1 } }, - "spec_version": "1.0", - "version": 1 - } + "consistent_snapshot": true + }, + "signatures": [ + { + "keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda", + "sig": "304602210085927cdb96e1d9d0876bfc26b6ceea7421a54f959e30b9af3e12d31f6c750543022100dde611b58a1f2b9fb26c43767138c68f4422cdeb898c8b63f3f0193791030d12" + } + ] } \ No newline at end of file diff --git a/tests/data/repository/1.snapshot.json b/tests/data/repository/1.snapshot.json new file mode 100644 index 0000000000..fcb179878c --- /dev/null +++ b/tests/data/repository/1.snapshot.json @@ -0,0 +1,32 @@ +{ + "signed": { + "_type": "snapshot", + "spec_version": "1.0", + "version": 1, + "expires": "2024-04-19T16:47:48Z", + "meta": { + "registry.npmjs.org.json": { + "length": 713, + "hashes": { + "sha256": "17b361687dbb401c2d51d7ce21688d13547eae7f8e7b2183b7dd6d94fa675705", + "sha512": "3f60a08cdbab650ece48ded43b54943dc816580fdb2f5a2a20c30e878eb2489ab817f0308666cac80da03d75d6f5b71959431b1ba7794335fece8a4ed635eb4d" + }, + "version": 1 + }, + "targets.json": { + "length": 4518, + "hashes": { + "sha256": "cc62e5fb1644717c7429c82b6a1cbd085008f9a2e07aad38573f8fdf9d55386c", + "sha512": "5709bc76bc35da403a9a0a5ec96890db49e797c986eda9e5f7973938dbccad96838c8136617c91f5218cfd919d93745d3942ca6d50a52b5fd0e662e6876b395f" + }, + "version": 1 + } + } + }, + "signatures": [ + { + "keyid": "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600", + "sig": "304602210082d244d5dab0c20ee07b3229964beffaa8bb0bdf4c5107e2f764619878d124a2022100e7c50116ef636c41348ec49a7502f1c98037238b9c717ee781b62c5154f5a1f0" + } + ] +} \ No newline at end of file diff --git a/tests/data/repository/1.targets.json b/tests/data/repository/1.targets.json new file mode 100644 index 0000000000..6844bad771 --- /dev/null +++ b/tests/data/repository/1.targets.json @@ -0,0 +1,148 @@ +{ + "signed": { + "_type": "targets", + "spec_version": "1.0", + "version": 1, + "expires": "2024-09-29T16:47:20Z", + "targets": { + "artifact.pub": { + "length": 177, + "hashes": { + "sha256": "59ebf97a9850aecec4bc39c1f5c1dc46e6490a6b5fd2a6cacdcac0c3a6fc4cbf", + "sha512": "308fd1d1d95d7f80aa33b837795251cc3e886792982275e062409e13e4e236ffc34d676682aa96fdc751414de99c864bf132dde71581fa651c6343905e3bf988" + }, + "custom": { + "sigstore": { + "status": "Active", + "usage": "Unknown" + } + } + }, + "ctfe.pub": { + "length": 177, + "hashes": { + "sha256": "7fcb94a5d0ed541260473b990b99a6c39864c1fb16f3f3e594a5a3cebbfe138a", + "sha512": "4b20747d1afe2544238ad38cc0cc3010921b177d60ac743767e0ef675b915489bd01a36606c0ff83c06448622d7160f0d866c83d20f0c0f44653dcc3f9aa0bd4" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstore.dev/test", + "usage": "CTFE" + } + } + }, + "ctfe_2022.pub": { + "length": 178, + "hashes": { + "sha256": "270488a309d22e804eeb245493e87c667658d749006b9fee9cc614572d4fbbdc", + "sha512": "e83fa4f427b24ee7728637fad1b4aa45ebde2ba02751fa860694b1bb16059a490328f9985e51cc70e4d237545315a1bc866dc4fdeef2f6248d99cc7a6077bf85" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstore.dev/2022", + "usage": "CTFE" + } + } + }, + "fulcio.crt.pem": { + "length": 744, + "hashes": { + "sha256": "f360c53b2e13495a628b9b8096455badcb6d375b185c4816d95a5d746ff29908", + "sha512": "0713252a7fd17f7f3ab12f88a64accf2eb14b8ad40ca711d7fe8b4ecba3b24db9e9dffadb997b196d3867b8f9ff217faf930d80e4dab4e235c7fc3f07be69224" + }, + "custom": { + "sigstore": { + "status": "Expired", + "uri": "https://fulcio.sigstore.dev", + "usage": "Fulcio" + } + } + }, + "fulcio_intermediate_v1.crt.pem": { + "length": 789, + "hashes": { + "sha256": "f8cbecf186db7714624a5f4e99da31a917cbef70a94dd6921f5c3ca969dfe30a", + "sha512": "0f99f47dbc26c5f1e3cba0bfd9af4245a26e5cb735d6ef005792ec7e603f66fdb897de985973a6e50940ca7eff5e1849719e967b5ad2dac74a29115a41cf6f21" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://fulcio.sigstore.dev", + "usage": "Fulcio" + } + } + }, + "fulcio_v1.crt.pem": { + "length": 740, + "hashes": { + "sha256": "f989aa23def87c549404eadba767768d2a3c8d6d30a8b793f9f518a8eafd2cf5", + "sha512": "f2e33a6dc208cee1f51d33bbea675ab0f0ced269617497985f9a0680689ee7073e4b6f8fef64c91bda590d30c129b3070dddce824c05bc165ac9802f0705cab6" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://fulcio.sigstore.dev", + "usage": "Fulcio" + } + } + }, + "rekor.pub": { + "length": 178, + "hashes": { + "sha256": "dce5ef715502ec9f3cdfd11f8cc384b31a6141023d3e7595e9908a81cb6241bd", + "sha512": "0ae7705e02db33e814329746a4a0e5603c5bdcd91c96d072158d71011a2695788866565a2fec0fe363eb72cbcaeda39e54c5fe8d416daf9f3101fdba4217ef35" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://rekor.sigstore.dev", + "usage": "Rekor" + } + } + }, + "trusted_root.json": { + "length": 4567, + "hashes": { + "sha256": "cec894ad77f79b1cb324150f6363012bcef7492954f3ab9134f932e6aa2e2e20", + "sha512": "08be2fd75c19e654caad30852847c566f97e6245f2bbcc54d347d6bdec7e879135e3395b5633b9e3b85d739fdb9b4eb8c09ddc70495792bc2ea65c8caf770d27" + } + } + }, + "delegations": { + "keys": { + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": { + "keytype": "ecdsa-sha2-nistp256", + "scheme": "ecdsa-sha2-nistp256", + "keyid_hash_algorithms": [ + "sha256", + "sha512" + ], + "keyval": { + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n" + } + } + }, + "roles": [ + { + "name": "registry.npmjs.org", + "keyids": [ + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" + ], + "threshold": 1, + "terminating": true, + "paths": [ + "registry.npmjs.org/*" + ] + } + ] + } + }, + "signatures": [ + { + "keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda", + "sig": "304402201662b260e99e59f7271bd9e3fb01aa47a399bef8c5ec808bea6d40ae2d93625d022042fd2a275d84196dc50e17ca9c9408a34349372410febc7217415b11eb978bbb" + } + ] +} \ No newline at end of file diff --git a/tests/data/repository/2.registry.npmjs.org.json b/tests/data/repository/2.registry.npmjs.org.json new file mode 100644 index 0000000000..d53f15267b --- /dev/null +++ b/tests/data/repository/2.registry.npmjs.org.json @@ -0,0 +1,23 @@ +{ + "signed": { + "_type": "targets", + "spec_version": "1.0", + "version": 2, + "expires": "2028-09-29T21:10:55Z", + "targets": { + "registry.npmjs.org/keys.json": { + "length": 1017, + "hashes": { + "sha256": "7a8ec9678ad824cdccaa7a6dc0961caf8f8df61bc7274189122c123446248426", + "sha512": "881a853ee92d8cf513b07c164fea36b22a7305c256125bdfffdc5c65a4205c4c3fc2b5bcc98964349167ea68d40b8cd02551fcaa870a30d4601ba1caf6f63699" + } + } + } + }, + "signatures": [ + { + "keyid": "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600", + "sig": "3045022057b9fc8afd9feaf45cf3173d3420fdcd6b68c22e4ef7b47e80a6887e1f20246c0221009f39c42fac630ab354c5197288c9a82ab6d46a59b423f81fff719da57cff16ab" + } + ] +} \ No newline at end of file diff --git a/tests/data/repository/2.root.json b/tests/data/repository/2.root.json index 386ebe62c1..f848d7d846 100644 --- a/tests/data/repository/2.root.json +++ b/tests/data/repository/2.root.json @@ -1,144 +1,65 @@ { - "signatures": [ - { - "keyid": "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "sig": "3046022100d3ea59490b253beae0926c6fa63f54336dea1ed700555be9f27ff55cd347639c0221009157d1ba012cead81948a4ab777d355451d57f5c4a2d333fc68d2e3f358093c2" - }, - { - "keyid": "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "sig": "304502206eaef40564403ce572c6d062e0c9b0aab5e0223576133e081e1b495e8deb9efd02210080fd6f3464d759601b4afec596bbd5952f3a224cd06ed1cdfc3c399118752ba2" - }, - { - "keyid": "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "sig": "304502207baace02f56d8e6069f10b6ff098a26e7f53a7f9324ad62cffa0557bdeb9036c022100fb3032baaa090d0040c3f2fd872571c84479309b773208601d65948df87a9720" - }, - { - "keyid": "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "sig": "304402205180c01905505dd88acd7a2dad979dd75c979b3722513a7bdedac88c6ae8dbeb022056d1ddf7a192f0b1c2c90ff487de2fb3ec9f0c03f66ea937c78d3b6a493504ca" - }, - { - "keyid": "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209", - "sig": "3046022100c8806d4647c514d80fd8f707d3369444c4fd1d0812a2d25f828e564c99790e3f022100bb51f12e862ef17a7d3da2ac103bebc5c7e792237006c4cafacd76267b249c2f" - } - ], "signed": { "_type": "root", - "consistent_snapshot": false, - "expires": "2022-05-11T19:09:02.663975009Z", + "spec_version": "1.0", + "version": 2, + "expires": "2028-09-29T21:10:11Z", "keys": { - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": { "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04cbc5cab2684160323c25cd06c3307178a6b1d1c9b949328453ae473c5ba7527e35b13f298b41633382241f3fd8526c262d43b45adee5c618fa0642c82b8a9803" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "b6710623a30c010738e64c5209d367df1c0a18cf90e6ab5292fb01680f83453d": { + "scheme": "ecdsa-sha2-nistp256", "keyid_hash_algorithms": [ "sha256", "sha512" ], - "keytype": "ecdsa-sha2-nistp256", "keyval": { - "public": "04fa1a3e42f2300cd3c5487a61509348feb1e936920fef2f83b7cd5dbe7ba045f538725ab8f18a666e6233edb7e0db8766c8dc336633449c5e1bbe0c182b02df0b" - }, - "scheme": "ecdsa-sha2-nistp256" + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n" + } }, - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda": { "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04a71aacd835dc170ba6db3fa33a1a33dee751d4f8b0217b805b9bd3242921ee93672fdcfd840576c5bb0dc0ed815edf394c1ee48c2b5e02485e59bfc512f3adc7" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b": { + "scheme": "ecdsa-sha2-nistp256", "keyid_hash_algorithms": [ "sha256", "sha512" ], - "keytype": "ecdsa-sha2-nistp256", "keyval": { - "public": "04117b33dd265715bf23315e368faa499728db8d1f0a377070a1c7b1aba2cc21be6ab1628e42f2cdd7a35479f2dce07b303a8ba646c55569a8d2a504ba7e86e447" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04cc1cd53a61c23e88cc54b488dfae168a257c34fac3e88811c55962b24cffbfecb724447999c54670e365883716302e49da57c79a33cd3e16f81fbc66f0bcdf48" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "048a78a44ac01099890d787e5e62afc29c8ccb69a70ec6549a6b04033b0a8acbfb42ab1ab9c713d225cdb52b858886cf46c8e90a7f3b9e6371882f370c259e1c5b" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "fc61191ba8a516fe386c7d6c97d918e1d241e1589729add09b122725b8c32451": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "044c7793ab74b9ddd713054e587b8d9c75c5f6025633d0fef7ca855ed5b8d5a474b23598fe33eb4a63630d526f74d4bdaec8adcb51993ed65652d651d7c49203eb" - }, - "scheme": "ecdsa-sha2-nistp256" + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL3vL/VeaH6nBbo4rekyO4cc/QthS\n+nlyJXCXSnyIMAtLmVTa8Pf0qG6YIVaR0TmLkyk9YoSVsZakxuMTuaEwrg==\n-----END PUBLIC KEY-----\n" + } } }, "roles": { "root": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda" ], - "threshold": 3 + "threshold": 1 }, "snapshot": { "keyids": [ - "fc61191ba8a516fe386c7d6c97d918e1d241e1589729add09b122725b8c32451" + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" ], "threshold": 1 }, "targets": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda" ], - "threshold": 3 + "threshold": 1 }, "timestamp": { "keyids": [ - "b6710623a30c010738e64c5209d367df1c0a18cf90e6ab5292fb01680f83453d" + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" ], "threshold": 1 } }, - "spec_version": "1.0", - "version": 2 - } + "consistent_snapshot": true + }, + "signatures": [ + { + "keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda", + "sig": "3045022057bbd23dd9f69f8280c5e5d2b0a0b1ace98d6d8efa0f59ef0a3190188f6e2c89022100b39e6c24091c4271d2b8b4cfa75e6120638b276fbffddda8da5bca1778c8f08c" + } + ] } \ No newline at end of file diff --git a/tests/data/repository/2.snapshot.json b/tests/data/repository/2.snapshot.json new file mode 100644 index 0000000000..6c1e4dd147 --- /dev/null +++ b/tests/data/repository/2.snapshot.json @@ -0,0 +1,32 @@ +{ + "signed": { + "_type": "snapshot", + "spec_version": "1.0", + "version": 2, + "expires": "2028-04-19T21:11:16Z", + "meta": { + "registry.npmjs.org.json": { + "length": 715, + "hashes": { + "sha256": "4dc55b2b468b0d1c9629c457c5cfce2cc1c330c59c5a7cf71cb7549f1ef76f1d", + "sha512": "278f4b6112db9d4bd9366e1717cf710ad7eacf44605fd4f894c3374fc5dff850a1a03c24c4a885d050a4ac1a86fa6929537fae12d8c2864c8e0c239b382d5556" + }, + "version": 2 + }, + "targets.json": { + "length": 4120, + "hashes": { + "sha256": "095d093de09350cec021828f49361688b5dd692486ad7bfb03d4150b3269ef8a", + "sha512": "97b9c75f49fb41eaf2f33c5f58b125febc3bbecd4c97f6edd0901423a231e4d0c5760d4780bc180a364d7198b5e0710f07ee0abf84dcd163fe3348d6bce26fab" + }, + "version": 2 + } + } + }, + "signatures": [ + { + "keyid": "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600", + "sig": "3044022013bf1032cf0a37d9f88ab9d33d0abb7a932efd95fadbc354fc21a807c7be29ef0220677e651c3e67e0728591faa20c5a09b8a16953038c3ceeffb7d9cfec766b3245" + } + ] +} \ No newline at end of file diff --git a/tests/data/repository/2.targets.json b/tests/data/repository/2.targets.json new file mode 100644 index 0000000000..dea42487f0 --- /dev/null +++ b/tests/data/repository/2.targets.json @@ -0,0 +1,135 @@ +{ + "signed": { + "_type": "targets", + "spec_version": "1.0", + "version": 2, + "expires": "2028-09-29T21:10:55Z", + "targets": { + "ctfe.pub": { + "length": 775, + "hashes": { + "sha256": "bd7a6812a1f239dfddbbb19d36c7423d21510da56d466ba5018401959cd66037", + "sha512": "b861189e48df51186a39612230fba6b02af951f7b35ad9375e8ca182d0e085d470e26d69f7cd4d7450a0f223991e8e5a4ddf8f1968caa15255de8e37035af43a" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstage.dev/test", + "usage": "CTFE" + } + } + }, + "ctfe_2022.pub": { + "length": 178, + "hashes": { + "sha256": "910d899c7763563095a0fe684c8477573fedc19a78586de6ecfbfd8f289f5423", + "sha512": "ab975a75600fc366a837536d0dcba841b755552d21bb114498ff8ac9d2403f76643f5b91269bce5d124a365514719a3edee9dcc2b046cb173f51af659911fcd3" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstage.dev/2022", + "usage": "CTFE" + } + } + }, + "ctfe_2022_2.pub": { + "length": 178, + "hashes": { + "sha256": "7054b4f15f969daca1c242bb9e77527abaf0b9acf9818a2a35144e4b32b20dc6", + "sha512": "3d035f94e1b14ac84627a28afdbed9a34861fb84239f76d73aa1a99f52262bfd95c4fa0ee71f1fd7e3bfb998d89cd5e0f0eafcff9fa7fa87c6e23484fc1e0cec" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstage.dev/2022-2", + "usage": "CTFE" + } + } + }, + "fulcio.crt.pem": { + "length": 741, + "hashes": { + "sha256": "0e6b0442485ad552bea5f62f11c29e2acfda35307d7538430b4cc1dbef49bff1", + "sha512": "c69ae618883a0c89c282c0943a1ad0c16b0a7788f74e47a1adefc631dac48a0c4449d8c3de7455ae7d772e43c4a87e341f180b0614a46a86006969f8a7b84532" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://fulcio.sigstage.dev", + "usage": "Fulcio" + } + } + }, + "fulcio_intermediate.crt.pem": { + "length": 790, + "hashes": { + "sha256": "782868913fe13c385105ddf33e827191386f58da40a931f2075a7e27b1b6ac7b", + "sha512": "90659875a02f73d1026055427c6d857c556e410e23748ff88aeb493227610fd2f5fbdd95ef2a21565f91438dfb3e073f50c4c9dd06f9a601b5d9b064d5cb60b4" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://fulcio.sigstage.dev", + "usage": "Fulcio" + } + } + }, + "rekor.pub": { + "length": 178, + "hashes": { + "sha256": "1d80b8f72505a43e65e6e125247cd508f61b459dc457c1d1bcb78d96e1760959", + "sha512": "09ab08698a67354a95d3b8897d9ce7eaef05f06f5ed5f0202d79c228579858ecc5816b7e1b7cc6786abe7d6aaa758e1fcb05900cb749235186c3bf9522d6d7ce" + }, + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://rekor.sigstage.dev", + "usage": "Rekor" + } + } + }, + "trusted_root.json": { + "length": 4521, + "hashes": { + "sha256": "6494317303d0e04509a30b239bf8290057164fba67072b6f89ddf1032273a78b", + "sha512": "fa2ca05656176f993fd616fa8586f3deeaacfb891dfb6f58e02b26073cb0233a52b7e66338d0053c8549f551485581141094c2de40ca812d8ac47a128bf84963" + } + } + }, + "delegations": { + "keys": { + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": { + "keytype": "ecdsa-sha2-nistp256", + "scheme": "ecdsa-sha2-nistp256", + "keyid_hash_algorithms": [ + "sha256", + "sha512" + ], + "keyval": { + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n" + } + } + }, + "roles": [ + { + "name": "registry.npmjs.org", + "keyids": [ + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" + ], + "threshold": 1, + "terminating": true, + "paths": [ + "registry.npmjs.org/*" + ] + } + ] + } + }, + "signatures": [ + { + "keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda", + "sig": "304502210090b089087d1b17b2517c464b7774d76d3ea558ffca874eed63ccbee8f6bc3b76022022b56f551bcd0ac8a9c35cd0724ac5b00b4984544cbf812f47f276a9b48db8db" + } + ] +} \ No newline at end of file diff --git a/tests/data/repository/registry.npmjs.org.json b/tests/data/repository/registry.npmjs.org.json new file mode 100644 index 0000000000..d53f15267b --- /dev/null +++ b/tests/data/repository/registry.npmjs.org.json @@ -0,0 +1,23 @@ +{ + "signed": { + "_type": "targets", + "spec_version": "1.0", + "version": 2, + "expires": "2028-09-29T21:10:55Z", + "targets": { + "registry.npmjs.org/keys.json": { + "length": 1017, + "hashes": { + "sha256": "7a8ec9678ad824cdccaa7a6dc0961caf8f8df61bc7274189122c123446248426", + "sha512": "881a853ee92d8cf513b07c164fea36b22a7305c256125bdfffdc5c65a4205c4c3fc2b5bcc98964349167ea68d40b8cd02551fcaa870a30d4601ba1caf6f63699" + } + } + } + }, + "signatures": [ + { + "keyid": "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600", + "sig": "3045022057b9fc8afd9feaf45cf3173d3420fdcd6b68c22e4ef7b47e80a6887e1f20246c0221009f39c42fac630ab354c5197288c9a82ab6d46a59b423f81fff719da57cff16ab" + } + ] +} \ No newline at end of file diff --git a/tests/data/repository/rekor.json b/tests/data/repository/rekor.json deleted file mode 100644 index f86930d537..0000000000 --- a/tests/data/repository/rekor.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "signatures": [ - { - "keyid": "ae0c689c6347ada7359df48934991f4e013193d6ddf3482a5ffb293f74f3b217", - "sig": "3045022076eadd73f6664bac5cc91f12d3a7ddcdd53f9bde661f147651196ff66e7235d1022100f7b3143792405f9e8a75331a05d4128bdf083de302801e99c3d027919a4b03da" - } - ], - "signed": { - "_type": "targets", - "expires": "2022-05-11T19:10:11Z", - "spec_version": "1.0", - "targets": { - "rekor.0.pub": { - "hashes": { - "sha256": "dce5ef715502ec9f3cdfd11f8cc384b31a6141023d3e7595e9908a81cb6241bd", - "sha512": "0ae7705e02db33e814329746a4a0e5603c5bdcd91c96d072158d71011a2695788866565a2fec0fe363eb72cbcaeda39e54c5fe8d416daf9f3101fdba4217ef35" - }, - "length": 178 - } - }, - "version": 1 - } -} \ No newline at end of file diff --git a/tests/data/repository/root.json b/tests/data/repository/root.json index 386ebe62c1..f848d7d846 100644 --- a/tests/data/repository/root.json +++ b/tests/data/repository/root.json @@ -1,144 +1,65 @@ { - "signatures": [ - { - "keyid": "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "sig": "3046022100d3ea59490b253beae0926c6fa63f54336dea1ed700555be9f27ff55cd347639c0221009157d1ba012cead81948a4ab777d355451d57f5c4a2d333fc68d2e3f358093c2" - }, - { - "keyid": "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "sig": "304502206eaef40564403ce572c6d062e0c9b0aab5e0223576133e081e1b495e8deb9efd02210080fd6f3464d759601b4afec596bbd5952f3a224cd06ed1cdfc3c399118752ba2" - }, - { - "keyid": "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "sig": "304502207baace02f56d8e6069f10b6ff098a26e7f53a7f9324ad62cffa0557bdeb9036c022100fb3032baaa090d0040c3f2fd872571c84479309b773208601d65948df87a9720" - }, - { - "keyid": "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "sig": "304402205180c01905505dd88acd7a2dad979dd75c979b3722513a7bdedac88c6ae8dbeb022056d1ddf7a192f0b1c2c90ff487de2fb3ec9f0c03f66ea937c78d3b6a493504ca" - }, - { - "keyid": "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209", - "sig": "3046022100c8806d4647c514d80fd8f707d3369444c4fd1d0812a2d25f828e564c99790e3f022100bb51f12e862ef17a7d3da2ac103bebc5c7e792237006c4cafacd76267b249c2f" - } - ], "signed": { "_type": "root", - "consistent_snapshot": false, - "expires": "2022-05-11T19:09:02.663975009Z", + "spec_version": "1.0", + "version": 2, + "expires": "2028-09-29T21:10:11Z", "keys": { - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": { "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04cbc5cab2684160323c25cd06c3307178a6b1d1c9b949328453ae473c5ba7527e35b13f298b41633382241f3fd8526c262d43b45adee5c618fa0642c82b8a9803" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "b6710623a30c010738e64c5209d367df1c0a18cf90e6ab5292fb01680f83453d": { + "scheme": "ecdsa-sha2-nistp256", "keyid_hash_algorithms": [ "sha256", "sha512" ], - "keytype": "ecdsa-sha2-nistp256", "keyval": { - "public": "04fa1a3e42f2300cd3c5487a61509348feb1e936920fef2f83b7cd5dbe7ba045f538725ab8f18a666e6233edb7e0db8766c8dc336633449c5e1bbe0c182b02df0b" - }, - "scheme": "ecdsa-sha2-nistp256" + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n" + } }, - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda": { "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04a71aacd835dc170ba6db3fa33a1a33dee751d4f8b0217b805b9bd3242921ee93672fdcfd840576c5bb0dc0ed815edf394c1ee48c2b5e02485e59bfc512f3adc7" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b": { + "scheme": "ecdsa-sha2-nistp256", "keyid_hash_algorithms": [ "sha256", "sha512" ], - "keytype": "ecdsa-sha2-nistp256", "keyval": { - "public": "04117b33dd265715bf23315e368faa499728db8d1f0a377070a1c7b1aba2cc21be6ab1628e42f2cdd7a35479f2dce07b303a8ba646c55569a8d2a504ba7e86e447" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "04cc1cd53a61c23e88cc54b488dfae168a257c34fac3e88811c55962b24cffbfecb724447999c54670e365883716302e49da57c79a33cd3e16f81fbc66f0bcdf48" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "048a78a44ac01099890d787e5e62afc29c8ccb69a70ec6549a6b04033b0a8acbfb42ab1ab9c713d225cdb52b858886cf46c8e90a7f3b9e6371882f370c259e1c5b" - }, - "scheme": "ecdsa-sha2-nistp256" - }, - "fc61191ba8a516fe386c7d6c97d918e1d241e1589729add09b122725b8c32451": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "044c7793ab74b9ddd713054e587b8d9c75c5f6025633d0fef7ca855ed5b8d5a474b23598fe33eb4a63630d526f74d4bdaec8adcb51993ed65652d651d7c49203eb" - }, - "scheme": "ecdsa-sha2-nistp256" + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEL3vL/VeaH6nBbo4rekyO4cc/QthS\n+nlyJXCXSnyIMAtLmVTa8Pf0qG6YIVaR0TmLkyk9YoSVsZakxuMTuaEwrg==\n-----END PUBLIC KEY-----\n" + } } }, "roles": { "root": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda" ], - "threshold": 3 + "threshold": 1 }, "snapshot": { "keyids": [ - "fc61191ba8a516fe386c7d6c97d918e1d241e1589729add09b122725b8c32451" + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" ], "threshold": 1 }, "targets": { "keyids": [ - "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209" + "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda" ], - "threshold": 3 + "threshold": 1 }, "timestamp": { "keyids": [ - "b6710623a30c010738e64c5209d367df1c0a18cf90e6ab5292fb01680f83453d" + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" ], "threshold": 1 } }, - "spec_version": "1.0", - "version": 2 - } + "consistent_snapshot": true + }, + "signatures": [ + { + "keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda", + "sig": "3045022057bbd23dd9f69f8280c5e5d2b0a0b1ace98d6d8efa0f59ef0a3190188f6e2c89022100b39e6c24091c4271d2b8b4cfa75e6120638b276fbffddda8da5bca1778c8f08c" + } + ] } \ No newline at end of file diff --git a/tests/data/repository/snapshot.json b/tests/data/repository/snapshot.json index 61636531c6..6c1e4dd147 100644 --- a/tests/data/repository/snapshot.json +++ b/tests/data/repository/snapshot.json @@ -1,48 +1,32 @@ { - "signatures": [ - { - "keyid": "fc61191ba8a516fe386c7d6c97d918e1d241e1589729add09b122725b8c32451", - "sig": "3046022100f59f6f92d8c61519afd0de0642ff45419ac960954cf412549874c247c6ae509902210085da85c9df818c3072c0b7744b75e92d2ee521402d4bac77c985b8fc6d138e41" - } - ], "signed": { "_type": "snapshot", - "expires": "2022-01-05T00:40:06Z", + "spec_version": "1.0", + "version": 2, + "expires": "2028-04-19T21:11:16Z", "meta": { - "rekor.json": { + "registry.npmjs.org.json": { + "length": 715, "hashes": { - "sha256": "a7412a87f8d7b330e0380b19a4a76c00357c39a1aa7f56fd87445d4e12faafe4", - "sha512": "720cb3c42bac50c5bc3cb7076e730301ef29f1893ea52e25f9393fc05851c7a531638c42d9fc992969805982a2bf51d676e33d28a7382ea589b5a9f87474c63f" + "sha256": "4dc55b2b468b0d1c9629c457c5cfce2cc1c330c59c5a7cf71cb7549f1ef76f1d", + "sha512": "278f4b6112db9d4bd9366e1717cf710ad7eacf44605fd4f894c3374fc5dff850a1a03c24c4a885d050a4ac1a86fa6929537fae12d8c2864c8e0c239b382d5556" }, - "length": 697, - "version": 1 - }, - "root.json": { - "hashes": { - "sha256": "f5ad897c9414cca99629f400ac3585e41bd8ebb44c5af07fb08dd636a9eced9c", - "sha512": "7445ddfdd338ef786c324fc3d68f75be28cb95b7fb581d2a383e3e5dde18aa17029a5636ec0a22e9631931bbcb34057788311718ea41e21e7cdd3c0de13ede42" - }, - "length": 5297, "version": 2 }, - "staging.json": { - "hashes": { - "sha256": "c7f32379c2a76f0ec0af84e86794a8f4fe285e44fb62f336d598810dccdc7343", - "sha512": "5462cb15fe5248a12cc12387a732ad43caf42391361f36113ea3d4b7e5e193cdf39fbe91c309c0691134377cb83afeba50cf6d711537d8280ce16ce9cd8752ba" - }, - "length": 399, - "version": 1 - }, "targets.json": { + "length": 4120, "hashes": { - "sha256": "18d10c07c8d6bd7484772b02dcc988d0abf8a0fa379d5893a502410590c17fe6", - "sha512": "c2ba2a84820288997c8fae264776df7b262dde97c4f9e0320ad354879ce5afabd1d43494734fecffd23253442a14cfe217787de8b65cf7fd1f03130b72a0767c" + "sha256": "095d093de09350cec021828f49361688b5dd692486ad7bfb03d4150b3269ef8a", + "sha512": "97b9c75f49fb41eaf2f33c5f58b125febc3bbecd4c97f6edd0901423a231e4d0c5760d4780bc180a364d7198b5e0710f07ee0abf84dcd163fe3348d6bce26fab" }, - "length": 4167, "version": 2 } - }, - "spec_version": "1.0", - "version": 6 - } + } + }, + "signatures": [ + { + "keyid": "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600", + "sig": "3044022013bf1032cf0a37d9f88ab9d33d0abb7a932efd95fadbc354fc21a807c7be29ef0220677e651c3e67e0728591faa20c5a09b8a16953038c3ceeffb7d9cfec766b3245" + } + ] } \ No newline at end of file diff --git a/tests/data/repository/staging.json b/tests/data/repository/staging.json deleted file mode 100644 index 084010de75..0000000000 --- a/tests/data/repository/staging.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "signatures": [ - { - "keyid": "b811bd53f2d7adcf5d93e6bb4a8ed2e0ca0f83d454a3e51f105c8e8376bc80d4", - "sig": "304502204486f7b23eadb69df87776ac7a4938ac75a8a2b2e93c84c05d962373837ea91c022100aaeb0fa587430f49618711bb4bd0c1092637c22c223d03c0f1b5a09baea0ed9f" - } - ], - "signed": { - "_type": "targets", - "expires": "2022-02-11T20:10:16Z", - "spec_version": "1.0", - "targets": {}, - "version": 1 - } -} \ No newline at end of file diff --git a/tests/data/repository/targets.json b/tests/data/repository/targets.json index b26926a438..dea42487f0 100644 --- a/tests/data/repository/targets.json +++ b/tests/data/repository/targets.json @@ -1,117 +1,135 @@ { - "signatures": [ - { - "keyid": "2f64fb5eac0cf94dd39bb45308b98920055e9a0d8e012a7220787834c60aef97", - "sig": "3046022100cc1b2ed390e75a112c0fdd6bcbd8bb775300a410f5737ae39996b1858753c8e4022100b591f73370e9378914fb2fab837f700661abd1a74c680f139f6164ec12cb538f" - }, - { - "keyid": "bdde902f5ec668179ff5ca0dabf7657109287d690bf97e230c21d65f99155c62", - "sig": "3045022100bc6c45a125e45507339af96aa63983e847565c769f20d7d71bcd2deb7bd36ea902202bf6bd3b76d434c318287899e53f64b4dc178eb0ba403080f1c4fba88a2177ca" - }, - { - "keyid": "eaf22372f417dd618a46f6c627dbc276e9fd30a004fc94f9be946e73f8bd090b", - "sig": "304502210085d5bc8a158d31536b4e76cddceef25185c7abbe9091b84f5f2b0d615d9b4ee90220136a36fed2d5986c2519b7d165556f20dfe41fddececda48dffa8dec5258cb95" - }, - { - "keyid": "f40f32044071a9365505da3d1e3be6561f6f22d0e60cf51df783999f6c3429cb", - "sig": "304402202fe73a61dfe05b4202bc50f66e52bba3d3475134434dab9576735caed659b03c0220449755a87f4dab9961566f10477204637b2415f87e162b58a23b13327dec53e3" - }, - { - "keyid": "f505595165a177a41750a8e864ed1719b1edfccd5a426fd2c0ffda33ce7ff209", - "sig": "304602210091f453ef75c5178299175734355a65a2fc2d0ee137410f46ba8439d99037fc08022100fc800d15f0b751fa225a77542928f4264835c013054a5c409c674e2ea5a70384" - } - ], "signed": { "_type": "targets", - "delegations": { - "keys": { - "ae0c689c6347ada7359df48934991f4e013193d6ddf3482a5ffb293f74f3b217": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "043463588ae9df33a419d1099761245af52aaf7e638b2047bc0f739a62de9808c50a21ea8a1a273799f857f31a1bcb66e6661dd9d5ac7ac3ca260b0b8130c3fed8" - }, - "scheme": "ecdsa-sha2-nistp256" + "spec_version": "1.0", + "version": 2, + "expires": "2028-09-29T21:10:55Z", + "targets": { + "ctfe.pub": { + "length": 775, + "hashes": { + "sha256": "bd7a6812a1f239dfddbbb19d36c7423d21510da56d466ba5018401959cd66037", + "sha512": "b861189e48df51186a39612230fba6b02af951f7b35ad9375e8ca182d0e085d470e26d69f7cd4d7450a0f223991e8e5a4ddf8f1968caa15255de8e37035af43a" }, - "b811bd53f2d7adcf5d93e6bb4a8ed2e0ca0f83d454a3e51f105c8e8376bc80d4": { - "keyid_hash_algorithms": [ - "sha256", - "sha512" - ], - "keytype": "ecdsa-sha2-nistp256", - "keyval": { - "public": "041b4b13a6e7110292d284c0dbfc3962a12d2a779a800c99aff59c6afe779296943c75d84aa5bad0be28e4061cf93e0cd3d372d9b2f75ea9f29b907cbccd82006f" - }, - "scheme": "ecdsa-sha2-nistp256" + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstage.dev/test", + "usage": "CTFE" + } } }, - "roles": [ - { - "keyids": [ - "ae0c689c6347ada7359df48934991f4e013193d6ddf3482a5ffb293f74f3b217" - ], - "name": "rekor", - "paths": [ - "rekor.*.pub" - ], - "terminating": true, - "threshold": 1 - }, - { - "keyids": [ - "b811bd53f2d7adcf5d93e6bb4a8ed2e0ca0f83d454a3e51f105c8e8376bc80d4" - ], - "name": "staging", - "paths": [ - "*" - ], - "terminating": false, - "threshold": 1 - } - ] - }, - "expires": "2022-05-11T19:10:16Z", - "spec_version": "1.0", - "targets": { - "artifact.pub": { + "ctfe_2022.pub": { + "length": 178, "hashes": { - "sha256": "59ebf97a9850aecec4bc39c1f5c1dc46e6490a6b5fd2a6cacdcac0c3a6fc4cbf", - "sha512": "308fd1d1d95d7f80aa33b837795251cc3e886792982275e062409e13e4e236ffc34d676682aa96fdc751414de99c864bf132dde71581fa651c6343905e3bf988" + "sha256": "910d899c7763563095a0fe684c8477573fedc19a78586de6ecfbfd8f289f5423", + "sha512": "ab975a75600fc366a837536d0dcba841b755552d21bb114498ff8ac9d2403f76643f5b91269bce5d124a365514719a3edee9dcc2b046cb173f51af659911fcd3" }, - "length": 177 + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstage.dev/2022", + "usage": "CTFE" + } + } }, - "ctfe.pub": { + "ctfe_2022_2.pub": { + "length": 178, "hashes": { - "sha256": "7fcb94a5d0ed541260473b990b99a6c39864c1fb16f3f3e594a5a3cebbfe138a", - "sha512": "4b20747d1afe2544238ad38cc0cc3010921b177d60ac743767e0ef675b915489bd01a36606c0ff83c06448622d7160f0d866c83d20f0c0f44653dcc3f9aa0bd4" + "sha256": "7054b4f15f969daca1c242bb9e77527abaf0b9acf9818a2a35144e4b32b20dc6", + "sha512": "3d035f94e1b14ac84627a28afdbed9a34861fb84239f76d73aa1a99f52262bfd95c4fa0ee71f1fd7e3bfb998d89cd5e0f0eafcff9fa7fa87c6e23484fc1e0cec" }, - "length": 177 + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://ctfe.sigstage.dev/2022-2", + "usage": "CTFE" + } + } }, "fulcio.crt.pem": { + "length": 741, "hashes": { - "sha256": "f360c53b2e13495a628b9b8096455badcb6d375b185c4816d95a5d746ff29908", - "sha512": "0713252a7fd17f7f3ab12f88a64accf2eb14b8ad40ca711d7fe8b4ecba3b24db9e9dffadb997b196d3867b8f9ff217faf930d80e4dab4e235c7fc3f07be69224" + "sha256": "0e6b0442485ad552bea5f62f11c29e2acfda35307d7538430b4cc1dbef49bff1", + "sha512": "c69ae618883a0c89c282c0943a1ad0c16b0a7788f74e47a1adefc631dac48a0c4449d8c3de7455ae7d772e43c4a87e341f180b0614a46a86006969f8a7b84532" }, - "length": 744 + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://fulcio.sigstage.dev", + "usage": "Fulcio" + } + } }, - "fulcio_v1.crt.pem": { + "fulcio_intermediate.crt.pem": { + "length": 790, "hashes": { - "sha256": "f989aa23def87c549404eadba767768d2a3c8d6d30a8b793f9f518a8eafd2cf5", - "sha512": "f2e33a6dc208cee1f51d33bbea675ab0f0ced269617497985f9a0680689ee7073e4b6f8fef64c91bda590d30c129b3070dddce824c05bc165ac9802f0705cab6" + "sha256": "782868913fe13c385105ddf33e827191386f58da40a931f2075a7e27b1b6ac7b", + "sha512": "90659875a02f73d1026055427c6d857c556e410e23748ff88aeb493227610fd2f5fbdd95ef2a21565f91438dfb3e073f50c4c9dd06f9a601b5d9b064d5cb60b4" }, - "length": 740 + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://fulcio.sigstage.dev", + "usage": "Fulcio" + } + } }, "rekor.pub": { + "length": 178, "hashes": { - "sha256": "dce5ef715502ec9f3cdfd11f8cc384b31a6141023d3e7595e9908a81cb6241bd", - "sha512": "0ae7705e02db33e814329746a4a0e5603c5bdcd91c96d072158d71011a2695788866565a2fec0fe363eb72cbcaeda39e54c5fe8d416daf9f3101fdba4217ef35" + "sha256": "1d80b8f72505a43e65e6e125247cd508f61b459dc457c1d1bcb78d96e1760959", + "sha512": "09ab08698a67354a95d3b8897d9ce7eaef05f06f5ed5f0202d79c228579858ecc5816b7e1b7cc6786abe7d6aaa758e1fcb05900cb749235186c3bf9522d6d7ce" }, - "length": 178 + "custom": { + "sigstore": { + "status": "Active", + "uri": "https://rekor.sigstage.dev", + "usage": "Rekor" + } + } + }, + "trusted_root.json": { + "length": 4521, + "hashes": { + "sha256": "6494317303d0e04509a30b239bf8290057164fba67072b6f89ddf1032273a78b", + "sha512": "fa2ca05656176f993fd616fa8586f3deeaacfb891dfb6f58e02b26073cb0233a52b7e66338d0053c8549f551485581141094c2de40ca812d8ac47a128bf84963" + } } }, - "version": 2 - } + "delegations": { + "keys": { + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600": { + "keytype": "ecdsa-sha2-nistp256", + "scheme": "ecdsa-sha2-nistp256", + "keyid_hash_algorithms": [ + "sha256", + "sha512" + ], + "keyval": { + "public": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXMZ7rD8tWDE4lK/+naJN7INMxNC7\nbMMANDqTQE7WpzyzffWOg59hc/MwbvJtvuxhO9mEu3GD3Cn0HffFlmVRiA==\n-----END PUBLIC KEY-----\n" + } + } + }, + "roles": [ + { + "name": "registry.npmjs.org", + "keyids": [ + "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600" + ], + "threshold": 1, + "terminating": true, + "paths": [ + "registry.npmjs.org/*" + ] + } + ] + } + }, + "signatures": [ + { + "keyid": "c8e09a68b5821b75462ae0df52151c81deb7f1838246dc1da8c34cc91ec12bda", + "sig": "304502210090b089087d1b17b2517c464b7774d76d3ea558ffca874eed63ccbee8f6bc3b76022022b56f551bcd0ac8a9c35cd0724ac5b00b4984544cbf812f47f276a9b48db8db" + } + ] } \ No newline at end of file diff --git a/tests/data/repository/targets/6494317303d0e04509a30b239bf8290057164fba67072b6f89ddf1032273a78b.trusted_root.json b/tests/data/repository/targets/6494317303d0e04509a30b239bf8290057164fba67072b6f89ddf1032273a78b.trusted_root.json new file mode 100644 index 0000000000..6a1c1f5a40 --- /dev/null +++ b/tests/data/repository/targets/6494317303d0e04509a30b239bf8290057164fba67072b6f89ddf1032273a78b.trusted_root.json @@ -0,0 +1,86 @@ +{ + "mediaType": "application/vnd.dev.sigstore.trustedroot+json;version=0.1", + "tlogs": [ + { + "baseUrl": "https://rekor.sigstage.dev", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDODRU688UYGuy54mNUlaEBiQdTE9nYLr0lg6RXowI/QV/RE1azBn4Eg5/2uTOMbhB1/gfcHzijzFi9Tk+g1Prg==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2021-01-12T11:53:27.000Z" + } + }, + "logId": { + "keyId": "0y8wo8MtY5wrdiIFohx7sHeI5oKDpK5vQhGHI6G+pJY=" + } + } + ], + "certificateAuthorities": [ + { + "subject": { + "organization": "sigstore.dev", + "commonName": "sigstore" + }, + "uri": "https://fulcio.sigstage.dev", + "certChain": { + "certificates": [ + { + "rawBytes": "MIIB9jCCAXugAwIBAgITDdEJvluliE0AzYaIE4jTMdnFTzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIyMDMyNTE2NTA0NloXDTMyMDMyMjE2NTA0NVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMo9BUNk9QIYisYysC24+2OytoV72YiLonYcqR3yeVnYziPt7Xv++CYE8yoCTiwedUECCWKOcvQKRCJZb9ht4Hzy+VvBx36hK+C6sECCSR0x6pPSiz+cTk1f788ZjBlUZaNjMGEwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP9CMrpofas6cK/cDNQa4j6Hj2ZlMB8GA1UdIwQYMBaAFP9CMrpofas6cK/cDNQa4j6Hj2ZlMAoGCCqGSM49BAMDA2kAMGYCMQD+kojuzMwztNay9Ibzjuk//ZL5m6T2OCsm45l1lY004pcb984L926BowodoirFMcMCMQDIJtFHhP/1D3a+M3dAGomOb6O4CmTry3TTPbPsAFnv22YA0Y+P21NVoxKDjdu0tkw=" + }, + { + "rawBytes": "MIICGTCCAaCgAwIBAgITJta/okfgHvjabGm1BOzuhrwA1TAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIyMDQxNDIxMzg0MFoXDTMyMDMyMjE2NTA0NVowNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASosAySWJQ/tK5r8T5aHqavk0oI+BKQbnLLdmOMRXHQF/4Hx9KtNfpcdjH9hNKQSBxSlLFFN3tvFCco0qFBzWYwZtsYsBe1l91qYn/9VHFTaEVwYQWIJEEvrs0fvPuAqjajezB5MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRxhjCmFHxib/n31vQFGn9f/+tvrDAfBgNVHSMEGDAWgBT/QjK6aH2rOnCv3AzUGuI+h49mZTAKBggqhkjOPQQDAwNnADBkAjAM1lbKkcqQlE/UspMTbWNo1y2TaJ44tx3l/FJFceTSdDZ+0W1OHHeU4twie/lq8XgCMHQxgEv26xNNiAGyPXbkYgrDPvbOqp0UeWX4mJnLSrBr3aN/KX1SBrKQu220FmVL0Q==" + } + ] + }, + "validFor": { + "start": "2022-03-25T16:50:46.000Z" + } + } + ], + "ctlogs": [ + { + "baseUrl": "https://ctfe.sigstage.dev/test", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MIICCgKCAgEA27A2MPQXm0I0v7/Ly5BIauDjRZF5Jor9vU+QheoE2UIIsZHcyYq3slHzSSHy2lLj1ZD2d91CtJ492ZXqnBmsr4TwZ9jQ05tW2mGIRI8u2DqN8LpuNYZGz/f9SZrjhQQmUttqWmtu3UoLfKz6NbNXUnoo+NhZFcFRLXJ8VporVhuiAmL7zqT53cXR3yQfFPCUDeGnRksnlhVIAJc3AHZZSHQJ8DEXMhh35TVv2nYhTI3rID7GwjXXw4ocz7RGDD37ky6p39Tl5NB71gT1eSqhZhGHEYHIPXraEBd5+3w9qIuLWlp5Ej/K6Mu4ELioXKCUimCbwy+Cs8UhHFlqcyg4AysOHJwIadXIa8LsY51jnVSGrGOEBZevopmQPNPtyfFY3dmXSS+6Z3RD2Gd6oDnNGJzpSyEk410Ag5uvNDfYzJLCWX9tU8lIxNwdFYmIwpd89HijyRyoGnoJ3entd63cvKfuuix5r+GHyKp1Xm1L5j5AWM6P+z0xigwkiXnt+adexAl1J9wdDxv/pUFEESRF4DG8DFGVtbdH6aR1A5/vD4krO4tC1QYUSeyL5Mvsw8WRqIFHcXtgybtxylljvNcGMV1KXQC8UFDmpGZVDSHx6v3e/BHMrZ7gjoCCfVMZ/cFcQi0W2AIHPYEMH/C95J2r4XbHMRdYXpovpOoT5Ca78gsCAwEAAQ==", + "keyDetails": "PKCS1_RSA_PKCS1V5", + "validFor": { + "start": "2021-03-14T00:00:00.000Z" + } + }, + "logId": { + "keyId": "s9AOb93xWxr+a4ztxJnxxJCX7VZ0V3IF4jTu/OoL84A=" + } + }, + { + "baseUrl": "https://ctfe.sigstage.dev/2022", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh99xuRi6slBFd8VUJoK/rLigy4bYeSYWO/fE6Br7r0D8NpMI94+A63LR/WvLxpUUGBpY8IJA3iU2telag5CRpA==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2022-07-01T00:00:00.000Z" + } + }, + "logId": { + "keyId": "++JKOMQt7SJ3ynUHnCfnDhcKP8/58J4TueMqXuk3HmA=" + } + }, + { + "baseUrl": "https://ctfe.sigstage.dev/2022-2", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8gEDKNme8AnXuPBgHjrtXdS6miHqc24CRblNEOFpiJRngeq8Ko73Y+K18yRYVf1DXD4AVLwvKyzdNdl5n0jUSQ==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2022-07-01T00:00:00.000Z" + } + }, + "logId": { + "keyId": "KzC83GiIyeLh2CYpXnQfSDkxlgLynDPLXkNA/rKshno=" + } + } + ], + "timestampAuthorities": [] +} diff --git a/tests/data/repository/targets/artifact.pub b/tests/data/repository/targets/artifact.pub deleted file mode 100644 index d6e745bdd0..0000000000 --- a/tests/data/repository/targets/artifact.pub +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhyQCx0E9wQWSFI9ULGwy3BuRklnt -IqozONbbdbqz11hlRJy9c7SG+hdcFl9jE9uE/dwtuwU2MqU9T/cN0YkWww== ------END PUBLIC KEY----- \ No newline at end of file diff --git a/tests/data/repository/targets/ctfe.pub b/tests/data/repository/targets/ctfe.pub deleted file mode 100644 index 1bb1488c99..0000000000 --- a/tests/data/repository/targets/ctfe.pub +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEbfwR+RJudXscgRBRpKX1XFDy3Pyu -dDxz/SfnRi1fT8ekpfBd2O1uoz7jr3Z8nKzxA69EUQ+eFCFI3zeubPWU7w== ------END PUBLIC KEY----- \ No newline at end of file diff --git a/tests/data/repository/targets/fa2ca05656176f993fd616fa8586f3deeaacfb891dfb6f58e02b26073cb0233a52b7e66338d0053c8549f551485581141094c2de40ca812d8ac47a128bf84963.trusted_root.json b/tests/data/repository/targets/fa2ca05656176f993fd616fa8586f3deeaacfb891dfb6f58e02b26073cb0233a52b7e66338d0053c8549f551485581141094c2de40ca812d8ac47a128bf84963.trusted_root.json new file mode 100644 index 0000000000..6a1c1f5a40 --- /dev/null +++ b/tests/data/repository/targets/fa2ca05656176f993fd616fa8586f3deeaacfb891dfb6f58e02b26073cb0233a52b7e66338d0053c8549f551485581141094c2de40ca812d8ac47a128bf84963.trusted_root.json @@ -0,0 +1,86 @@ +{ + "mediaType": "application/vnd.dev.sigstore.trustedroot+json;version=0.1", + "tlogs": [ + { + "baseUrl": "https://rekor.sigstage.dev", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEDODRU688UYGuy54mNUlaEBiQdTE9nYLr0lg6RXowI/QV/RE1azBn4Eg5/2uTOMbhB1/gfcHzijzFi9Tk+g1Prg==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2021-01-12T11:53:27.000Z" + } + }, + "logId": { + "keyId": "0y8wo8MtY5wrdiIFohx7sHeI5oKDpK5vQhGHI6G+pJY=" + } + } + ], + "certificateAuthorities": [ + { + "subject": { + "organization": "sigstore.dev", + "commonName": "sigstore" + }, + "uri": "https://fulcio.sigstage.dev", + "certChain": { + "certificates": [ + { + "rawBytes": "MIIB9jCCAXugAwIBAgITDdEJvluliE0AzYaIE4jTMdnFTzAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIyMDMyNTE2NTA0NloXDTMyMDMyMjE2NTA0NVowKjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMo9BUNk9QIYisYysC24+2OytoV72YiLonYcqR3yeVnYziPt7Xv++CYE8yoCTiwedUECCWKOcvQKRCJZb9ht4Hzy+VvBx36hK+C6sECCSR0x6pPSiz+cTk1f788ZjBlUZaNjMGEwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP9CMrpofas6cK/cDNQa4j6Hj2ZlMB8GA1UdIwQYMBaAFP9CMrpofas6cK/cDNQa4j6Hj2ZlMAoGCCqGSM49BAMDA2kAMGYCMQD+kojuzMwztNay9Ibzjuk//ZL5m6T2OCsm45l1lY004pcb984L926BowodoirFMcMCMQDIJtFHhP/1D3a+M3dAGomOb6O4CmTry3TTPbPsAFnv22YA0Y+P21NVoxKDjdu0tkw=" + }, + { + "rawBytes": "MIICGTCCAaCgAwIBAgITJta/okfgHvjabGm1BOzuhrwA1TAKBggqhkjOPQQDAzAqMRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIyMDQxNDIxMzg0MFoXDTMyMDMyMjE2NTA0NVowNzEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MR4wHAYDVQQDExVzaWdzdG9yZS1pbnRlcm1lZGlhdGUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASosAySWJQ/tK5r8T5aHqavk0oI+BKQbnLLdmOMRXHQF/4Hx9KtNfpcdjH9hNKQSBxSlLFFN3tvFCco0qFBzWYwZtsYsBe1l91qYn/9VHFTaEVwYQWIJEEvrs0fvPuAqjajezB5MA4GA1UdDwEB/wQEAwIBBjATBgNVHSUEDDAKBggrBgEFBQcDAzASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRxhjCmFHxib/n31vQFGn9f/+tvrDAfBgNVHSMEGDAWgBT/QjK6aH2rOnCv3AzUGuI+h49mZTAKBggqhkjOPQQDAwNnADBkAjAM1lbKkcqQlE/UspMTbWNo1y2TaJ44tx3l/FJFceTSdDZ+0W1OHHeU4twie/lq8XgCMHQxgEv26xNNiAGyPXbkYgrDPvbOqp0UeWX4mJnLSrBr3aN/KX1SBrKQu220FmVL0Q==" + } + ] + }, + "validFor": { + "start": "2022-03-25T16:50:46.000Z" + } + } + ], + "ctlogs": [ + { + "baseUrl": "https://ctfe.sigstage.dev/test", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MIICCgKCAgEA27A2MPQXm0I0v7/Ly5BIauDjRZF5Jor9vU+QheoE2UIIsZHcyYq3slHzSSHy2lLj1ZD2d91CtJ492ZXqnBmsr4TwZ9jQ05tW2mGIRI8u2DqN8LpuNYZGz/f9SZrjhQQmUttqWmtu3UoLfKz6NbNXUnoo+NhZFcFRLXJ8VporVhuiAmL7zqT53cXR3yQfFPCUDeGnRksnlhVIAJc3AHZZSHQJ8DEXMhh35TVv2nYhTI3rID7GwjXXw4ocz7RGDD37ky6p39Tl5NB71gT1eSqhZhGHEYHIPXraEBd5+3w9qIuLWlp5Ej/K6Mu4ELioXKCUimCbwy+Cs8UhHFlqcyg4AysOHJwIadXIa8LsY51jnVSGrGOEBZevopmQPNPtyfFY3dmXSS+6Z3RD2Gd6oDnNGJzpSyEk410Ag5uvNDfYzJLCWX9tU8lIxNwdFYmIwpd89HijyRyoGnoJ3entd63cvKfuuix5r+GHyKp1Xm1L5j5AWM6P+z0xigwkiXnt+adexAl1J9wdDxv/pUFEESRF4DG8DFGVtbdH6aR1A5/vD4krO4tC1QYUSeyL5Mvsw8WRqIFHcXtgybtxylljvNcGMV1KXQC8UFDmpGZVDSHx6v3e/BHMrZ7gjoCCfVMZ/cFcQi0W2AIHPYEMH/C95J2r4XbHMRdYXpovpOoT5Ca78gsCAwEAAQ==", + "keyDetails": "PKCS1_RSA_PKCS1V5", + "validFor": { + "start": "2021-03-14T00:00:00.000Z" + } + }, + "logId": { + "keyId": "s9AOb93xWxr+a4ztxJnxxJCX7VZ0V3IF4jTu/OoL84A=" + } + }, + { + "baseUrl": "https://ctfe.sigstage.dev/2022", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEh99xuRi6slBFd8VUJoK/rLigy4bYeSYWO/fE6Br7r0D8NpMI94+A63LR/WvLxpUUGBpY8IJA3iU2telag5CRpA==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2022-07-01T00:00:00.000Z" + } + }, + "logId": { + "keyId": "++JKOMQt7SJ3ynUHnCfnDhcKP8/58J4TueMqXuk3HmA=" + } + }, + { + "baseUrl": "https://ctfe.sigstage.dev/2022-2", + "hashAlgorithm": "SHA2_256", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8gEDKNme8AnXuPBgHjrtXdS6miHqc24CRblNEOFpiJRngeq8Ko73Y+K18yRYVf1DXD4AVLwvKyzdNdl5n0jUSQ==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2022-07-01T00:00:00.000Z" + } + }, + "logId": { + "keyId": "KzC83GiIyeLh2CYpXnQfSDkxlgLynDPLXkNA/rKshno=" + } + } + ], + "timestampAuthorities": [] +} diff --git a/tests/data/repository/targets/fulcio.crt.pem b/tests/data/repository/targets/fulcio.crt.pem deleted file mode 100644 index 6a06ff300b..0000000000 --- a/tests/data/repository/targets/fulcio.crt.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIB+DCCAX6gAwIBAgITNVkDZoCiofPDsy7dfm6geLbuhzAKBggqhkjOPQQDAzAq -MRUwEwYDVQQKEwxzaWdzdG9yZS5kZXYxETAPBgNVBAMTCHNpZ3N0b3JlMB4XDTIx -MDMwNzAzMjAyOVoXDTMxMDIyMzAzMjAyOVowKjEVMBMGA1UEChMMc2lnc3RvcmUu -ZGV2MREwDwYDVQQDEwhzaWdzdG9yZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABLSy -A7Ii5k+pNO8ZEWY0ylemWDowOkNa3kL+GZE5Z5GWehL9/A9bRNA3RbrsZ5i0Jcas -taRL7Sp5fp/jD5dxqc/UdTVnlvS16an+2Yfswe/QuLolRUCrcOE2+2iA5+tzd6Nm -MGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE -FMjFHQBBmiQpMlEk6w2uSu1KBtPsMB8GA1UdIwQYMBaAFMjFHQBBmiQpMlEk6w2u -Su1KBtPsMAoGCCqGSM49BAMDA2gAMGUCMH8liWJfMui6vXXBhjDgY4MwslmN/TJx -Ve/83WrFomwmNf056y1X48F9c4m3a3ozXAIxAKjRay5/aj/jsKKGIkmQatjI8uup -Hr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ== ------END CERTIFICATE----- \ No newline at end of file diff --git a/tests/data/repository/targets/fulcio_v1.crt.pem b/tests/data/repository/targets/fulcio_v1.crt.pem deleted file mode 100644 index 3afc46bb6e..0000000000 --- a/tests/data/repository/targets/fulcio_v1.crt.pem +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIB9zCCAXygAwIBAgIUALZNAPFdxHPwjeDloDwyYChAO/4wCgYIKoZIzj0EAwMw -KjEVMBMGA1UEChMMc2lnc3RvcmUuZGV2MREwDwYDVQQDEwhzaWdzdG9yZTAeFw0y -MTEwMDcxMzU2NTlaFw0zMTEwMDUxMzU2NThaMCoxFTATBgNVBAoTDHNpZ3N0b3Jl -LmRldjERMA8GA1UEAxMIc2lnc3RvcmUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAT7 -XeFT4rb3PQGwS4IajtLk3/OlnpgangaBclYpsYBr5i+4ynB07ceb3LP0OIOZdxex -X69c5iVuyJRQ+Hz05yi+UF3uBWAlHpiS5sh0+H2GHE7SXrk1EC5m1Tr19L9gg92j -YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRY -wB5fkUWlZql6zJChkyLQKsXF+jAfBgNVHSMEGDAWgBRYwB5fkUWlZql6zJChkyLQ -KsXF+jAKBggqhkjOPQQDAwNpADBmAjEAj1nHeXZp+13NWBNa+EDsDP8G1WWg1tCM -WP/WHPqpaVo0jhsweNFZgSs0eE7wYI4qAjEA2WB9ot98sIkoF3vZYdd3/VtWB5b9 -TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ ------END CERTIFICATE----- \ No newline at end of file diff --git a/tests/data/repository/targets/registry.npmjs.org/7a8ec9678ad824cdccaa7a6dc0961caf8f8df61bc7274189122c123446248426.keys.json b/tests/data/repository/targets/registry.npmjs.org/7a8ec9678ad824cdccaa7a6dc0961caf8f8df61bc7274189122c123446248426.keys.json new file mode 100644 index 0000000000..f5667a5f0e --- /dev/null +++ b/tests/data/repository/targets/registry.npmjs.org/7a8ec9678ad824cdccaa7a6dc0961caf8f8df61bc7274189122c123446248426.keys.json @@ -0,0 +1,26 @@ +{ + "keys": [ + { + "keyId": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", + "keyUsage": "npm:signatures", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "1999-01-01T00:00:00.000Z" + } + } + }, + { + "keyId": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", + "keyUsage": "npm:attestations", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2022-12-01T00:00:00.000Z" + } + } + } + ] +} diff --git a/tests/data/repository/targets/registry.npmjs.org/881a853ee92d8cf513b07c164fea36b22a7305c256125bdfffdc5c65a4205c4c3fc2b5bcc98964349167ea68d40b8cd02551fcaa870a30d4601ba1caf6f63699.keys.json b/tests/data/repository/targets/registry.npmjs.org/881a853ee92d8cf513b07c164fea36b22a7305c256125bdfffdc5c65a4205c4c3fc2b5bcc98964349167ea68d40b8cd02551fcaa870a30d4601ba1caf6f63699.keys.json new file mode 100644 index 0000000000..f5667a5f0e --- /dev/null +++ b/tests/data/repository/targets/registry.npmjs.org/881a853ee92d8cf513b07c164fea36b22a7305c256125bdfffdc5c65a4205c4c3fc2b5bcc98964349167ea68d40b8cd02551fcaa870a30d4601ba1caf6f63699.keys.json @@ -0,0 +1,26 @@ +{ + "keys": [ + { + "keyId": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", + "keyUsage": "npm:signatures", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "1999-01-01T00:00:00.000Z" + } + } + }, + { + "keyId": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA", + "keyUsage": "npm:attestations", + "publicKey": { + "rawBytes": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1Olb3zMAFFxXKHiIkQO5cJ3Yhl5i6UPp+IhuteBJbuHcA5UogKo0EWtlWwW6KSaKoTNEYL7JlCQiVnkhBktUgg==", + "keyDetails": "PKIX_ECDSA_P256_SHA_256", + "validFor": { + "start": "2022-12-01T00:00:00.000Z" + } + } + } + ] +} diff --git a/tests/data/repository/targets/rekor.0.pub b/tests/data/repository/targets/rekor.0.pub deleted file mode 100644 index 050ef60149..0000000000 --- a/tests/data/repository/targets/rekor.0.pub +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwr -kBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw== ------END PUBLIC KEY----- diff --git a/tests/data/repository/targets/rekor.json b/tests/data/repository/targets/rekor.json deleted file mode 100644 index f86930d537..0000000000 --- a/tests/data/repository/targets/rekor.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "signatures": [ - { - "keyid": "ae0c689c6347ada7359df48934991f4e013193d6ddf3482a5ffb293f74f3b217", - "sig": "3045022076eadd73f6664bac5cc91f12d3a7ddcdd53f9bde661f147651196ff66e7235d1022100f7b3143792405f9e8a75331a05d4128bdf083de302801e99c3d027919a4b03da" - } - ], - "signed": { - "_type": "targets", - "expires": "2022-05-11T19:10:11Z", - "spec_version": "1.0", - "targets": { - "rekor.0.pub": { - "hashes": { - "sha256": "dce5ef715502ec9f3cdfd11f8cc384b31a6141023d3e7595e9908a81cb6241bd", - "sha512": "0ae7705e02db33e814329746a4a0e5603c5bdcd91c96d072158d71011a2695788866565a2fec0fe363eb72cbcaeda39e54c5fe8d416daf9f3101fdba4217ef35" - }, - "length": 178 - } - }, - "version": 1 - } -} \ No newline at end of file diff --git a/tests/data/repository/targets/rekor.pub b/tests/data/repository/targets/rekor.pub deleted file mode 100644 index 050ef60149..0000000000 --- a/tests/data/repository/targets/rekor.pub +++ /dev/null @@ -1,4 +0,0 @@ ------BEGIN PUBLIC KEY----- -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2G2Y+2tabdTV5BcGiBIx0a9fAFwr -kBbmLSGtks4L3qX6yYY0zufBnhC8Ur/iy55GhWP/9A/bY2LhC30M9+RYtw== ------END PUBLIC KEY----- diff --git a/tests/data/repository/timestamp.json b/tests/data/repository/timestamp.json index 8cb4f094b7..4b4a4dec2c 100644 --- a/tests/data/repository/timestamp.json +++ b/tests/data/repository/timestamp.json @@ -1,24 +1,24 @@ { - "signatures": [ - { - "keyid": "b6710623a30c010738e64c5209d367df1c0a18cf90e6ab5292fb01680f83453d", - "sig": "30440220590dc4d9eb4e3b2745315348c1ea5481f29f981dfd6c2d72bde13256a25e0caf02205704352c828451bf1e41bba154db9ecb4e901b4bc47d721a91fabfb84a48c61f" - } - ], "signed": { "_type": "timestamp", - "expires": "2022-01-05T00:40:07Z", + "spec_version": "1.0", + "version": 2, + "expires": "2028-04-12T21:11:28Z", "meta": { "snapshot.json": { + "length": 1039, "hashes": { - "sha256": "e202c20580ac4edc7a52ad2bcbe97c5af557c04463f10f2d9a28e2624e0c8edf", - "sha512": "f0b9f17797fe6d89a745f8fc9a39a073823bc04400307711eebe3b00dfe418e4d1d4419697eee29445c9cd5e03c3e24532d4fb03824d7555ecc0de54bd73ffd1" + "sha256": "b480856ab72c80fe10902ffac69ec10340e827e02b2bd114d6f141de910a96c5", + "sha512": "da06f65c1ee242d63820ba646fb1b4037fe355460309d89f98a923d1d009e7d46f11d4272a0d8e07829734baea655f7692d8c23383d6044b4f72263a4dbf3057" }, - "length": 1658, - "version": 6 + "version": 2 } - }, - "spec_version": "1.0", - "version": 6 - } + } + }, + "signatures": [ + { + "keyid": "314ae73abd3012fc73bfcc3783e31d03852716597642b891d6a33155c4baf600", + "sig": "3044022040e243b1bc8edb798df66803c2460471a4129704421d59f55c825dc549493f840220267e4684875d4803ae0948140af32fc9f560453efb84d9728ee66619e8767d8c" + } + ] } \ No newline at end of file