diff --git a/radicle-crypto/src/cyphernet.rs b/radicle-crypto/src/cyphernet.rs new file mode 100644 index 00000000..3f2a6fa3 --- /dev/null +++ b/radicle-crypto/src/cyphernet.rs @@ -0,0 +1,89 @@ +use std::ops::Deref; + +use cyphernet::crypto::{Ec, EcPrivKey, EcPubKey, EcSig}; +use ed25519_compact::x25519; + +use crate::{PublicKey, SecretKey, Signature}; + +// Derivations required for automatic derivations of other types +#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)] +pub struct Ed25519; + +pub type SharedSecret = [u8; 32]; + +impl Ec for Ed25519 { + type PubKey = PublicKey; + type PrivKey = SecretKey; + type EcdhSecret = SharedSecret; + type EcdhErr = ed25519_compact::Error; +} + +impl EcPubKey for PublicKey { + type Raw = [u8; ed25519_compact::PublicKey::BYTES]; + + fn from_raw(raw: Self::Raw) -> Self { + PublicKey::from(raw) + } + + fn into_raw(self) -> Self::Raw { + *self.0.deref() + } + + fn ecdh(self, sk: &SecretKey) -> Result { + let xpk = x25519::PublicKey::from_ed25519(&self.0)?; + let xsk = x25519::SecretKey::from_ed25519(&sk.0)?; + let ss = xpk.dh(&xsk)?; + Ok(*ss) + } +} + +impl EcPrivKey for SecretKey { + type Raw = [u8; ed25519_compact::SecretKey::BYTES]; + + fn from_raw(raw: Self::Raw) -> Self { + SecretKey::from(raw) + } + + fn into_raw(self) -> Self::Raw { + *self.0.deref() + } + + fn to_raw(&self) -> Self::Raw { + *self.0.deref() + } + + fn as_raw(&self) -> &Self::Raw { + self.0.deref() + } + + fn to_public_key(&self) -> PublicKey { + self.0.public_key().into() + } + + fn ecdh(&self, pk: PublicKey) -> Result { + let xpk = x25519::PublicKey::from_ed25519(&pk.0)?; + let xsk = x25519::SecretKey::from_ed25519(&self.0)?; + let ss = xpk.dh(&xsk)?; + Ok(*ss) + } +} + +impl EcSig for Signature { + type Raw = [u8; ed25519_compact::Signature::BYTES]; + + fn from_raw(raw: Self::Raw) -> Self { + Signature::from(raw) + } + + fn into_raw(self) -> Self::Raw { + *self.0 + } + + fn sign(self, sk: SecretKey, msg: impl AsRef<[u8]>) -> Self { + sk.0.sign(msg, None).into() + } + + fn verify(self, pk: PublicKey, msg: impl AsRef<[u8]>) -> bool { + pk.0.verify(msg, &self.0).is_ok() + } +} diff --git a/radicle-crypto/src/lib.rs b/radicle-crypto/src/lib.rs index a1392f52..96f9aa5f 100644 --- a/radicle-crypto/src/lib.rs +++ b/radicle-crypto/src/lib.rs @@ -13,6 +13,11 @@ pub mod test; #[cfg(feature = "ssh")] pub mod ssh; +#[cfg(feature = "cyphernet")] +mod cyphernet; +#[cfg(feature = "cyphernet")] +pub use self::cyphernet::Ed25519; + /// Verified (used as type witness). #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct Verified;