Skip to content

Commit

Permalink
sign: init
Browse files Browse the repository at this point in the history
Signed-off-by: Jack Leightcap <jack.leightcap@trailofbits.com>
Signed-off-by: Andrew Pan <andrew.pan@trailofbits.com>
Co-authored-by: Jack Leightcap <jack.leightcap@trailofbits.com>
  • Loading branch information
tnytown and jleightcap committed Nov 15, 2023
1 parent f89751d commit a4ec98e
Show file tree
Hide file tree
Showing 42 changed files with 1,871 additions and 555 deletions.
17 changes: 9 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ readme = "README.md"
repository = "https://github.com/sigstore/sigstore-rs"

[features]
default = ["full-native-tls", "cached-client", "tuf"]
default = ["full-native-tls", "cached-client", "tuf", "sign"]
wasm = ["getrandom/js"]

full-native-tls = [
Expand Down Expand Up @@ -42,6 +42,8 @@ rekor = ["reqwest"]

tuf = ["tough", "regex"]

sign = []

cosign-native-tls = [
"oci-distribution/native-tls",
"cert",
Expand Down Expand Up @@ -72,7 +74,7 @@ async-trait = "0.1.52"
base64 = "0.21.0"
cached = { version = "0.46.0", optional = true, features = ["async"] }
cfg-if = "1.0.0"
chrono = { version = "0.4.27", default-features = false }
chrono = { version = "0.4.27", default-features = false, features = ["serde"] }
const-oid = "0.9.1"
digest = { version = "0.10.3", default-features = false }
ecdsa = { version = "0.16.7", features = ["pkcs8", "digest", "der", "signing"] }
Expand All @@ -88,10 +90,7 @@ openidconnect = { version = "3.0", default-features = false, features = [
p256 = "0.13.2"
p384 = "0.13"
webbrowser = "0.8.4"
pem = "3.0"
picky = { version = "7.0.0-rc.8", default-features = false, features = [
"x509",
] }
pem = { version = "3.0", features = ["serde"] }
pkcs1 = { version = "0.7.5", features = ["std"] }
pkcs8 = { version = "0.10.2", features = [
"pem",
Expand All @@ -113,17 +112,20 @@ serde_json = "1.0.79"
serde_with = { version = "3.4.0", features = ["base64"] }
sha2 = { version = "0.10.6", features = ["oid"] }
signature = { version = "2.0" }
sigstore_protobuf_specs = "0.1.0-rc.2"
thiserror = "1.0.30"
tokio = { version = "1.17.0", features = ["rt"] }
tough = { version = "0.14", features = ["http"], optional = true }
tracing = "0.1.31"
url = "2.2.2"
x509-cert = { version = "0.2.2", features = ["pem", "std"] }
x509-cert = { version = "0.2.2", features = ["builder", "pem", "std"] }
crypto_secretbox = "0.1.1"
zeroize = "1.5.7"
rustls-webpki = { version = "0.102.0-alpha.4", features = ["alloc"] }
rustls-pki-types = { version = "0.2.1", features = ["std"] }
serde_repr = "0.1.16"
hex = "0.4.3"
json-syntax = { version = "0.9.6", features = ["canonicalize", "serde"] }

[dev-dependencies]
anyhow = { version = "1.0", features = ["backtrace"] }
Expand All @@ -137,7 +139,6 @@ serial_test = "2.0.0"
tempfile = "3.3.0"
testcontainers = "0.15"
tracing-subscriber = { version = "0.3.9", features = ["env-filter"] }
hex = "0.4.3"

# cosign example mappings

Expand Down
54 changes: 54 additions & 0 deletions src/bundle/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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.

//! Useful types for Sigstore bundles.
use std::fmt::Display;

pub use sigstore_protobuf_specs::Bundle;

// Known Sigstore bundle media types.
#[derive(Clone, Copy, Debug)]
pub enum Version {
Bundle0_1,
Bundle0_2,
}

impl TryFrom<&str> for Version {
type Error = ();

fn try_from(value: &str) -> Result<Self, Self::Error> {
match value {
"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(()),
}
}
}

impl From<Version> for &str {
fn from(value: Version) -> Self {
match value {
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 Display for Version {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str((*self).into())?;
Ok(())
}
}
12 changes: 12 additions & 0 deletions src/crypto/verification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use rustls_pki_types::CertificateDer;
use webpki::TrustAnchor;

/// Machinery for Sigstore end entity certificate verification.
struct CertificateVerificationContext<'a> {
pub trust_anchors: Vec<TrustAnchor<'a>>,
pub intermediate_certs: Vec<CertificateDer<'a>>,
}

impl CertificateVerificationContext<'_> {
pub fn new() {}
}
64 changes: 63 additions & 1 deletion src/crypto/verification_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -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)]
Expand Down
30 changes: 30 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ pub enum SigstoreError {
#[error("invalid key format: {error}")]
InvalidKeyFormat { error: String },

#[error("Unable to parse identity token: {0}")]
IdentityTokenError(&'static str),

#[error("unmatched key type {key_typ} and signing scheme {scheme}")]
UnmatchedKeyAndSigningScheme { key_typ: String, scheme: String },

Expand All @@ -70,6 +73,9 @@ pub enum SigstoreError {
#[error("Public key verification error")]
PublicKeyVerificationError,

#[error("X.509 certificate version is not V3")]
CertificateUnsupportedVersionError,

#[error("Certificate validity check failed: cannot be used before {0}")]
CertificateValidityError(String),

Expand Down Expand Up @@ -103,6 +109,12 @@ pub enum SigstoreError {
#[error("Certificate pool error: {0}")]
CertificatePoolError(&'static str),

#[error("Signing session expired")]
ExpiredSigningSession(),

#[error("Fulcio request unsuccessful: {0}")]
FulcioClientError(&'static str),

#[error("Cannot fetch manifest of {image}: {error}")]
RegistryFetchManifestError { image: String, error: String },

Expand All @@ -115,9 +127,18 @@ pub enum SigstoreError {
#[error("Cannot push {image}: {error}")]
RegistryPushError { image: String, error: String },

#[error("Rekor request unsuccessful: {0}")]
RekorClientError(String),

#[error(transparent)]
ReqwestError(#[from] reqwest::Error),

Check failure on line 134 in src/errors.rs

View workflow job for this annotation

GitHub Actions / Check WASM

failed to resolve: use of undeclared crate or module `reqwest`

#[error("OCI reference not valid: {reference}")]
OciReferenceNotValidError { reference: String },

#[error("Sigstore bundle malformed: {0}")]
SigstoreBundleMalformedError(String),

#[error("Layer doesn't have Sigstore media type")]
SigstoreMediaTypeNotFoundError,

Expand Down Expand Up @@ -155,6 +176,9 @@ pub enum SigstoreError {
#[error("{0}")]
VerificationConstraintError(String),

#[error("{0}")]
VerificationMaterialError(String),

#[error("{0}")]
ApplyConstraintError(String),

Expand Down Expand Up @@ -214,4 +238,10 @@ pub enum SigstoreError {

#[error(transparent)]
Ed25519PKCS8Error(#[from] ed25519_dalek::pkcs8::spki::Error),

#[error(transparent)]
X509ParseError(#[from] x509_cert::der::Error),

#[error(transparent)]
X509BuilderError(#[from] x509_cert::builder::Error),
}
Loading

0 comments on commit a4ec98e

Please sign in to comment.