safe_nd/keys/
mod.rs

1// Copyright 2019 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
4// https://opensource.org/licenses/MIT> or the Modified BSD license <LICENSE-BSD
5// https://opensource.org/licenses/BSD-3-Clause>, at your option. This file may not be copied,
6// modified, or distributed except according to those terms. Please review the Licences for the
7// specific language governing permissions and limitations relating to use of the SAFE Network
8// Software.
9
10//! Module providing keys, keypairs, and signatures.
11//!
12//! The easiest way to get a `PublicKey` is to create a random `Keypair` first through one of the
13//! `new` functions. A `PublicKey` can't be generated by itself; it must always be derived from a
14//! secret key.
15
16mod proof;
17
18use crate::{utils, Error, Result};
19use hex_fmt::HexFmt;
20pub use proof::{BlsProof, BlsProofShare, Ed25519Proof, Proof, Proven};
21use rand::{CryptoRng, Rng};
22use serde::{Deserialize, Serialize};
23use signature::{Signer, Verifier};
24use std::{
25    cmp::Ordering,
26    fmt::{self, Debug, Display, Formatter},
27    hash::{Hash, Hasher},
28};
29use threshold_crypto::{self, serde_impl::SerdeSecret};
30use unwrap::unwrap;
31use xor_name::{XorName, XOR_NAME_LEN};
32
33/// Wrapper for different public key types.
34#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
35pub enum PublicKey {
36    /// Ed25519 public key.
37    Ed25519(ed25519_dalek::PublicKey),
38    /// BLS public key.
39    Bls(threshold_crypto::PublicKey),
40    /// BLS public key share.
41    BlsShare(threshold_crypto::PublicKeyShare),
42}
43
44impl PublicKey {
45    /// Returns the ed25519 key, if applicable.
46    pub fn ed25519(&self) -> Option<ed25519_dalek::PublicKey> {
47        if let Self::Ed25519(key) = self {
48            Some(*key)
49        } else {
50            None
51        }
52    }
53
54    /// Returns the BLS key, if applicable.
55    pub fn bls(&self) -> Option<threshold_crypto::PublicKey> {
56        if let Self::Bls(key) = self {
57            Some(*key)
58        } else {
59            None
60        }
61    }
62
63    /// Returns the BLS key share, if applicable.
64    pub fn bls_share(&self) -> Option<threshold_crypto::PublicKeyShare> {
65        if let Self::BlsShare(key) = self {
66            Some(*key)
67        } else {
68            None
69        }
70    }
71
72    /// Returns `Ok(())` if `signature` matches the message and `Err(Error::InvalidSignature)`
73    /// otherwise.
74    pub fn verify<T: AsRef<[u8]>>(&self, signature: &Signature, data: T) -> Result<()> {
75        let is_valid = match (self, signature) {
76            (Self::Ed25519(pub_key), Signature::Ed25519(sig)) => {
77                pub_key.verify(data.as_ref(), sig).is_ok()
78            }
79            (Self::Bls(pub_key), Signature::Bls(sig)) => pub_key.verify(sig, data),
80            (Self::BlsShare(pub_key), Signature::BlsShare(sig)) => pub_key.verify(&sig.share, data),
81            _ => return Err(Error::SigningKeyTypeMismatch),
82        };
83        if is_valid {
84            Ok(())
85        } else {
86            Err(Error::InvalidSignature)
87        }
88    }
89
90    /// Returns the `PublicKey` serialised and encoded in z-base-32.
91    pub fn encode_to_zbase32(&self) -> String {
92        utils::encode(&self)
93    }
94
95    /// Creates from z-base-32 encoded string.
96    pub fn decode_from_zbase32<I: AsRef<str>>(encoded: I) -> Result<Self> {
97        utils::decode(encoded)
98    }
99}
100
101#[allow(clippy::derive_hash_xor_eq)]
102impl Hash for PublicKey {
103    fn hash<H: Hasher>(&self, state: &mut H) {
104        utils::serialise(&self).hash(state)
105    }
106}
107
108impl Ord for PublicKey {
109    fn cmp(&self, other: &PublicKey) -> Ordering {
110        utils::serialise(&self).cmp(&utils::serialise(other))
111    }
112}
113
114impl PartialOrd for PublicKey {
115    fn partial_cmp(&self, other: &PublicKey) -> Option<Ordering> {
116        Some(self.cmp(other))
117    }
118}
119
120impl From<PublicKey> for XorName {
121    fn from(public_key: PublicKey) -> Self {
122        let bytes = match public_key {
123            PublicKey::Ed25519(pub_key) => {
124                return XorName(pub_key.to_bytes());
125            }
126            PublicKey::Bls(pub_key) => pub_key.to_bytes(),
127            PublicKey::BlsShare(pub_key) => pub_key.to_bytes(),
128        };
129        let mut xor_name = XorName::random();
130        xor_name.0.clone_from_slice(&bytes[..XOR_NAME_LEN]);
131        xor_name
132    }
133}
134
135impl From<ed25519_dalek::PublicKey> for PublicKey {
136    fn from(public_key: ed25519_dalek::PublicKey) -> Self {
137        Self::Ed25519(public_key)
138    }
139}
140
141impl From<threshold_crypto::PublicKey> for PublicKey {
142    fn from(public_key: threshold_crypto::PublicKey) -> Self {
143        Self::Bls(public_key)
144    }
145}
146
147impl From<threshold_crypto::PublicKeyShare> for PublicKey {
148    fn from(public_key: threshold_crypto::PublicKeyShare) -> Self {
149        Self::BlsShare(public_key)
150    }
151}
152
153impl From<&Keypair> for PublicKey {
154    fn from(keypair: &Keypair) -> Self {
155        keypair.public_key()
156    }
157}
158
159impl Debug for PublicKey {
160    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
161        write!(formatter, "PublicKey::")?;
162        match self {
163            Self::Ed25519(pub_key) => {
164                write!(formatter, "Ed25519({:<8})", HexFmt(&pub_key.to_bytes()))
165            }
166            Self::Bls(pub_key) => write!(
167                formatter,
168                "Bls({:<8})",
169                HexFmt(&pub_key.to_bytes()[..XOR_NAME_LEN])
170            ),
171            Self::BlsShare(pub_key) => write!(
172                formatter,
173                "BlsShare({:<8})",
174                HexFmt(&pub_key.to_bytes()[..XOR_NAME_LEN])
175            ),
176        }
177    }
178}
179
180impl Display for PublicKey {
181    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
182        Debug::fmt(self, formatter)
183    }
184}
185
186/// A signature share, with its index in the combined collection.
187#[derive(Clone, Hash, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
188pub struct SignatureShare {
189    /// Index in the combined collection.
190    pub index: usize,
191    /// Signature over some data.
192    pub share: threshold_crypto::SignatureShare,
193}
194
195/// Wrapper for different signature types.
196#[derive(Clone, Eq, PartialEq, Serialize, Deserialize)]
197#[allow(clippy::large_enum_variant)]
198pub enum Signature {
199    /// Ed25519 signature.
200    Ed25519(ed25519_dalek::Signature),
201    /// BLS signature.
202    Bls(threshold_crypto::Signature),
203    /// BLS signature share.
204    BlsShare(SignatureShare),
205}
206
207impl Signature {
208    /// Returns threshold_crypto::Signature if Self is a BLS variant.
209    pub fn into_bls(self) -> Option<threshold_crypto::Signature> {
210        match self {
211            Self::Bls(sig) => Some(sig),
212            _ => None,
213        }
214    }
215}
216
217impl From<threshold_crypto::Signature> for Signature {
218    fn from(sig: threshold_crypto::Signature) -> Self {
219        Self::Bls(sig)
220    }
221}
222
223impl From<ed25519_dalek::Signature> for Signature {
224    fn from(sig: ed25519_dalek::Signature) -> Self {
225        Self::Ed25519(sig)
226    }
227}
228
229impl From<SignatureShare> for Signature {
230    fn from(sig: SignatureShare) -> Self {
231        Self::BlsShare(sig)
232    }
233}
234
235impl From<(usize, threshold_crypto::SignatureShare)> for Signature {
236    fn from(sig: (usize, threshold_crypto::SignatureShare)) -> Self {
237        let (index, share) = sig;
238        Self::BlsShare(SignatureShare { index, share })
239    }
240}
241
242#[allow(clippy::derive_hash_xor_eq)]
243impl Hash for Signature {
244    fn hash<H: Hasher>(&self, state: &mut H) {
245        utils::serialise(&self).hash(state)
246    }
247}
248
249impl Ord for Signature {
250    fn cmp(&self, other: &Signature) -> Ordering {
251        utils::serialise(&self).cmp(&utils::serialise(other))
252    }
253}
254
255impl PartialOrd for Signature {
256    fn partial_cmp(&self, other: &Signature) -> Option<Ordering> {
257        Some(self.cmp(other))
258    }
259}
260
261impl Debug for Signature {
262    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
263        write!(formatter, "Signature::")?;
264        match self {
265            Self::Ed25519(_) => write!(formatter, "Ed25519(..)"),
266            Self::Bls(_) => write!(formatter, "Bls(..)"),
267            Self::BlsShare(_) => write!(formatter, "BlsShare(..)"),
268        }
269    }
270}
271
272/// Wrapper for different keypair types.
273#[derive(Serialize, Deserialize)]
274pub enum Keypair {
275    /// Ed25519 keypair.
276    Ed25519(ed25519_dalek::Keypair),
277    /// BLS keypair.
278    Bls(BlsKeypair),
279    /// BLS keypair share.
280    BlsShare(BlsKeypairShare),
281}
282
283// Need to manually implement this due to a missing impl in `Ed25519::Keypair`.
284impl Clone for Keypair {
285    fn clone(&self) -> Self {
286        match self {
287            Self::Ed25519(keypair) => Self::Ed25519(unwrap!(ed25519_dalek::Keypair::from_bytes(
288                &keypair.to_bytes()
289            ))),
290            Self::Bls(keypair) => Self::Bls(keypair.clone()),
291            Self::BlsShare(keypair) => Self::BlsShare(keypair.clone()),
292        }
293    }
294}
295
296impl Debug for Keypair {
297    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
298        write!(formatter, "Keypair::")?;
299        match self {
300            Self::Ed25519(_) => write!(formatter, "Ed25519(..)"),
301            Self::Bls(_) => write!(formatter, "Bls(..)"),
302            Self::BlsShare(_) => write!(formatter, "BlsShare(..)"),
303        }
304    }
305}
306
307// Need to manually implement this due to a missing impl in `Ed25519::Keypair`.
308impl PartialEq for Keypair {
309    fn eq(&self, other: &Self) -> bool {
310        match (self, other) {
311            (Self::Ed25519(keypair), Self::Ed25519(other_keypair)) => {
312                // TODO: After const generics land, remove the `to_vec()` calls.
313                keypair.to_bytes().to_vec() == other_keypair.to_bytes().to_vec()
314            }
315            (Self::Bls(keypair), Self::Bls(other_keypair)) => keypair == other_keypair,
316            (Self::BlsShare(keypair), Self::BlsShare(other_keypair)) => keypair == other_keypair,
317            _ => false,
318        }
319    }
320}
321
322// Need to manually implement this due to a missing impl in `Ed25519::Keypair`.
323impl Eq for Keypair {}
324
325impl Keypair {
326    /// Constructs a random Ed25519 public keypair.
327    pub fn new_ed25519<T: CryptoRng + Rng>(rng: &mut T) -> Self {
328        let keypair = ed25519_dalek::Keypair::generate(rng);
329        Self::Ed25519(keypair)
330    }
331
332    /// Constructs a random BLS public keypair.
333    pub fn new_bls<T: CryptoRng + Rng>(rng: &mut T) -> Self {
334        let bls_secret_key: threshold_crypto::SecretKey = rng.gen();
335        let bls_public_key = bls_secret_key.public_key();
336        let keypair = BlsKeypair {
337            secret: SerdeSecret(bls_secret_key),
338            public: bls_public_key,
339        };
340        Self::Bls(keypair)
341    }
342
343    /// Constructs a BLS public keypair share.
344    pub fn new_bls_share(
345        index: usize,
346        secret_share: threshold_crypto::SecretKeyShare,
347        public_key_set: threshold_crypto::PublicKeySet,
348    ) -> Self {
349        let public_share = secret_share.public_key_share();
350        let keypair_share = BlsKeypairShare {
351            index,
352            secret: SerdeSecret(secret_share),
353            public: public_share,
354            public_key_set,
355        };
356        Self::BlsShare(keypair_share)
357    }
358
359    /// Returns the public key associated with this keypair.
360    pub fn public_key(&self) -> PublicKey {
361        match self {
362            Self::Ed25519(keypair) => PublicKey::Ed25519(keypair.public),
363            Self::Bls(keypair) => PublicKey::Bls(keypair.public),
364            Self::BlsShare(keypair) => PublicKey::BlsShare(keypair.public),
365        }
366    }
367
368    /// Signs with the underlying keypair.
369    pub fn sign(&self, data: &[u8]) -> Signature {
370        match self {
371            Self::Ed25519(keypair) => Signature::Ed25519(keypair.sign(&data)),
372            Self::Bls(keypair) => Signature::Bls(keypair.secret.sign(data)),
373            Self::BlsShare(keypair) => {
374                let index = keypair.index;
375                let share = keypair.secret.sign(data);
376                Signature::BlsShare(SignatureShare { index, share })
377            }
378        }
379    }
380}
381
382/// BLS keypair.
383#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
384pub struct BlsKeypair {
385    /// Secret key.
386    pub secret: SerdeSecret<threshold_crypto::SecretKey>,
387    /// Public key.
388    pub public: threshold_crypto::PublicKey,
389}
390
391/// BLS keypair share.
392#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
393pub struct BlsKeypairShare {
394    /// Share index.
395    pub index: usize,
396    /// Secret key share.
397    pub secret: SerdeSecret<threshold_crypto::SecretKeyShare>,
398    /// Public key share.
399    pub public: threshold_crypto::PublicKeyShare,
400    /// Public key set. Necessary for producing proofs.
401    pub public_key_set: threshold_crypto::PublicKeySet,
402}
403
404#[cfg(test)]
405mod tests {
406    use super::*;
407    use crate::utils;
408    use bincode::deserialize as deserialise;
409    use threshold_crypto::{self};
410
411    fn gen_keypairs() -> Vec<Keypair> {
412        let mut rng = rand::thread_rng();
413        let bls_secret_key = threshold_crypto::SecretKeySet::random(1, &mut rng);
414        vec![
415            Keypair::new_ed25519(&mut rng),
416            Keypair::new_bls(&mut rng),
417            Keypair::new_bls_share(
418                0,
419                bls_secret_key.secret_key_share(0),
420                bls_secret_key.public_keys(),
421            ),
422        ]
423    }
424
425    fn gen_keys() -> Vec<PublicKey> {
426        gen_keypairs().iter().map(PublicKey::from).collect()
427    }
428
429    #[test]
430    fn zbase32_encode_decode_public_key() {
431        use unwrap::unwrap;
432
433        let keys = gen_keys();
434
435        for key in keys {
436            assert_eq!(
437                key,
438                unwrap!(PublicKey::decode_from_zbase32(&key.encode_to_zbase32()))
439            );
440        }
441    }
442
443    // Test serialising and deserialising public keys.
444    #[test]
445    fn serialisation_public_key() {
446        let keys = gen_keys();
447
448        for key in keys {
449            let encoded = utils::serialise(&key);
450            let decoded: PublicKey = unwrap!(deserialise(&encoded));
451
452            assert_eq!(decoded, key);
453        }
454    }
455
456    // Test serialising and deserialising key pairs.
457    #[test]
458    fn serialisation_key_pair() {
459        let keypairs = gen_keypairs();
460
461        for keypair in keypairs {
462            let encoded = utils::serialise(&keypair);
463            let decoded: Keypair = unwrap!(deserialise(&encoded));
464
465            assert_eq!(decoded, keypair);
466        }
467    }
468}