sn_interface/messaging/system/
section_sig.rs

1// Copyright 2023 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use crate::messaging::{
10    signature_aggregator::{AggregatorError, SignatureAggregator},
11    AuthorityProof,
12};
13use serde::{Deserialize, Serialize};
14use std::{
15    borrow::Borrow,
16    fmt::{self, Debug, Formatter},
17    ops::Deref,
18};
19use xor_name::Prefix;
20
21/// Signature created when a quorum of the section elders has agreed on something.
22#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
23pub struct SectionSig {
24    /// The BLS public key.
25    pub public_key: bls::PublicKey,
26    /// The BLS signature corresponding to the public key.
27    pub signature: bls::Signature,
28}
29
30impl Debug for SectionSig {
31    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
32        f.debug_tuple("SectionSig").field(&self.public_key).finish()
33    }
34}
35
36impl SectionSig {
37    /// Verifies this signature against the payload.
38    pub fn verify(&self, payload: &[u8]) -> bool {
39        self.public_key.verify(&self.signature, payload)
40    }
41
42    /// Try to construct verified section authority by aggregating a new share.
43    pub fn try_authorize(
44        aggregator: &mut SignatureAggregator,
45        share: SectionSigShare,
46        payload: impl AsRef<[u8]>,
47    ) -> Result<Option<AuthorityProof<Self>>, AggregatorError> {
48        match aggregator.try_aggregate(payload.as_ref(), share)? {
49            Some(sig) => Ok(Some(AuthorityProof(Self {
50                public_key: sig.public_key,
51                signature: sig.signature,
52            }))),
53            None => Ok(None),
54        }
55    }
56}
57
58/// Single share of `SectionSig`.
59#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
60pub struct SectionSigShare {
61    /// BLS public key set.
62    pub public_key_set: bls::PublicKeySet,
63    /// Index of the node that created this signature share.
64    pub index: usize,
65    /// BLS signature share corresponding to the `index`-th public key share of the public key set.
66    pub signature_share: bls::SignatureShare,
67}
68
69impl SectionSigShare {
70    /// Creates new signature share.
71    pub fn new(
72        public_key_set: bls::PublicKeySet,
73        index: usize,
74        secret_key_share: &bls::SecretKeyShare,
75        payload: &[u8],
76    ) -> Self {
77        Self {
78            public_key_set,
79            index,
80            signature_share: secret_key_share.sign(payload),
81        }
82    }
83
84    /// Verifies this signature share against the payload.
85    pub fn verify(&self, payload: &[u8]) -> bool {
86        self.public_key_set
87            .public_key_share(self.index)
88            .verify(&self.signature_share, payload)
89    }
90}
91
92/// A section signed piece of data
93#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize, Deserialize)]
94pub struct SectionSigned<T: Serialize> {
95    /// some value agreed upon by elders
96    pub value: T,
97    /// section signature over the value
98    pub sig: SectionSig,
99}
100
101impl<T> Borrow<Prefix> for SectionSigned<T>
102where
103    T: Borrow<Prefix> + Serialize,
104{
105    fn borrow(&self) -> &Prefix {
106        self.value.borrow()
107    }
108}
109
110impl<T: Serialize> Deref for SectionSigned<T> {
111    type Target = T;
112
113    fn deref(&self) -> &Self::Target {
114        &self.value
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use crate::test_utils::TestKeys;
121    use bls::SecretKey;
122
123    #[test]
124    fn verify_keyed_sig() {
125        let sk = SecretKey::random();
126        let data = "hello";
127        let sig = TestKeys::get_section_sig_bytes(&sk, data.as_bytes());
128        assert!(sig.verify(data.as_bytes()));
129    }
130}