libp2prs_core/identity/
ed25519.rs

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