mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-02-10 08:53:08 +00:00
replace StaticSecret with PrivateKey32
This commit is contained in:
parent
c1abc82f28
commit
5adee47a97
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -473,6 +473,7 @@ dependencies = [
|
||||
"crypto",
|
||||
"hex",
|
||||
"prost",
|
||||
"rand",
|
||||
"rand_core",
|
||||
"safer-ffi",
|
||||
"thiserror",
|
||||
|
||||
@ -13,6 +13,7 @@ crypto = { path = "../crypto" }
|
||||
hex = "0.4.3"
|
||||
prost = "0.14.1"
|
||||
rand_core = { version = "0.6" }
|
||||
rand = "0.8.5"
|
||||
safer-ffi = "0.1.13"
|
||||
thiserror = "2.0.17"
|
||||
x25519-dalek = { version = "2.0.1", features = ["static_secrets", "reusable_secrets", "getrandom"] }
|
||||
|
||||
@ -2,8 +2,7 @@ pub use blake2::Digest;
|
||||
use blake2::{Blake2b, digest};
|
||||
use prost::bytes::Bytes;
|
||||
|
||||
pub use crypto::PublicKey32;
|
||||
pub use x25519_dalek::StaticSecret;
|
||||
pub use crypto::{PrivateKey32, PublicKey32};
|
||||
|
||||
pub trait CopyBytes {
|
||||
fn copy_to_bytes(&self) -> Bytes;
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
use blake2::{Blake2b512, Digest};
|
||||
use std::fmt;
|
||||
|
||||
use crate::crypto::{PublicKey32, StaticSecret};
|
||||
use x25519_dalek::PublicKey;
|
||||
use crate::crypto::{PrivateKey32, PublicKey32};
|
||||
|
||||
pub struct Identity {
|
||||
secret: StaticSecret,
|
||||
secret: PrivateKey32,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Identity {
|
||||
@ -20,7 +19,7 @@ impl fmt::Debug for Identity {
|
||||
impl Identity {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
secret: StaticSecret::random(),
|
||||
secret: PrivateKey32::random(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,10 +28,10 @@ impl Identity {
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> PublicKey32 {
|
||||
PublicKey::from(&self.secret).into()
|
||||
PublicKey32::from(&self.secret)
|
||||
}
|
||||
|
||||
pub fn secret(&self) -> &StaticSecret {
|
||||
pub fn secret(&self) -> &PrivateKey32 {
|
||||
&self.secret
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ use blake2::{
|
||||
use crypto::{DomainSeparator, PrekeyBundle, SecretKey32, X3Handshake};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use crate::crypto::{PublicKey32, StaticSecret};
|
||||
use crate::crypto::{PrivateKey32, PublicKey32};
|
||||
|
||||
type Blake2bMac256 = Blake2bMac<U32>;
|
||||
|
||||
@ -21,7 +21,7 @@ pub struct InboxHandshake {}
|
||||
impl InboxHandshake {
|
||||
/// Performs
|
||||
pub fn perform_as_initiator<R: RngCore + CryptoRng>(
|
||||
identity_keypair: &StaticSecret,
|
||||
identity_keypair: &PrivateKey32,
|
||||
recipient_bundle: &PrekeyBundle,
|
||||
rng: &mut R,
|
||||
) -> (SecretKey32, PublicKey32) {
|
||||
@ -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: &PrivateKey32,
|
||||
signed_prekey: &PrivateKey32,
|
||||
onetime_prekey: Option<&PrivateKey32>,
|
||||
initiator_identity: &PublicKey32,
|
||||
initiator_ephemeral: &PublicKey32,
|
||||
) -> SecretKey32 {
|
||||
@ -85,12 +85,12 @@ mod tests {
|
||||
let mut rng = OsRng;
|
||||
|
||||
// Alice (initiator) generates her identity key
|
||||
let alice_identity = StaticSecret::random_from_rng(&mut rng);
|
||||
let alice_identity = PrivateKey32::random_from_rng(&mut rng);
|
||||
let alice_identity_pub = PublicKey32::from(&alice_identity);
|
||||
|
||||
// Bob (responder) generates his keys
|
||||
let bob_identity = StaticSecret::random_from_rng(&mut rng);
|
||||
let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
|
||||
let bob_identity = PrivateKey32::random_from_rng(&mut rng);
|
||||
let bob_signed_prekey = PrivateKey32::random_from_rng(&mut rng);
|
||||
let bob_signed_prekey_pub = PublicKey32::from(&bob_signed_prekey);
|
||||
|
||||
// Create Bob's prekey bundle
|
||||
|
||||
@ -9,7 +9,7 @@ use crypto::{PrekeyBundle, SecretKey32};
|
||||
|
||||
use crate::context::Introduction;
|
||||
use crate::conversation::{ChatError, ConversationId, Convo, ConvoFactory, Id, PrivateV1Convo};
|
||||
use crate::crypto::{Blake2b128, CopyBytes, Digest, PublicKey32, StaticSecret};
|
||||
use crate::crypto::{Blake2b128, CopyBytes, Digest, PrivateKey32, PublicKey32};
|
||||
use crate::identity::Identity;
|
||||
use crate::inbox::handshake::InboxHandshake;
|
||||
use crate::proto;
|
||||
@ -24,7 +24,7 @@ fn delivery_address_for_installation(_: PublicKey32) -> String {
|
||||
pub struct Inbox {
|
||||
ident: Rc<Identity>,
|
||||
local_convo_id: String,
|
||||
ephemeral_keys: HashMap<String, StaticSecret>,
|
||||
ephemeral_keys: HashMap<String, PrivateKey32>,
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Debug for Inbox {
|
||||
@ -46,7 +46,7 @@ impl Inbox {
|
||||
Self {
|
||||
ident,
|
||||
local_convo_id,
|
||||
ephemeral_keys: HashMap::<String, StaticSecret>::new(),
|
||||
ephemeral_keys: HashMap::<String, PrivateKey32>::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ impl Inbox {
|
||||
}
|
||||
|
||||
pub fn create_bundle(&mut self) -> PrekeyBundle {
|
||||
let ephemeral = StaticSecret::random();
|
||||
let ephemeral = PrivateKey32::random_from_rng(&mut OsRng);
|
||||
|
||||
let signed_prekey = PublicKey32::from(&ephemeral);
|
||||
self.ephemeral_keys
|
||||
@ -193,7 +193,7 @@ impl Inbox {
|
||||
Ok(frame)
|
||||
}
|
||||
|
||||
fn lookup_ephemeral_key(&self, key: &str) -> Result<&StaticSecret, ChatError> {
|
||||
fn lookup_ephemeral_key(&self, key: &str) -> Result<&PrivateKey32, ChatError> {
|
||||
self.ephemeral_keys
|
||||
.get(key)
|
||||
.ok_or_else(|| return ChatError::UnknownEphemeralKey())
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use generic_array::{GenericArray, typenum::U32};
|
||||
use rand_core::{CryptoRng, OsRng, RngCore};
|
||||
use std::{fmt::Debug, ops::Deref};
|
||||
use x25519_dalek;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
@ -18,6 +19,12 @@ impl From<&x25519_dalek::StaticSecret> for PublicKey32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&PrivateKey32> for PublicKey32 {
|
||||
fn from(value: &PrivateKey32) -> Self {
|
||||
Self(x25519_dalek::PublicKey::from(&value.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for PublicKey32 {
|
||||
fn from(value: [u8; 32]) -> Self {
|
||||
Self(x25519_dalek::PublicKey::from(value))
|
||||
@ -37,6 +44,27 @@ impl AsRef<[u8]> for PublicKey32 {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
|
||||
pub struct PrivateKey32(x25519_dalek::StaticSecret);
|
||||
|
||||
impl PrivateKey32 {
|
||||
pub fn random_from_rng<T: RngCore + CryptoRng>(mut csprng: T) -> Self {
|
||||
Self(x25519_dalek::StaticSecret::random_from_rng(csprng))
|
||||
}
|
||||
|
||||
//TODO: Remove. Force internal callers provide Rng to make deterministic testing possible
|
||||
pub fn random() -> PrivateKey32 {
|
||||
Self::random_from_rng(&mut OsRng)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PrivateKey32 {
|
||||
type Target = x25519_dalek::StaticSecret;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Zeroize, ZeroizeOnDrop, PartialEq)]
|
||||
pub struct SecretKey32([u8; 32]);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
mod keys;
|
||||
mod x3dh;
|
||||
|
||||
pub use keys::{PublicKey32, SecretKey32};
|
||||
pub use keys::{PrivateKey32, PublicKey32, SecretKey32};
|
||||
pub use x3dh::{DomainSeparator, PrekeyBundle, X3Handshake};
|
||||
|
||||
@ -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::{PublicKey32, SecretKey32};
|
||||
use crate::keys::{PrivateKey32, PublicKey32, SecretKey32};
|
||||
|
||||
/// A prekey bundle containing the public keys needed to initiate an X3DH key exchange.
|
||||
#[derive(Clone, Debug)]
|
||||
@ -66,12 +66,12 @@ impl<D: DomainSeparator> X3Handshake<D> {
|
||||
/// # Returns
|
||||
/// A tuple of (shared secret bytes, ephemeral public key)
|
||||
pub fn initator<R: RngCore + CryptoRng>(
|
||||
identity_keypair: &StaticSecret,
|
||||
identity_keypair: &PrivateKey32,
|
||||
recipient_bundle: &PrekeyBundle,
|
||||
rng: &mut R,
|
||||
) -> (SecretKey32, PublicKey32) {
|
||||
// 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
|
||||
let ephemeral_secret = PrivateKey32::random_from_rng(rng);
|
||||
let ephemeral_public = PublicKey32::from(&ephemeral_secret);
|
||||
|
||||
// Perform the 4 Diffie-Hellman operations
|
||||
@ -101,9 +101,9 @@ impl<D: DomainSeparator> X3Handshake<D> {
|
||||
/// # Returns
|
||||
/// The derived shared secret bytes
|
||||
pub fn responder(
|
||||
identity_keypair: &StaticSecret,
|
||||
signed_prekey: &StaticSecret,
|
||||
onetime_prekey: Option<&StaticSecret>,
|
||||
identity_keypair: &PrivateKey32,
|
||||
signed_prekey: &PrivateKey32,
|
||||
onetime_prekey: Option<&PrivateKey32>,
|
||||
initiator_identity: &PublicKey32,
|
||||
initiator_ephemeral: &PublicKey32,
|
||||
) -> SecretKey32 {
|
||||
@ -134,17 +134,17 @@ mod tests {
|
||||
let mut rng = OsRng;
|
||||
|
||||
// Alice (initiator) generates her identity key
|
||||
let alice_identity = StaticSecret::random_from_rng(&mut rng);
|
||||
let alice_identity = PrivateKey32::random_from_rng(&mut rng);
|
||||
let alice_identity_pub = PublicKey32::from(&alice_identity);
|
||||
|
||||
// Bob (responder) generates his keys
|
||||
let bob_identity = StaticSecret::random_from_rng(&mut rng);
|
||||
let bob_identity = PrivateKey32::random_from_rng(&mut rng);
|
||||
let bob_identity_pub = PublicKey32::from(&bob_identity);
|
||||
|
||||
let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
|
||||
let bob_signed_prekey = PrivateKey32::random_from_rng(&mut rng);
|
||||
let bob_signed_prekey_pub = PublicKey32::from(&bob_signed_prekey);
|
||||
|
||||
let bob_onetime_prekey = StaticSecret::random_from_rng(&mut rng);
|
||||
let bob_onetime_prekey = PrivateKey32::random_from_rng(&mut rng);
|
||||
let bob_onetime_prekey_pub = PublicKey32::from(&bob_onetime_prekey);
|
||||
|
||||
// Create Bob's prekey bundle (with one-time prekey)
|
||||
@ -177,14 +177,14 @@ mod tests {
|
||||
let mut rng = OsRng;
|
||||
|
||||
// Alice (initiator) generates her identity key
|
||||
let alice_identity = StaticSecret::random_from_rng(&mut rng);
|
||||
let alice_identity = PrivateKey32::random_from_rng(&mut rng);
|
||||
let alice_identity_pub = PublicKey32::from(&alice_identity);
|
||||
|
||||
// Bob (responder) generates his keys
|
||||
let bob_identity = StaticSecret::random_from_rng(&mut rng);
|
||||
let bob_identity = PrivateKey32::random_from_rng(&mut rng);
|
||||
let bob_identity_pub = PublicKey32::from(&bob_identity);
|
||||
|
||||
let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
|
||||
let bob_signed_prekey = PrivateKey32::random_from_rng(&mut rng);
|
||||
let bob_signed_prekey_pub = PublicKey32::from(&bob_signed_prekey);
|
||||
|
||||
// Create Bob's prekey bundle (without one-time prekey)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user