referrerpolicy=no-referrer-when-downgrade

sc_network_types/
ed25519.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19//! Ed25519 keys.
20
21use crate::PeerId;
22use core::{cmp, fmt, hash};
23use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
24use libp2p_identity::ed25519 as libp2p_ed25519;
25use litep2p::crypto::ed25519 as litep2p_ed25519;
26use zeroize::Zeroize;
27
28/// An Ed25519 keypair.
29#[derive(Clone)]
30pub struct Keypair(ed25519::SigningKey);
31
32impl Keypair {
33	/// Generate a new random Ed25519 keypair.
34	pub fn generate() -> Keypair {
35		Keypair::from(SecretKey::generate())
36	}
37
38	/// Convert the keypair into a byte array by concatenating the bytes
39	/// of the secret scalar and the compressed public point,
40	/// an informal standard for encoding Ed25519 keypairs.
41	pub fn to_bytes(&self) -> [u8; 64] {
42		self.0.to_keypair_bytes()
43	}
44
45	/// Try to parse a keypair from the [binary format](https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.5)
46	/// produced by [`Keypair::to_bytes`], zeroing the input on success.
47	///
48	/// Note that this binary format is the same as `ed25519_dalek`'s and `ed25519_zebra`'s.
49	pub fn try_from_bytes(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
50		let bytes = <[u8; 64]>::try_from(&*kp)
51			.map_err(|e| DecodingError::KeypairParseError(Box::new(e)))?;
52
53		ed25519::SigningKey::from_keypair_bytes(&bytes)
54			.map(|k| {
55				kp.zeroize();
56				Keypair(k)
57			})
58			.map_err(|e| DecodingError::KeypairParseError(Box::new(e)))
59	}
60
61	/// Sign a message using the private key of this keypair.
62	pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
63		self.0.sign(msg).to_bytes().to_vec()
64	}
65
66	/// Get the public key of this keypair.
67	pub fn public(&self) -> PublicKey {
68		PublicKey(self.0.verifying_key())
69	}
70
71	/// Get the secret key of this keypair.
72	pub fn secret(&self) -> SecretKey {
73		SecretKey(self.0.to_bytes())
74	}
75}
76
77impl fmt::Debug for Keypair {
78	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79		f.debug_struct("Keypair").field("public", &self.0.verifying_key()).finish()
80	}
81}
82
83impl From<litep2p_ed25519::Keypair> for Keypair {
84	fn from(kp: litep2p_ed25519::Keypair) -> Self {
85		Self::try_from_bytes(&mut kp.to_bytes())
86			.expect("ed25519_dalek in substrate & litep2p to use the same format")
87	}
88}
89
90impl From<Keypair> for litep2p_ed25519::Keypair {
91	fn from(kp: Keypair) -> Self {
92		Self::try_from_bytes(&mut kp.to_bytes())
93			.expect("ed25519_dalek in substrate & litep2p to use the same format")
94	}
95}
96
97impl From<libp2p_ed25519::Keypair> for Keypair {
98	fn from(kp: libp2p_ed25519::Keypair) -> Self {
99		Self::try_from_bytes(&mut kp.to_bytes())
100			.expect("ed25519_dalek in substrate & libp2p to use the same format")
101	}
102}
103
104impl From<Keypair> for libp2p_ed25519::Keypair {
105	fn from(kp: Keypair) -> Self {
106		Self::try_from_bytes(&mut kp.to_bytes())
107			.expect("ed25519_dalek in substrate & libp2p to use the same format")
108	}
109}
110
111/// Demote an Ed25519 keypair to a secret key.
112impl From<Keypair> for SecretKey {
113	fn from(kp: Keypair) -> SecretKey {
114		SecretKey(kp.0.to_bytes())
115	}
116}
117
118/// Promote an Ed25519 secret key into a keypair.
119impl From<SecretKey> for Keypair {
120	fn from(sk: SecretKey) -> Keypair {
121		let signing = ed25519::SigningKey::from_bytes(&sk.0);
122		Keypair(signing)
123	}
124}
125
126/// An Ed25519 public key.
127#[derive(Eq, Clone)]
128pub struct PublicKey(ed25519::VerifyingKey);
129
130impl fmt::Debug for PublicKey {
131	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132		f.write_str("PublicKey(compressed): ")?;
133		for byte in self.0.as_bytes() {
134			write!(f, "{byte:x}")?;
135		}
136		Ok(())
137	}
138}
139
140impl cmp::PartialEq for PublicKey {
141	fn eq(&self, other: &Self) -> bool {
142		self.0.as_bytes().eq(other.0.as_bytes())
143	}
144}
145
146impl hash::Hash for PublicKey {
147	fn hash<H: hash::Hasher>(&self, state: &mut H) {
148		self.0.as_bytes().hash(state);
149	}
150}
151
152impl cmp::PartialOrd for PublicKey {
153	fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
154		Some(self.cmp(other))
155	}
156}
157
158impl cmp::Ord for PublicKey {
159	fn cmp(&self, other: &Self) -> cmp::Ordering {
160		self.0.as_bytes().cmp(other.0.as_bytes())
161	}
162}
163
164impl PublicKey {
165	/// Verify the Ed25519 signature on a message using the public key.
166	pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
167		ed25519::Signature::try_from(sig).and_then(|s| self.0.verify(msg, &s)).is_ok()
168	}
169
170	/// Convert the public key to a byte array in compressed form, i.e.
171	/// where one coordinate is represented by a single bit.
172	pub fn to_bytes(&self) -> [u8; 32] {
173		self.0.to_bytes()
174	}
175
176	/// Try to parse a public key from a byte array containing the actual key as produced by
177	/// `to_bytes`.
178	pub fn try_from_bytes(k: &[u8]) -> Result<PublicKey, DecodingError> {
179		let k =
180			<[u8; 32]>::try_from(k).map_err(|e| DecodingError::PublicKeyParseError(Box::new(e)))?;
181		ed25519::VerifyingKey::from_bytes(&k)
182			.map_err(|e| DecodingError::PublicKeyParseError(Box::new(e)))
183			.map(PublicKey)
184	}
185
186	/// Convert public key to `PeerId`.
187	pub fn to_peer_id(&self) -> PeerId {
188		litep2p::PeerId::from(litep2p::crypto::PublicKey::Ed25519(self.clone().into())).into()
189	}
190}
191
192impl From<litep2p_ed25519::PublicKey> for PublicKey {
193	fn from(k: litep2p_ed25519::PublicKey) -> Self {
194		Self::try_from_bytes(&k.to_bytes())
195			.expect("ed25519_dalek in substrate & litep2p to use the same format")
196	}
197}
198
199impl From<PublicKey> for litep2p_ed25519::PublicKey {
200	fn from(k: PublicKey) -> Self {
201		Self::try_from_bytes(&k.to_bytes())
202			.expect("ed25519_dalek in substrate & litep2p to use the same format")
203	}
204}
205
206impl From<libp2p_ed25519::PublicKey> for PublicKey {
207	fn from(k: libp2p_ed25519::PublicKey) -> Self {
208		Self::try_from_bytes(&k.to_bytes())
209			.expect("ed25519_dalek in substrate & libp2p to use the same format")
210	}
211}
212
213impl From<PublicKey> for libp2p_ed25519::PublicKey {
214	fn from(k: PublicKey) -> Self {
215		Self::try_from_bytes(&k.to_bytes())
216			.expect("ed25519_dalek in substrate & libp2p to use the same format")
217	}
218}
219
220/// An Ed25519 secret key.
221#[derive(Clone)]
222pub struct SecretKey(ed25519::SecretKey);
223
224/// View the bytes of the secret key.
225impl AsRef<[u8]> for SecretKey {
226	fn as_ref(&self) -> &[u8] {
227		&self.0[..]
228	}
229}
230
231impl fmt::Debug for SecretKey {
232	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233		write!(f, "SecretKey")
234	}
235}
236
237impl SecretKey {
238	/// Generate a new Ed25519 secret key.
239	pub fn generate() -> SecretKey {
240		let signing = ed25519::SigningKey::generate(&mut rand::rngs::OsRng);
241		SecretKey(signing.to_bytes())
242	}
243
244	/// Try to parse an Ed25519 secret key from a byte slice
245	/// containing the actual key, zeroing the input on success.
246	/// If the bytes do not constitute a valid Ed25519 secret key, an error is
247	/// returned.
248	pub fn try_from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
249		let sk_bytes = sk_bytes.as_mut();
250		let secret = <[u8; 32]>::try_from(&*sk_bytes)
251			.map_err(|e| DecodingError::SecretKeyParseError(Box::new(e)))?;
252		sk_bytes.zeroize();
253		Ok(SecretKey(secret))
254	}
255
256	pub fn to_bytes(&self) -> [u8; 32] {
257		self.0
258	}
259}
260
261impl Drop for SecretKey {
262	fn drop(&mut self) {
263		self.0.zeroize();
264	}
265}
266
267impl From<litep2p_ed25519::SecretKey> for SecretKey {
268	fn from(sk: litep2p_ed25519::SecretKey) -> Self {
269		Self::try_from_bytes(&mut sk.to_bytes()).expect("Ed25519 key to be 32 bytes length")
270	}
271}
272
273impl From<SecretKey> for litep2p_ed25519::SecretKey {
274	fn from(sk: SecretKey) -> Self {
275		Self::try_from_bytes(&mut sk.to_bytes())
276			.expect("litep2p `SecretKey` to accept 32 bytes as Ed25519 key")
277	}
278}
279
280impl From<libp2p_ed25519::SecretKey> for SecretKey {
281	fn from(sk: libp2p_ed25519::SecretKey) -> Self {
282		Self::try_from_bytes(&mut sk.as_ref().to_owned())
283			.expect("Ed25519 key to be 32 bytes length")
284	}
285}
286
287impl From<SecretKey> for libp2p_ed25519::SecretKey {
288	fn from(sk: SecretKey) -> Self {
289		Self::try_from_bytes(&mut sk.to_bytes())
290			.expect("libp2p `SecretKey` to accept 32 bytes as Ed25519 key")
291	}
292}
293
294/// Error when decoding `ed25519`-related types.
295#[derive(Debug, thiserror::Error)]
296pub enum DecodingError {
297	#[error("failed to parse Ed25519 keypair: {0}")]
298	KeypairParseError(Box<dyn std::error::Error + Send + Sync>),
299	#[error("failed to parse Ed25519 secret key: {0}")]
300	SecretKeyParseError(Box<dyn std::error::Error + Send + Sync>),
301	#[error("failed to parse Ed25519 public key: {0}")]
302	PublicKeyParseError(Box<dyn std::error::Error + Send + Sync>),
303}
304
305#[cfg(test)]
306mod tests {
307	use super::*;
308	use quickcheck::*;
309
310	fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
311		kp1.public() == kp2.public() && kp1.0.to_bytes() == kp2.0.to_bytes()
312	}
313
314	#[test]
315	fn ed25519_keypair_encode_decode() {
316		fn prop() -> bool {
317			let kp1 = Keypair::generate();
318			let mut kp1_enc = kp1.to_bytes();
319			let kp2 = Keypair::try_from_bytes(&mut kp1_enc).unwrap();
320			eq_keypairs(&kp1, &kp2) && kp1_enc.iter().all(|b| *b == 0)
321		}
322		QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
323	}
324
325	#[test]
326	fn ed25519_keypair_from_secret() {
327		fn prop() -> bool {
328			let kp1 = Keypair::generate();
329			let mut sk = kp1.0.to_bytes();
330			let kp2 = Keypair::from(SecretKey::try_from_bytes(&mut sk).unwrap());
331			eq_keypairs(&kp1, &kp2) && sk == [0u8; 32]
332		}
333		QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
334	}
335
336	#[test]
337	fn ed25519_signature() {
338		let kp = Keypair::generate();
339		let pk = kp.public();
340
341		let msg = "hello world".as_bytes();
342		let sig = kp.sign(msg);
343		assert!(pk.verify(msg, &sig));
344
345		let mut invalid_sig = sig.clone();
346		invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
347		assert!(!pk.verify(msg, &invalid_sig));
348
349		let invalid_msg = "h3ll0 w0rld".as_bytes();
350		assert!(!pk.verify(invalid_msg, &sig));
351	}
352
353	#[test]
354	fn substrate_kp_to_libs() {
355		let kp = Keypair::generate();
356		let kp_bytes = kp.to_bytes();
357		let kp1: libp2p_ed25519::Keypair = kp.clone().into();
358		let kp2: litep2p_ed25519::Keypair = kp.clone().into();
359		let kp3 = libp2p_ed25519::Keypair::try_from_bytes(&mut kp_bytes.clone()).unwrap();
360		let kp4 = litep2p_ed25519::Keypair::try_from_bytes(&mut kp_bytes.clone()).unwrap();
361
362		assert_eq!(kp_bytes, kp1.to_bytes());
363		assert_eq!(kp_bytes, kp2.to_bytes());
364
365		let msg = "hello world".as_bytes();
366		let sig = kp.sign(msg);
367		let sig1 = kp1.sign(msg);
368		let sig2 = kp2.sign(msg);
369		let sig3 = kp3.sign(msg);
370		let sig4 = kp4.sign(msg);
371
372		assert_eq!(sig, sig1);
373		assert_eq!(sig, sig2);
374		assert_eq!(sig, sig3);
375		assert_eq!(sig, sig4);
376
377		let pk1 = kp1.public();
378		let pk2 = kp2.public();
379		let pk3 = kp3.public();
380		let pk4 = kp4.public();
381
382		assert!(pk1.verify(msg, &sig));
383		assert!(pk2.verify(msg, &sig));
384		assert!(pk3.verify(msg, &sig));
385		assert!(pk4.verify(msg, &sig));
386	}
387
388	#[test]
389	fn litep2p_kp_to_substrate_kp() {
390		let kp = litep2p_ed25519::Keypair::generate();
391		let kp1: Keypair = kp.clone().into();
392		let kp2 = Keypair::try_from_bytes(&mut kp.to_bytes()).unwrap();
393
394		assert_eq!(kp.to_bytes(), kp1.to_bytes());
395
396		let msg = "hello world".as_bytes();
397		let sig = kp.sign(msg);
398		let sig1 = kp1.sign(msg);
399		let sig2 = kp2.sign(msg);
400
401		assert_eq!(sig, sig1);
402		assert_eq!(sig, sig2);
403
404		let pk1 = kp1.public();
405		let pk2 = kp2.public();
406
407		assert!(pk1.verify(msg, &sig));
408		assert!(pk2.verify(msg, &sig));
409	}
410
411	#[test]
412	fn libp2p_kp_to_substrate_kp() {
413		let kp = libp2p_ed25519::Keypair::generate();
414		let kp1: Keypair = kp.clone().into();
415		let kp2 = Keypair::try_from_bytes(&mut kp.to_bytes()).unwrap();
416
417		assert_eq!(kp.to_bytes(), kp1.to_bytes());
418
419		let msg = "hello world".as_bytes();
420		let sig = kp.sign(msg);
421		let sig1 = kp1.sign(msg);
422		let sig2 = kp2.sign(msg);
423
424		assert_eq!(sig, sig1);
425		assert_eq!(sig, sig2);
426
427		let pk1 = kp1.public();
428		let pk2 = kp2.public();
429
430		assert!(pk1.verify(msg, &sig));
431		assert!(pk2.verify(msg, &sig));
432	}
433
434	#[test]
435	fn substrate_pk_to_libs() {
436		let kp = Keypair::generate();
437		let pk = kp.public();
438		let pk_bytes = pk.to_bytes();
439		let pk1: libp2p_ed25519::PublicKey = pk.clone().into();
440		let pk2: litep2p_ed25519::PublicKey = pk.clone().into();
441		let pk3 = libp2p_ed25519::PublicKey::try_from_bytes(&pk_bytes).unwrap();
442		let pk4 = litep2p_ed25519::PublicKey::try_from_bytes(&pk_bytes).unwrap();
443
444		assert_eq!(pk_bytes, pk1.to_bytes());
445		assert_eq!(pk_bytes, pk2.to_bytes());
446
447		let msg = "hello world".as_bytes();
448		let sig = kp.sign(msg);
449
450		assert!(pk.verify(msg, &sig));
451		assert!(pk1.verify(msg, &sig));
452		assert!(pk2.verify(msg, &sig));
453		assert!(pk3.verify(msg, &sig));
454		assert!(pk4.verify(msg, &sig));
455	}
456
457	#[test]
458	fn litep2p_pk_to_substrate_pk() {
459		let kp = litep2p_ed25519::Keypair::generate();
460		let pk = kp.public();
461		let pk_bytes = pk.clone().to_bytes();
462		let pk1: PublicKey = pk.clone().into();
463		let pk2 = PublicKey::try_from_bytes(&pk_bytes).unwrap();
464
465		assert_eq!(pk_bytes, pk1.to_bytes());
466
467		let msg = "hello world".as_bytes();
468		let sig = kp.sign(msg);
469
470		assert!(pk.verify(msg, &sig));
471		assert!(pk1.verify(msg, &sig));
472		assert!(pk2.verify(msg, &sig));
473	}
474
475	#[test]
476	fn libp2p_pk_to_substrate_pk() {
477		let kp = libp2p_ed25519::Keypair::generate();
478		let pk = kp.public();
479		let pk_bytes = pk.clone().to_bytes();
480		let pk1: PublicKey = pk.clone().into();
481		let pk2 = PublicKey::try_from_bytes(&pk_bytes).unwrap();
482
483		assert_eq!(pk_bytes, pk1.to_bytes());
484
485		let msg = "hello world".as_bytes();
486		let sig = kp.sign(msg);
487
488		assert!(pk.verify(msg, &sig));
489		assert!(pk1.verify(msg, &sig));
490		assert!(pk2.verify(msg, &sig));
491	}
492
493	#[test]
494	fn substrate_sk_to_libs() {
495		let sk = SecretKey::generate();
496		let sk_bytes = sk.to_bytes();
497		let sk1: libp2p_ed25519::SecretKey = sk.clone().into();
498		let sk2: litep2p_ed25519::SecretKey = sk.clone().into();
499		let sk3 = libp2p_ed25519::SecretKey::try_from_bytes(&mut sk_bytes.clone()).unwrap();
500		let sk4 = litep2p_ed25519::SecretKey::try_from_bytes(&mut sk_bytes.clone()).unwrap();
501
502		let kp: Keypair = sk.into();
503		let kp1: libp2p_ed25519::Keypair = sk1.into();
504		let kp2: litep2p_ed25519::Keypair = sk2.into();
505		let kp3: libp2p_ed25519::Keypair = sk3.into();
506		let kp4: litep2p_ed25519::Keypair = sk4.into();
507
508		let msg = "hello world".as_bytes();
509		let sig = kp.sign(msg);
510
511		assert_eq!(sig, kp1.sign(msg));
512		assert_eq!(sig, kp2.sign(msg));
513		assert_eq!(sig, kp3.sign(msg));
514		assert_eq!(sig, kp4.sign(msg));
515	}
516
517	#[test]
518	fn litep2p_sk_to_substrate_sk() {
519		let sk = litep2p_ed25519::SecretKey::generate();
520		let sk1: SecretKey = sk.clone().into();
521		let sk2 = SecretKey::try_from_bytes(&mut sk.to_bytes()).unwrap();
522
523		let kp: litep2p_ed25519::Keypair = sk.into();
524		let kp1: Keypair = sk1.into();
525		let kp2: Keypair = sk2.into();
526
527		let msg = "hello world".as_bytes();
528		let sig = kp.sign(msg);
529
530		assert_eq!(sig, kp1.sign(msg));
531		assert_eq!(sig, kp2.sign(msg));
532	}
533
534	#[test]
535	fn libp2p_sk_to_substrate_sk() {
536		let sk = libp2p_ed25519::SecretKey::generate();
537		let sk_bytes = sk.as_ref().to_owned();
538		let sk1: SecretKey = sk.clone().into();
539		let sk2 = SecretKey::try_from_bytes(sk_bytes).unwrap();
540
541		let kp: libp2p_ed25519::Keypair = sk.into();
542		let kp1: Keypair = sk1.into();
543		let kp2: Keypair = sk2.into();
544
545		let msg = "hello world".as_bytes();
546		let sig = kp.sign(msg);
547
548		assert_eq!(sig, kp1.sign(msg));
549		assert_eq!(sig, kp2.sign(msg));
550	}
551}