diff options
| -rw-r--r-- | Cargo.lock | 1 | ||||
| -rw-r--r-- | oxish-aws-lc/Cargo.toml | 1 | ||||
| -rw-r--r-- | oxish-aws-lc/src/lib.rs | 15 | ||||
| -rw-r--r-- | oxish-graviola/src/lib.rs | 12 | ||||
| -rw-r--r-- | oxish-proto/src/crypto.rs | 13 |
5 files changed, 41 insertions, 1 deletions
@@ -549,6 +549,7 @@ version = "0.1.0" dependencies = [ "aws-lc-rs", "oxish-proto", + "zeroize", ] [[package]] diff --git a/oxish-aws-lc/Cargo.toml b/oxish-aws-lc/Cargo.toml index c8628db..fa7c62b 100644 --- a/oxish-aws-lc/Cargo.toml +++ b/oxish-aws-lc/Cargo.toml @@ -17,6 +17,7 @@ fips = ["aws-lc-rs/fips"] [dependencies] aws-lc-rs = { workspace = true } proto = { package = "oxish-proto", version = "0.1", path = "../oxish-proto" } +zeroize = { workspace = true } [lints] workspace = true diff --git a/oxish-aws-lc/src/lib.rs b/oxish-aws-lc/src/lib.rs index f7e95cc..b203c56 100644 --- a/oxish-aws-lc/src/lib.rs +++ b/oxish-aws-lc/src/lib.rs @@ -4,6 +4,7 @@ use ::aws_lc_rs::{ aead::{AES_128_GCM, Aad, LessSafeKey, NONCE_LEN, Nonce, UnboundKey}, agreement::{self, EphemeralPrivateKey, X25519}, digest, + encoding::{AsBigEndian, Curve25519SeedBin, EcPrivateKeyBin}, kem::ML_KEM_768, rand, signature::{self, EcdsaKeyPair, Ed25519KeyPair, KeyPair, UnparsedPublicKey}, @@ -17,6 +18,7 @@ use proto::{ }, named::{EncryptionAlgorithm, KeyExchangeAlgorithm, MacAlgorithm, PublicKeyAlgorithm}, }; +use zeroize::Zeroizing; pub const DEFAULT_PROVIDER: &'static dyn CryptoProvider = &Provider; @@ -404,6 +406,13 @@ impl SigningKey for Ed25519SigningKey { fn algorithm(&self) -> PublicKeyAlgorithm<'static> { PublicKeyAlgorithm::Ed25519 } + + fn private_key(&self) -> Result<Zeroizing<Vec<u8>>, CryptoError> { + let seed = self.key_pair.seed().map_err(|_| CryptoError::Unspecified)?; + let bytes = AsBigEndian::<Curve25519SeedBin<'_>>::as_be_bytes(&seed) + .map_err(|_| CryptoError::Unspecified)?; + Ok(Zeroizing::new(bytes.as_ref().to_vec())) + } } struct EcdsaP256SigningKey { @@ -439,6 +448,12 @@ impl SigningKey for EcdsaP256SigningKey { fn algorithm(&self) -> PublicKeyAlgorithm<'static> { PublicKeyAlgorithm::EcdsaSha2Nistp256 } + + fn private_key(&self) -> Result<Zeroizing<Vec<u8>>, CryptoError> { + let d = AsBigEndian::<EcPrivateKeyBin<'_>>::as_be_bytes(&self.key_pair.private_key()) + .map_err(|_| CryptoError::Unspecified)?; + Ok(Zeroizing::new(d.as_ref().to_vec())) + } } struct EcdsaP256VerifyingKey { diff --git a/oxish-graviola/src/lib.rs b/oxish-graviola/src/lib.rs index 7cccdbf..ebe1fc9 100644 --- a/oxish-graviola/src/lib.rs +++ b/oxish-graviola/src/lib.rs @@ -385,6 +385,12 @@ impl SigningKey for Ed25519Key { fn algorithm(&self) -> PublicKeyAlgorithm<'static> { PublicKeyAlgorithm::Ed25519 } + + fn private_key(&self) -> Result<Zeroizing<Vec<u8>>, CryptoError> { + // as_seed() returns an owned copy, so wrap it too + let seed = Zeroizing::new(self.key.as_seed()); + Ok(Zeroizing::new(seed.to_vec())) + } } struct EcdsaP256Key { @@ -418,6 +424,12 @@ impl SigningKey for EcdsaP256Key { fn algorithm(&self) -> PublicKeyAlgorithm<'static> { PublicKeyAlgorithm::EcdsaSha2Nistp256 } + + fn private_key(&self) -> Result<Zeroizing<Vec<u8>>, CryptoError> { + // as_bytes() returns an owned copy, so wrap it too + let d = Zeroizing::new(self.key.private_key.as_bytes()); + Ok(Zeroizing::new(d.to_vec())) + } } struct EcdsaP256VerifyingKey(ecdsa::VerifyingKey<P256>); diff --git a/oxish-proto/src/crypto.rs b/oxish-proto/src/crypto.rs index 9e9c247..f2d6d9d 100644 --- a/oxish-proto/src/crypto.rs +++ b/oxish-proto/src/crypto.rs @@ -1,7 +1,7 @@ use core::{error::Error as StdError, fmt}; use std::sync::Arc; -use zeroize::Zeroize; +use zeroize::{Zeroize, Zeroizing}; use crate::named::{EncryptionAlgorithm, KeyExchangeAlgorithm, MacAlgorithm, PublicKeyAlgorithm}; @@ -425,6 +425,17 @@ pub trait SigningKey: Send + Sync { /// The public key algorithm of this key fn algorithm(&self) -> PublicKeyAlgorithm<'static>; + + /// The private key material, in the form the key is stored in + /// + /// For Ed25519 this is the 32-byte seed, not the derived signing + /// scalar. For ECDSA, it is the scalar `d` as a big-endian + /// fixed-length integer. + /// + /// Returns `Err` for keys held in hardware or by an agent. + fn private_key(&self) -> Result<Zeroizing<Vec<u8>>, CryptoError> { + Err(CryptoError::Unspecified) + } } /// A public key that can verify signatures |
