diff options
| author | Will Dillon <william@housedillon.com> | 2025-11-07 02:46:41 +0000 |
|---|---|---|
| committer | Will Dillon <william@housedillon.com> | 2025-11-07 02:46:41 +0000 |
| commit | 6729ee2532ca01f7af88cc47208627453e3ba80c (patch) | |
| tree | 20ff039050fe61aded17caab8fc70ffdd48c4921 /src | |
| parent | Try moving from PrivateKey to Static Secret (diff) | |
| download | meshcore-rs-6729ee2532ca01f7af88cc47208627453e3ba80c.tar.gz meshcore-rs-6729ee2532ca01f7af88cc47208627453e3ba80c.zip | |
Moving back to laptop
Diffstat (limited to 'src')
| -rw-r--r-- | src/crypto.rs | 116 |
1 files changed, 66 insertions, 50 deletions
diff --git a/src/crypto.rs b/src/crypto.rs index 63532ab..31d2cb7 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -2,10 +2,6 @@ use std::str::FromStr; use tokio_util::bytes::{Buf, BufMut, Bytes, BytesMut}; use hex::{decode, decode_to_slice, encode}; -use ed25519_dalek::hazmat::ExpandedSecretKey; -use curve25519_dalek::{Scalar, constants, edwards::CompressedEdwardsY}; -use x25519_dalek::StaticSecret; - // This seems to be an absolute nightmare. GenericArray sucks // but I can't seem to figure out how to pull it out of this // stack of software @@ -14,6 +10,7 @@ use aes::cipher::{ BlockCipher, BlockEncrypt, BlockDecrypt, generic_array::GenericArray, }; +use curve25519_dalek::MontgomeryPoint; use aes::Aes256; use sha2::{Sha256}; use hmac::{Hmac, Mac}; @@ -27,14 +24,49 @@ pub enum MeshcoreCryptoError { HexDecodeError } -#[derive(PartialEq, Debug)] -pub struct PrivateKey(ExpandedSecretKey); +pub struct PrivateKey(x25519_dalek::StaticSecret); -#[derive(PartialEq, Debug, Clone)] -pub struct PublicKey(CompressedEdwardsY); +impl PartialEq for PrivateKey { + fn eq(&self, other: &Self) -> bool { + self.0.as_bytes() == other.0.as_bytes() + } + + fn ne(&self, other: &Self) -> bool { + !self.eq(other) + } +} -#[derive(Debug, PartialEq)] -pub struct SharedSecret([u8; 32]); +impl std::fmt::Debug for PrivateKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("PrivateKey").field(&encode(self.0.as_bytes())).finish() + } +} + +#[derive(PartialEq, Clone)] +pub struct PublicKey(x25519_dalek::PublicKey); +impl std::fmt::Debug for PublicKey { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("PublicKey").field(&encode(self.0.as_bytes())).finish() + } +} + +pub struct SharedSecret(MontgomeryPoint); + +impl PartialEq for SharedSecret { + fn eq(&self, other: &Self) -> bool { + self.0.as_bytes() == other.0.as_bytes() + } + + fn ne(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +impl std::fmt::Debug for SharedSecret { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("SharedSecret").field(&encode(self.0.as_bytes())).finish() + } +} impl FromStr for SharedSecret { type Err = MeshcoreCryptoError; @@ -44,7 +76,7 @@ impl FromStr for SharedSecret { if decode_to_slice(s, &mut slice).is_err() { return Err(MeshcoreCryptoError::TryFromSliceError) } else { - Ok(SharedSecret(slice)) + Ok(SharedSecret(MontgomeryPoint(slice))) } } } @@ -59,11 +91,11 @@ impl SharedSecret { let mut slice = [0_u8; 32]; group_secret.copy_to_slice(&mut slice); - SharedSecret(slice) + SharedSecret(MontgomeryPoint(slice)) } pub fn get_hmac(&self, ciphertext: Bytes) -> Result<u16, MeshcoreCryptoError> { - if let Ok(mut mac) = HmacSha256::new_from_slice(&self.0) { + if let Ok(mut mac) = HmacSha256::new_from_slice(self.0.as_bytes()) { mac.update(&ciphertext); let result = mac.finalize(); let mut bytes = Bytes::copy_from_slice(&result.into_bytes()); @@ -77,7 +109,7 @@ impl SharedSecret { pub fn decrypt(&self, ciphertext: Bytes) -> Result<Bytes, MeshcoreCryptoError> { use aes::cipher::KeyInit; - if let Ok(mut aes) = Aes256::new_from_slice(&self.0) { + if let Ok(aes) = Aes256::new_from_slice(self.0.as_bytes()) { let mut text = BytesMut::from(ciphertext); // The decryption function works on a 16-byte block of data. @@ -116,7 +148,7 @@ impl SharedSecret { pub fn encrypt(&self, plaintext: Bytes) -> Result<Bytes, MeshcoreCryptoError> { use aes::cipher::KeyInit; - if let Ok(aes) = Aes256::new_from_slice(&self.0) { + if let Ok(aes) = Aes256::new_from_slice(self.0.as_bytes()) { let mut text = BytesMut::from(plaintext); // The decryption function works on a 16-byte block of data. @@ -153,7 +185,7 @@ impl SharedSecret { // This is just for creating placeholders impl Default for PublicKey { fn default() -> Self { - PublicKey(CompressedEdwardsY::from_slice(&[0_u8; 32]).unwrap()) + PublicKey(x25519_dalek::PublicKey::from([0_u8; 32])) } } @@ -171,7 +203,7 @@ impl TryFrom<Bytes> for PublicKey { return Err(MeshcoreCryptoError::TryFromSliceError) } - Ok(PublicKey(curve25519_dalek::edwards::CompressedEdwardsY(slice))) + Ok(PublicKey(x25519_dalek::PublicKey::from(slice))) } } @@ -182,8 +214,8 @@ impl FromStr for PublicKey { fn from_str(hex_str: &str) -> Result<Self, Self::Err> { let hex = decode(hex_str)?; - if let Ok(edx) = CompressedEdwardsY::from_slice(&hex) { - Ok(PublicKey(edx)) + if let Ok(bytes) = TryInto::<[u8; 32]>::try_into(hex) { + Ok(PublicKey(x25519_dalek::PublicKey::from(bytes))) } else { Err(hex::FromHexError::InvalidStringLength) } @@ -194,22 +226,11 @@ impl FromStr for PrivateKey { type Err = MeshcoreCryptoError; fn from_str(hex_str: &str) -> Result<Self, Self::Err> { - if let Ok(hex) = decode(hex_str) { - match hex.len() { - 32 => { - let bytes: [u8; 32] = hex.try_into().unwrap(); - let exp_sec_key = ExpandedSecretKey { - scalar: Scalar::from_bytes_mod_order(bytes), - hash_prefix: [0_u8; 32] - }; - - Ok(PrivateKey(exp_sec_key)) - }, - 64 => { - let bytes: [u8; 64] = hex.try_into().unwrap(); - Ok(PrivateKey(ExpandedSecretKey::from_bytes(&bytes))) - } - _ => Err(MeshcoreCryptoError::KeyLengthError) + if let Ok(mut hex) = decode(hex_str) { + if let Ok(bytes) = TryInto::<[u8; 32]>::try_into(hex.split_off(32)) { + Ok(PrivateKey(x25519_dalek::StaticSecret::from(bytes))) + } else { + Err(MeshcoreCryptoError::HexDecodeError) } } else { Err(MeshcoreCryptoError::HexDecodeError) @@ -219,14 +240,14 @@ impl FromStr for PrivateKey { impl From<&PrivateKey> for PublicKey { fn from(key: &PrivateKey) -> Self { - PublicKey((key.0.scalar * constants::ED25519_BASEPOINT_POINT).compress()) + let key = x25519_dalek::PublicKey::from(&key.0); + PublicKey(key) } } impl PrivateKey { pub fn create_secret(&self, other: &PublicKey) -> SharedSecret { - let private = StaticSecret::from(*self.0.scalar.as_bytes()); - SharedSecret(private.diffie_hellman(&other.0.to_bytes().into()).to_bytes()) + SharedSecret(MontgomeryPoint(*self.0.diffie_hellman(&other.0).as_bytes())) } } @@ -250,7 +271,6 @@ pub struct Keychain { #[cfg(test)] mod tests { use hex::{decode_to_slice, encode}; - use rand_core::TryRngCore; use super::*; #[test] @@ -258,18 +278,14 @@ mod tests { let mut slice = [0_u8; 32]; decode_to_slice("12349bdc1f76a0c12149bb15f791dbe42fde02c209b04a85c6f512990c8cedec", &mut slice).unwrap(); let public_key = PublicKey::from_str("12349bdc1f76a0c12149bb15f791dbe42fde02c209b04a85c6f512990c8cedec"); - assert!(Ok(PublicKey(CompressedEdwardsY(slice))) == public_key); + assert!(Ok(PublicKey(x25519_dalek::PublicKey::from(slice))) == public_key); } #[test] fn private_key() { - // Create a private key in two different ways - let bytes = Bytes::copy_from_slice(&decode("38DAA98490B7284697C7ADA6175FD1F8DAD12032AD7ABAE625B7EAD8FEC6444CA281C3370B97155D9C8CECD89A929FDDE0FBF3A9D5C92A1B3C24D711934CD69D").unwrap()); - let private_key = PrivateKey::from_str("38DAA98490B7284697C7ADA6175FD1F8DAD12032AD7ABAE625B7EAD8FEC6444CA281C3370B97155D9C8CECD89A929FDDE0FBF3A9D5C92A1B3C24D711934CD69D"); - assert!(Ok(PrivateKey(ExpandedSecretKey::from_bytes(bytes.get(0 .. 64).unwrap().try_into().unwrap()))) == private_key); - - // Ensure that the expected public key can be derived from it. - let public_key = PublicKey::from(&private_key.unwrap()); + let private_key = PrivateKey::from_str("38DAA98490B7284697C7ADA6175FD1F8DAD12032AD7ABAE625B7EAD8FEC6444CA281C3370B97155D9C8CECD89A929FDDE0FBF3A9D5C92A1B3C24D711934CD69D").unwrap(); + let public_key = PublicKey::from(&private_key); + println!("Public key: {:#?}", public_key); assert!(PublicKey::from_str("12349bdc1f76a0c12149bb15f791dbe42fde02c209b04a85c6f512990c8cedec").unwrap() == public_key); } @@ -291,10 +307,10 @@ mod tests { let left_secret = alice_private.create_secret(&bob_public); let right_secret = bob_private.create_secret(&alice_public); - assert!(left_secret.0.to_vec() == decode("ddbb8b5e70099817db83b48caa73f44a120b12a26072e5c29a023f16a2cd8b2a").unwrap()); + assert!(left_secret.0.as_bytes().to_vec() == decode("ddbb8b5e70099817db83b48caa73f44a120b12a26072e5c29a023f16a2cd8b2a").unwrap()); - println!("Left shared secret: {}", encode(left_secret.0)); - println!("Right shared secret: {}", encode(right_secret.0)); + println!("Left shared secret: {}", encode(&left_secret.0.as_bytes())); + println!("Right shared secret: {}", encode(&right_secret.0.as_bytes())); assert!(left_secret == right_secret); } |
