safe_nd/identity/
node.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
10use crate::keys::{BlsKeypairShare, SignatureShare};
11use crate::{utils, Error, PublicKey, Signature};
12use ed25519_dalek::{Keypair as Ed25519Keypair, PublicKey as Ed25519PublicKey};
13use hex_fmt::HexFmt;
14use rand::{CryptoRng, Rng};
15use serde::{Deserialize, Deserializer, Serialize, Serializer};
16use signature::Signer;
17use std::{
18    cmp::Ordering,
19    fmt::{self, Debug, Display, Formatter},
20    hash::{Hash, Hasher},
21};
22use threshold_crypto::{
23    serde_impl::SerdeSecret, PublicKeySet, PublicKeyShare as BlsPublicKeyShare,
24    SecretKeyShare as BlsSecretKeyShare,
25};
26use xor_name::XorName;
27
28/// A struct holding an Ed25519 keypair, an optional BLS keypair share, and the corresponding public
29/// ID for a network Node.
30#[derive(Serialize, Deserialize)]
31pub struct FullId {
32    ed25519: Ed25519Keypair,
33    bls: Option<BlsKeypairShare>,
34    public_id: PublicId,
35}
36
37impl FullId {
38    /// Constructs a `FullId` with a random Ed25519 keypair and no BLS keys.
39    pub fn new<T: CryptoRng + Rng>(rng: &mut T) -> Self {
40        let ed25519 = Ed25519Keypair::generate(rng);
41        let name = PublicKey::Ed25519(ed25519.public).into();
42        let public_id = PublicId {
43            name,
44            ed25519: ed25519.public,
45            bls: None,
46        };
47        Self {
48            ed25519,
49            bls: None,
50            public_id,
51        }
52    }
53
54    /// Constructs a `FullId` whose name is in the interval [start, end] (both endpoints inclusive).
55    pub fn within_range<T: CryptoRng + Rng>(start: &XorName, end: &XorName, rng: &mut T) -> Self {
56        let mut ed25519 = Ed25519Keypair::generate(rng);
57        loop {
58            let name = PublicKey::Ed25519(ed25519.public).into();
59            if name >= *start && name <= *end {
60                let public_id = PublicId {
61                    name,
62                    ed25519: ed25519.public,
63                    bls: None,
64                };
65                return Self {
66                    ed25519,
67                    bls: None,
68                    public_id,
69                };
70            }
71            ed25519 = Ed25519Keypair::generate(rng);
72        }
73    }
74
75    /// Returns the public ID.
76    pub fn public_id(&self) -> &PublicId {
77        &self.public_id
78    }
79
80    /// Creates a detached Ed25519 signature of `data`.
81    pub fn sign_using_ed25519<T: AsRef<[u8]>>(&self, data: T) -> Signature {
82        Signature::Ed25519(self.ed25519.sign(data.as_ref()))
83    }
84
85    /// Creates a detached BLS signature share of `data` if the `self` holds a BLS keypair share.
86    pub fn sign_using_bls<T: AsRef<[u8]>>(&self, data: T) -> Option<Signature> {
87        self.bls.as_ref().map(|keys| {
88            Signature::BlsShare(SignatureShare {
89                index: keys.index,
90                share: keys.secret.inner().sign(data),
91            })
92        })
93    }
94
95    /// Sets the `FullId`'s BLS keypair share using the provided BLS secret key share.
96    pub fn set_bls_keys(&mut self, secret_share: BlsSecretKeyShare, public_set: PublicKeySet) {
97        let public = secret_share.public_key_share();
98        let secret = SerdeSecret(secret_share);
99        self.public_id.bls = Some(public);
100        self.bls = Some(BlsKeypairShare {
101            index: 0,
102            secret,
103            public,
104            public_key_set: public_set,
105        });
106    }
107
108    /// Clears the `FullId`'s BLS keypair share, i.e. sets it to `None`.
109    pub fn clear_bls_keys(&mut self) {
110        self.public_id.bls = None;
111        self.bls = None;
112    }
113}
114
115/// A struct representing the public identity of a network Node.
116///
117/// It includes the Ed25519 public key and the optional BLS public key.  This struct also provides
118/// the Node's network address, i.e. `name()` derived from the Ed25519 public key.
119#[derive(Clone, Eq, PartialEq)]
120pub struct PublicId {
121    name: XorName,
122    ed25519: Ed25519PublicKey,
123    bls: Option<BlsPublicKeyShare>,
124}
125
126impl PublicId {
127    /// Returns the Node's network address.
128    pub fn name(&self) -> &XorName {
129        &self.name
130    }
131
132    /// Returns the Node's Ed25519 public key.
133    pub fn ed25519_public_key(&self) -> &Ed25519PublicKey {
134        &self.ed25519
135    }
136
137    /// Returns the Node's BLS public key share.
138    pub fn bls_public_key(&self) -> &Option<BlsPublicKeyShare> {
139        &self.bls
140    }
141
142    /// Returns the PublicId serialised and encoded in z-base-32.
143    pub fn encode_to_zbase32(&self) -> String {
144        utils::encode(&self)
145    }
146
147    /// Creates from z-base-32 encoded string.
148    pub fn decode_from_zbase32<T: AsRef<str>>(encoded: T) -> Result<Self, Error> {
149        utils::decode(encoded)
150    }
151}
152
153impl Serialize for PublicId {
154    fn serialize<S: Serializer>(&self, serialiser: S) -> Result<S::Ok, S::Error> {
155        (&self.ed25519, &self.bls).serialize(serialiser)
156    }
157}
158
159impl<'de> Deserialize<'de> for PublicId {
160    fn deserialize<D: Deserializer<'de>>(deserialiser: D) -> Result<Self, D::Error> {
161        let (ed25519, bls): (Ed25519PublicKey, Option<BlsPublicKeyShare>) =
162            Deserialize::deserialize(deserialiser)?;
163        let name = PublicKey::Ed25519(ed25519).into();
164        Ok(PublicId { name, ed25519, bls })
165    }
166}
167
168impl Ord for PublicId {
169    fn cmp(&self, other: &PublicId) -> Ordering {
170        utils::serialise(&self).cmp(&utils::serialise(other))
171    }
172}
173
174impl PartialOrd for PublicId {
175    fn partial_cmp(&self, other: &PublicId) -> Option<Ordering> {
176        Some(self.cmp(other))
177    }
178}
179
180#[allow(clippy::derive_hash_xor_eq)]
181impl Hash for PublicId {
182    fn hash<H: Hasher>(&self, state: &mut H) {
183        utils::serialise(&self).hash(state)
184    }
185}
186
187impl Debug for PublicId {
188    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
189        write!(formatter, "Node({:<8})", HexFmt(&self.ed25519.to_bytes()))
190    }
191}
192
193impl Display for PublicId {
194    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
195        Debug::fmt(self, formatter)
196    }
197}
198
199/// This is used at a network node for holding the
200/// obligatory Ed25519 keypair needed as Adult, and
201/// then a BLS keypair share when being promoted to Elder.
202/// (Also the corresponding public keys).
203/// The Ed25519 is kept as Elder, in case it is demoted.
204#[derive(Serialize, Deserialize)]
205pub struct NodeKeypairs {
206    ed25519: Ed25519Keypair,
207    bls: Option<BlsKeypairShare>,
208    public_id: PublicId,
209}
210
211impl NodeKeypairs {
212    /// Constructs a `NodeKeypairs` with a random Ed25519 keypair and no BLS keys.
213    pub fn new<T: CryptoRng + Rng>(rng: &mut T) -> Self {
214        let ed25519 = Ed25519Keypair::generate(rng);
215        let name = PublicKey::Ed25519(ed25519.public).into();
216        let public_id = PublicId {
217            name,
218            ed25519: ed25519.public,
219            bls: None,
220        };
221        Self {
222            ed25519,
223            bls: None,
224            public_id,
225        }
226    }
227
228    /// Constructs a `NodeKeypairs` whose name is in the interval [start, end] (both endpoints inclusive).
229    pub fn within_range<T: CryptoRng + Rng>(start: &XorName, end: &XorName, rng: &mut T) -> Self {
230        let mut ed25519 = Ed25519Keypair::generate(rng);
231        loop {
232            let name = PublicKey::Ed25519(ed25519.public).into();
233            if name >= *start && name <= *end {
234                let public_id = PublicId {
235                    name,
236                    ed25519: ed25519.public,
237                    bls: None,
238                };
239                return Self {
240                    ed25519,
241                    bls: None,
242                    public_id,
243                };
244            }
245            ed25519 = Ed25519Keypair::generate(rng);
246        }
247    }
248
249    /// Returns the BLS if any, else the Ed25519.
250    pub fn public_key(&self) -> PublicKey {
251        if let Some(key) = self.public_id.bls {
252            PublicKey::BlsShare(key)
253        } else {
254            PublicKey::Ed25519(self.public_id.ed25519)
255        }
256    }
257
258    /// Returns the public keys.
259    pub fn public_id(&self) -> &PublicId {
260        &self.public_id
261    }
262
263    /// Returns the BLS public key set if any.
264    pub fn public_key_set(&self) -> Option<&PublicKeySet> {
265        self.bls.as_ref().map(|s| &s.public_key_set)
266    }
267
268    /// Signs with the BLS if any, else the Ed25519.
269    pub fn sign(&self, data: &[u8]) -> Signature {
270        if let Some(sig) = self.sign_using_bls(data) {
271            sig
272        } else {
273            self.sign_using_ed25519(data)
274        }
275    }
276
277    /// Creates a detached Ed25519 signature of `data`.
278    pub fn sign_using_ed25519<T: AsRef<[u8]>>(&self, data: T) -> Signature {
279        Signature::Ed25519(self.ed25519.sign(data.as_ref()))
280    }
281
282    /// Creates a detached BLS signature share of `data` if the `self` holds a BLS keypair share.
283    pub fn sign_using_bls<T: AsRef<[u8]>>(&self, data: T) -> Option<Signature> {
284        self.bls.as_ref().map(|keys| {
285            Signature::BlsShare(SignatureShare {
286                index: keys.index,
287                share: keys.secret.inner().sign(data),
288            })
289        })
290    }
291
292    /// Sets the `NodeKeypairs`'s BLS keypair share using the provided BLS secret key share.
293    pub fn set_bls_keys(
294        &mut self,
295        index: usize,
296        secret_share: BlsSecretKeyShare,
297        public_set: PublicKeySet,
298    ) {
299        let public = secret_share.public_key_share();
300        let secret = SerdeSecret(secret_share);
301        self.public_id.bls = Some(public);
302        self.bls = Some(BlsKeypairShare {
303            index,
304            secret,
305            public,
306            public_key_set: public_set,
307        });
308    }
309
310    /// Clears the `NodeKeypairs`'s BLS keypair share, i.e. sets it to `None`.
311    pub fn clear_bls_keys(&mut self) {
312        self.public_id.bls = None;
313        self.bls = None;
314    }
315}