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