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 = [
|
dependencies = [
|
||||||
"blake2",
|
"blake2",
|
||||||
"chacha20poly1305",
|
"chacha20poly1305",
|
||||||
|
"crypto",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"rand",
|
"rand",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
|||||||
@ -4,6 +4,7 @@ use prost::bytes::Bytes;
|
|||||||
|
|
||||||
pub use crypto::{PrivateKey32, PublicKey32};
|
pub use crypto::{PrivateKey32, PublicKey32};
|
||||||
|
|
||||||
|
// TODO: (P4) Make handing of Keys in Prost easier
|
||||||
pub trait CopyBytes {
|
pub trait CopyBytes {
|
||||||
fn copy_to_bytes(&self) -> Bytes;
|
fn copy_to_bytes(&self) -> Bytes;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +1,15 @@
|
|||||||
use generic_array::{GenericArray, typenum::U32};
|
use generic_array::{GenericArray, typenum::U32};
|
||||||
use rand_core::{CryptoRng, OsRng, RngCore};
|
use rand_core::{CryptoRng, OsRng, RngCore};
|
||||||
use std::{fmt::Debug, ops::Deref};
|
use std::{
|
||||||
|
fmt::Debug,
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
};
|
||||||
use x25519_dalek;
|
use x25519_dalek;
|
||||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct PublicKey32(x25519_dalek::PublicKey);
|
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 {
|
impl From<&PrivateKey32> for PublicKey32 {
|
||||||
fn from(value: &PrivateKey32) -> Self {
|
fn from(value: &PrivateKey32) -> Self {
|
||||||
Self(x25519_dalek::PublicKey::from(&value.0))
|
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 {
|
impl AsRef<[u8]> for PublicKey32 {
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
self.0.as_ref()
|
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 {
|
impl Deref for PrivateKey32 {
|
||||||
type Target = x25519_dalek::StaticSecret;
|
type Target = x25519_dalek::StaticSecret;
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|||||||
@ -11,8 +11,8 @@ name = "generate-headers"
|
|||||||
required-features = ["headers"]
|
required-features = ["headers"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
x25519-dalek = { version="2.0.1", features=["static_secrets"] }
|
|
||||||
chacha20poly1305 = "0.10.1"
|
chacha20poly1305 = "0.10.1"
|
||||||
|
crypto = { path = "../crypto" }
|
||||||
rand_core = "0.6.4"
|
rand_core = "0.6.4"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
hkdf = "0.12.4"
|
hkdf = "0.12.4"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
use crypto::PublicKey32;
|
||||||
use safer_ffi::prelude::*;
|
use safer_ffi::prelude::*;
|
||||||
use x25519_dalek::PublicKey;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Header, RatchetState,
|
Header, RatchetState,
|
||||||
@ -22,7 +22,7 @@ fn double_ratchet_init_sender(
|
|||||||
shared_secret: [u8; 32],
|
shared_secret: [u8; 32],
|
||||||
remote_pub: [u8; 32],
|
remote_pub: [u8; 32],
|
||||||
) -> repr_c::Box<FFIRatchetState> {
|
) -> 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()
|
Box::new(FFIRatchetState(state)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,27 @@
|
|||||||
|
use crypto::{PrivateKey32, PublicKey32};
|
||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
use x25519_dalek::{PublicKey, StaticSecret};
|
|
||||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
use crate::types::SharedSecret;
|
use crate::types::SharedSecret;
|
||||||
|
|
||||||
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
|
#[derive(Clone, Zeroize, ZeroizeOnDrop)]
|
||||||
pub struct InstallationKeyPair {
|
pub struct InstallationKeyPair {
|
||||||
secret: StaticSecret,
|
secret: PrivateKey32,
|
||||||
public: PublicKey,
|
public: PublicKey32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InstallationKeyPair {
|
impl InstallationKeyPair {
|
||||||
pub fn generate() -> Self {
|
pub fn generate() -> Self {
|
||||||
let secret = StaticSecret::random_from_rng(OsRng);
|
let secret = PrivateKey32::random_from_rng(OsRng);
|
||||||
let public = PublicKey::from(&secret);
|
let public = PublicKey32::from(&secret);
|
||||||
Self { secret, public }
|
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()
|
self.secret.diffie_hellman(their_public).to_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn public(&self) -> &PublicKey {
|
pub fn public(&self) -> &PublicKey32 {
|
||||||
&self.public
|
&self.public
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,8 +32,8 @@ impl InstallationKeyPair {
|
|||||||
|
|
||||||
/// Import the secret key from raw bytes.
|
/// Import the secret key from raw bytes.
|
||||||
pub fn from_secret_bytes(bytes: [u8; 32]) -> Self {
|
pub fn from_secret_bytes(bytes: [u8; 32]) -> Self {
|
||||||
let secret = StaticSecret::from(bytes);
|
let secret = PrivateKey32::from(bytes);
|
||||||
let public = PublicKey::from(&secret);
|
let public = PublicKey32::from(&secret);
|
||||||
Self { secret, public }
|
Self { secret, public }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::{collections::HashMap, marker::PhantomData};
|
use std::{collections::HashMap, marker::PhantomData};
|
||||||
|
|
||||||
|
use crypto::PublicKey32;
|
||||||
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeError};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as DeError};
|
||||||
use x25519_dalek::PublicKey;
|
|
||||||
use zeroize::{Zeroize, Zeroizing};
|
use zeroize::{Zeroize, Zeroizing};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -29,13 +29,13 @@ pub struct RatchetState<D: HkdfInfo = DefaultDomain> {
|
|||||||
pub receiving_chain: Option<ChainKey>,
|
pub receiving_chain: Option<ChainKey>,
|
||||||
|
|
||||||
pub dh_self: InstallationKeyPair,
|
pub dh_self: InstallationKeyPair,
|
||||||
pub dh_remote: Option<PublicKey>,
|
pub dh_remote: Option<PublicKey32>,
|
||||||
|
|
||||||
pub msg_send: u32,
|
pub msg_send: u32,
|
||||||
pub msg_recv: u32,
|
pub msg_recv: u32,
|
||||||
pub prev_chain_len: 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>,
|
pub(crate) _domain: PhantomData<D>,
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ impl<D: HkdfInfo> RatchetState<D> {
|
|||||||
let dh_self = InstallationKeyPair::from_secret_bytes(dh_self_bytes);
|
let dh_self = InstallationKeyPair::from_secret_bytes(dh_self_bytes);
|
||||||
dh_self_bytes.zeroize();
|
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_send = reader.read_u32()?;
|
||||||
let msg_recv = 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 skipped_count = reader.read_u32()? as usize;
|
||||||
let mut skipped_keys = HashMap::with_capacity(skipped_count);
|
let mut skipped_keys = HashMap::with_capacity(skipped_count);
|
||||||
for _ in 0..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 msg_num = reader.read_u32()?;
|
||||||
let mk: MessageKey = reader.read_array()?;
|
let mk: MessageKey = reader.read_array()?;
|
||||||
skipped_keys.insert((pk, msg_num), mk);
|
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).
|
/// Public header attached to every encrypted message (unencrypted but authenticated).
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Header {
|
pub struct Header {
|
||||||
pub dh_pub: PublicKey,
|
pub dh_pub: PublicKey32,
|
||||||
pub msg_num: u32,
|
pub msg_num: u32,
|
||||||
pub prev_chain_len: u32,
|
pub prev_chain_len: u32,
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ impl<D: HkdfInfo> RatchetState<D> {
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
///
|
///
|
||||||
/// A new `RatchetState` ready to send the first message.
|
/// 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();
|
let dh_self = InstallationKeyPair::generate();
|
||||||
|
|
||||||
// Initial DH
|
// Initial DH
|
||||||
@ -296,7 +296,7 @@ impl<D: HkdfInfo> RatchetState<D> {
|
|||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `remote_pub` - The new DH public key from the sender.
|
/// * `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 dh_out = self.dh_self.dh(&remote_pub);
|
||||||
let (new_root, recv_chain) = kdf_root::<D>(&self.root_key, &dh_out);
|
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)
|
// Tamper with header (change DH pub byte)
|
||||||
let mut tampered_pub_bytes = header.dh_pub.to_bytes();
|
let mut tampered_pub_bytes = header.dh_pub.to_bytes();
|
||||||
tampered_pub_bytes[0] ^= 0xff;
|
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);
|
let result = bob.decrypt_message(&ct, header);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use x25519_dalek::PublicKey;
|
use crypto::PublicKey32;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
InstallationKeyPair,
|
InstallationKeyPair,
|
||||||
@ -82,7 +82,7 @@ impl<'a, D: HkdfInfo + Clone> RatchetSession<'a, D> {
|
|||||||
storage: &'a mut SqliteStorage,
|
storage: &'a mut SqliteStorage,
|
||||||
conversation_id: impl Into<String>,
|
conversation_id: impl Into<String>,
|
||||||
shared_secret: SharedSecret,
|
shared_secret: SharedSecret,
|
||||||
remote_pub: PublicKey,
|
remote_pub: PublicKey32,
|
||||||
) -> Result<Self, StorageError> {
|
) -> Result<Self, StorageError> {
|
||||||
let state = RatchetState::<D>::init_sender(shared_secret, remote_pub);
|
let state = RatchetState::<D>::init_sender(shared_secret, remote_pub);
|
||||||
Self::create(storage, conversation_id, state)
|
Self::create(storage, conversation_id, state)
|
||||||
|
|||||||
@ -3,8 +3,8 @@ use crate::{
|
|||||||
state::{RatchetState, SkippedKey},
|
state::{RatchetState, SkippedKey},
|
||||||
types::MessageKey,
|
types::MessageKey,
|
||||||
};
|
};
|
||||||
|
use crypto::PublicKey32;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use x25519_dalek::PublicKey;
|
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum StorageError {
|
pub enum StorageError {
|
||||||
@ -58,11 +58,16 @@ impl RatchetStateRecord {
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
let dh_self = InstallationKeyPair::from_secret_bytes(self.dh_self_secret);
|
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()
|
.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();
|
.collect();
|
||||||
|
|
||||||
RatchetState {
|
RatchetState {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user