mithril_stm/bls_multi_signature/
verification_key.rs

1use crate::bls_multi_signature::helper::unsafe_helpers::verify_pairing;
2use crate::bls_multi_signature::proof_of_possession::ProofOfPossession;
3use crate::bls_multi_signature::signing_key::SigningKey;
4use crate::bls_multi_signature::POP;
5use crate::error::{blst_err_to_mithril, MultiSignatureError};
6use blst::min_sig::{AggregatePublicKey, PublicKey as BlstVk};
7use blst::BLST_ERROR;
8use serde::{Deserialize, Serialize};
9use std::{
10    cmp::Ordering,
11    fmt::{Display, Formatter},
12    hash::{Hash, Hasher},
13    iter::Sum,
14};
15
16/// MultiSig verification key, which is a wrapper over the BlstVk (element in G2)
17/// from the blst library.
18#[derive(Debug, Clone, Copy, Default)]
19pub struct VerificationKey(pub BlstVk);
20
21impl VerificationKey {
22    /// Convert an `VerificationKey` to its compressed byte representation.
23    pub fn to_bytes(self) -> [u8; 96] {
24        self.0.to_bytes()
25    }
26
27    /// Convert a compressed byte string into a `VerificationKey`.
28    ///
29    /// # Error
30    /// This function fails if the bytes do not represent a compressed point of the prime
31    /// order subgroup of the curve Bls12-381.
32    pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
33        match BlstVk::key_validate(&bytes[..96]) {
34            Ok(vk) => Ok(Self(vk)),
35            Err(e) => Err(blst_err_to_mithril(e, None, None)
36                .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
37        }
38    }
39
40    /// Compare two `VerificationKey`. Used for PartialOrd impl, used to order signatures. The comparison
41    /// function can be anything, as long as it is consistent.
42    fn cmp_msp_mvk(&self, other: &VerificationKey) -> Ordering {
43        let self_bytes = self.to_bytes();
44        let other_bytes = other.to_bytes();
45        let mut result = Ordering::Equal;
46
47        for (i, j) in self_bytes.iter().zip(other_bytes.iter()) {
48            result = i.cmp(j);
49            if result != Ordering::Equal {
50                return result;
51            }
52        }
53
54        result
55    }
56
57    pub(crate) fn to_blst_vk(self) -> BlstVk {
58        self.0
59    }
60}
61
62impl Display for VerificationKey {
63    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64        write!(f, "{:?}", self.to_bytes())
65    }
66}
67
68impl Hash for VerificationKey {
69    fn hash<H: Hasher>(&self, state: &mut H) {
70        Hash::hash_slice(&self.to_bytes(), state)
71    }
72}
73
74impl PartialEq for VerificationKey {
75    fn eq(&self, other: &Self) -> bool {
76        self.0 == other.0
77    }
78}
79
80impl Eq for VerificationKey {}
81
82impl PartialOrd for VerificationKey {
83    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
84        Some(std::cmp::Ord::cmp(self, other))
85    }
86}
87
88impl Ord for VerificationKey {
89    fn cmp(&self, other: &Self) -> Ordering {
90        self.cmp_msp_mvk(other)
91    }
92}
93
94impl<'a> Sum<&'a Self> for VerificationKey {
95    fn sum<I>(iter: I) -> Self
96    where
97        I: Iterator<Item = &'a Self>,
98    {
99        let keys: Vec<&BlstVk> = iter.map(|x| &x.0).collect();
100
101        assert!(!keys.is_empty(), "One cannot add an empty vector");
102        let aggregate_key = AggregatePublicKey::aggregate(&keys, false)
103            .expect("An MspMvk is always a valid key. This function only fails if keys is empty or if the keys are invalid, none of which can happen.")
104            .to_public_key();
105
106        Self(aggregate_key)
107    }
108}
109
110impl From<&SigningKey> for VerificationKey {
111    /// Convert a secret key into an `MspMvk`. This is performed by computing
112    /// `MspMvk = g2 * sk`, where `g2` is the generator in G2. We can use the
113    /// blst built-in function `sk_to_pk`.
114    fn from(sk: &SigningKey) -> Self {
115        VerificationKey(sk.to_blst_sk().sk_to_pk())
116    }
117}
118
119/// MultiSig public key, contains the verification key and the proof of possession.
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
121pub struct VerificationKeyPoP {
122    /// The verification key.
123    pub vk: VerificationKey,
124    /// Proof of Possession.
125    pub pop: ProofOfPossession,
126}
127
128impl VerificationKeyPoP {
129    /// if `e(k1,g2) = e(H_G1("PoP" || mvk),mvk)` and `e(g1,mvk) = e(k2,g2)`
130    /// are both true, return 1. The first part is a signature verification
131    /// of message "PoP", while the second we need to compute the pairing
132    /// manually.
133    // If we are really looking for performance improvements, we can combine the
134    // two final exponentiations (for verifying k1 and k2) into a single one.
135    pub fn check(&self) -> Result<(), MultiSignatureError> {
136        match self.vk.to_blst_vk().validate() {
137            Ok(_) => {
138                let result = verify_pairing(&self.vk, &self.pop);
139                if !(self
140                    .pop
141                    .to_k1()
142                    .verify(false, POP, &[], &[], &self.vk.to_blst_vk(), false)
143                    == BLST_ERROR::BLST_SUCCESS
144                    && result)
145                {
146                    return Err(MultiSignatureError::KeyInvalid(Box::new(*self)));
147                }
148                Ok(())
149            }
150            Err(e) => blst_err_to_mithril(e, None, Some(self.vk)),
151        }
152    }
153
154    /// Convert to a 144 byte string.
155    ///
156    /// # Layout
157    /// The layout of a `PublicKeyPoP` encoding is
158    /// * Public key
159    /// * Proof of Possession
160    pub fn to_bytes(self) -> [u8; 192] {
161        let mut vkpop_bytes = [0u8; 192];
162        vkpop_bytes[..96].copy_from_slice(&self.vk.to_bytes());
163        vkpop_bytes[96..].copy_from_slice(&self.pop.to_bytes());
164        vkpop_bytes
165    }
166
167    /// Deserialize a byte string to a `PublicKeyPoP`.
168    pub fn from_bytes(bytes: &[u8]) -> Result<Self, MultiSignatureError> {
169        let mvk = VerificationKey::from_bytes(&bytes[..96])?;
170
171        let pop = ProofOfPossession::from_bytes(&bytes[96..])?;
172
173        Ok(Self { vk: mvk, pop })
174    }
175}
176
177impl From<&SigningKey> for VerificationKeyPoP {
178    /// Convert a secret key into a `VerificationKeyPoP` by simply converting to a
179    /// `MspMvk` and `MspPoP`.
180    fn from(sk: &SigningKey) -> Self {
181        Self {
182            vk: sk.into(),
183            pop: sk.into(),
184        }
185    }
186}