diff --git a/common/crypto/src/encryption/x25519.rs b/common/crypto/src/encryption/x25519.rs new file mode 100644 index 0000000000..a48d5c5ca7 --- /dev/null +++ b/common/crypto/src/encryption/x25519.rs @@ -0,0 +1,77 @@ +use crate::encryption::{ + MixnetEncryptionKeyPair, MixnetEncryptionPrivateKey, MixnetEncryptionPublicKey, +}; +use curve25519_dalek::montgomery::MontgomeryPoint; +use curve25519_dalek::scalar::Scalar; + +// TODO: ensure this is a proper name for this considering we are not implementing entire DH here + +pub const CURVE_GENERATOR: MontgomeryPoint = curve25519_dalek::constants::X25519_BASEPOINT; + +pub struct KeyPair { + pub(crate) private_key: PrivateKey, + pub(crate) public_key: PublicKey, +} + +impl MixnetEncryptionKeyPair for KeyPair { + fn new() -> Self { + let mut rng = rand_os::OsRng::new().unwrap(); + let private_key_value = Scalar::random(&mut rng); + let public_key_value = CURVE_GENERATOR * private_key_value; + + KeyPair { + private_key: PrivateKey(private_key_value), + public_key: PublicKey(public_key_value), + } + } + + fn private_key(&self) -> &PrivateKey { + &self.private_key + } + + fn public_key(&self) -> &PublicKey { + &self.public_key + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct PrivateKey(pub Scalar); + +impl MixnetEncryptionPrivateKey for PrivateKey { + type PublicKeyMaterial = PublicKey; + + fn to_bytes(&self) -> Vec { + self.0.to_bytes().to_vec() + } + + fn from_bytes(b: &[u8]) -> Self { + let mut bytes = [0; 32]; + bytes.copy_from_slice(&b[..]); + let key = Scalar::from_canonical_bytes(bytes).unwrap(); + Self(key) + } +} + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct PublicKey(pub MontgomeryPoint); + +impl<'a> From<&'a PrivateKey> for PublicKey { + fn from(pk: &'a PrivateKey) -> Self { + PublicKey(CURVE_GENERATOR * pk.0) + } +} + +impl MixnetEncryptionPublicKey for PublicKey { + type PrivateKeyMaterial = PrivateKey; + + fn to_bytes(&self) -> Vec { + self.0.to_bytes().to_vec() + } + + fn from_bytes(b: &[u8]) -> Self { + let mut bytes = [0; 32]; + bytes.copy_from_slice(&b[..]); + let key = MontgomeryPoint(bytes); + Self(key) + } +}