1use anyhow::anyhow;
2use std::{
3 cmp::Ordering,
4 fmt::{Display, Formatter},
5 hash::{Hash, Hasher},
6 iter::Sum,
7};
8
9use blst::{
10 BLST_ERROR,
11 min_sig::{AggregatePublicKey, PublicKey as BlstVk},
12};
13use serde::{Deserialize, Serialize};
14
15use super::{BlsProofOfPossession, BlsSigningKey, POP, helper::unsafe_helpers::verify_pairing};
16use crate::{MultiSignatureError, StmResult, blst_error_to_stm_error};
17
18#[derive(Debug, Clone, Copy, Default)]
21pub struct BlsVerificationKey(pub BlstVk);
22
23impl BlsVerificationKey {
24 pub fn to_bytes(self) -> [u8; 96] {
26 self.0.to_bytes()
27 }
28
29 pub fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
35 let bytes = bytes.get(..96).ok_or(MultiSignatureError::SerializationError)?;
36 match BlstVk::key_validate(bytes) {
37 Ok(vk) => Ok(Self(vk)),
38 Err(e) => Err(blst_error_to_stm_error(e, None, None)
39 .expect_err("If deserialization is not successful, blst returns and error different to SUCCESS."))
40 }
41 }
42
43 fn compare_verification_keys(&self, other: &BlsVerificationKey) -> Ordering {
46 let self_bytes = self.to_bytes();
47 let other_bytes = other.to_bytes();
48 let mut result = Ordering::Equal;
49
50 for (i, j) in self_bytes.iter().zip(other_bytes.iter()) {
51 result = i.cmp(j);
52 if result != Ordering::Equal {
53 return result;
54 }
55 }
56
57 result
58 }
59
60 pub(crate) fn to_blst_verification_key(self) -> BlstVk {
61 self.0
62 }
63}
64
65impl Display for BlsVerificationKey {
66 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
67 write!(f, "{:?}", self.to_bytes())
68 }
69}
70
71impl Hash for BlsVerificationKey {
72 fn hash<H: Hasher>(&self, state: &mut H) {
73 Hash::hash_slice(&self.to_bytes(), state)
74 }
75}
76
77impl PartialEq for BlsVerificationKey {
78 fn eq(&self, other: &Self) -> bool {
79 self.0 == other.0
80 }
81}
82
83impl Eq for BlsVerificationKey {}
84
85impl PartialOrd for BlsVerificationKey {
86 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
87 Some(std::cmp::Ord::cmp(self, other))
88 }
89}
90
91impl Ord for BlsVerificationKey {
92 fn cmp(&self, other: &Self) -> Ordering {
93 self.compare_verification_keys(other)
94 }
95}
96
97impl<'a> Sum<&'a Self> for BlsVerificationKey {
98 fn sum<I>(iter: I) -> Self
99 where
100 I: Iterator<Item = &'a Self>,
101 {
102 let keys: Vec<&BlstVk> = iter.map(|x| &x.0).collect();
103
104 assert!(!keys.is_empty(), "One cannot add an empty vector");
105 let aggregate_key = AggregatePublicKey::aggregate(&keys, false)
106 .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.")
107 .to_public_key();
108
109 Self(aggregate_key)
110 }
111}
112
113impl From<&BlsSigningKey> for BlsVerificationKey {
114 fn from(sk: &BlsSigningKey) -> Self {
118 BlsVerificationKey(sk.to_blst_secret_key().sk_to_pk())
119 }
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
124pub struct BlsVerificationKeyProofOfPossession {
125 pub vk: BlsVerificationKey,
127 pub pop: BlsProofOfPossession,
129}
130
131impl BlsVerificationKeyProofOfPossession {
132 pub(crate) fn verify_proof_of_possession(&self) -> StmResult<()> {
139 match self.vk.to_blst_verification_key().validate() {
140 Ok(_) => {
141 let result = verify_pairing(&self.vk, &self.pop);
142 if !(self.pop.get_k1().verify(
143 false,
144 POP,
145 &[],
146 &[],
147 &self.vk.to_blst_verification_key(),
148 false,
149 ) == BLST_ERROR::BLST_SUCCESS
150 && result)
151 {
152 return Err(anyhow!(MultiSignatureError::KeyInvalid(Box::new(*self))));
153 }
154 Ok(())
155 }
156 Err(e) => blst_error_to_stm_error(e, None, Some(self.vk)),
157 }
158 }
159
160 #[deprecated(
167 since = "0.5.0",
168 note = "The verification of the proof of possession is not part of the public API any more"
169 )]
170 pub fn check(&self) -> StmResult<()> {
171 Self::verify_proof_of_possession(self)
172 }
173
174 pub fn to_bytes(self) -> [u8; 192] {
181 let mut vkpop_bytes = [0u8; 192];
182 vkpop_bytes[..96].copy_from_slice(&self.vk.to_bytes());
183 vkpop_bytes[96..].copy_from_slice(&self.pop.to_bytes());
184 vkpop_bytes
185 }
186
187 pub fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
189 let mvk = BlsVerificationKey::from_bytes(
190 bytes.get(..96).ok_or(MultiSignatureError::SerializationError)?,
191 )?;
192
193 let pop = BlsProofOfPossession::from_bytes(
194 bytes.get(96..).ok_or(MultiSignatureError::SerializationError)?,
195 )?;
196
197 Ok(Self { vk: mvk, pop })
198 }
199}
200
201impl From<&BlsSigningKey> for BlsVerificationKeyProofOfPossession {
202 fn from(sk: &BlsSigningKey) -> Self {
205 Self {
206 vk: sk.into(),
207 pop: sk.into(),
208 }
209 }
210}
211
212#[cfg(test)]
213mod tests {
214 use super::*;
215
216 mod golden {
217
218 use rand_chacha::ChaCha20Rng;
219 use rand_core::SeedableRng;
220
221 use super::*;
222
223 const GOLDEN_JSON: &str = r#"
224 {
225 "vk": [143, 161, 255, 48, 78, 57, 204, 220, 25, 221, 164, 252, 248, 14, 56, 126, 186, 135, 228, 188, 145, 181, 52, 200, 97, 99, 213, 46, 0, 199, 193, 89, 187, 88, 29, 135, 173, 244, 86, 36, 83, 54, 67, 164, 6, 137, 94, 72, 6, 105, 128, 128, 93, 48, 176, 11, 4, 246, 138, 48, 180, 133, 90, 142, 192, 24, 193, 111, 142, 31, 76, 111, 110, 234, 153, 90, 208, 192, 31, 124, 95, 102, 49, 158, 99, 52, 220, 165, 94, 251, 68, 69, 121, 16, 224, 194],
226 "pop": [168, 50, 233, 193, 15, 136, 65, 72, 123, 148, 129, 176, 38, 198, 209, 47, 28, 204, 176, 144, 57, 251, 42, 28, 66, 76, 89, 97, 158, 63, 54, 198, 194, 176, 135, 221, 14, 185, 197, 225, 202, 98, 243, 74, 233, 225, 143, 151, 147, 177, 170, 117, 66, 165, 66, 62, 33, 216, 232, 75, 68, 114, 195, 22, 100, 65, 44, 198, 4, 166, 102, 233, 253, 240, 59, 175, 60, 117, 142, 114, 140, 122, 17, 87, 110, 187, 1, 17, 10, 195, 154, 13, 249, 86, 54, 226]
227 }
228 "#;
229
230 fn golden_value() -> BlsVerificationKeyProofOfPossession {
231 let mut rng = ChaCha20Rng::from_seed([0u8; 32]);
232 let sk = BlsSigningKey::generate(&mut rng);
233 BlsVerificationKeyProofOfPossession {
234 vk: BlsVerificationKey::from(&sk),
235 pop: BlsProofOfPossession::from(&sk),
236 }
237 }
238
239 #[test]
240 fn golden_conversions() {
241 let value = serde_json::from_str(GOLDEN_JSON)
242 .expect("This JSON deserialization should not fail");
243 assert_eq!(golden_value(), value);
244
245 let serialized =
246 serde_json::to_string(&value).expect("This JSON serialization should not fail");
247 let golden_serialized = serde_json::to_string(&golden_value())
248 .expect("This JSON serialization should not fail");
249 assert_eq!(golden_serialized, serialized);
250 }
251 }
252}