Skip to content

Commit

Permalink
refactor: remove ring dependency
Browse files Browse the repository at this point in the history
- replace ring crate with RustCrypto
- refactor CosignVerificationKey implementation and interface
- fix the code which references CosignVerificationKey

Signed-off-by: Xynnn007 <mading.ma@alibaba-inc.com>
  • Loading branch information
Xynnn007 committed Sep 13, 2022
1 parent 7805f14 commit fe13148
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 287 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ openidconnect = { version = "2.3", default-features = false, features = [ "reqwe
pem = "1.0.2"
picky = { version = "7.0.0-rc.3", default-features = false, features = [ "x509", "ec" ] }
regex = "1.5.5"
ring = "0.16.20"
serde_json = "1.0.79"
serde = { version = "1.0.136", features = ["derive"] }
sha2 = "0.10.2"
Expand All @@ -44,7 +43,7 @@ pkcs8 = { version = "0.9.0", features = ["pem", "alloc", "pkcs5", "encryption"]
elliptic-curve = { version = "0.12.2", features = [ "arithmetic", "pem" ] }
p256 = "0.11.1"
p384 = "0.11.1"
ecdsa = { version = "0.14.3", features = [ "pkcs8", "digest" ] }
ecdsa = { version = "0.14.3", features = [ "pkcs8", "digest", "der" ] }
digest = "0.10.3"
signature = { version = "1.5.0", features = [ "digest-preview" ] }
ed25519 = { version = "1", features = [ "alloc" ] }
Expand Down
15 changes: 7 additions & 8 deletions examples/cosign/verify/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use sigstore::cosign::verification_constraint::{
VerificationConstraintVec,
};
use sigstore::cosign::{CosignCapabilities, SignatureLayer};
use sigstore::crypto::SignatureDigestAlgorithm;
use sigstore::crypto::SigningScheme;
use sigstore::errors::SigstoreVerifyConstraintsError;
use sigstore::tuf::SigstoreRepository;
use std::boxed::Box;
Expand Down Expand Up @@ -47,9 +47,9 @@ struct Cli {
#[clap(short, long, required(false))]
key: Option<String>,

/// Digest algorithm to use when processing a signature
#[clap(long, default_value = "sha256")]
signature_digest_algorithm: String,
/// Signing scheme when signing and verifying
#[clap(long, default_value = "ECDSA_P256_SHA256_ASN1")]
signing_scheme: String,

/// Fetch Rekor and Fulcio data from Sigstore's TUF repository"
#[clap(long)]
Expand Down Expand Up @@ -156,10 +156,9 @@ async fn run_app(
}
if let Some(path_to_key) = cli.key.as_ref() {
let key = fs::read(path_to_key).map_err(|e| anyhow!("Cannot read key: {:?}", e))?;
let signature_digest_algorithm =
SignatureDigestAlgorithm::try_from(cli.signature_digest_algorithm.as_str())
.map_err(anyhow::Error::msg)?;
let verifier = PublicKeyVerifier::new(&key, signature_digest_algorithm)
let signing_scheme =
SigningScheme::try_from(cli.signing_scheme.as_str()).map_err(anyhow::Error::msg)?;
let verifier = PublicKeyVerifier::new(&key, &signing_scheme)
.map_err(|e| anyhow!("Cannot create public key verifier: {}", e))?;
verification_constraints.push(Box::new(verifier));
}
Expand Down
2 changes: 1 addition & 1 deletion examples/key_interface/key_pair_gen_and_export/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// limitations under the License.

use anyhow::Result;
use sigstore::crypto::signing_key::SigningScheme;
use sigstore::crypto::SigningScheme;

const PASSWORD: &str = "example password";

Expand Down
2 changes: 1 addition & 1 deletion examples/key_interface/key_pair_gen_sign_verify/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// limitations under the License.

use anyhow::{anyhow, Result};
use sigstore::crypto::{signing_key::SigningScheme, Signature};
use sigstore::crypto::{Signature, SigningScheme};

const DATA_TO_BE_SIGNED: &str = "this is an example data to be signed";

Expand Down
10 changes: 3 additions & 7 deletions examples/key_interface/key_pair_import/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
// limitations under the License.

use anyhow::{bail, Result};
use ring::signature::ECDSA_P256_SHA256_ASN1;
use sigstore::crypto::{
signing_key::{ecdsa::ECDSAKeys, SigStoreKeyPair},
CosignVerificationKey, SignatureDigestAlgorithm,
CosignVerificationKey, SigningScheme,
};

const PASSWORD: &str = "password";
Expand All @@ -30,13 +29,10 @@ const ECDSA_P256_ASN1_ENCRYPTED_PRIVATE_PEM: &[u8] =
include_bytes!("./ECDSA_P256_ASN1_ENCRYPTED_PRIVATE_PEM.key");

fn main() -> Result<()> {
let _ = CosignVerificationKey::from_pem(
ECDSA_P256_ASN1_PUBLIC_PEM,
SignatureDigestAlgorithm::Sha256,
)?;
let _ = CosignVerificationKey::from_pem(ECDSA_P256_ASN1_PUBLIC_PEM, &SigningScheme::default())?;
println!("Imported PEM encoded public key as CosignVerificationKey.");

let _ = CosignVerificationKey::from_der(ECDSA_P256_ASN1_PUBLIC_DER, &ECDSA_P256_SHA256_ASN1)?;
let _ = CosignVerificationKey::from_der(ECDSA_P256_ASN1_PUBLIC_DER, &SigningScheme::default())?;
println!("Imported DER encoded public key as CosignVerificationKey.");

let _ = SigStoreKeyPair::from_pem(ECDSA_P256_ASN1_PRIVATE_PEM)?;
Expand Down
10 changes: 4 additions & 6 deletions src/cosign/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ mod tests {
use serde_json::json;

use crate::cosign::tests::get_rekor_public_key;
use crate::crypto::SignatureDigestAlgorithm;
use crate::crypto::SigningScheme;

fn build_correct_bundle() -> String {
let bundle_json = json!({
Expand Down Expand Up @@ -101,11 +101,9 @@ mod tests {
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAENptdY/l3nB0yqkXLBWkZWQwo6+cu
OSWS1X9vPavpiQOoTTGC0xX57OojUadxF1cdQmrsiReWg2Wn4FneJfa8xw==
-----END PUBLIC KEY-----"#;
let not_rekor_pub_key = CosignVerificationKey::from_pem(
public_key.as_bytes(),
SignatureDigestAlgorithm::default(),
)
.expect("Cannot create CosignVerificationKey");
let not_rekor_pub_key =
CosignVerificationKey::from_pem(public_key.as_bytes(), &SigningScheme::default())
.expect("Cannot create CosignVerificationKey");

let bundle_json = build_correct_bundle();
let bundle = Bundle::new_verified(&bundle_json, &not_rekor_pub_key);
Expand Down
11 changes: 5 additions & 6 deletions src/cosign/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,13 @@ impl Client {
mod tests {
use super::*;
use crate::cosign::tests::{get_fulcio_cert_pool, REKOR_PUB_KEY};
use crate::{crypto::SignatureDigestAlgorithm, mock_client::test::MockOciClient};
use crate::crypto::SigningScheme;
use crate::mock_client::test::MockOciClient;

fn build_test_client(mock_client: MockOciClient) -> Client {
let rekor_pub_key = CosignVerificationKey::from_pem(
REKOR_PUB_KEY.as_bytes(),
SignatureDigestAlgorithm::default(),
)
.expect("Cannot create CosignVerificationKey");
let rekor_pub_key =
CosignVerificationKey::from_pem(REKOR_PUB_KEY.as_bytes(), &SigningScheme::default())
.expect("Cannot create CosignVerificationKey");

Client {
registry_client: Box::new(mock_client),
Expand Down
7 changes: 3 additions & 4 deletions src/cosign/client_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
use tracing::info;

use super::client::Client;
use crate::crypto::{
certificate_pool::CertificatePool, CosignVerificationKey, SignatureDigestAlgorithm,
};
use crate::crypto::SigningScheme;
use crate::crypto::{certificate_pool::CertificatePool, CosignVerificationKey};
use crate::errors::Result;
use crate::registry::{Certificate, ClientConfig};

Expand Down Expand Up @@ -125,7 +124,7 @@ impl ClientBuilder {
}
Some(data) => Some(CosignVerificationKey::from_pem(
data.as_bytes(),
SignatureDigestAlgorithm::default(),
&SigningScheme::default(),
)?),
};

Expand Down
9 changes: 3 additions & 6 deletions src/cosign/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ mod tests {
AnnotationVerifier, CertSubjectEmailVerifier, VerificationConstraintVec,
};
use crate::crypto::certificate_pool::CertificatePool;
use crate::crypto::{CosignVerificationKey, SignatureDigestAlgorithm};
use crate::crypto::{CosignVerificationKey, SigningScheme};
use crate::simple_signing::Optional;

pub(crate) const REKOR_PUB_KEY: &str = r#"-----BEGIN PUBLIC KEY-----
Expand Down Expand Up @@ -201,11 +201,8 @@ TNMea7Ix/stJ5TfcLLeABLE4BNJOsQ4vnBHJ
}

pub(crate) fn get_rekor_public_key() -> CosignVerificationKey {
CosignVerificationKey::from_pem(
REKOR_PUB_KEY.as_bytes(),
SignatureDigestAlgorithm::default(),
)
.expect("Cannot create test REKOR_PUB_KEY")
CosignVerificationKey::from_pem(REKOR_PUB_KEY.as_bytes(), &SigningScheme::default())
.expect("Cannot create test REKOR_PUB_KEY")
}

#[test]
Expand Down
23 changes: 8 additions & 15 deletions src/cosign/signature_layers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ use super::constants::{
};
use crate::crypto::certificate_pool::CertificatePool;
use crate::{
crypto::{
self, CosignVerificationKey, Signature, SIGSTORE_DEFAULT_SIGNATURE_VERIFICATION_ALGORITHM,
},
crypto::{self, CosignVerificationKey, Signature, SigningScheme},
errors::{Result, SigstoreError},
simple_signing::SimpleSigning,
};
Expand Down Expand Up @@ -366,10 +364,8 @@ impl CertificateSignature {
crypto::certificate::is_trusted(&cert, integrated_time)?;

let subject = CertificateSubject::from_certificate(&cert)?;
let verification_key = CosignVerificationKey::from_der(
cert.public_key().raw,
SIGSTORE_DEFAULT_SIGNATURE_VERIFICATION_ALGORITHM,
)?;
let verification_key =
CosignVerificationKey::from_der(cert.public_key().raw, &SigningScheme::default())?;

let issuer = get_cert_extension_by_oid(&cert, SIGSTORE_ISSUER_OID, "Issuer")?;

Expand Down Expand Up @@ -464,7 +460,6 @@ pub(crate) mod tests {
use std::convert::TryFrom;

use crate::cosign::tests::{get_fulcio_cert_pool, get_rekor_public_key};
use crate::crypto::SignatureDigestAlgorithm;

pub(crate) fn build_correct_signature_layer_without_bundle(
) -> (SignatureLayer, CosignVerificationKey) {
Expand All @@ -474,11 +469,9 @@ OSWS1X9vPavpiQOoTTGC0xX57OojUadxF1cdQmrsiReWg2Wn4FneJfa8xw==
-----END PUBLIC KEY-----"#;

let signature = String::from("MEUCIQD6q/COgzOyW0YH1Dk+CCYSt4uAhm3FDHUwvPI55zwnlwIgE0ZK58ZOWpZw8YVmBapJhBqCfdPekIknimuO0xH8Jh8=");
let verification_key = CosignVerificationKey::from_pem(
public_key.as_bytes(),
SignatureDigestAlgorithm::default(),
)
.expect("Cannot create CosignVerificationKey");
let verification_key =
CosignVerificationKey::from_pem(public_key.as_bytes(), &SigningScheme::default())
.expect("Cannot create CosignVerificationKey");
let ss_value = json!({
"critical": {
"identity": {
Expand Down Expand Up @@ -576,7 +569,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETJP9cqpUQsn2ggmJniWGjHdlsHzD
JsB89BPhZYch0U0hKANx5TY+ncrm0s8bfJxxHoenAEFhwhuXeb4PqIrtoQ==
-----END PUBLIC KEY-----"#
.as_bytes(),
SignatureDigestAlgorithm::default(),
&SigningScheme::default(),
)
.expect("Cannot create CosignVerificationKey");

Expand Down Expand Up @@ -789,7 +782,7 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETJP9cqpUQsn2ggmJniWGjHdlsHzD
JsB89BPhZYch0U0hKANx5TY+ncrm0s8bfJxxHoenAEFhwhuXeb4PqIrtoQ==
-----END PUBLIC KEY-----"#
.as_bytes(),
SignatureDigestAlgorithm::default(),
&SigningScheme::default(),
)
.expect("Cannot create CosignVerificationKey");
assert!(!sl.is_signed_by_key(&verification_key));
Expand Down
9 changes: 3 additions & 6 deletions src/cosign/verification_constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
use std::collections::HashMap;

use super::signature_layers::{CertificateSubject, SignatureLayer};
use crate::crypto::{CosignVerificationKey, SignatureDigestAlgorithm};
use crate::crypto::{CosignVerificationKey, SigningScheme};
use crate::errors::Result;

/// A list of objects implementing the [`VerificationConstraint`] trait
Expand Down Expand Up @@ -79,11 +79,8 @@ impl PublicKeyVerifier {
/// Create a new instance of `PublicKeyVerifier`.
/// The `key_raw` variable holds a PEM encoded rapresentation of the
/// public key to be used at verification time.
pub fn new(
key_raw: &[u8],
signature_digest_algorithm: SignatureDigestAlgorithm,
) -> Result<Self> {
let key = CosignVerificationKey::from_pem(key_raw, signature_digest_algorithm)?;
pub fn new(key_raw: &[u8], signing_scheme: &SigningScheme) -> Result<Self> {
let key = CosignVerificationKey::from_pem(key_raw, signing_scheme)?;
Ok(PublicKeyVerifier { key })
}
}
Expand Down
82 changes: 56 additions & 26 deletions src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,70 @@

//! Structures and constants required to perform cryptographic operations.

use ring::signature;
use sha2::{Sha256, Sha384};
use std::convert::TryFrom;

/// The default signature verification algorithm used by Sigstore.
/// Sigstore relies on NIST P-256
/// NIST P-256 is a Weierstrass curve specified in [FIPS 186-4: Digital Signature Standard (DSS)](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf).
/// Also known as prime256v1 (ANSI X9.62) and secp256r1 (SECG)
pub static SIGSTORE_DEFAULT_SIGNATURE_VERIFICATION_ALGORITHM:
&signature::EcdsaVerificationAlgorithm = &signature::ECDSA_P256_SHA256_ASN1;

/// Describes the signature digest algorithms supported.
/// The default one is sha256.
#[derive(Debug, Clone)]
pub enum SignatureDigestAlgorithm {
Sha256,
Sha384,
Sha512,
use crate::errors::*;

pub use signing_key::SigStoreSigner;
pub use verification_key::CosignVerificationKey;

/// Different digital signature algorithms.
/// * `ECDSA_P256_SHA256_ASN1`: ASN.1 DER-encoded ECDSA
/// signatures using the P-256 curve and SHA-256. It
/// is the default signing scheme.
/// * `ECDSA_P384_SHA384_ASN1`: ASN.1 DER-encoded ECDSA
/// signatures using the P-384 curve and SHA-384.
/// * `ED25519`: ECDSA signature using SHA2-512
/// as the digest function and curve edwards25519. The
/// signature format please refer
/// to [RFC 8032](https://www.rfc-editor.org/rfc/rfc8032.html#section-5.1.6).
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy)]
pub enum SigningScheme {
// TODO: Support RSA
ECDSA_P256_SHA256_ASN1,
ECDSA_P384_SHA384_ASN1,
ED25519,
}

impl TryFrom<&str> for SignatureDigestAlgorithm {
impl TryFrom<&str> for SigningScheme {
type Error = String;

fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
match value {
"sha256" => Ok(Self::Sha256),
"sha384" => Ok(Self::Sha384),
"sha512" => Ok(Self::Sha512),
unknown => Err(format!(
"Unsupported signature digest algorithm: {}",
unknown
)),
"ECDSA_P256_SHA256_ASN1" => Ok(Self::ECDSA_P256_SHA256_ASN1),
"ECDSA_P384_SHA384_ASN1" => Ok(Self::ECDSA_P384_SHA384_ASN1),
"ED25519" => Ok(Self::ED25519),
unknown => Err(format!("Unsupported signing algorithm: {}", unknown)),
}
}
}

impl Default for SignatureDigestAlgorithm {
impl SigningScheme {
/// Create a key-pair due to the given signing scheme.
pub fn create_signer(&self) -> Result<SigStoreSigner> {
Ok(match self {
SigningScheme::ECDSA_P256_SHA256_ASN1 => SigStoreSigner::ECDSA_P256_SHA256_ASN1(
EcdsaSigner::<_, Sha256>::from_ecdsa_keys(&EcdsaKeys::<p256::NistP256>::new()?)?,
),
SigningScheme::ECDSA_P384_SHA384_ASN1 => SigStoreSigner::ECDSA_P384_SHA384_ASN1(
EcdsaSigner::<_, Sha384>::from_ecdsa_keys(&EcdsaKeys::<p384::NistP384>::new()?)?,
),
SigningScheme::ED25519 => {
SigStoreSigner::ED25519(Ed25519Signer::from_ed25519_keys(&Ed25519Keys::new()?)?)
}
})
}
}

/// The default signature verification algorithm used by Sigstore.
/// Sigstore relies on NIST P-256
/// NIST P-256 is a Weierstrass curve specified in [FIPS 186-4: Digital Signature Standard (DSS)](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf).
/// Also known as prime256v1 (ANSI X9.62) and secp256r1 (SECG)
impl Default for SigningScheme {
fn default() -> Self {
Self::Sha256
SigningScheme::ECDSA_P256_SHA256_ASN1
}
}

Expand All @@ -68,7 +94,11 @@ pub(crate) mod certificate;
pub(crate) mod certificate_pool;

pub mod verification_key;
pub use verification_key::CosignVerificationKey;

use self::signing_key::{
ecdsa::ec::{EcdsaKeys, EcdsaSigner},
ed25519::{Ed25519Keys, Ed25519Signer},
};

pub mod signing_key;

Expand Down
Loading

0 comments on commit fe13148

Please sign in to comment.