libp2p_identity/
ed25519.rs1use super::error::DecodingError;
24use core::cmp;
25use core::fmt;
26use core::hash;
27use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
28use zeroize::Zeroize;
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> {
157 let k = <[u8; 32]>::try_from(k)
158 .map_err(|e| DecodingError::failed_to_parse("Ed25519 public key", e))?;
159 ed25519::VerifyingKey::from_bytes(&k)
160 .map_err(|e| DecodingError::failed_to_parse("Ed25519 public key", e))
161 .map(PublicKey)
162 }
163}
164
165#[derive(Clone)]
167pub struct SecretKey(ed25519::SecretKey);
168
169impl AsRef<[u8]> for SecretKey {
171 fn as_ref(&self) -> &[u8] {
172 &self.0[..]
173 }
174}
175
176impl fmt::Debug for SecretKey {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 write!(f, "SecretKey")
179 }
180}
181
182impl SecretKey {
183 #[cfg(feature = "rand")]
185 pub fn generate() -> SecretKey {
186 let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng);
187 SecretKey(signing.to_bytes())
188 }
189
190 pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
195 let sk_bytes = sk_bytes.as_mut();
196 let secret = <[u8; 32]>::try_from(&*sk_bytes)
197 .map_err(|e| DecodingError::failed_to_parse("Ed25519 secret key", e))?;
198 sk_bytes.zeroize();
199 Ok(SecretKey(secret))
200 }
201
202 pub(crate) fn to_bytes(&self) -> [u8; 32] {
203 self.0
204 }
205}
206
207#[cfg(test)]
208mod tests {
209 use super::*;
210 use quickcheck::*;
211
212 fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
213 kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes()
214 }
215
216 #[test]
217 #[cfg(feature = "rand")]
218 fn ed25519_keypair_encode_decode() {
219 fn prop() -> bool {
220 let kp1 = Keypair::generate();
221 let mut kp1_enc = kp1.to_bytes();
222 let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap();
223 eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0)
224 }
225 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
226 }
227
228 #[test]
229 #[cfg(feature = "rand")]
230 fn ed25519_keypair_from_secret() {
231 fn prop() -> bool {
232 let kp1 = Keypair::generate();
233 let mut sk = kp1.0.to_bytes();
234 let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap());
235 eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
236 }
237 QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
238 }
239
240 #[test]
241 #[cfg(feature = "rand")]
242 fn ed25519_signature() {
243 let kp = Keypair::generate();
244 let pk = kp.public();
245
246 let msg = "hello world".as_bytes();
247 let sig = kp.sign(msg);
248 assert!(pk.verify(msg, &sig));
249
250 let mut invalid_sig = sig.clone();
251 invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
252 assert!(!pk.verify(msg, &invalid_sig));
253
254 let invalid_msg = "h3ll0 w0rld".as_bytes();
255 assert!(!pk.verify(invalid_msg, &sig));
256 }
257}