litep2p/crypto/
ed25519.rs1use crate::{
25 error::{Error, ParseError},
26 PeerId,
27};
28
29use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
30use std::fmt;
31use zeroize::Zeroize;
32
33#[derive(Clone)]
35pub struct Keypair(ed25519::SigningKey);
36
37impl Keypair {
38 pub fn generate() -> Keypair {
40 Keypair::from(SecretKey::generate())
41 }
42
43 pub fn to_bytes(&self) -> [u8; 64] {
47 self.0.to_keypair_bytes()
48 }
49
50 pub fn try_from_bytes(kp: &mut [u8]) -> Result<Keypair, Error> {
55 let bytes = <[u8; 64]>::try_from(&*kp)
56 .map_err(|e| Error::Other(format!("Failed to parse ed25519 keypair: {e}")))?;
57
58 ed25519::SigningKey::from_keypair_bytes(&bytes)
59 .map(|k| {
60 kp.zeroize();
61 Keypair(k)
62 })
63 .map_err(|e| Error::Other(format!("Failed to parse ed25519 keypair: {e}")))
64 }
65
66 pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
68 self.0.sign(msg).to_bytes().to_vec()
69 }
70
71 pub fn public(&self) -> PublicKey {
73 PublicKey(self.0.verifying_key())
74 }
75
76 pub fn secret(&self) -> SecretKey {
78 SecretKey(self.0.to_bytes())
79 }
80}
81
82impl fmt::Debug for Keypair {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.debug_struct("Keypair").field("public", &self.0.verifying_key()).finish()
85 }
86}
87
88impl From<Keypair> for SecretKey {
90 fn from(kp: Keypair) -> SecretKey {
91 SecretKey(kp.0.to_bytes())
92 }
93}
94
95impl From<SecretKey> for Keypair {
97 fn from(sk: SecretKey) -> Keypair {
98 let signing = ed25519::SigningKey::from_bytes(&sk.0);
99 Keypair(signing)
100 }
101}
102
103#[derive(Eq, Clone)]
105pub struct PublicKey(ed25519::VerifyingKey);
106
107impl fmt::Debug for PublicKey {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 f.write_str("PublicKey(compressed): ")?;
110 for byte in self.0.as_bytes() {
111 write!(f, "{byte:x}")?;
112 }
113 Ok(())
114 }
115}
116
117impl PartialEq for PublicKey {
118 fn eq(&self, other: &Self) -> bool {
119 self.0.as_bytes().eq(other.0.as_bytes())
120 }
121}
122
123impl PublicKey {
124 pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
126 ed25519::Signature::try_from(sig).and_then(|s| self.0.verify(msg, &s)).is_ok()
127 }
128
129 pub fn to_bytes(&self) -> [u8; 32] {
132 self.0.to_bytes()
133 }
134
135 pub fn as_bytes(&self) -> &[u8] {
137 self.0.as_bytes()
138 }
139
140 pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, ParseError> {
143 let k = <[u8; 32]>::try_from(k).map_err(|_| ParseError::InvalidPublicKey)?;
144
145 ed25519::VerifyingKey::from_bytes(&k)
148 .map_err(|_| ParseError::InvalidPublicKey)
149 .map(PublicKey)
150 }
151
152 pub fn to_peer_id(&self) -> PeerId {
154 crate::crypto::PublicKey::Ed25519(self.clone()).into()
155 }
156}
157
158#[derive(Clone)]
160pub struct SecretKey(ed25519::SecretKey);
161
162impl AsRef<[u8]> for SecretKey {
164 fn as_ref(&self) -> &[u8] {
165 &self.0[..]
166 }
167}
168
169impl fmt::Debug for SecretKey {
170 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
171 write!(f, "SecretKey")
172 }
173}
174
175impl SecretKey {
176 pub fn generate() -> SecretKey {
178 let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng);
179 SecretKey(signing.to_bytes())
180 }
181 pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> crate::Result<SecretKey> {
186 let sk_bytes = sk_bytes.as_mut();
187 let secret = <[u8; 32]>::try_from(&*sk_bytes)
188 .map_err(|e| Error::Other(format!("Failed to parse ed25519 secret key: {e}")))?;
189 sk_bytes.zeroize();
190 Ok(SecretKey(secret))
191 }
192
193 pub fn to_bytes(&self) -> [u8; 32] {
195 self.0
196 }
197}
198
199#[cfg(test)]
200mod tests {
201 use super::*;
202 use quickcheck::*;
203
204 fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
205 kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes()
206 }
207
208 #[test]
209 fn ed25519_keypair_encode_decode() {
210 fn prop() -> bool {
211 let kp1 = Keypair::generate();
212 let mut kp1_enc = kp1.to_bytes();
213 let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap();
214 eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0)
215 }
216 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
217 }
218
219 #[test]
220 fn ed25519_keypair_from_secret() {
221 fn prop() -> bool {
222 let kp1 = Keypair::generate();
223 let mut sk = kp1.0.to_bytes();
224 let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap());
225 eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
226 }
227 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
228 }
229
230 #[test]
231 fn ed25519_signature() {
232 let kp = Keypair::generate();
233 let pk = kp.public();
234
235 let msg = "hello world".as_bytes();
236 let sig = kp.sign(msg);
237 assert!(pk.verify(msg, &sig));
238
239 let mut invalid_sig = sig.clone();
240 invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
241 assert!(!pk.verify(msg, &invalid_sig));
242
243 let invalid_msg = "h3ll0 w0rld".as_bytes();
244 assert!(!pk.verify(invalid_msg, &sig));
245 }
246
247 #[test]
248 fn secret_key() {
249 let _ = tracing_subscriber::fmt()
250 .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
251 .try_init();
252
253 let key = Keypair::generate();
254 tracing::trace!("keypair: {:?}", key);
255 tracing::trace!("secret: {:?}", key.secret());
256 tracing::trace!("public: {:?}", key.public());
257
258 let new_key = Keypair::from(key.secret());
259 assert_eq!(new_key.secret().as_ref(), key.secret().as_ref());
260 assert_eq!(new_key.public(), key.public());
261
262 let new_secret = SecretKey::from(new_key.clone());
263 assert_eq!(new_secret.as_ref(), new_key.secret().as_ref());
264
265 let cloned_secret = new_secret.clone();
266 assert_eq!(cloned_secret.as_ref(), new_secret.as_ref());
267 }
268}