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