mithril_stm/bls_multi_signature/
verification_key.rs

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