mirror of
https://github.com/logos-messaging/libchat.git
synced 2026-02-10 00:43:09 +00:00
Migrate to Crypto::PublicKey32 and PrivateKey32
This commit is contained in:
parent
5adee47a97
commit
143cb38052
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -218,6 +218,7 @@ version = "0.0.1"
|
||||
dependencies = [
|
||||
"blake2",
|
||||
"chacha20poly1305",
|
||||
"crypto",
|
||||
"hkdf",
|
||||
"rand",
|
||||
"rand_core",
|
||||
|
||||
@ -4,6 +4,7 @@ use prost::bytes::Bytes;
|
||||
|
||||
pub use crypto::{PrivateKey32, PublicKey32};
|
||||
|
||||
// TODO: (P4) Make handing of Keys in Prost easier
|
||||
pub trait CopyBytes {
|
||||
fn copy_to_bytes(&self) -> Bytes;
|
||||
}
|
||||
|
||||
@ -1,24 +1,15 @@
|
||||
use generic_array::{GenericArray, typenum::U32};
|
||||
use rand_core::{CryptoRng, OsRng, RngCore};
|
||||
use std::{fmt::Debug, ops::Deref};
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
use x25519_dalek;
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
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<&PrivateKey32> for PublicKey32 {
|
||||
fn from(value: &PrivateKey32) -> Self {
|
||||
Self(x25519_dalek::PublicKey::from(&value.0))
|
||||
@ -38,6 +29,12 @@ impl Deref for PublicKey32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PublicKey32 {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for PublicKey32 {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
@ -58,6 +55,12 @@ impl PrivateKey32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for PrivateKey32 {
|
||||
fn from(value: [u8; 32]) -> Self {
|
||||
Self(x25519_dalek::StaticSecret::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PrivateKey32 {
|
||||
type Target = x25519_dalek::StaticSecret;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
|
||||
@ -11,8 +11,8 @@ name = "generate-headers"
|
||||
required-features = ["headers"]
|
||||
|
||||
[dependencies]
|
||||
x25519-dalek = { version="2.0.1", features=["static_secrets"] }
|
||||
chacha20poly1305 = "0.10.1"
|
||||
crypto = { path = "../crypto" }
|
||||
rand_core = "0.6.4"
|
||||
rand = "0.8.5"
|
||||
hkdf = "0.12.4"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crypto::PublicKey32;
|
||||
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, PublicKey32::from(remote_pub));
|
||||
Box::new(FFIRatchetState(state)).into()
|
||||
}
|
||||
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
use crypto::{PrivateKey32, PublicKey32};
|
||||
use rand_core::OsRng;
|
||||
use x25519_dalek::{PublicKey, StaticSecret};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
use crate::types::SharedSecret;
|
||||
|
||||
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
|
||||
pub struct InstallationKeyPair {
|
||||
secret: StaticSecret,
|
||||
public: PublicKey,
|
||||
secret: PrivateKey32,
|
||||
public: PublicKey32,
|
||||
}
|
||||
|
||||
impl InstallationKeyPair {
|
||||
pub fn generate() -> Self {
|
||||
let secret = StaticSecret::random_from_rng(OsRng);
|
||||
let public = PublicKey::from(&secret);
|
||||
let secret = PrivateKey32::random_from_rng(OsRng);
|
||||
let public = PublicKey32::from(&secret);
|
||||
Self { secret, public }
|
||||
}
|
||||
|
||||
pub fn dh(&self, their_public: &PublicKey) -> SharedSecret {
|
||||
pub fn dh(&self, their_public: &PublicKey32) -> SharedSecret {
|
||||
self.secret.diffie_hellman(their_public).to_bytes()
|
||||
}
|
||||
|
||||
pub fn public(&self) -> &PublicKey {
|
||||
pub fn public(&self) -> &PublicKey32 {
|
||||
&self.public
|
||||
}
|
||||
|
||||
@ -32,8 +32,8 @@ 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 secret = PrivateKey32::from(bytes);
|
||||
let public = PublicKey32::from(&secret);
|
||||
Self { secret, public }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::{collections::HashMap, marker::PhantomData};
|
||||
|
||||
use crypto::PublicKey32;
|
||||
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<PublicKey32>,
|
||||
|
||||
pub msg_send: u32,
|
||||
pub msg_recv: u32,
|
||||
pub prev_chain_len: u32,
|
||||
|
||||
pub skipped_keys: HashMap<(PublicKey, u32), MessageKey>,
|
||||
pub skipped_keys: HashMap<(PublicKey32, 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(PublicKey32::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 = PublicKey32::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: PublicKey32,
|
||||
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: PublicKey32) -> 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: PublicKey32) {
|
||||
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 = PublicKey32::from(tampered_pub_bytes);
|
||||
|
||||
let result = bob.decrypt_message(&ct, header);
|
||||
assert!(result.is_err());
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use x25519_dalek::PublicKey;
|
||||
use crypto::PublicKey32;
|
||||
|
||||
use crate::{
|
||||
InstallationKeyPair,
|
||||
@ -82,7 +82,7 @@ impl<'a, D: HkdfInfo + Clone> RatchetSession<'a, D> {
|
||||
storage: &'a mut SqliteStorage,
|
||||
conversation_id: impl Into<String>,
|
||||
shared_secret: SharedSecret,
|
||||
remote_pub: PublicKey,
|
||||
remote_pub: PublicKey32,
|
||||
) -> Result<Self, StorageError> {
|
||||
let state = RatchetState::<D>::init_sender(shared_secret, remote_pub);
|
||||
Self::create(storage, conversation_id, state)
|
||||
|
||||
@ -3,8 +3,8 @@ use crate::{
|
||||
state::{RatchetState, SkippedKey},
|
||||
types::MessageKey,
|
||||
};
|
||||
use crypto::PublicKey32;
|
||||
use thiserror::Error;
|
||||
use x25519_dalek::PublicKey;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum StorageError {
|
||||
@ -58,11 +58,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(PublicKey32::from);
|
||||
|
||||
let skipped: HashMap<(PublicKey, u32), MessageKey> = skipped_keys
|
||||
let skipped: HashMap<(PublicKey32, u32), MessageKey> = skipped_keys
|
||||
.into_iter()
|
||||
.map(|sk| ((PublicKey::from(sk.public_key), sk.msg_num), sk.message_key))
|
||||
.map(|sk| {
|
||||
(
|
||||
(PublicKey32::from(sk.public_key), sk.msg_num),
|
||||
sk.message_key,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
RatchetState {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user