mwc_libp2p_core/identity/
ed25519.rs

1// Copyright 2019 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21//! Ed25519 keys.
22
23use ed25519_dalek::{self as ed25519, Signer as _, Verifier as _};
24use rand::RngCore;
25use std::convert::TryFrom;
26use super::error::DecodingError;
27use zeroize::Zeroize;
28use core::fmt;
29
30/// An Ed25519 keypair.
31pub struct Keypair(ed25519::Keypair);
32
33impl Keypair {
34    /// Generate a new Ed25519 keypair.
35    pub fn generate() -> Keypair {
36        Keypair::from(SecretKey::generate())
37    }
38
39    pub fn from_secret( sk_bytes: impl AsMut<[u8]>) -> Result<Keypair, DecodingError> {
40        Ok( Keypair::from(SecretKey::from_bytes(sk_bytes)?) )
41    }
42
43    /// Encode the keypair into a byte array by concatenating the bytes
44    /// of the secret scalar and the compressed public point,
45    /// an informal standard for encoding Ed25519 keypairs.
46    pub fn encode(&self) -> [u8; 64] {
47        self.0.to_bytes()
48    }
49
50    /// Decode a keypair from the format produced by `encode`,
51    /// zeroing the input on success.
52    pub fn decode(kp: &mut [u8]) -> Result<Keypair, DecodingError> {
53        ed25519::Keypair::from_bytes(kp)
54            .map(|k| { kp.zeroize(); Keypair(k) })
55            .map_err(|e| DecodingError::new("Ed25519 keypair").source(e))
56    }
57
58    /// Sign a message using the private key of this keypair.
59    pub fn sign(&self, msg: &[u8]) -> Vec<u8> {
60        self.0.sign(msg).to_bytes().to_vec()
61    }
62
63    /// Get the public key of this keypair.
64    pub fn public(&self) -> PublicKey {
65        PublicKey(self.0.public)
66    }
67
68    /// Get the secret key of this keypair.
69    pub fn secret(&self) -> SecretKey {
70        SecretKey::from_bytes(&mut self.0.secret.to_bytes())
71            .expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
72    }
73}
74
75impl fmt::Debug for Keypair {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        f.debug_struct("Keypair").field("public", &self.0.public).finish()
78    }
79}
80
81impl Clone for Keypair {
82    fn clone(&self) -> Keypair {
83        let mut sk_bytes = self.0.secret.to_bytes();
84        let secret = SecretKey::from_bytes(&mut sk_bytes)
85            .expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k").0;
86        let public = ed25519::PublicKey::from_bytes(&self.0.public.to_bytes())
87            .expect("ed25519::PublicKey::from_bytes(to_bytes(k)) != k");
88        Keypair(ed25519::Keypair { secret, public })
89    }
90}
91
92/// Demote an Ed25519 keypair to a secret key.
93impl From<Keypair> for SecretKey {
94    fn from(kp: Keypair) -> SecretKey {
95        SecretKey(kp.0.secret)
96    }
97}
98
99/// Promote an Ed25519 secret key into a keypair.
100impl From<SecretKey> for Keypair {
101    fn from(sk: SecretKey) -> Keypair {
102        let secret: ed25519::ExpandedSecretKey = (&sk.0).into();
103        let public = ed25519::PublicKey::from(&secret);
104        Keypair(ed25519::Keypair { secret: sk.0, public })
105    }
106}
107
108/// An Ed25519 public key.
109#[derive(PartialEq, Eq, Debug, Clone)]
110pub struct PublicKey(pub ed25519::PublicKey);
111
112impl PublicKey {
113    /// Verify the Ed25519 signature on a message using the public key.
114    pub fn verify(&self, msg: &[u8], sig: &[u8]) -> bool {
115        ed25519::Signature::try_from(sig).and_then(|s| self.0.verify(msg, &s)).is_ok()
116    }
117
118    /// Encode the public key into a byte array in compressed form, i.e.
119    /// where one coordinate is represented by a single bit.
120    pub fn encode(&self) -> [u8; 32] {
121        self.0.to_bytes()
122    }
123
124    /// Decode a public key from a byte array as produced by `encode`.
125    pub fn decode(k: &[u8]) -> Result<PublicKey, DecodingError> {
126        ed25519::PublicKey::from_bytes(k)
127            .map_err(|e| DecodingError::new("Ed25519 public key").source(e))
128            .map(PublicKey)
129    }
130}
131
132/// An Ed25519 secret key.
133pub struct SecretKey(ed25519::SecretKey);
134
135/// View the bytes of the secret key.
136impl AsRef<[u8]> for SecretKey {
137    fn as_ref(&self) -> &[u8] {
138        self.0.as_bytes()
139    }
140}
141
142impl Clone for SecretKey {
143    fn clone(&self) -> SecretKey {
144        let mut sk_bytes = self.0.to_bytes();
145        Self::from_bytes(&mut sk_bytes)
146            .expect("ed25519::SecretKey::from_bytes(to_bytes(k)) != k")
147    }
148}
149
150impl fmt::Debug for SecretKey {
151    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152        write!(f, "SecretKey")
153    }
154}
155
156impl SecretKey {
157    /// Generate a new Ed25519 secret key.
158    pub fn generate() -> SecretKey {
159        let mut bytes = [0u8; 32];
160        rand::thread_rng().fill_bytes(&mut bytes);
161        SecretKey(ed25519::SecretKey::from_bytes(&bytes)
162            .expect("this returns `Err` only if the length is wrong; the length is correct; qed"))
163    }
164
165    /// Create an Ed25519 secret key from a byte slice, zeroing the input on success.
166    /// If the bytes do not constitute a valid Ed25519 secret key, an error is
167    /// returned.
168    pub fn from_bytes(mut sk_bytes: impl AsMut<[u8]>) -> Result<SecretKey, DecodingError> {
169        let sk_bytes = sk_bytes.as_mut();
170        let secret = ed25519::SecretKey::from_bytes(&*sk_bytes)
171            .map_err(|e| DecodingError::new("Ed25519 secret key").source(e))?;
172        sk_bytes.zeroize();
173        Ok(SecretKey(secret))
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use quickcheck::*;
181
182    fn eq_keypairs(kp1: &Keypair, kp2: &Keypair) -> bool {
183        kp1.public() == kp2.public()
184            &&
185        kp1.0.secret.as_bytes() == kp2.0.secret.as_bytes()
186    }
187
188    #[test]
189    fn ed25519_keypair_encode_decode() {
190        fn prop() -> bool {
191            let kp1 = Keypair::generate();
192            let mut kp1_enc = kp1.encode();
193            let kp2 = Keypair::decode(&mut kp1_enc).unwrap();
194            eq_keypairs(&kp1, &kp2)
195                &&
196            kp1_enc.iter().all(|b| *b == 0)
197        }
198        QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
199    }
200
201    #[test]
202    fn ed25519_keypair_from_secret() {
203        fn prop() -> bool {
204            let kp1 = Keypair::generate();
205            let mut sk = kp1.0.secret.to_bytes();
206            let kp2 = Keypair::from(SecretKey::from_bytes(&mut sk).unwrap());
207            eq_keypairs(&kp1, &kp2)
208                &&
209            sk == [0u8; 32]
210        }
211        QuickCheck::new().tests(10).quickcheck(prop as fn() -> _);
212    }
213
214    #[test]
215    fn ed25519_signature() {
216        let kp = Keypair::generate();
217        let pk = kp.public();
218
219        let msg = "hello world".as_bytes();
220        let sig = kp.sign(msg);
221        assert!(pk.verify(msg, &sig));
222
223        let mut invalid_sig = sig.clone();
224        invalid_sig[3..6].copy_from_slice(&[10, 23, 42]);
225        assert!(!pk.verify(msg, &invalid_sig));
226
227        let invalid_msg = "h3ll0 w0rld".as_bytes();
228        assert!(!pk.verify(invalid_msg, &sig));
229    }
230}