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 try_from_bytes(k: &[u8]) -> Result<PublicKey, ParseError> {
138 let k = <[u8; 32]>::try_from(k).map_err(|_| ParseError::InvalidPublicKey)?;
139
140 ed25519::VerifyingKey::from_bytes(&k)
143 .map_err(|_| ParseError::InvalidPublicKey)
144 .map(PublicKey)
145 }
146
147 pub fn to_peer_id(&self) -> PeerId {
149 crate::crypto::PublicKey::Ed25519(self.clone()).into()
150 }
151}
152
153#[derive(Clone)]
155pub struct SecretKey(ed25519::SecretKey);
156
157impl AsRef<[u8]> for SecretKey {
159 fn as_ref(&self) -> &[u8] {
160 &self.0[..]
161 }
162}
163
164impl fmt::Debug for SecretKey {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 write!(f, "SecretKey")
167 }
168}
169
170impl SecretKey {
171 pub fn generate() -> SecretKey {
173 let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng);
174 SecretKey(signing.to_bytes())
175 }
176 pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> crate::Result<SecretKey> {
181 let sk_bytes = sk_bytes.as_mut();
182 let secret = <[u8; 32]>::try_from(&*sk_bytes)
183 .map_err(|e| Error::Other(format!("Failed to parse ed25519 secret key: {e}")))?;
184 sk_bytes.zeroize();
185 Ok(SecretKey(secret))
186 }
187
188 pub fn to_bytes(&self) -> [u8; 32] {
190 self.0
191 }
192}
193
194#[cfg(test)]
195mod tests {
196 use super::*;
197 use quickcheck::*;
198
199 fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
200 kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes()
201 }
202
203 #[test]
204 fn ed25519_keypair_encode_decode() {
205 fn prop() -> bool {
206 let kp1 = Keypair::generate();
207 let mut kp1_enc = kp1.to_bytes();
208 let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap();
209 eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0)
210 }
211 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
212 }
213
214 #[test]
215 fn ed25519_keypair_from_secret() {
216 fn prop() -> bool {
217 let kp1 = Keypair::generate();
218 let mut sk = kp1.0.to_bytes();
219 let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap());
220 eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
221 }
222 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
223 }
224
225 #[test]
226 fn ed25519_signature() {
227 let kp = Keypair::generate();
228 let pk = kp.public();
229
230 let msg = "hello world".as_bytes();
231 let sig = kp.sign(msg);
232 assert!(pk.verify(msg, &sig));
233
234 let mut invalid_sig = sig.clone();
235 invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
236 assert!(!pk.verify(msg, &invalid_sig));
237
238 let invalid_msg = "h3ll0 w0rld".as_bytes();
239 assert!(!pk.verify(invalid_msg, &sig));
240 }
241
242 #[test]
243 fn secret_key() {
244 let _ = tracing_subscriber::fmt()
245 .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
246 .try_init();
247
248 let key = Keypair::generate();
249 tracing::trace!("keypair: {:?}", key);
250 tracing::trace!("secret: {:?}", key.secret());
251 tracing::trace!("public: {:?}", key.public());
252
253 let new_key = Keypair::from(key.secret());
254 assert_eq!(new_key.secret().as_ref(), key.secret().as_ref());
255 assert_eq!(new_key.public(), key.public());
256
257 let new_secret = SecretKey::from(new_key.clone());
258 assert_eq!(new_secret.as_ref(), new_key.secret().as_ref());
259
260 let cloned_secret = new_secret.clone();
261 assert_eq!(cloned_secret.as_ref(), new_secret.as_ref());
262 }
263}