diff --git a/conversations/src/conversation/privatev1.rs b/conversations/src/conversation/privatev1.rs index e48c27c..1182ed9 100644 --- a/conversations/src/conversation/privatev1.rs +++ b/conversations/src/conversation/privatev1.rs @@ -39,7 +39,7 @@ struct BaseConvoId([u8; 18]); impl BaseConvoId { fn new(key: &SecretKey) -> Self { - let base = Blake2bMac::::new_with_salt_and_personal(key.as_slice(), b"", b"L-PV1-CID") + let base = Blake2bMac::::new_with_salt_and_personal(key.as_bytes(), b"", b"L-PV1-CID") .expect("fixed inputs should never fail"); Self(base.finalize_fixed().into()) } @@ -87,7 +87,7 @@ impl PrivateV1Convo { let remote_convo_id = base_convo_id.id_for_participant(Role::Initiator); // TODO: Danger - Fix double-ratchets types to Accept SecretKey - let dr_state = RatchetState::init_receiver(seed_key.as_bytes().to_owned(), dh_self); + let dr_state = RatchetState::init_receiver(seed_key.DANGER_to_bytes(), dh_self); Self { local_convo_id, @@ -234,14 +234,11 @@ mod tests { let seed_key = saro.diffie_hellman(&pub_raya); let send_content_bytes = vec![0, 2, 4, 6, 8]; - let mut sr_convo = - PrivateV1Convo::new_initiator(SecretKey::from(seed_key.to_bytes()), pub_raya); + let mut sr_convo = PrivateV1Convo::new_initiator(SymmetricKey32::from(&seed_key), pub_raya); let installation_key_pair = InstallationKeyPair::from(raya); - let mut rs_convo = PrivateV1Convo::new_responder( - SecretKey::from(seed_key.to_bytes()), - installation_key_pair, - ); + let mut rs_convo = + PrivateV1Convo::new_responder(SymmetricKey32::from(&seed_key), installation_key_pair); let send_frame = PrivateV1Frame { conversation_id: "_".into(), diff --git a/crypto/src/keys.rs b/crypto/src/keys.rs index 4eeccb1..6751f37 100644 --- a/crypto/src/keys.rs +++ b/crypto/src/keys.rs @@ -1,35 +1,53 @@ use std::fmt::Debug; pub use generic_array::{GenericArray, typenum::U32}; +use x25519_dalek::SharedSecret; use zeroize::{Zeroize, ZeroizeOnDrop}; +/// A Generic secret key container for symmetric keys. +/// SymmetricKey retains ownership of bytes to ensure they are Zeroized on drop. #[derive(Clone, Zeroize, ZeroizeOnDrop, PartialEq)] -pub struct SecretKey([u8; 32]); +pub struct SymmetricKey([u8; N]); -impl SecretKey { - pub fn as_slice(&self) -> &[u8] { +impl SymmetricKey { + pub fn as_bytes(&self) -> &[u8] { self.0.as_slice() } - pub fn as_bytes(&self) -> &[u8; 32] { - &self.0 + /// Returns internal [u8; N]. + /// This function by passes zeroize_on_drop, and will be deprecated once all consumers have been migrated + #[allow(nonstandard_style)] + pub fn DANGER_to_bytes(self) -> [u8; N] { + // TODO: (P3) Remove once DR ported to use safe keys. + self.0 } } -impl From<[u8; 32]> for SecretKey { - fn from(value: [u8; 32]) -> Self { - SecretKey(value) +impl From<[u8; N]> for SymmetricKey { + fn from(value: [u8; N]) -> Self { + SymmetricKey(value) } } -impl From> for SecretKey { - fn from(value: GenericArray) -> Self { - SecretKey(value.into()) - } -} - -impl Debug for SecretKey { +impl Debug for SymmetricKey { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("SecretKey").field(&"<32 bytes>").finish() + write!(f, "SymmetricKey(...{N} Bytes Redacted...)") + } +} + +// TODO: (P5) look into typenum::generic_const_mappings to avoid having to implment From +pub type SymmetricKey32 = SymmetricKey<32>; + +impl From> for SymmetricKey32 { + fn from(value: GenericArray) -> Self { + SymmetricKey(value.into()) + } +} + +impl From<&SharedSecret> for SymmetricKey32 { + // This relies on the feature 'zeroize' being set for x25519-dalek. + // If not the SharedSecret will need to manually zeroized + fn from(value: &SharedSecret) -> Self { + value.to_bytes().into() } }