libp2p_identity/
ed25519.rs1use core::{cmp, fmt, hash};
24
25use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
26use zeroize::Zeroize;
27
28use super::error::DecodingError;
29
30#[derive(Clone)]
32pub struct Keypair(ed25519::SigningKey);
33
34impl Keypair {
35 #[cfg(feature = "rand")]
37 pub fn generate() -> Keypair {
38 Keypair::from(SecretKey::generate())
39 }
40
41 pub fn to_bytes(&self) -> [u8; 64] {
45 self.0.to_keypair_bytes()
46 }
47
48 pub fn try_from_bytes(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
53 let bytes = <[u8; 64]>::try_from(&*kp)
54 .map_err(|e| DecodingError::failed_to_parse("Ed25519 keypair", e))?;
55
56 ed25519::SigningKey::from_keypair_bytes(&bytes)
57 .map(|k| {
58 kp.zeroize();
59 Keypair(k)
60 })
61 .map_err(|e| DecodingError::failed_to_parse("Ed25519 keypair", e))
62 }
63
64 pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
66 self.0.sign(msg).to_bytes().to_vec()
67 }
68
69 pub fn public(&self) -> PublicKey {
71 PublicKey(self.0.verifying_key())
72 }
73
74 pub fn secret(&self) -> SecretKey {
76 SecretKey(self.0.to_bytes())
77 }
78}
79
80impl fmt::Debug for Keypair {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.debug_struct("Keypair")
83 .field("public", &self.0.verifying_key())
84 .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 cmp::PartialEq for PublicKey {
118 fn eq(&self, other: &Self) -> bool {
119 self.0.as_bytes().eq(other.0.as_bytes())
120 }
121}
122
123impl hash::Hash for PublicKey {
124 fn hash<H: hash::Hasher>(&self, state: &mut H) {
125 self.0.as_bytes().hash(state);
126 }
127}
128
129impl cmp::PartialOrd for PublicKey {
130 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
131 Some(self.cmp(other))
132 }
133}
134
135impl cmp::Ord for PublicKey {
136 fn cmp(&self, other: &Self) -> cmp::Ordering {
137 self.0.as_bytes().cmp(other.0.as_bytes())
138 }
139}
140
141impl PublicKey {
142 pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
144 ed25519::Signature::try_from(sig)
145 .and_then(|s| self.0.verify(msg, &s))
146 .is_ok()
147 }
148
149 pub fn to_bytes(&self) -> [u8; 32] {
152 self.0.to_bytes()
153 }
154
155 pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
158 let k = <[u8; 32]>::try_from(k)
159 .map_err(|e| DecodingError::failed_to_parse("Ed25519 public key", e))?;
160 ed25519::VerifyingKey::from_bytes(&k)
161 .map_err(|e| DecodingError::failed_to_parse("Ed25519 public key", e))
162 .map(PublicKey)
163 }
164}
165
166#[derive(Clone)]
168pub struct SecretKey(ed25519::SecretKey);
169
170impl AsRef<[u8]> for SecretKey {
172 fn as_ref(&self) -> &[u8] {
173 &self.0[..]
174 }
175}
176
177impl fmt::Debug for SecretKey {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 write!(f, "SecretKey")
180 }
181}
182
183impl SecretKey {
184 #[cfg(feature = "rand")]
186 pub fn generate() -> SecretKey {
187 let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng);
188 SecretKey(signing.to_bytes())
189 }
190
191 pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
196 let sk_bytes = sk_bytes.as_mut();
197 let secret = <[u8; 32]>::try_from(&*sk_bytes)
198 .map_err(|e| DecodingError::failed_to_parse("Ed25519 secret key", e))?;
199 sk_bytes.zeroize();
200 Ok(SecretKey(secret))
201 }
202
203 pub(crate) fn to_bytes(&self) -> [u8; 32] {
204 self.0
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use quickcheck::*;
211
212 use super::*;
213
214 fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
215 kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes()
216 }
217
218 #[test]
219 #[cfg(feature = "rand")]
220 fn ed25519_keypair_encode_decode() {
221 fn prop() -> bool {
222 let kp1 = Keypair::generate();
223 let mut kp1_enc = kp1.to_bytes();
224 let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap();
225 eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0)
226 }
227 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
228 }
229
230 #[test]
231 #[cfg(feature = "rand")]
232 fn ed25519_keypair_from_secret() {
233 fn prop() -> bool {
234 let kp1 = Keypair::generate();
235 let mut sk = kp1.0.to_bytes();
236 let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap());
237 eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
238 }
239 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
240 }
241
242 #[test]
243 #[cfg(feature = "rand")]
244 fn ed25519_signature() {
245 let kp = Keypair::generate();
246 let pk = kp.public();
247
248 let msg = "hello world".as_bytes();
249 let sig = kp.sign(msg);
250 assert!(pk.verify(msg, &sig));
251
252 let mut invalid_sig = sig.clone();
253 invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
254 assert!(!pk.verify(msg, &invalid_sig));
255
256 let invalid_msg = "h3ll0 w0rld".as_bytes();
257 assert!(!pk.verify(invalid_msg, &sig));
258 }
259}