mithril_stm/signature_scheme/bls_multi_signature/
mod.rs1mod error;
4pub(super) mod helper;
5mod proof_of_possession;
6mod signature;
7mod signing_key;
8mod verification_key;
9
10pub use error::*;
11pub use proof_of_possession::*;
12pub use signature::*;
13pub use signing_key::*;
14pub use verification_key::*;
15
16use serde::{
17 de::Visitor,
18 {Deserialize, Deserializer, Serialize, Serializer},
19};
20
21pub(crate) const POP: &[u8] = b"PoP";
23
24macro_rules! impl_serde {
29 ($st:ty,$visitor:ident,$size:expr) => {
30 impl Serialize for $st {
31 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32 where
33 S: Serializer,
34 {
35 use serde::ser::SerializeTuple;
36 let mut seq = serializer.serialize_tuple($size)?;
37 for e in self.to_bytes().iter() {
38 seq.serialize_element(e)?;
39 }
40 seq.end()
41 }
42 }
43
44 impl<'de> Deserialize<'de> for $st {
45 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
46 where
47 D: Deserializer<'de>,
48 {
49 struct $visitor;
50
51 impl<'de> Visitor<'de> for $visitor {
52 type Value = $st;
53
54 fn expecting(
55 &self,
56 formatter: &mut ::core::fmt::Formatter,
57 ) -> ::core::fmt::Result {
58 formatter
59 .write_str(format!("a multi signature {}", stringify!($st)).as_str())
60 }
61
62 fn visit_seq<A>(self, mut seq: A) -> Result<$st, A::Error>
63 where
64 A: serde::de::SeqAccess<'de>,
65 {
66 let mut bytes = [0u8; $size];
67 for i in 0..$size {
68 bytes[i] =
69 seq.next_element()?.ok_or(serde::de::Error::invalid_length(
70 i,
71 &format!("expected bytes{}", $size.to_string()).as_str(),
72 ))?;
73 }
74 <$st>::from_bytes(&bytes).map_err(|_| {
75 serde::de::Error::custom(
76 &format!("deserialization failed [{}]", stringify!($st)).as_str(),
77 )
78 })
79 }
80 }
81
82 deserializer.deserialize_tuple($size, $visitor)
83 }
84 }
85 };
86}
87impl_serde!(BlsSigningKey, SigningKeyVisitor, 32);
88impl_serde!(BlsVerificationKey, VerificationKeyVisitor, 96);
89impl_serde!(BlsProofOfPossession, ProofOfPossessionVisitor, 96);
90impl_serde!(BlsSignature, SignatureVisitor, 48);
91
92#[cfg(test)]
93mod tests {
94 use blst::{blst_p1, blst_p2};
95 use proptest::prelude::*;
96 use rand_chacha::ChaCha20Rng;
97 use rand_core::{RngCore, SeedableRng};
98
99 use super::error::BlsSignatureError;
100 use super::helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk};
101 use crate::{KeyRegistration, RegisterError};
102
103 use super::*;
104
105 impl PartialEq for BlsSigningKey {
106 fn eq(&self, other: &Self) -> bool {
107 self.to_blst_secret_key().to_bytes() == other.to_blst_secret_key().to_bytes()
108 }
109 }
110
111 impl Eq for BlsSigningKey {}
112
113 proptest! {
114 #![proptest_config(ProptestConfig::with_cases(1000))]
115
116 #[test]
117 fn test_sig(
118 msg in prop::collection::vec(any::<u8>(), 1..128),
119 seed in any::<[u8;32]>(),
120 ) {
121 let sk = BlsSigningKey::generate(&mut ChaCha20Rng::from_seed(seed));
122 let vk = BlsVerificationKey::from(&sk);
123 let sig = sk.sign(&msg);
124
125 sig.verify(&msg, &vk).unwrap();
126 }
127
128 #[test]
129 fn test_invalid_sig(msg in prop::collection::vec(any::<u8>(), 1..128), seed in any::<[u8;32]>()) {
130 let mut rng = ChaCha20Rng::from_seed(seed);
131 let sk1 = BlsSigningKey::generate(&mut rng);
132 let vk1 = BlsVerificationKey::from(&sk1);
133 let sk2 = BlsSigningKey::generate(&mut rng);
134 let fake_sig = sk2.sign(&msg);
135
136 let error = fake_sig.verify(&msg, &vk1).expect_err("Fake signature should not be verified");
137
138 assert!(
139 matches!(
140 error.downcast_ref::<BlsSignatureError>(),
141 Some(BlsSignatureError::SignatureInvalid(_))
142 ),
143 "Unexpected error: {error:?}");
144 }
145
146 #[test]
147 fn test_infinity_sig(msg in prop::collection::vec(any::<u8>(), 1..128), seed in any::<[u8;32]>()) {
148 let mut rng = ChaCha20Rng::from_seed(seed);
149 let sk = BlsSigningKey::generate(&mut rng);
150 let vk = BlsVerificationKey::from(&sk);
151
152 let p1 = blst_p1::default();
153 let sig_infinity = BlsSignature(p1_affine_to_sig(&p1));
154
155 let error = sig_infinity.verify(&msg, &vk).expect_err("Verification should fail");
156 assert!(
157 matches!(
158 error.downcast_ref::<BlsSignatureError>(),
159 Some(BlsSignatureError::SignatureInfinity(_))
160 ),
161 "Unexpected error: {error:?}");
162 }
163
164 #[test]
165 fn test_infinity_vk(seed in any::<[u8;32]>()) {
166 let mut rng = ChaCha20Rng::from_seed(seed);
167 let sk = BlsSigningKey::generate(&mut rng);
168 let pop = BlsProofOfPossession::from(&sk);
169
170 let p2 = blst_p2::default();
171 let vk_infinity = BlsVerificationKey(p2_affine_to_vk(&p2));
172 let vkpop_infinity = BlsVerificationKeyProofOfPossession { vk: vk_infinity, pop };
173
174 let error = vkpop_infinity.verify_proof_of_possession().expect_err("VK pop infinity should fail");
175 assert!(
176 matches!(
177 error.downcast_ref::<BlsSignatureError>(),
178 Some(BlsSignatureError::VerificationKeyInfinity(_))
179 ),
180 "Unexpected error: {error:?}");
181 }
182
183 #[test]
184 fn test_keyreg_with_infinity_vk(num_sigs in 2..16usize, seed in any::<[u8;32]>()) {
185 let mut rng = ChaCha20Rng::from_seed(seed);
186 let mut kr = KeyRegistration::init();
187
188 let sk = BlsSigningKey::generate(&mut rng);
189 let pop = BlsProofOfPossession::from(&sk);
190 let p2 = blst_p2::default();
191 let vk_infinity = BlsVerificationKey(p2_affine_to_vk(&p2));
192 let vkpop_infinity = BlsVerificationKeyProofOfPossession { vk: vk_infinity, pop };
193
194 for _ in 0..num_sigs {
195 let sk = BlsSigningKey::generate(&mut rng);
196 let vkpop = BlsVerificationKeyProofOfPossession::from(&sk);
197 let _ = kr.register(1, vkpop);
198 }
199
200 let error = kr.register(1, vkpop_infinity).expect_err("VK pop infinity should not be registered");
201
202 assert!(
203 matches!(
204 error.downcast_ref::<RegisterError>(),
205 Some(RegisterError::KeyInvalid(_))
206 ),
207 "Unexpected error: {error:?}");
208 }
209
210 #[test]
211 fn test_aggregate_sig(msg in prop::collection::vec(any::<u8>(), 1..128),
212 num_sigs in 2..16,
213 seed in any::<[u8;32]>(),
214 ) {
215 let mut rng = ChaCha20Rng::from_seed(seed);
216 let mut mvks = Vec::new();
217 let mut sigs = Vec::new();
218 for _ in 0..num_sigs {
219 let sk = BlsSigningKey::generate(&mut rng);
220 let vk = BlsVerificationKey::from(&sk);
221 let sig = sk.sign(&msg);
222 assert!(sig.verify(&msg, &vk).is_ok());
223 sigs.push(sig);
224 mvks.push(vk);
225 }
226
227 let result = BlsSignature::verify_aggregate(&msg, &mvks, &sigs);
228 assert!(result.is_ok(), "Aggregate verification failed {result:?}");
229 }
230
231 #[test]
232 fn test_eval_sanity_check(msg in prop::collection::vec(any::<u8>(), 1..128),
233 idx in any::<u64>(),
234 seed in any::<[u8;32]>()) {
235 let sk = BlsSigningKey::generate(&mut ChaCha20Rng::from_seed(seed));
236 let sig = sk.sign(&msg);
237 sig.evaluate_dense_mapping(&msg, idx);
238 }
239
240 #[test]
241 fn serialize_deserialize_vk(seed in any::<u64>()) {
242 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
243 let sk = BlsSigningKey::generate(&mut rng);
244 let vk = BlsVerificationKey::from(&sk);
245 let vk_bytes = vk.to_bytes();
246 let vk2 = BlsVerificationKey::from_bytes(&vk_bytes).unwrap();
247 assert_eq!(vk, vk2);
248 let vkpop = BlsVerificationKeyProofOfPossession::from(&sk);
249 let vkpop_bytes = vkpop.to_bytes();
250 let vkpop2: BlsVerificationKeyProofOfPossession = BlsVerificationKeyProofOfPossession::from_bytes(&vkpop_bytes).unwrap();
251 assert_eq!(vkpop, vkpop2);
252 }
253
254 #[test]
255 fn serialize_deserialize_sk(seed in any::<u64>()) {
256 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
257 let sk = BlsSigningKey::generate(&mut rng);
258 let sk_bytes: [u8; 32] = sk.to_bytes();
259 let sk2 = BlsSigningKey::from_bytes(&sk_bytes).unwrap();
260 assert_eq!(sk, sk2);
261 }
262
263 #[test]
264 fn batch_verify(num_batches in 2..10usize,
265 seed in any::<[u8;32]>(),
266 ) {
267 let mut rng = ChaCha20Rng::from_seed(seed);
268 let num_sigs = 10;
269 let mut batch_msgs = Vec::new();
270 let mut batch_vk = Vec::new();
271 let mut batch_sig = Vec::new();
272 for _ in 0..num_batches {
273 let mut msg = [0u8; 32];
274 rng.fill_bytes(&mut msg);
275 let mut mvks = Vec::new();
276 let mut sigs = Vec::new();
277 for _ in 0..num_sigs {
278 let sk = BlsSigningKey::generate(&mut rng);
279 let vk = BlsVerificationKey::from(&sk);
280 let sig = sk.sign(&msg);
281 sigs.push(sig);
282 mvks.push(vk);
283 }
284 assert!(BlsSignature::verify_aggregate(&msg, &mvks, &sigs).is_ok());
285 let (agg_vk, agg_sig) = BlsSignature::aggregate(&mvks, &sigs).unwrap();
286 batch_msgs.push(msg.to_vec());
287 batch_vk.push(agg_vk);
288 batch_sig.push(agg_sig);
289 }
290 assert!(BlsSignature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig).is_ok());
291
292 let mut msg = [0u8; 32];
294 rng.fill_bytes(&mut msg);
295 let sk = BlsSigningKey::generate(&mut rng);
296 let fake_sig = sk.sign(&msg);
297 batch_sig[0] = fake_sig;
298
299 let error = BlsSignature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig).expect_err("Batch verify should fail");
300 assert!(
301 matches!(
302 error.downcast_ref::<BlsSignatureError>(),
303 Some(BlsSignatureError::BatchInvalid)
304 ),
305 "Unexpected error: {error:?}");
306 }
307 }
308}