aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWill Dillon <william@housedillon.com>2025-11-07 02:46:41 +0000
committerWill Dillon <william@housedillon.com>2025-11-07 02:46:41 +0000
commit6729ee2532ca01f7af88cc47208627453e3ba80c (patch)
tree20ff039050fe61aded17caab8fc70ffdd48c4921 /src
parentTry moving from PrivateKey to Static Secret (diff)
downloadmeshcore-rs-6729ee2532ca01f7af88cc47208627453e3ba80c.tar.gz
meshcore-rs-6729ee2532ca01f7af88cc47208627453e3ba80c.zip
Moving back to laptop
Diffstat (limited to 'src')
-rw-r--r--src/crypto.rs116
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);
}