mithril_stm/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!(SigningKey, SigningKeyVisitor, 32);
86impl_serde!(VerificationKey, VerificationKeyVisitor, 96);
87impl_serde!(ProofOfPossession, ProofOfPossessionVisitor, 96);
88impl_serde!(Signature, 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::SeedableRng;
96
97 use crate::bls_multi_signature::helper::unsafe_helpers::{p1_affine_to_sig, p2_affine_to_vk};
98 use crate::error::{MultiSignatureError, RegisterError};
99 use crate::key_reg::KeyReg;
100
101 use super::*;
102
103 impl PartialEq for SigningKey {
104 fn eq(&self, other: &Self) -> bool {
105 self.to_blst_sk().to_bytes() == other.to_blst_sk().to_bytes()
106 }
107 }
108
109 impl Eq for SigningKey {}
110
111 proptest! {
112 #![proptest_config(ProptestConfig::with_cases(1000))]
113
114 #[test]
115 fn test_sig(
116 msg in prop::collection::vec(any::<u8>(), 1..128),
117 seed in any::<[u8;32]>(),
118 ) {
119 let sk = SigningKey::gen(&mut ChaCha20Rng::from_seed(seed));
120 let vk = VerificationKey::from(&sk);
121 let sig = sk.sign(&msg);
122
123 sig.verify(&msg, &vk).unwrap();
124 }
125
126 #[test]
127 fn test_invalid_sig(msg in prop::collection::vec(any::<u8>(), 1..128), seed in any::<[u8;32]>()) {
128 let mut rng = ChaCha20Rng::from_seed(seed);
129 let sk1 = SigningKey::gen(&mut rng);
130 let vk1 = VerificationKey::from(&sk1);
131 let sk2 = SigningKey::gen(&mut rng);
132 let fake_sig = sk2.sign(&msg);
133
134 let result = fake_sig.verify(&msg, &vk1);
135 assert_eq!(result, Err(MultiSignatureError::SignatureInvalid(fake_sig)));
136 }
137
138 #[test]
139 fn test_infinity_sig(msg in prop::collection::vec(any::<u8>(), 1..128), seed in any::<[u8;32]>()) {
140 let mut rng = ChaCha20Rng::from_seed(seed);
141 let sk = SigningKey::gen(&mut rng);
142 let vk = VerificationKey::from(&sk);
143
144 let p1 = blst_p1::default();
145 let sig_infinity = Signature(p1_affine_to_sig(&p1));
146
147 let result = sig_infinity.verify(&msg, &vk);
148 assert_eq!(result, Err(MultiSignatureError::SignatureInfinity(sig_infinity)));
149 }
150
151 #[test]
152 fn test_infinity_vk(seed in any::<[u8;32]>()) {
153 let mut rng = ChaCha20Rng::from_seed(seed);
154 let sk = SigningKey::gen(&mut rng);
155 let pop = ProofOfPossession::from(&sk);
156
157 let p2 = blst_p2::default();
158 let vk_infinity = VerificationKey(p2_affine_to_vk(&p2));
159 let vkpop_infinity = VerificationKeyPoP { vk: vk_infinity, pop };
160
161 let result = vkpop_infinity.check();
162 assert_eq!(result, Err(MultiSignatureError::VerificationKeyInfinity(Box::new(vkpop_infinity.vk))));
163 }
164
165 #[test]
166 fn test_keyreg_with_infinity_vk(num_sigs in 2..16usize, seed in any::<[u8;32]>()) {
167 let mut rng = ChaCha20Rng::from_seed(seed);
168 let mut kr = KeyReg::init();
169
170 let sk = SigningKey::gen(&mut rng);
171 let pop = ProofOfPossession::from(&sk);
172 let p2 = blst_p2::default();
173 let vk_infinity = VerificationKey(p2_affine_to_vk(&p2));
174 let vkpop_infinity = VerificationKeyPoP { vk: vk_infinity, pop };
175
176 for _ in 0..num_sigs {
177 let sk = SigningKey::gen(&mut rng);
178 let vkpop = VerificationKeyPoP::from(&sk);
179 let _ = kr.register(1, vkpop);
180 }
181
182 let result = kr.register(1, vkpop_infinity);
183 assert_eq!(result, Err(RegisterError::VerificationKeyInfinity(Box::new(vkpop_infinity.vk))));
184 }
185
186 #[test]
187 fn test_aggregate_sig(msg in prop::collection::vec(any::<u8>(), 1..128),
188 num_sigs in 2..16,
189 seed in any::<[u8;32]>(),
190 ) {
191 let mut rng = ChaCha20Rng::from_seed(seed);
192 let mut mvks = Vec::new();
193 let mut sigs = Vec::new();
194 for _ in 0..num_sigs {
195 let sk = SigningKey::gen(&mut rng);
196 let vk = VerificationKey::from(&sk);
197 let sig = sk.sign(&msg);
198 assert!(sig.verify(&msg, &vk).is_ok());
199 sigs.push(sig);
200 mvks.push(vk);
201 }
202
203 let result = Signature::verify_aggregate(&msg, &mvks, &sigs);
204 assert!(result.is_ok(), "Aggregate verification failed {result:?}");
205 }
206
207 #[test]
208 fn test_eval_sanity_check(msg in prop::collection::vec(any::<u8>(), 1..128),
209 idx in any::<u64>(),
210 seed in any::<[u8;32]>()) {
211 let sk = SigningKey::gen(&mut ChaCha20Rng::from_seed(seed));
212 let sig = sk.sign(&msg);
213 sig.eval(&msg, idx);
214 }
215
216 #[test]
217 fn serialize_deserialize_vk(seed in any::<u64>()) {
218 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
219 let sk = SigningKey::gen(&mut rng);
220 let vk = VerificationKey::from(&sk);
221 let vk_bytes = vk.to_bytes();
222 let vk2 = VerificationKey::from_bytes(&vk_bytes).unwrap();
223 assert_eq!(vk, vk2);
224 let vkpop = VerificationKeyPoP::from(&sk);
225 let vkpop_bytes = vkpop.to_bytes();
226 let vkpop2: VerificationKeyPoP = VerificationKeyPoP::from_bytes(&vkpop_bytes).unwrap();
227 assert_eq!(vkpop, vkpop2);
228
229 let encoded = bincode::serde::encode_to_vec(vk, bincode::config::legacy()).unwrap();
231 assert_eq!(encoded, vk_bytes);
232 let (decoded,_) = bincode::serde::decode_from_slice::<VerificationKey,_>(&encoded, bincode::config::legacy()).unwrap();
233 assert_eq!(vk, decoded);
234 let encoded = bincode::serde::encode_to_vec(vkpop, bincode::config::legacy()).unwrap();
235 let (decoded,_) = bincode::serde::decode_from_slice::<VerificationKeyPoP,_>(&encoded, bincode::config::legacy()).unwrap();
236 assert_eq!(vkpop, decoded);
237 }
238
239 #[test]
240 fn serialize_deserialize_sk(seed in any::<u64>()) {
241 let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(seed);
242 let sk = SigningKey::gen(&mut rng);
243 let sk_bytes: [u8; 32] = sk.to_bytes();
244 let sk2 = SigningKey::from_bytes(&sk_bytes).unwrap();
245 assert_eq!(sk, sk2);
246
247 let encoded = bincode::serde::encode_to_vec(&sk, bincode::config::legacy()).unwrap();
249 let (decoded,_) = bincode::serde::decode_from_slice::<SigningKey,_>(&encoded, bincode::config::legacy()).unwrap();
250 assert_eq!(sk, decoded);
251
252 let (decoded_bytes,_) = bincode::serde::decode_from_slice::<SigningKey,_>(&sk_bytes, bincode::config::legacy()).unwrap();
254 assert_eq!(sk, decoded_bytes);
255 }
256
257 #[test]
258 fn batch_verify(num_batches in 2..10usize,
259 seed in any::<[u8;32]>(),
260 ) {
261 let mut rng = ChaCha20Rng::from_seed(seed);
262 let num_sigs = 10;
263 let mut batch_msgs = Vec::new();
264 let mut batch_vk = Vec::new();
265 let mut batch_sig = Vec::new();
266 for _ in 0..num_batches {
267 let mut msg = [0u8; 32];
268 rng.fill_bytes(&mut msg);
269 let mut mvks = Vec::new();
270 let mut sigs = Vec::new();
271 for _ in 0..num_sigs {
272 let sk = SigningKey::gen(&mut rng);
273 let vk = VerificationKey::from(&sk);
274 let sig = sk.sign(&msg);
275 sigs.push(sig);
276 mvks.push(vk);
277 }
278 assert!(Signature::verify_aggregate(&msg, &mvks, &sigs).is_ok());
279 let (agg_vk, agg_sig) = Signature::aggregate(&mvks, &sigs).unwrap();
280 batch_msgs.push(msg.to_vec());
281 batch_vk.push(agg_vk);
282 batch_sig.push(agg_sig);
283 }
284 assert!(Signature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig).is_ok());
285
286 let mut msg = [0u8; 32];
288 rng.fill_bytes(&mut msg);
289 let sk = SigningKey::gen(&mut rng);
290 let fake_sig = sk.sign(&msg);
291 batch_sig[0] = fake_sig;
292
293 let batch_result = Signature::batch_verify_aggregates(&batch_msgs, &batch_vk, &batch_sig);
294 assert_eq!(batch_result, Err(MultiSignatureError::BatchInvalid));
295 }
296 }
297}