Update PublicKey -> X25519PublicKey

This commit is contained in:
Jazz Turner-Baggs 2026-02-12 16:02:49 -08:00
parent 28d74b7404
commit 5121ba4eed
No known key found for this signature in database
17 changed files with 100 additions and 85 deletions

1
Cargo.lock generated
View File

@ -225,6 +225,7 @@ version = "0.0.1"
dependencies = [
"blake2",
"chacha20poly1305",
"crypto",
"hkdf",
"rand",
"rand_core",

View File

@ -12,3 +12,6 @@ members = [
[workspace.dependencies]
blake2 = "0.10"
storage = { path = "storage" }
# Internal crates
crypto = { path = "crypto" }

View File

@ -7,10 +7,10 @@ use chat_proto::logoschat::{
encryption::{Doubleratchet, EncryptedPayload, encrypted_payload::Encryption},
};
use crypto::SymmetricKey32;
use crypto::X25519PublicKey;
use double_ratchets::{Header, InstallationKeyPair, RatchetState};
use prost::{Message, bytes::Bytes};
use std::fmt::Debug;
use x25519_dalek::PublicKey;
use crate::{
conversation::{ChatError, ConversationId, Convo, Id},
@ -60,7 +60,7 @@ pub struct PrivateV1Convo {
}
impl PrivateV1Convo {
pub fn new_initiator(seed_key: SymmetricKey32, remote: PublicKey) -> Self {
pub fn new_initiator(seed_key: SymmetricKey32, remote: X25519PublicKey) -> Self {
let base_convo_id = BaseConvoId::new(&seed_key);
let local_convo_id = base_convo_id.id_for_participant(Role::Initiator);
let remote_convo_id = base_convo_id.id_for_participant(Role::Responder);
@ -125,13 +125,13 @@ impl PrivateV1Convo {
return Err(EncryptionError::Decryption("missing payload".into()));
};
// Turn the bytes into a PublicKey
// Turn the bytes into a X25519PublicKey
let byte_arr: [u8; 32] = dr_header
.dh
.to_vec()
.try_into()
.map_err(|_| EncryptionError::Decryption("invalid public key length".into()))?;
let dh_pub = PublicKey::from(byte_arr);
let dh_pub = X25519PublicKey::from(byte_arr);
// Build the Header that DR impl expects
let header = Header {
@ -230,7 +230,7 @@ mod tests {
let saro = StaticSecret::random();
let raya = StaticSecret::random();
let pub_raya = PublicKey::from(&raya);
let pub_raya = X25519PublicKey::from(&raya);
let seed_key = saro.diffie_hellman(&pub_raya);
let send_content_bytes = vec![0, 2, 4, 6, 8];

View File

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

View File

@ -1,6 +1,6 @@
use std::fmt;
use crate::crypto::{PublicKey, StaticSecret};
use crate::crypto::{StaticSecret, X25519PublicKey};
pub struct Identity {
secret: StaticSecret,
@ -22,8 +22,8 @@ impl Identity {
}
}
pub fn public_key(&self) -> PublicKey {
PublicKey::from(&self.secret)
pub fn public_key(&self) -> X25519PublicKey {
X25519PublicKey::from(&self.secret)
}
pub fn secret(&self) -> &StaticSecret {

View File

@ -10,14 +10,14 @@ use crypto::{PrekeyBundle, SymmetricKey32};
use crate::context::Introduction;
use crate::conversation::{ChatError, ConversationId, Convo, Id, PrivateV1Convo};
use crate::crypto::{CopyBytes, PublicKey, StaticSecret};
use crate::crypto::{CopyBytes, StaticSecret, X25519PublicKey};
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(_: X25519PublicKey) -> String {
// TODO: Implement Delivery Address
"delivery_address".into()
}
@ -54,7 +54,7 @@ impl Inbox {
pub fn create_intro_bundle(&mut self) -> Introduction {
let ephemeral = StaticSecret::random();
let ephemeral_key: PublicKey = (&ephemeral).into();
let ephemeral_key: X25519PublicKey = (&ephemeral).into();
self.ephemeral_keys
.insert(hex::encode(ephemeral_key.as_bytes()), ephemeral);
@ -173,13 +173,13 @@ impl Inbox {
header: proto::InboxHeaderV1,
bytes: Bytes,
) -> Result<(SymmetricKey32, proto::InboxV1Frame), ChatError> {
// Get PublicKeys from protobuf
let initator_static = PublicKey::from(
// Get X25519PublicKeys from protobuf
let initator_static = X25519PublicKey::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 = X25519PublicKey::from(
<[u8; 32]>::try_from(header.initiator_ephemeral.as_ref())
.map_err(|_| ChatError::BadBundleValue("wrong size - initator ephemeral".into()))?,
);
@ -221,7 +221,7 @@ impl Inbox {
.ok_or(ChatError::UnknownEphemeralKey())
}
pub fn inbox_identifier_for_key(pubkey: PublicKey) -> String {
pub fn inbox_identifier_for_key(pubkey: X25519PublicKey) -> String {
// TODO: Implement ID according to spec
hex::encode(Blake2b512::digest(pubkey))
}

View File

@ -5,7 +5,7 @@ use blake2::{
use crypto::{DomainSeparator, PrekeyBundle, SymmetricKey32, X3Handshake};
use rand_core::{CryptoRng, RngCore};
use crate::crypto::{PublicKey, StaticSecret};
use crate::crypto::{StaticSecret, X25519PublicKey};
type Blake2bMac256 = Blake2bMac<U32>;
@ -24,7 +24,7 @@ impl InboxHandshake {
identity_keypair: &StaticSecret,
recipient_bundle: &PrekeyBundle,
rng: &mut R,
) -> (SymmetricKey32, PublicKey) {
) -> (SymmetricKey32, X25519PublicKey) {
// Perform X3DH handshake to get shared secret
let (shared_secret, ephemeral_public) =
InboxKeyExchange::initator(identity_keypair, recipient_bundle, rng);
@ -45,8 +45,8 @@ impl InboxHandshake {
identity_keypair: &StaticSecret,
signed_prekey: &StaticSecret,
onetime_prekey: Option<&StaticSecret>,
initiator_identity: &PublicKey,
initiator_ephemeral: &PublicKey,
initiator_identity: &X25519PublicKey,
initiator_ephemeral: &X25519PublicKey,
) -> SymmetricKey32 {
// 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(rng);
let alice_identity_pub = PublicKey::from(&alice_identity);
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_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);
let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey);
// Create Bob's prekey bundle
let bob_bundle = PrekeyBundle {
identity_key: PublicKey::from(&bob_identity),
identity_key: X25519PublicKey::from(&bob_identity),
signed_prekey: bob_signed_prekey_pub,
signature: crypto::Ed25519Signature([0u8; 64]),
onetime_prekey: None,

View File

@ -1,15 +1,15 @@
use base64::{Engine, engine::general_purpose::URL_SAFE_NO_PAD};
use chat_proto::logoschat::intro::IntroBundle;
use crypto::Ed25519Signature;
use crypto::{Ed25519Signature, X25519PublicKey};
use prost::Message;
use rand_core::{CryptoRng, RngCore};
use x25519_dalek::{PublicKey, StaticSecret};
use x25519_dalek::StaticSecret;
use crate::errors::ChatError;
const BUNDLE_PREFIX: &str = "logos_chatintro_1_";
fn intro_binding_message(ephemeral: &PublicKey) -> Vec<u8> {
fn intro_binding_message(ephemeral: &X25519PublicKey) -> Vec<u8> {
let mut message = Vec::with_capacity(BUNDLE_PREFIX.len() + 32);
message.extend_from_slice(BUNDLE_PREFIX.as_bytes());
message.extend_from_slice(ephemeral.as_bytes());
@ -18,7 +18,7 @@ fn intro_binding_message(ephemeral: &PublicKey) -> Vec<u8> {
pub(crate) fn sign_intro_binding<R: RngCore + CryptoRng>(
secret: &StaticSecret,
ephemeral: &PublicKey,
ephemeral: &X25519PublicKey,
rng: R,
) -> Ed25519Signature {
let message = intro_binding_message(ephemeral);
@ -26,8 +26,8 @@ pub(crate) fn sign_intro_binding<R: RngCore + CryptoRng>(
}
pub(crate) fn verify_intro_binding(
pubkey: &PublicKey,
ephemeral: &PublicKey,
pubkey: &X25519PublicKey,
ephemeral: &X25519PublicKey,
signature: &Ed25519Signature,
) -> Result<(), crypto::SignatureError> {
let message = intro_binding_message(ephemeral);
@ -36,8 +36,8 @@ pub(crate) fn verify_intro_binding(
/// Supplies remote participants with the required keys to use Inbox protocol
pub struct Introduction {
installation_key: PublicKey,
ephemeral_key: PublicKey,
installation_key: X25519PublicKey,
ephemeral_key: X25519PublicKey,
signature: Ed25519Signature,
}
@ -45,7 +45,7 @@ impl Introduction {
/// Create a new `Introduction` by signing the ephemeral key with the installation secret.
pub(crate) fn new<R: RngCore + CryptoRng>(
installation_secret: &StaticSecret,
ephemeral_key: PublicKey,
ephemeral_key: X25519PublicKey,
rng: R,
) -> Self {
let installation_key = installation_secret.into();
@ -57,11 +57,11 @@ impl Introduction {
}
}
pub fn installation_key(&self) -> &PublicKey {
pub fn installation_key(&self) -> &X25519PublicKey {
&self.installation_key
}
pub fn ephemeral_key(&self) -> &PublicKey {
pub fn ephemeral_key(&self) -> &X25519PublicKey {
&self.ephemeral_key
}
@ -126,8 +126,8 @@ impl TryFrom<&[u8]> for Introduction {
.try_into()
.map_err(|_| ChatError::BadBundleValue("invalid signature length".into()))?;
let installation_key = PublicKey::from(installation_bytes);
let ephemeral_key = PublicKey::from(ephemeral_bytes);
let installation_key = X25519PublicKey::from(installation_bytes);
let ephemeral_key = X25519PublicKey::from(ephemeral_bytes);
let signature = Ed25519Signature(signature_bytes);
verify_intro_binding(&installation_key, &ephemeral_key, &signature)
@ -150,7 +150,7 @@ mod tests {
let install_secret = StaticSecret::random_from_rng(OsRng);
let ephemeral_secret = StaticSecret::random_from_rng(OsRng);
let ephemeral_pub: PublicKey = (&ephemeral_secret).into();
let ephemeral_pub: X25519PublicKey = (&ephemeral_secret).into();
Introduction::new(&install_secret, ephemeral_pub, OsRng)
}

View File

@ -2,6 +2,6 @@ mod keys;
mod x3dh;
mod xeddsa_sign;
pub use keys::{GenericArray, SymmetricKey32};
pub use keys::{GenericArray, SymmetricKey32, X25519PublicKey};
pub use x3dh::{DomainSeparator, PrekeyBundle, X3Handshake};
pub use xeddsa_sign::{Ed25519Signature, SignatureError, xeddsa_sign, xeddsa_verify};

View File

@ -3,18 +3,18 @@ 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::SymmetricKey32;
use crate::keys::{SymmetricKey32, X25519PublicKey};
use crate::xeddsa_sign::Ed25519Signature;
/// 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: X25519PublicKey,
pub signed_prekey: X25519PublicKey,
pub signature: Ed25519Signature,
pub onetime_prekey: Option<PublicKey>,
pub onetime_prekey: Option<X25519PublicKey>,
}
pub trait DomainSeparator {
@ -70,10 +70,10 @@ impl<D: DomainSeparator> X3Handshake<D> {
identity_keypair: &StaticSecret,
recipient_bundle: &PrekeyBundle,
rng: &mut R,
) -> (SymmetricKey32, PublicKey) {
) -> (SymmetricKey32, X25519PublicKey) {
// 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 = X25519PublicKey::from(&ephemeral_secret);
// Perform the 4 Diffie-Hellman operations
let dh1 = identity_keypair.diffie_hellman(&recipient_bundle.signed_prekey);
@ -105,8 +105,8 @@ impl<D: DomainSeparator> X3Handshake<D> {
identity_keypair: &StaticSecret,
signed_prekey: &StaticSecret,
onetime_prekey: Option<&StaticSecret>,
initiator_identity: &PublicKey,
initiator_ephemeral: &PublicKey,
initiator_identity: &X25519PublicKey,
initiator_ephemeral: &X25519PublicKey,
) -> SymmetricKey32 {
let dh1 = signed_prekey.diffie_hellman(initiator_identity);
let dh2 = identity_keypair.diffie_hellman(initiator_ephemeral);
@ -136,17 +136,17 @@ mod tests {
// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(rng);
let alice_identity_pub = PublicKey::from(&alice_identity);
let alice_identity_pub = X25519PublicKey::from(&alice_identity);
// Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(rng);
let bob_identity_pub = PublicKey::from(&bob_identity);
let bob_identity_pub = X25519PublicKey::from(&bob_identity);
let bob_signed_prekey = StaticSecret::random_from_rng(rng);
let bob_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);
let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey);
let bob_onetime_prekey = StaticSecret::random_from_rng(rng);
let bob_onetime_prekey_pub = PublicKey::from(&bob_onetime_prekey);
let bob_onetime_prekey_pub = X25519PublicKey::from(&bob_onetime_prekey);
// Create Bob's prekey bundle (with one-time prekey)
let bob_bundle = PrekeyBundle {
@ -179,14 +179,14 @@ mod tests {
// Alice (initiator) generates her identity key
let alice_identity = StaticSecret::random_from_rng(rng);
let alice_identity_pub = PublicKey::from(&alice_identity);
let alice_identity_pub = X25519PublicKey::from(&alice_identity);
// Bob (responder) generates his keys
let bob_identity = StaticSecret::random_from_rng(rng);
let bob_identity_pub = PublicKey::from(&bob_identity);
let bob_identity_pub = X25519PublicKey::from(&bob_identity);
let bob_signed_prekey = StaticSecret::random_from_rng(rng);
let bob_signed_prekey_pub = PublicKey::from(&bob_signed_prekey);
let bob_signed_prekey_pub = X25519PublicKey::from(&bob_signed_prekey);
// Create Bob's prekey bundle (without one-time prekey)
let bob_bundle = PrekeyBundle {

View File

@ -4,9 +4,11 @@
//! that allow signing arbitrary messages with X25519 keys.
use rand_core::{CryptoRng, RngCore};
use x25519_dalek::{PublicKey, StaticSecret};
use x25519_dalek::StaticSecret;
use xeddsa::{Sign, Verify, xed25519};
use crate::keys::X25519PublicKey;
/// A 64-byte XEdDSA signature over an Ed25519-compatible curve.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Ed25519Signature(pub [u8; 64]);
@ -62,7 +64,7 @@ pub fn xeddsa_sign<R: RngCore + CryptoRng>(
/// # Returns
/// `Ok(())` if the signature is valid, `Err(SignatureError)` otherwise
pub fn xeddsa_verify(
pubkey: &PublicKey,
pubkey: &X25519PublicKey,
message: &[u8],
signature: &Ed25519Signature,
) -> Result<(), SignatureError> {
@ -80,7 +82,7 @@ mod tests {
#[test]
fn test_sign_and_verify_roundtrip() {
let secret = StaticSecret::random_from_rng(OsRng);
let public = PublicKey::from(&secret);
let public = X25519PublicKey::from(&secret);
let message = b"test message";
let signature = xeddsa_sign(&secret, message, OsRng);
@ -96,7 +98,7 @@ mod tests {
let signature = xeddsa_sign(&secret, message, OsRng);
let wrong_secret = StaticSecret::random_from_rng(OsRng);
let wrong_public = PublicKey::from(&wrong_secret);
let wrong_public = X25519PublicKey::from(&wrong_secret);
assert_eq!(
xeddsa_verify(&wrong_public, message, &signature),
@ -107,7 +109,7 @@ mod tests {
#[test]
fn test_wrong_message_fails() {
let secret = StaticSecret::random_from_rng(OsRng);
let public = PublicKey::from(&secret);
let public = X25519PublicKey::from(&secret);
let message = b"test message";
let signature = xeddsa_sign(&secret, message, OsRng);
@ -121,7 +123,7 @@ mod tests {
#[test]
fn test_corrupted_signature_fails() {
let secret = StaticSecret::random_from_rng(OsRng);
let public = PublicKey::from(&secret);
let public = X25519PublicKey::from(&secret);
let message = b"test message";
let mut signature = xeddsa_sign(&secret, message, OsRng);

View File

@ -13,6 +13,7 @@ required-features = ["headers"]
[dependencies]
x25519-dalek = { version="2.0.1", features=["static_secrets"] }
chacha20poly1305 = "0.10.1"
crypto.workspace = true
rand_core = "0.6.4"
rand = "0.8.5"
hkdf = "0.12.4"

View File

@ -1,5 +1,5 @@
use crypto::X25519PublicKey;
use safer_ffi::prelude::*;
use x25519_dalek::PublicKey;
use crate::{
Header, RatchetState,
@ -22,7 +22,7 @@ fn double_ratchet_init_sender(
shared_secret: [u8; 32],
remote_pub: [u8; 32],
) -> repr_c::Box<FFIRatchetState> {
let state = RatchetState::init_sender(shared_secret, PublicKey::from(remote_pub));
let state = RatchetState::init_sender(shared_secret, X25519PublicKey::from(remote_pub));
Box::new(FFIRatchetState(state)).into()
}

View File

@ -1,5 +1,6 @@
use crypto::X25519PublicKey;
use rand_core::OsRng;
use x25519_dalek::{PublicKey, StaticSecret};
use x25519_dalek::StaticSecret;
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::types::SharedSecret;
@ -7,21 +8,21 @@ use crate::types::SharedSecret;
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
pub struct InstallationKeyPair {
secret: StaticSecret,
public: PublicKey,
public: X25519PublicKey,
}
impl InstallationKeyPair {
pub fn generate() -> Self {
let secret = StaticSecret::random_from_rng(OsRng);
let public = PublicKey::from(&secret);
let public = X25519PublicKey::from(&secret);
Self { secret, public }
}
pub fn dh(&self, their_public: &PublicKey) -> SharedSecret {
pub fn dh(&self, their_public: &X25519PublicKey) -> SharedSecret {
self.secret.diffie_hellman(their_public).to_bytes()
}
pub fn public(&self) -> &PublicKey {
pub fn public(&self) -> &X25519PublicKey {
&self.public
}
@ -33,14 +34,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 public = PublicKey::from(&secret);
let public = X25519PublicKey::from(&secret);
Self { secret, public }
}
}
impl From<StaticSecret> for InstallationKeyPair {
fn from(value: StaticSecret) -> Self {
let public = PublicKey::from(&value);
let public = X25519PublicKey::from(&value);
Self {
secret: value,
public,

View File

@ -1,7 +1,7 @@
use std::{collections::HashMap, marker::PhantomData};
use crypto::X25519PublicKey;
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeError};
use x25519_dalek::PublicKey;
use zeroize::{Zeroize, Zeroizing};
use crate::{
@ -29,13 +29,13 @@ pub struct RatchetState<D: HkdfInfo = DefaultDomain> {
pub receiving_chain: Option<ChainKey>,
pub dh_self: InstallationKeyPair,
pub dh_remote: Option<PublicKey>,
pub dh_remote: Option<X25519PublicKey>,
pub msg_send: u32,
pub msg_recv: u32,
pub prev_chain_len: u32,
pub skipped_keys: HashMap<(PublicKey, u32), MessageKey>,
pub skipped_keys: HashMap<(X25519PublicKey, u32), MessageKey>,
pub(crate) _domain: PhantomData<D>,
}
@ -144,7 +144,7 @@ impl<D: HkdfInfo> RatchetState<D> {
let dh_self = InstallationKeyPair::from_secret_bytes(dh_self_bytes);
dh_self_bytes.zeroize();
let dh_remote = reader.read_option()?.map(PublicKey::from);
let dh_remote = reader.read_option()?.map(X25519PublicKey::from);
let msg_send = reader.read_u32()?;
let msg_recv = reader.read_u32()?;
@ -153,7 +153,7 @@ impl<D: HkdfInfo> RatchetState<D> {
let skipped_count = reader.read_u32()? as usize;
let mut skipped_keys = HashMap::with_capacity(skipped_count);
for _ in 0..skipped_count {
let pk = PublicKey::from(reader.read_array::<32>()?);
let pk = X25519PublicKey::from(reader.read_array::<32>()?);
let msg_num = reader.read_u32()?;
let mk: MessageKey = reader.read_array()?;
skipped_keys.insert((pk, msg_num), mk);
@ -198,7 +198,7 @@ impl<'de, D: HkdfInfo> Deserialize<'de> for RatchetState<D> {
/// Public header attached to every encrypted message (unencrypted but authenticated).
#[derive(Clone, Debug)]
pub struct Header {
pub dh_pub: PublicKey,
pub dh_pub: X25519PublicKey,
pub msg_num: u32,
pub prev_chain_len: u32,
}
@ -233,7 +233,7 @@ impl<D: HkdfInfo> RatchetState<D> {
/// # Returns
///
/// A new `RatchetState` ready to send the first message.
pub fn init_sender(shared_secret: SharedSecret, remote_pub: PublicKey) -> Self {
pub fn init_sender(shared_secret: SharedSecret, remote_pub: X25519PublicKey) -> Self {
let dh_self = InstallationKeyPair::generate();
// Initial DH
@ -296,7 +296,7 @@ impl<D: HkdfInfo> RatchetState<D> {
/// # Arguments
///
/// * `remote_pub` - The new DH public key from the sender.
pub fn dh_ratchet_receive(&mut self, remote_pub: PublicKey) {
pub fn dh_ratchet_receive(&mut self, remote_pub: X25519PublicKey) {
let dh_out = self.dh_self.dh(&remote_pub);
let (new_root, recv_chain) = kdf_root::<D>(&self.root_key, &dh_out);
@ -605,7 +605,7 @@ mod tests {
// Tamper with header (change DH pub byte)
let mut tampered_pub_bytes = header.dh_pub.to_bytes();
tampered_pub_bytes[0] ^= 0xff;
header.dh_pub = PublicKey::from(tampered_pub_bytes);
header.dh_pub = X25519PublicKey::from(tampered_pub_bytes);
let result = bob.decrypt_message(&ct, header);
assert!(result.is_err());

View File

@ -1,6 +1,6 @@
//! Session wrapper for automatic state persistence.
use x25519_dalek::PublicKey;
use crypto::X25519PublicKey;
use crate::{
InstallationKeyPair, SessionError,
@ -54,7 +54,7 @@ impl<'a, D: HkdfInfo + Clone> RatchetSession<'a, D> {
storage: &'a mut RatchetStorage,
conversation_id: &str,
shared_secret: SharedSecret,
remote_pub: PublicKey,
remote_pub: X25519PublicKey,
) -> Result<Self, SessionError> {
if storage.exists(conversation_id)? {
return Err(SessionError::ConvAlreadyExists(conversation_id.to_string()));

View File

@ -1,11 +1,11 @@
//! Storage types for ratchet state.
use crypto::X25519PublicKey;
use crate::{
hkdf::HkdfInfo,
state::{RatchetState, SkippedKey},
types::MessageKey,
};
use x25519_dalek::PublicKey;
/// Raw state data for storage (without generic parameter).
#[derive(Debug, Clone)]
@ -42,11 +42,16 @@ impl RatchetStateRecord {
use std::marker::PhantomData;
let dh_self = InstallationKeyPair::from_secret_bytes(self.dh_self_secret);
let dh_remote = self.dh_remote.map(PublicKey::from);
let dh_remote = self.dh_remote.map(X25519PublicKey::from);
let skipped: HashMap<(PublicKey, u32), MessageKey> = skipped_keys
let skipped: HashMap<(X25519PublicKey, u32), MessageKey> = skipped_keys
.into_iter()
.map(|sk| ((PublicKey::from(sk.public_key), sk.msg_num), sk.message_key))
.map(|sk| {
(
(X25519PublicKey::from(sk.public_key), sk.msg_num),
sk.message_key,
)
})
.collect();
RatchetState {