diff --git a/conversations/src/conversation/privatev1.rs b/conversations/src/conversation/privatev1.rs index 3b36381..59a5b94 100644 --- a/conversations/src/conversation/privatev1.rs +++ b/conversations/src/conversation/privatev1.rs @@ -221,14 +221,14 @@ impl Debug for PrivateV1Convo { #[cfg(test)] mod tests { - use x25519_dalek::StaticSecret; + use crypto::X25519PrivateKey; use super::*; #[test] fn test_encrypt_roundtrip() { - let saro = StaticSecret::random(); - let raya = StaticSecret::random(); + let saro = X25519PrivateKey::random(); + let raya = X25519PrivateKey::random(); let pub_raya = X25519PublicKey::from(&raya); diff --git a/conversations/src/crypto.rs b/conversations/src/crypto.rs index 5104a9b..f58309f 100644 --- a/conversations/src/crypto.rs +++ b/conversations/src/crypto.rs @@ -1,5 +1,4 @@ -pub use crypto::X25519PublicKey; -pub use x25519_dalek::StaticSecret; +pub use crypto::{X25519PrivateKey, X25519PublicKey}; use prost::bytes::Bytes; diff --git a/conversations/src/identity.rs b/conversations/src/identity.rs index dea0532..861897f 100644 --- a/conversations/src/identity.rs +++ b/conversations/src/identity.rs @@ -1,9 +1,9 @@ use std::fmt; -use crate::crypto::{StaticSecret, X25519PublicKey}; +use crate::crypto::{X25519PrivateKey, X25519PublicKey}; pub struct Identity { - secret: StaticSecret, + secret: X25519PrivateKey, } impl fmt::Debug for Identity { @@ -18,7 +18,7 @@ impl fmt::Debug for Identity { impl Identity { pub fn new() -> Self { Self { - secret: StaticSecret::random(), + secret: X25519PrivateKey::random(), } } @@ -26,7 +26,7 @@ impl Identity { X25519PublicKey::from(&self.secret) } - pub fn secret(&self) -> &StaticSecret { + pub fn secret(&self) -> &X25519PrivateKey { &self.secret } } diff --git a/conversations/src/inbox/handler.rs b/conversations/src/inbox/handler.rs index 6fa1faf..332598a 100644 --- a/conversations/src/inbox/handler.rs +++ b/conversations/src/inbox/handler.rs @@ -10,7 +10,7 @@ use crypto::{PrekeyBundle, SymmetricKey32}; use crate::context::Introduction; use crate::conversation::{ChatError, ConversationId, Convo, Id, PrivateV1Convo}; -use crate::crypto::{CopyBytes, StaticSecret, X25519PublicKey}; +use crate::crypto::{CopyBytes, X25519PrivateKey, X25519PublicKey}; use crate::identity::Identity; use crate::inbox::handshake::InboxHandshake; use crate::proto; @@ -25,7 +25,7 @@ fn delivery_address_for_installation(_: X25519PublicKey) -> String { pub struct Inbox { ident: Rc, local_convo_id: String, - ephemeral_keys: HashMap, + ephemeral_keys: HashMap, } impl std::fmt::Debug for Inbox { @@ -47,12 +47,12 @@ impl Inbox { Self { ident, local_convo_id, - ephemeral_keys: HashMap::::new(), + ephemeral_keys: HashMap::::new(), } } pub fn create_intro_bundle(&mut self) -> Introduction { - let ephemeral = StaticSecret::random(); + let ephemeral = X25519PrivateKey::random(); let ephemeral_key: X25519PublicKey = (&ephemeral).into(); self.ephemeral_keys @@ -169,7 +169,7 @@ impl Inbox { fn perform_handshake( &self, - ephemeral_key: &StaticSecret, + ephemeral_key: &X25519PrivateKey, header: proto::InboxHeaderV1, bytes: Bytes, ) -> Result<(SymmetricKey32, proto::InboxV1Frame), ChatError> { @@ -215,7 +215,7 @@ impl Inbox { Ok(frame) } - fn lookup_ephemeral_key(&self, key: &str) -> Result<&StaticSecret, ChatError> { + fn lookup_ephemeral_key(&self, key: &str) -> Result<&X25519PrivateKey, ChatError> { self.ephemeral_keys .get(key) .ok_or(ChatError::UnknownEphemeralKey()) diff --git a/conversations/src/inbox/handshake.rs b/conversations/src/inbox/handshake.rs index 157b5c5..5e8ffe1 100644 --- a/conversations/src/inbox/handshake.rs +++ b/conversations/src/inbox/handshake.rs @@ -5,7 +5,7 @@ use blake2::{ use crypto::{DomainSeparator, PrekeyBundle, SymmetricKey32, X3Handshake}; use rand_core::{CryptoRng, RngCore}; -use crate::crypto::{StaticSecret, X25519PublicKey}; +use crate::crypto::{X25519PrivateKey, X25519PublicKey}; type Blake2bMac256 = Blake2bMac; @@ -21,7 +21,7 @@ pub struct InboxHandshake {} impl InboxHandshake { /// Performs pub fn perform_as_initiator( - identity_keypair: &StaticSecret, + identity_keypair: &X25519PrivateKey, recipient_bundle: &PrekeyBundle, rng: &mut R, ) -> (SymmetricKey32, X25519PublicKey) { @@ -42,9 +42,9 @@ impl InboxHandshake { /// * `initiator_identity` - Initiator's identity public key /// * `initiator_ephemeral` - Initiator's ephemeral public key pub fn perform_as_responder( - identity_keypair: &StaticSecret, - signed_prekey: &StaticSecret, - onetime_prekey: Option<&StaticSecret>, + identity_keypair: &X25519PrivateKey, + signed_prekey: &X25519PrivateKey, + onetime_prekey: Option<&X25519PrivateKey>, initiator_identity: &X25519PublicKey, initiator_ephemeral: &X25519PublicKey, ) -> SymmetricKey32 { @@ -85,12 +85,12 @@ mod tests { let mut rng = OsRng; // Alice (initiator) generates her identity key - let alice_identity = StaticSecret::random_from_rng(rng); + let alice_identity = X25519PrivateKey::random_from_rng(rng); let alice_identity_pub = X25519PublicKey::from(&alice_identity); // Bob (responder) generates his keys - let bob_identity = StaticSecret::random_from_rng(rng); - let bob_signed_prekey = StaticSecret::random_from_rng(rng); + let bob_identity = X25519PrivateKey::random_from_rng(rng); + let bob_signed_prekey = X25519PrivateKey::random_from_rng(rng); let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey); // Create Bob's prekey bundle diff --git a/conversations/src/inbox/introduction.rs b/conversations/src/inbox/introduction.rs index 0080c43..5c4397e 100644 --- a/conversations/src/inbox/introduction.rs +++ b/conversations/src/inbox/introduction.rs @@ -1,9 +1,8 @@ use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD}; use chat_proto::logoschat::intro::IntroBundle; -use crypto::{Ed25519Signature, X25519PublicKey}; +use crypto::{Ed25519Signature, X25519PrivateKey, X25519PublicKey}; use prost::Message; use rand_core::{CryptoRng, RngCore}; -use x25519_dalek::StaticSecret; use crate::errors::ChatError; @@ -17,7 +16,7 @@ fn intro_binding_message(ephemeral: &X25519PublicKey) -> Vec { } pub(crate) fn sign_intro_binding( - secret: &StaticSecret, + secret: &X25519PrivateKey, ephemeral: &X25519PublicKey, rng: R, ) -> Ed25519Signature { @@ -44,7 +43,7 @@ pub struct Introduction { impl Introduction { /// Create a new `Introduction` by signing the ephemeral key with the installation secret. pub(crate) fn new( - installation_secret: &StaticSecret, + installation_secret: &X25519PrivateKey, ephemeral_key: X25519PublicKey, rng: R, ) -> Self { @@ -147,9 +146,9 @@ mod tests { use rand_core::OsRng; fn create_test_introduction() -> Introduction { - let install_secret = StaticSecret::random_from_rng(OsRng); + let install_secret = X25519PrivateKey::random_from_rng(OsRng); - let ephemeral_secret = StaticSecret::random_from_rng(OsRng); + let ephemeral_secret = X25519PrivateKey::random_from_rng(OsRng); let ephemeral_pub: X25519PublicKey = (&ephemeral_secret).into(); Introduction::new(&install_secret, ephemeral_pub, OsRng) diff --git a/crypto/src/keys.rs b/crypto/src/keys.rs index 01a6783..ad8bba7 100644 --- a/crypto/src/keys.rs +++ b/crypto/src/keys.rs @@ -2,7 +2,7 @@ pub use generic_array::{GenericArray, typenum::U32}; use rand_core::{CryptoRng, OsRng, RngCore}; use std::{fmt::Debug, ops::Deref}; -use x25519_dalek::{PublicKey, SharedSecret, StaticSecret}; +use x25519_dalek; use xeddsa::xed25519; use zeroize::{Zeroize, ZeroizeOnDrop}; @@ -15,9 +15,9 @@ impl From for X25519PublicKey { } } -impl From<&StaticSecret> for X25519PublicKey { - fn from(value: &StaticSecret) -> Self { - Self(x25519_dalek::PublicKey::from(value)) +impl From<&X25519PrivateKey> for X25519PublicKey { + fn from(value: &X25519PrivateKey) -> Self { + Self(x25519_dalek::PublicKey::from(&value.0)) } } @@ -28,7 +28,7 @@ impl From<[u8; 32]> for X25519PublicKey { } impl Deref for X25519PublicKey { - type Target = PublicKey; + type Target = x25519_dalek::PublicKey; fn deref(&self) -> &Self::Target { &self.0 } @@ -60,6 +60,12 @@ impl X25519PrivateKey { } } +impl From<[u8; 32]> for X25519PrivateKey { + fn from(value: [u8; 32]) -> Self { + Self(x25519_dalek::StaticSecret::from(value)) + } +} + impl Deref for X25519PrivateKey { type Target = x25519_dalek::StaticSecret; fn deref(&self) -> &Self::Target { @@ -67,6 +73,12 @@ impl Deref for X25519PrivateKey { } } +impl From<&X25519PrivateKey> for xed25519::PrivateKey { + fn from(value: &X25519PrivateKey) -> Self { + Self::from(&value.0) + } +} + /// 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)] @@ -107,10 +119,10 @@ impl From> for SymmetricKey32 { } } -impl From<&SharedSecret> for SymmetricKey32 { +impl From<&x25519_dalek::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 { + fn from(value: &x25519_dalek::SharedSecret) -> Self { value.to_bytes().into() } } diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index 5c305a9..a746996 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -2,6 +2,6 @@ mod keys; mod x3dh; mod xeddsa_sign; -pub use keys::{GenericArray, SymmetricKey32, X25519PublicKey}; +pub use keys::{GenericArray, SymmetricKey32, X25519PrivateKey, X25519PublicKey}; pub use x3dh::{DomainSeparator, PrekeyBundle, X3Handshake}; pub use xeddsa_sign::{Ed25519Signature, SignatureError, xeddsa_sign, xeddsa_verify}; diff --git a/crypto/src/x3dh.rs b/crypto/src/x3dh.rs index 1de0919..e7e5099 100644 --- a/crypto/src/x3dh.rs +++ b/crypto/src/x3dh.rs @@ -3,9 +3,9 @@ use std::marker::PhantomData; use hkdf::Hkdf; use rand_core::{CryptoRng, RngCore}; use sha2::Sha256; -use x25519_dalek::{SharedSecret, StaticSecret}; +use x25519_dalek::SharedSecret; -use crate::keys::{SymmetricKey32, X25519PublicKey}; +use crate::keys::{SymmetricKey32, X25519PrivateKey, X25519PublicKey}; use crate::xeddsa_sign::Ed25519Signature; /// A prekey bundle containing the public keys needed to initiate an X3DH key exchange. @@ -67,12 +67,12 @@ impl X3Handshake { /// # Returns /// A tuple of (shared secret bytes, ephemeral public key) pub fn initator( - identity_keypair: &StaticSecret, + identity_keypair: &X25519PrivateKey, recipient_bundle: &PrekeyBundle, rng: &mut R, ) -> (SymmetricKey32, X25519PublicKey) { - // Generate ephemeral key for this handshake (using StaticSecret for multiple DH operations) - let ephemeral_secret = StaticSecret::random_from_rng(rng); + // Generate ephemeral key for this handshake (using X25519PrivateKey for multiple DH operations) + let ephemeral_secret = X25519PrivateKey::random_from_rng(rng); let ephemeral_public = X25519PublicKey::from(&ephemeral_secret); // Perform the 4 Diffie-Hellman operations @@ -102,9 +102,9 @@ impl X3Handshake { /// # Returns /// The derived shared secret bytes pub fn responder( - identity_keypair: &StaticSecret, - signed_prekey: &StaticSecret, - onetime_prekey: Option<&StaticSecret>, + identity_keypair: &X25519PrivateKey, + signed_prekey: &X25519PrivateKey, + onetime_prekey: Option<&X25519PrivateKey>, initiator_identity: &X25519PublicKey, initiator_ephemeral: &X25519PublicKey, ) -> SymmetricKey32 { @@ -135,17 +135,17 @@ mod tests { let mut rng = OsRng; // Alice (initiator) generates her identity key - let alice_identity = StaticSecret::random_from_rng(rng); + let alice_identity = X25519PrivateKey::random_from_rng(rng); let alice_identity_pub = X25519PublicKey::from(&alice_identity); // Bob (responder) generates his keys - let bob_identity = StaticSecret::random_from_rng(rng); + let bob_identity = X25519PrivateKey::random_from_rng(rng); let bob_identity_pub = X25519PublicKey::from(&bob_identity); - let bob_signed_prekey = StaticSecret::random_from_rng(rng); + let bob_signed_prekey = X25519PrivateKey::random_from_rng(rng); let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey); - let bob_onetime_prekey = StaticSecret::random_from_rng(rng); + let bob_onetime_prekey = X25519PrivateKey::random_from_rng(rng); let bob_onetime_prekey_pub = X25519PublicKey::from(&bob_onetime_prekey); // Create Bob's prekey bundle (with one-time prekey) @@ -178,14 +178,14 @@ mod tests { let mut rng = OsRng; // Alice (initiator) generates her identity key - let alice_identity = StaticSecret::random_from_rng(rng); + let alice_identity = X25519PrivateKey::random_from_rng(rng); let alice_identity_pub = X25519PublicKey::from(&alice_identity); // Bob (responder) generates his keys - let bob_identity = StaticSecret::random_from_rng(rng); + let bob_identity = X25519PrivateKey::random_from_rng(rng); let bob_identity_pub = X25519PublicKey::from(&bob_identity); - let bob_signed_prekey = StaticSecret::random_from_rng(rng); + let bob_signed_prekey = X25519PrivateKey::random_from_rng(rng); let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey); // Create Bob's prekey bundle (without one-time prekey) diff --git a/crypto/src/xeddsa_sign.rs b/crypto/src/xeddsa_sign.rs index e598a3a..cc3bb26 100644 --- a/crypto/src/xeddsa_sign.rs +++ b/crypto/src/xeddsa_sign.rs @@ -4,10 +4,9 @@ //! that allow signing arbitrary messages with X25519 keys. use rand_core::{CryptoRng, RngCore}; -use x25519_dalek::StaticSecret; use xeddsa::{Sign, Verify, xed25519}; -use crate::keys::X25519PublicKey; +use crate::keys::{X25519PrivateKey, X25519PublicKey}; /// A 64-byte XEdDSA signature over an Ed25519-compatible curve. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -46,7 +45,7 @@ pub struct SignatureError; /// # Returns /// An `Ed25519Signature` pub fn xeddsa_sign( - secret: &StaticSecret, + secret: &X25519PrivateKey, message: &[u8], mut rng: R, ) -> Ed25519Signature { @@ -81,7 +80,7 @@ mod tests { #[test] fn test_sign_and_verify_roundtrip() { - let secret = StaticSecret::random_from_rng(OsRng); + let secret = X25519PrivateKey::random_from_rng(OsRng); let public = X25519PublicKey::from(&secret); let message = b"test message"; @@ -92,12 +91,12 @@ mod tests { #[test] fn test_wrong_key_fails() { - let secret = StaticSecret::random_from_rng(OsRng); + let secret = X25519PrivateKey::random_from_rng(OsRng); let message = b"test message"; let signature = xeddsa_sign(&secret, message, OsRng); - let wrong_secret = StaticSecret::random_from_rng(OsRng); + let wrong_secret = X25519PrivateKey::random_from_rng(OsRng); let wrong_public = X25519PublicKey::from(&wrong_secret); assert_eq!( @@ -108,7 +107,7 @@ mod tests { #[test] fn test_wrong_message_fails() { - let secret = StaticSecret::random_from_rng(OsRng); + let secret = X25519PrivateKey::random_from_rng(OsRng); let public = X25519PublicKey::from(&secret); let message = b"test message"; @@ -122,7 +121,7 @@ mod tests { #[test] fn test_corrupted_signature_fails() { - let secret = StaticSecret::random_from_rng(OsRng); + let secret = X25519PrivateKey::random_from_rng(OsRng); let public = X25519PublicKey::from(&secret); let message = b"test message"; diff --git a/double-ratchets/src/keypair.rs b/double-ratchets/src/keypair.rs index a7caa9c..724fbca 100644 --- a/double-ratchets/src/keypair.rs +++ b/double-ratchets/src/keypair.rs @@ -1,19 +1,18 @@ -use crypto::X25519PublicKey; +use crypto::{X25519PrivateKey, X25519PublicKey}; use rand_core::OsRng; -use x25519_dalek::StaticSecret; use zeroize::{Zeroize, ZeroizeOnDrop}; use crate::types::SharedSecret; #[derive(Clone, Zeroize, ZeroizeOnDrop)] pub struct InstallationKeyPair { - secret: StaticSecret, + secret: X25519PrivateKey, public: X25519PublicKey, } impl InstallationKeyPair { pub fn generate() -> Self { - let secret = StaticSecret::random_from_rng(OsRng); + let secret = X25519PrivateKey::random_from_rng(OsRng); let public = X25519PublicKey::from(&secret); Self { secret, public } } @@ -33,14 +32,14 @@ impl InstallationKeyPair { /// Import the secret key from raw bytes. pub fn from_secret_bytes(bytes: [u8; 32]) -> Self { - let secret = StaticSecret::from(bytes); + let secret = X25519PrivateKey::from(bytes); let public = X25519PublicKey::from(&secret); Self { secret, public } } } -impl From for InstallationKeyPair { - fn from(value: StaticSecret) -> Self { +impl From for InstallationKeyPair { + fn from(value: X25519PrivateKey) -> Self { let public = X25519PublicKey::from(&value); Self { secret: value,