mithril_stm/signature_scheme/bls_multi_signature/
mod.rs

1//! BLST Multi-signature module
2
3mod 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
21/// String used to generate the proofs of possession.
22pub(crate) const POP: &[u8] = b"PoP";
23
24// ---------------------------------------------------------------------
25// Serde implementation
26// ---------------------------------------------------------------------
27
28macro_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, RegistrationEntry};
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::initialize();
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 entry = RegistrationEntry::new(vkpop, 1).expect("Registration entry should be created");
198                kr.register_by_entry(&entry).expect("Valid VK pop should be registered");
199            }
200            let error = RegistrationEntry::new(vkpop_infinity, 1).expect_err("Registration entry with VK pop infinity should not be created");
201            assert!(
202                matches!(
203                    error.downcast_ref::<RegisterError>(),
204                    Some(RegisterError::KeyInvalid(_))
205                ),
206                "Unexpected error: {error:?}");
207        }
208
209        #[test]
210        fn test_aggregate_sig(msg in prop::collection::vec(any::<u8>(), 1..128),
211                              num_sigs in 2..16,
212                              seed in any::<[u8;32]>(),
213        ) {
214            let mut rng = ChaCha20Rng::from_seed(seed);
215            let mut mvks = Vec::new();
216            let mut sigs = Vec::new();
217            for _ in 0..num_sigs {
218                let sk = BlsSigningKey::generate(&mut rng);
219                let vk = BlsVerificationKey::from(&sk);
220                let sig = sk.sign(&msg);
221                assert!(sig.verify(&msg, &vk).is_ok());
222                sigs.push(sig);
223                mvks.push(vk);
224            }
225
226            let result = BlsSignature::verify_aggregate(&msg, &mvks, &sigs);
227            assert!(result.is_ok(), "Aggregate verification failed {result:?}");
228        }
229
230        #[test]
231        fn test_eval_sanity_check(msg in prop::collection::vec(any::<u8>(), 1..128),
232                                  idx in any::<u64>(),
233                                  seed in any::<[u8;32]>()) {
234            let sk = BlsSigningKey::generate(&mut ChaCha20Rng::from_seed(seed));
235            let sig = sk.sign(&msg);
236            sig.evaluate_dense_mapping(&msg, idx);
237        }
238
239        #[test]
240        fn serialize_deserialize_vk(seed in any::<u64>()) {
241            let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
242            let sk = BlsSigningKey::generate(&mut rng);
243            let vk = BlsVerificationKey::from(&sk);
244            let vk_bytes = vk.to_bytes();
245            let vk2 = BlsVerificationKey::from_bytes(&vk_bytes).unwrap();
246            assert_eq!(vk, vk2);
247            let vkpop = BlsVerificationKeyProofOfPossession::from(&sk);
248            let vkpop_bytes = vkpop.to_bytes();
249            let vkpop2: BlsVerificationKeyProofOfPossession = BlsVerificationKeyProofOfPossession::from_bytes(&vkpop_bytes).unwrap();
250            assert_eq!(vkpop, vkpop2);
251        }
252
253        #[test]
254        fn serialize_deserialize_sk(seed in any::<u64>()) {
255            let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
256            let sk = BlsSigningKey::generate(&mut rng);
257            let sk_bytes: [u8; 32] = sk.to_bytes();
258            let sk2 = BlsSigningKey::from_bytes(&sk_bytes).unwrap();
259            assert_eq!(sk, sk2);
260        }
261
262        #[test]
263        fn batch_verify(num_batches in 2..10usize,
264                              seed in any::<[u8;32]>(),
265        ) {
266            let mut rng = ChaCha20Rng::from_seed(seed);
267            let num_sigs = 10;
268            let mut batch_msgs = Vec::new();
269            let mut batch_vk = Vec::new();
270            let mut batch_sig = Vec::new();
271            for _ in 0..num_batches {
272                let mut msg = [0u8; 32];
273                rng.fill_bytes(&mut msg);
274                let mut mvks = Vec::new();
275                let mut sigs = Vec::new();
276                for _ in 0..num_sigs {
277                    let sk = BlsSigningKey::generate(&mut rng);
278                    let vk = BlsVerificationKey::from(&sk);
279                    let sig = sk.sign(&msg);
280                    sigs.push(sig);
281                    mvks.push(vk);
282                }
283                assert!(BlsSignature::verify_aggregate(&msg, &mvks, &sigs).is_ok());
284                let (agg_vk, agg_sig) = BlsSignature::aggregate(&mvks, &sigs).unwrap();
285                batch_msgs.push(msg.to_vec());
286                batch_vk.push(agg_vk);
287                batch_sig.push(agg_sig);
288            }
289            assert!(BlsSignature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig).is_ok());
290
291            // If we have an invalid signature, the batch verification will fail
292            let mut msg = [0u8; 32];
293            rng.fill_bytes(&mut msg);
294            let sk = BlsSigningKey::generate(&mut rng);
295            let fake_sig = sk.sign(&msg);
296            batch_sig[0] = fake_sig;
297
298            let error = BlsSignature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig).expect_err("Batch verify should fail");
299            assert!(
300                matches!(
301                    error.downcast_ref::<BlsSignatureError>(),
302                    Some(BlsSignatureError::BatchInvalid)
303                ),
304                "Unexpected error: {error:?}");
305        }
306    }
307}