From 450aec3836641202fddf7f0657c443136bdfb848 Mon Sep 17 00:00:00 2001 From: "Charles E. Lehner" Date: Wed, 20 Oct 2021 11:33:38 -0400 Subject: [PATCH 1/4] Zeroize values during Ed25519 key generation --- src/jwk.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/jwk.rs b/src/jwk.rs index 3ab3c6407..db454ba5f 100644 --- a/src/jwk.rs +++ b/src/jwk.rs @@ -244,19 +244,19 @@ impl Default for Algorithm { impl JWK { #[cfg(feature = "ring")] pub fn generate_ed25519() -> Result { - use ring::signature::KeyPair; let rng = ring::rand::SystemRandom::new(); - let doc = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng)?; - let key_pkcs8 = doc.as_ref(); - let keypair = ring::signature::Ed25519KeyPair::from_pkcs8(key_pkcs8)?; - let public_key = keypair.public_key().as_ref(); + let mut key_pkcs8 = ring::signature::Ed25519KeyPair::generate_pkcs8(&rng)? + .as_ref() + .to_vec(); // reference: ring/src/ec/curve25519/ed25519/signing.rs - let private_key = &key_pkcs8[0x10..0x30]; + let private_key = key_pkcs8[0x10..0x30].to_vec(); + let public_key = key_pkcs8[0x35..0x55].to_vec(); + key_pkcs8.zeroize(); Ok(JWK { params: Params::OKP(OctetParams { curve: "Ed25519".to_string(), - public_key: Base64urlUInt(public_key.to_vec()), - private_key: Some(Base64urlUInt(private_key.to_vec())), + public_key: Base64urlUInt(public_key), + private_key: Some(Base64urlUInt(private_key)), }), public_key_use: None, key_operations: None, From 5b438cdb5ea568a2dfea5f04dd1d119be0a244eb Mon Sep 17 00:00:00 2001 From: "Charles E. Lehner" Date: Wed, 20 Oct 2021 11:55:21 -0400 Subject: [PATCH 2/4] Use JWK::from for simpler construction --- src/jwk.rs | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/src/jwk.rs b/src/jwk.rs index db454ba5f..d5afe7651 100644 --- a/src/jwk.rs +++ b/src/jwk.rs @@ -252,21 +252,11 @@ impl JWK { let private_key = key_pkcs8[0x10..0x30].to_vec(); let public_key = key_pkcs8[0x35..0x55].to_vec(); key_pkcs8.zeroize(); - Ok(JWK { - params: Params::OKP(OctetParams { - curve: "Ed25519".to_string(), - public_key: Base64urlUInt(public_key), - private_key: Some(Base64urlUInt(private_key)), - }), - public_key_use: None, - key_operations: None, - algorithm: None, - key_id: None, - x509_url: None, - x509_certificate_chain: None, - x509_thumbprint_sha1: None, - x509_thumbprint_sha256: None, - }) + Ok(JWK::from(Params::OKP(OctetParams { + curve: "Ed25519".to_string(), + public_key: Base64urlUInt(public_key), + private_key: Some(Base64urlUInt(private_key)), + }))) } #[cfg(feature = "ed25519-dalek")] @@ -275,21 +265,11 @@ impl JWK { let keypair = ed25519_dalek::Keypair::generate(&mut csprng); let sk_bytes = keypair.secret.to_bytes(); let pk_bytes = keypair.public.to_bytes(); - Ok(JWK { - params: Params::OKP(OctetParams { - curve: "Ed25519".to_string(), - public_key: Base64urlUInt(pk_bytes.to_vec()), - private_key: Some(Base64urlUInt(sk_bytes.to_vec())), - }), - public_key_use: None, - key_operations: None, - algorithm: None, - key_id: None, - x509_url: None, - x509_certificate_chain: None, - x509_thumbprint_sha1: None, - x509_thumbprint_sha256: None, - }) + Ok(JWK::from(Params::OKP(OctetParams { + curve: "Ed25519".to_string(), + public_key: Base64urlUInt(pk_bytes.to_vec()), + private_key: Some(Base64urlUInt(sk_bytes.to_vec())), + }))) } #[cfg(feature = "k256")] From 49198f00b335862f216d16a3ba4ed5978d726cf5 Mon Sep 17 00:00:00 2001 From: "Charles E. Lehner" Date: Wed, 20 Oct 2021 11:57:11 -0400 Subject: [PATCH 3/4] Clarify p256 and k256 key generation --- src/jwk.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/jwk.rs b/src/jwk.rs index d5afe7651..cc90ccceb 100644 --- a/src/jwk.rs +++ b/src/jwk.rs @@ -276,10 +276,11 @@ impl JWK { pub fn generate_secp256k1() -> Result { let mut rng = rand::rngs::OsRng {}; let secret_key = k256::SecretKey::random(&mut rng); - let sk_bytes = secret_key.to_bytes(); + // SecretKey zeroizes on drop + let sk_bytes = secret_key.to_bytes().to_vec(); let public_key = secret_key.public_key(); let mut ec_params = ECParams::try_from(&public_key)?; - ec_params.ecc_private_key = Some(Base64urlUInt(sk_bytes.to_vec())); + ec_params.ecc_private_key = Some(Base64urlUInt(sk_bytes)); Ok(JWK::from(Params::EC(ec_params))) } @@ -287,11 +288,11 @@ impl JWK { pub fn generate_p256() -> Result { let mut rng = rand::rngs::OsRng {}; let secret_key = p256::SecretKey::random(&mut rng); - use p256::elliptic_curve::ff::PrimeField; - let sk_bytes = secret_key.secret_scalar().to_repr(); + // SecretKey zeroizes on drop + let sk_bytes = secret_key.to_bytes().to_vec(); let public_key: p256::PublicKey = secret_key.public_key(); let mut ec_params = ECParams::try_from(&public_key)?; - ec_params.ecc_private_key = Some(Base64urlUInt(sk_bytes.to_vec())); + ec_params.ecc_private_key = Some(Base64urlUInt(sk_bytes)); Ok(JWK::from(Params::EC(ec_params))) } From aeea9f4a52a0d11576435ee009d5191e46920389 Mon Sep 17 00:00:00 2001 From: "Charles E. Lehner" Date: Wed, 20 Oct 2021 12:08:36 -0400 Subject: [PATCH 4/4] Clear stack page after signing --- Cargo.toml | 1 + src/jws.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 7805e164d..f3cb25c60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,6 +78,7 @@ sshkeys = "0.3" reqwest = { version = "0.11", features = ["json"] } flate2 = "1.0" bitvec = "0.20" +clear_on_drop = "0.2.4" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] chrono = { version = "0.4", features = ["serde"] } diff --git a/src/jws.rs b/src/jws.rs index a4049d287..b52715298 100644 --- a/src/jws.rs +++ b/src/jws.rs @@ -217,6 +217,7 @@ pub fn sign_bytes(algorithm: Algorithm, data: &[u8], key: &JWK) -> Result return Err(Error::KeyTypeNotImplemented), }; + clear_on_drop::clear_stack(1); Ok(signature) }