replace PublicKey with PublicKey32

This commit is contained in:
Jazz Turner-Baggs 2026-01-30 10:53:31 -08:00
parent 649625311f
commit c1abc82f28
No known key found for this signature in database
8 changed files with 79 additions and 41 deletions

View File

@ -1,13 +1,15 @@
pub use blake2::Digest;
use blake2::{Blake2b, digest};
use prost::bytes::Bytes;
pub use x25519_dalek::{PublicKey, StaticSecret};
pub use crypto::PublicKey32;
pub use x25519_dalek::StaticSecret;
pub trait CopyBytes {
fn copy_to_bytes(&self) -> Bytes;
}
impl CopyBytes for PublicKey {
impl CopyBytes for PublicKey32 {
fn copy_to_bytes(&self) -> Bytes {
Bytes::copy_from_slice(self.as_bytes())
}

View File

@ -1,7 +1,8 @@
use blake2::{Blake2b512, Digest};
use std::fmt;
use crate::crypto::{PublicKey, StaticSecret};
use crate::crypto::{PublicKey32, StaticSecret};
use x25519_dalek::PublicKey;
pub struct Identity {
secret: StaticSecret,
@ -27,8 +28,8 @@ impl Identity {
hex::encode(Blake2b512::digest(self.public_key()))
}
pub fn public_key(&self) -> PublicKey {
PublicKey::from(&self.secret)
pub fn public_key(&self) -> PublicKey32 {
PublicKey::from(&self.secret).into()
}
pub fn secret(&self) -> &StaticSecret {

View File

@ -5,7 +5,7 @@ use blake2::{
use crypto::{DomainSeparator, PrekeyBundle, SecretKey32, X3Handshake};
use rand_core::{CryptoRng, RngCore};
use crate::crypto::{PublicKey, StaticSecret};
use crate::crypto::{PublicKey32, StaticSecret};
type Blake2bMac256 = Blake2bMac<U32>;
@ -24,13 +24,13 @@ impl InboxHandshake {
identity_keypair: &StaticSecret,
recipient_bundle: &PrekeyBundle,
rng: &mut R,
) -> (SecretKey32, PublicKey) {
) -> (SecretKey32, PublicKey32) {
// Perform X3DH handshake to get shared secret
let (shared_secret, ephemeral_public) =
InboxKeyExchange::initator(identity_keypair, recipient_bundle, rng);
let seed_key = Self::derive_keys_from_shared_secret(shared_secret);
(seed_key, ephemeral_public)
(seed_key, ephemeral_public.into())
}
/// Perform the Inbox Handshake after receiving a keyBundle
@ -45,8 +45,8 @@ impl InboxHandshake {
identity_keypair: &StaticSecret,
signed_prekey: &StaticSecret,
onetime_prekey: Option<&StaticSecret>,
initiator_identity: &PublicKey,
initiator_ephemeral: &PublicKey,
initiator_identity: &PublicKey32,
initiator_ephemeral: &PublicKey32,
) -> SecretKey32 {
// Perform X3DH to get shared secret
let shared_secret = InboxKeyExchange::responder(
@ -86,16 +86,16 @@ mod tests {
// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(&mut rng);
let alice_identity_pub = PublicKey::from(&alice_identity);
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_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);
let bob_signed_prekey_pub = PublicKey32::from(&bob_signed_prekey);
// Create Bob's prekey bundle
let bob_bundle = PrekeyBundle {
identity_key: PublicKey::from(&bob_identity),
identity_key: PublicKey32::from(&bob_identity),
signed_prekey: bob_signed_prekey_pub,
signature: [0u8; 64],
onetime_prekey: None,

View File

@ -9,14 +9,14 @@ use crypto::{PrekeyBundle, SecretKey32};
use crate::context::Introduction;
use crate::conversation::{ChatError, ConversationId, Convo, ConvoFactory, Id, PrivateV1Convo};
use crate::crypto::{Blake2b128, CopyBytes, Digest, PublicKey, StaticSecret};
use crate::crypto::{Blake2b128, CopyBytes, Digest, PublicKey32, StaticSecret};
use crate::identity::Identity;
use crate::inbox::handshake::InboxHandshake;
use crate::proto;
use crate::types::{AddressedEncryptedPayload, ContentData};
/// Compute the deterministic Delivery_address for an installation
fn delivery_address_for_installation(_: PublicKey) -> String {
fn delivery_address_for_installation(_: PublicKey32) -> String {
// TODO: Implement Delivery Address
"delivery_address".into()
}
@ -58,7 +58,7 @@ impl Inbox {
pub fn create_bundle(&mut self) -> PrekeyBundle {
let ephemeral = StaticSecret::random();
let signed_prekey = PublicKey::from(&ephemeral);
let signed_prekey = PublicKey32::from(&ephemeral);
self.ephemeral_keys
.insert(hex::encode(signed_prekey.as_bytes()), ephemeral);
@ -149,12 +149,12 @@ impl Inbox {
let ephemeral_key = self.lookup_ephemeral_key(&pubkey_hex)?;
let initator_static = PublicKey::from(
let initator_static = PublicKey32::from(
<[u8; 32]>::try_from(header.initiator_static.as_ref())
.map_err(|_| ChatError::BadBundleValue("wrong size - initator static".into()))?,
);
let initator_ephemeral = PublicKey::from(
let initator_ephemeral = PublicKey32::from(
<[u8; 32]>::try_from(header.initiator_ephemeral.as_ref())
.map_err(|_| ChatError::BadBundleValue("wrong size - initator ephemeral".into()))?,
);

View File

@ -1,12 +1,12 @@
use crypto::PrekeyBundle;
use x25519_dalek::PublicKey;
use crate::crypto::PublicKey32;
use crate::errors::ChatError;
/// Supplies remote participants with the required keys to use Inbox protocol
pub struct Introduction {
pub installation_key: PublicKey,
pub ephemeral_key: PublicKey,
pub installation_key: PublicKey32,
pub ephemeral_key: PublicKey32,
}
impl From<PrekeyBundle> for Introduction {
@ -48,13 +48,13 @@ impl TryFrom<&[u8]> for Introduction {
.map_err(|_| ChatError::BadParsing("installation_key"))?
.try_into()
.map_err(|_| ChatError::InvalidKeyLength)?;
let installation_key = PublicKey::from(installation_bytes);
let installation_key = PublicKey32::from(installation_bytes);
let ephemeral_bytes: [u8; 32] = hex::decode(parts[1])
.map_err(|_| ChatError::BadParsing("ephemeral_key"))?
.try_into()
.map_err(|_| ChatError::InvalidKeyLength)?;
let ephemeral_key = PublicKey::from(ephemeral_bytes);
let ephemeral_key = PublicKey32::from(ephemeral_bytes);
Ok(Introduction {
installation_key,

View File

@ -1,7 +1,42 @@
use generic_array::{GenericArray, typenum::U32};
use std::fmt::Debug;
use std::{fmt::Debug, ops::Deref};
use x25519_dalek;
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(Debug, Copy, Clone)]
pub struct PublicKey32(x25519_dalek::PublicKey);
impl From<x25519_dalek::PublicKey> for PublicKey32 {
fn from(value: x25519_dalek::PublicKey) -> Self {
Self(value)
}
}
impl From<&x25519_dalek::StaticSecret> for PublicKey32 {
fn from(value: &x25519_dalek::StaticSecret) -> Self {
Self(x25519_dalek::PublicKey::from(value))
}
}
impl From<[u8; 32]> for PublicKey32 {
fn from(value: [u8; 32]) -> Self {
Self(x25519_dalek::PublicKey::from(value))
}
}
impl Deref for PublicKey32 {
type Target = x25519_dalek::PublicKey;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<[u8]> for PublicKey32 {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
#[derive(Clone, Zeroize, ZeroizeOnDrop, PartialEq)]
pub struct SecretKey32([u8; 32]);

View File

@ -1,5 +1,5 @@
mod keys;
mod x3dh;
pub use keys::SecretKey32;
pub use keys::{PublicKey32, SecretKey32};
pub use x3dh::{DomainSeparator, PrekeyBundle, X3Handshake};

View File

@ -3,17 +3,17 @@ use std::marker::PhantomData;
use hkdf::Hkdf;
use rand_core::{CryptoRng, RngCore};
use sha2::Sha256;
use x25519_dalek::{PublicKey, SharedSecret, StaticSecret};
use x25519_dalek::{SharedSecret, StaticSecret};
use crate::keys::SecretKey32;
use crate::keys::{PublicKey32, SecretKey32};
/// A prekey bundle containing the public keys needed to initiate an X3DH key exchange.
#[derive(Clone, Debug)]
pub struct PrekeyBundle {
pub identity_key: PublicKey,
pub signed_prekey: PublicKey,
pub identity_key: PublicKey32,
pub signed_prekey: PublicKey32,
pub signature: [u8; 64],
pub onetime_prekey: Option<PublicKey>,
pub onetime_prekey: Option<PublicKey32>,
}
pub trait DomainSeparator {
@ -69,10 +69,10 @@ impl<D: DomainSeparator> X3Handshake<D> {
identity_keypair: &StaticSecret,
recipient_bundle: &PrekeyBundle,
rng: &mut R,
) -> (SecretKey32, PublicKey) {
) -> (SecretKey32, PublicKey32) {
// Generate ephemeral key for this handshake (using StaticSecret for multiple DH operations)
let ephemeral_secret = StaticSecret::random_from_rng(rng);
let ephemeral_public = PublicKey::from(&ephemeral_secret);
let ephemeral_public = PublicKey32::from(&ephemeral_secret);
// Perform the 4 Diffie-Hellman operations
let dh1 = identity_keypair.diffie_hellman(&recipient_bundle.signed_prekey);
@ -104,8 +104,8 @@ impl<D: DomainSeparator> X3Handshake<D> {
identity_keypair: &StaticSecret,
signed_prekey: &StaticSecret,
onetime_prekey: Option<&StaticSecret>,
initiator_identity: &PublicKey,
initiator_ephemeral: &PublicKey,
initiator_identity: &PublicKey32,
initiator_ephemeral: &PublicKey32,
) -> SecretKey32 {
let dh1 = signed_prekey.diffie_hellman(initiator_identity);
let dh2 = identity_keypair.diffie_hellman(initiator_ephemeral);
@ -135,17 +135,17 @@ mod tests {
// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(&mut rng);
let alice_identity_pub = PublicKey::from(&alice_identity);
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_pub = PublicKey::from(&bob_identity);
let bob_identity_pub = PublicKey32::from(&bob_identity);
let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
let bob_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);
let bob_signed_prekey_pub = PublicKey32::from(&bob_signed_prekey);
let bob_onetime_prekey = StaticSecret::random_from_rng(&mut rng);
let bob_onetime_prekey_pub = PublicKey::from(&bob_onetime_prekey);
let bob_onetime_prekey_pub = PublicKey32::from(&bob_onetime_prekey);
// Create Bob's prekey bundle (with one-time prekey)
let bob_bundle = PrekeyBundle {
@ -178,14 +178,14 @@ mod tests {
// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(&mut rng);
let alice_identity_pub = PublicKey::from(&alice_identity);
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_pub = PublicKey::from(&bob_identity);
let bob_identity_pub = PublicKey32::from(&bob_identity);
let bob_signed_prekey = StaticSecret::random_from_rng(&mut rng);
let bob_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);
let bob_signed_prekey_pub = PublicKey32::from(&bob_signed_prekey);
// Create Bob's prekey bundle (without one-time prekey)
let bob_bundle = PrekeyBundle {