1use crate::{
6 bls::{
7 BLSPrivateKey, BLSPublicKey, BLSSignature, BLS_PRIVATE_KEY_LENGTH,
8 BLS_PUBLIC_KEY_LENGTH,
9 },
10 hash::{CryptoHash, CryptoHasher},
11 traits::*,
12 CryptoMaterialError, PrivateKey, PublicKey, Signature, SigningKey, Uniform,
13 ValidCryptoMaterial, ValidCryptoMaterialStringExt, VerifyingKey,
14};
15use anyhow::{anyhow, Result};
16pub use bls_signatures::{
17 aggregate, hash as bls_hash, PrivateKey as RawPrivateKey,
18 PublicKey as RawPublicKey, Serialize as BLSSerialize,
19 Signature as RawSignature,
20};
21use core::convert::TryFrom;
22use diem_crypto_derive::{
23 DeserializeKey, SerializeKey, SilentDebug, SilentDisplay,
24};
25use mirai_annotations::*;
26use rand::Rng;
27use serde::Serialize;
28use std::fmt;
29
30const MAX_NUM_OF_KEYS: usize = 300;
31const BITMAP_NUM_OF_BYTES: usize = 40;
32
33#[derive(
35 DeserializeKey, Eq, PartialEq, SilentDisplay, SilentDebug, SerializeKey,
36)]
37pub struct MultiBLSPrivateKey {
38 private_keys: Vec<BLSPrivateKey>,
39}
40
41#[cfg(feature = "assert-private-keys-not-cloneable")]
42static_assertions::assert_not_impl_any!(MultiBLSPrivateKey: Clone);
43
44#[derive(Clone, DeserializeKey, Eq, PartialEq, SerializeKey)]
46pub struct MultiBLSPublicKey {
47 public_keys: Vec<BLSPublicKey>,
48}
49
50#[cfg(mirai)]
51use crate::tags::ValidatedPublicKeyTag;
52#[cfg(not(mirai))]
53struct ValidatedPublicKeyTag {}
54
55#[derive(DeserializeKey, Clone, SerializeKey, PartialEq)]
57pub struct MultiBLSSignature {
58 bitmap: [u8; BITMAP_NUM_OF_BYTES],
59 signature: RawSignature,
60}
61
62impl MultiBLSPrivateKey {
63 pub fn new(
65 private_keys: Vec<BLSPrivateKey>,
66 ) -> std::result::Result<Self, CryptoMaterialError> {
67 Ok(MultiBLSPrivateKey { private_keys })
68 }
69
70 pub fn to_bytes(&self) -> Vec<u8> { to_bytes(&self.private_keys) }
72}
73
74impl MultiBLSPublicKey {
75 pub fn new(public_keys: Vec<BLSPublicKey>) -> Self {
77 MultiBLSPublicKey { public_keys }
78 }
79
80 pub fn public_keys(&self) -> &Vec<BLSPublicKey> { &self.public_keys }
82
83 pub fn to_bytes(&self) -> Vec<u8> { to_bytes(&self.public_keys) }
85}
86
87impl From<&BLSPrivateKey> for MultiBLSPrivateKey {
94 fn from(bls_private_key: &BLSPrivateKey) -> Self {
95 MultiBLSPrivateKey {
96 private_keys: vec![BLSPrivateKey::try_from(
97 &bls_private_key.to_bytes()[..],
98 )
99 .unwrap()],
100 }
101 }
102}
103
104impl PrivateKey for MultiBLSPrivateKey {
105 type PublicKeyMaterial = MultiBLSPublicKey;
106}
107
108impl SigningKey for MultiBLSPrivateKey {
109 type SignatureMaterial = MultiBLSSignature;
110 type VerifyingKeyMaterial = MultiBLSPublicKey;
111
112 fn sign<T: CryptoHash + Serialize>(
113 &self, message: &T,
114 ) -> MultiBLSSignature {
115 let signatures: Vec<RawSignature> = self
116 .private_keys
117 .iter()
118 .enumerate()
119 .map(|(_, item)| item.sign(message).raw())
120 .collect();
121
122 MultiBLSSignature {
123 bitmap: [255; BITMAP_NUM_OF_BYTES],
124 signature: aggregate(&signatures).unwrap(),
125 }
126 }
127
128 #[cfg(any(test, feature = "fuzzing"))]
129 fn sign_arbitrary_message(&self, message: &[u8]) -> MultiBLSSignature {
130 let signatures: Vec<RawSignature> = self
131 .private_keys
132 .iter()
133 .enumerate()
134 .map(|(_, item)| item.sign_arbitrary_message(message).raw())
135 .collect();
136
137 MultiBLSSignature {
138 bitmap: [255; BITMAP_NUM_OF_BYTES],
139 signature: aggregate(&signatures).unwrap(),
140 }
141 }
142}
143
144impl Uniform for MultiBLSPrivateKey {
146 fn generate<R>(rng: &mut R) -> Self
147 where R: ::rand::RngCore + ::rand::CryptoRng {
148 let num_of_keys = rng.gen_range(1..=MAX_NUM_OF_KEYS);
149 let mut private_keys: Vec<BLSPrivateKey> =
150 Vec::with_capacity(num_of_keys);
151 for _ in 0..num_of_keys {
152 private_keys
153 .push(BLSPrivateKey::from(RawPrivateKey::generate(rng)));
154 }
155 MultiBLSPrivateKey { private_keys }
156 }
157}
158
159impl TryFrom<&[u8]> for MultiBLSPrivateKey {
160 type Error = CryptoMaterialError;
161
162 fn try_from(
165 bytes: &[u8],
166 ) -> std::result::Result<MultiBLSPrivateKey, CryptoMaterialError> {
167 if bytes.is_empty() {
168 return Err(CryptoMaterialError::WrongLengthError);
169 }
170
171 let private_keys: Result<Vec<BLSPrivateKey>, _> = bytes
172 .chunks_exact(BLS_PRIVATE_KEY_LENGTH)
173 .map(BLSPrivateKey::try_from)
174 .collect();
175
176 private_keys.map(|private_keys| MultiBLSPrivateKey { private_keys })
177 }
178}
179
180impl Length for MultiBLSPrivateKey {
181 fn length(&self) -> usize {
182 self.private_keys.len() * BLS_PRIVATE_KEY_LENGTH
183 }
184}
185
186impl ValidCryptoMaterial for MultiBLSPrivateKey {
187 fn to_bytes(&self) -> Vec<u8> { self.to_bytes() }
188}
189
190impl Genesis for MultiBLSPrivateKey {
191 fn genesis() -> Self {
192 let mut buf = [0u8; BLS_PRIVATE_KEY_LENGTH];
193 buf[BLS_PRIVATE_KEY_LENGTH - 1] = 1u8;
194 MultiBLSPrivateKey {
195 private_keys: vec![BLSPrivateKey::try_from(buf.as_ref()).unwrap()],
196 }
197 }
198}
199
200impl From<BLSPublicKey> for MultiBLSPublicKey {
207 fn from(ed_public_key: BLSPublicKey) -> Self {
208 MultiBLSPublicKey {
209 public_keys: vec![ed_public_key],
210 }
211 }
212}
213
214impl From<&MultiBLSPrivateKey> for MultiBLSPublicKey {
217 fn from(private_key: &MultiBLSPrivateKey) -> Self {
218 let public_keys = private_key
219 .private_keys
220 .iter()
221 .map(PrivateKey::public_key)
222 .collect();
223 MultiBLSPublicKey { public_keys }
224 }
225}
226
227impl PublicKey for MultiBLSPublicKey {
229 type PrivateKeyMaterial = MultiBLSPrivateKey;
230}
231
232#[allow(clippy::derive_hash_xor_eq)]
233impl std::hash::Hash for MultiBLSPublicKey {
234 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
235 let encoded_pubkey = self.to_bytes();
236 state.write(&encoded_pubkey);
237 }
238}
239
240impl TryFrom<&[u8]> for MultiBLSPublicKey {
241 type Error = CryptoMaterialError;
242
243 fn try_from(
247 bytes: &[u8],
248 ) -> std::result::Result<MultiBLSPublicKey, CryptoMaterialError> {
249 if bytes.is_empty() {
250 return Err(CryptoMaterialError::WrongLengthError);
251 }
252 let public_keys: Result<Vec<BLSPublicKey>, _> = bytes
253 .chunks_exact(BLS_PUBLIC_KEY_LENGTH)
254 .map(BLSPublicKey::try_from)
255 .collect();
256 public_keys.map(|public_keys| {
257 let public_key = MultiBLSPublicKey { public_keys };
258 add_tag!(&public_key, ValidatedPublicKeyTag);
259 public_key
260 })
261 }
262}
263
264impl VerifyingKey for MultiBLSPublicKey {
267 type SignatureMaterial = MultiBLSSignature;
268 type SigningKeyMaterial = MultiBLSPrivateKey;
269}
270
271impl fmt::Display for MultiBLSPublicKey {
272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
273 write!(f, "{}", hex::encode(&self.to_bytes()))
274 }
275}
276
277impl fmt::Debug for MultiBLSPublicKey {
278 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279 write!(f, "MultiBLSPublicKey({})", self)
280 }
281}
282
283impl Length for MultiBLSPublicKey {
284 fn length(&self) -> usize { self.public_keys.len() * BLS_PUBLIC_KEY_LENGTH }
285}
286
287impl ValidCryptoMaterial for MultiBLSPublicKey {
288 fn to_bytes(&self) -> Vec<u8> { self.to_bytes() }
289}
290
291impl MultiBLSSignature {
292 pub fn new(
294 signatures: Vec<(BLSSignature, usize)>,
295 ) -> std::result::Result<Self, CryptoMaterialError> {
296 let num_of_sigs = signatures.len();
297 if num_of_sigs == 0 || num_of_sigs > MAX_NUM_OF_KEYS {
298 return Err(CryptoMaterialError::ValidationError);
299 }
300 let mut bitmap = [0u8; BITMAP_NUM_OF_BYTES];
301 let (sigs, indexes): (Vec<_>, Vec<_>) =
302 signatures.iter().cloned().unzip();
303 for i in indexes {
304 if i >= MAX_NUM_OF_KEYS {
305 return Err(CryptoMaterialError::ValidationError);
306 }
307 if bitmap_get_bit(bitmap, i) {
308 return Err(CryptoMaterialError::BitVecError(
309 "Duplicate signature index".to_string(),
310 ));
311 } else {
312 bitmap_set_bit(&mut bitmap, i as usize);
313 }
314 }
315
316 let raw_signatures: Vec<RawSignature> =
317 sigs.into_iter().map(|sig| sig.raw()).collect();
318 let signature = match aggregate(&raw_signatures) {
319 Ok(signature) => Ok(signature),
320 Err(_) => Err(CryptoMaterialError::AggregateError),
321 }?;
322 Ok(Self { bitmap, signature })
323 }
324
325 pub fn raw(&self) -> &RawSignature { &self.signature }
327
328 pub fn to_bytes(&self) -> Vec<u8> {
330 let mut bytes: Vec<u8> = vec![];
331 bytes.extend(&self.bitmap[..]);
332 bytes.extend(&self.signature.as_bytes()[..]);
333 bytes
334 }
335}
336
337impl Eq for MultiBLSSignature {}
342
343impl TryFrom<&[u8]> for MultiBLSSignature {
344 type Error = CryptoMaterialError;
345
346 fn try_from(
349 bytes: &[u8],
350 ) -> std::result::Result<MultiBLSSignature, CryptoMaterialError> {
351 if bytes.len() < BITMAP_NUM_OF_BYTES {
352 return Err(CryptoMaterialError::DeserializationError);
353 }
354 let mut bitmap = [0u8; BITMAP_NUM_OF_BYTES];
355 for i in 0..BITMAP_NUM_OF_BYTES {
356 bitmap[i] = bytes[i];
357 }
358 let signature =
359 match RawSignature::from_bytes(&bytes[BITMAP_NUM_OF_BYTES..]) {
360 Ok(signature) => signature,
361 Err(_) => {
362 return Err(CryptoMaterialError::DeserializationError)
363 }
364 };
365 Ok(Self { bitmap, signature })
366 }
367}
368
369#[allow(clippy::derive_hash_xor_eq)]
370impl std::hash::Hash for MultiBLSSignature {
371 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
372 let encoded_signature = self.to_bytes();
373 state.write(&encoded_signature);
374 }
375}
376
377impl fmt::Display for MultiBLSSignature {
378 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379 write!(f, "{}", hex::encode(&self.to_bytes()[..]))
380 }
381}
382
383impl fmt::Debug for MultiBLSSignature {
384 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385 write!(f, "MultiBLSSignature({})", self)
386 }
387}
388
389impl ValidCryptoMaterial for MultiBLSSignature {
390 fn to_bytes(&self) -> Vec<u8> { self.to_bytes() }
391}
392
393impl Signature for MultiBLSSignature {
394 type SigningKeyMaterial = MultiBLSPrivateKey;
395 type VerifyingKeyMaterial = MultiBLSPublicKey;
396
397 fn verify<T: CryptoHash + Serialize>(
398 &self, message: &T, public_key: &MultiBLSPublicKey,
399 ) -> Result<()> {
400 precondition!(has_tag!(public_key, ValidatedPublicKeyTag));
403 let mut bytes = <T as CryptoHash>::Hasher::seed().to_vec();
404 bcs::serialize_into(&mut bytes, &message)
405 .map_err(|_| CryptoMaterialError::SerializationError)?;
406 Self::verify_arbitrary_msg(self, &bytes, public_key)
407 }
408
409 fn verify_arbitrary_msg(
413 &self, message: &[u8], public_key: &MultiBLSPublicKey,
414 ) -> Result<()> {
415 precondition!(has_tag!(public_key, ValidatedPublicKeyTag));
416 match bitmap_last_set_bit(self.bitmap) {
417 Some(last_bit)
418 if last_bit as usize <= public_key.public_keys().len() =>
419 {
420 ()
421 }
422 _ => {
423 return Err(anyhow!(
424 "{}",
425 CryptoMaterialError::BitVecError(
426 "Signature index is out of range".to_string()
427 )
428 ))
429 }
430 };
431
432 let mut raw_public_keys: Vec<RawPublicKey> = vec![];
433 for i in 0..public_key.public_keys().len() {
434 if bitmap_get_bit(self.bitmap, i) {
435 raw_public_keys.push(public_key.public_keys()[i].clone().raw())
436 }
437 }
438 match bls_signatures::verify_same_message(
439 &self.signature,
440 message,
441 &raw_public_keys,
442 ) {
443 true => Ok(()),
444 false => Err(anyhow!("Invalid BLS signature!")),
445 }
446 }
447}
448
449impl From<BLSSignature> for MultiBLSSignature {
450 fn from(bls_signature: BLSSignature) -> Self {
451 let mut bitmap = [0u8; BITMAP_NUM_OF_BYTES];
452 bitmap[0] = 1;
453 MultiBLSSignature {
454 bitmap,
455 signature: bls_signature.raw(),
456 }
457 }
458}
459
460fn to_bytes<T: ValidCryptoMaterial>(keys: &[T]) -> Vec<u8> {
466 let bytes: Vec<u8> = keys
467 .iter()
468 .flat_map(ValidCryptoMaterial::to_bytes)
469 .collect();
470 bytes
471}
472
473fn bitmap_set_bit(input: &mut [u8; BITMAP_NUM_OF_BYTES], index: usize) {
474 let bucket = index / 8;
475 let bucket_pos = index - (bucket * 8);
478 input[bucket] |= 128 >> bucket_pos as u8;
479}
480
481fn bitmap_get_bit(input: [u8; BITMAP_NUM_OF_BYTES], index: usize) -> bool {
483 let bucket = index / 8;
484 let bucket_pos = index - (bucket * 8);
487 (input[bucket] & (128 >> bucket_pos as u8)) != 0
488}
489
490fn bitmap_last_set_bit(input: [u8; BITMAP_NUM_OF_BYTES]) -> Option<u8> {
492 input
493 .iter()
494 .rev()
495 .enumerate()
496 .find(|(_, byte)| byte != &&0u8)
497 .map(|(i, byte)| {
498 (8 * (BITMAP_NUM_OF_BYTES - i) - byte.trailing_zeros() as usize - 1)
499 as u8
500 })
501}
502
503#[test]
504fn bitmap_tests() {
505 let mut bitmap = [0u8; BITMAP_NUM_OF_BYTES];
506 bitmap[0] = 0b0100_0000u8;
507 bitmap[1] = 0b1111_1111u8;
508 bitmap[3] = 0b1000_0000u8;
509 assert!(!bitmap_get_bit(bitmap, 0));
510 assert!(bitmap_get_bit(bitmap, 1));
511 for i in 8..16 {
512 assert!(bitmap_get_bit(bitmap, i));
513 }
514 for i in 16..24 {
515 assert!(!bitmap_get_bit(bitmap, i));
516 }
517 assert!(bitmap_get_bit(bitmap, 24));
518 assert!(!bitmap_get_bit(bitmap, 31));
519 assert_eq!(bitmap_last_set_bit(bitmap), Some(24));
520
521 bitmap_set_bit(&mut bitmap, 30);
522 assert!(bitmap_get_bit(bitmap, 30));
523 assert_eq!(bitmap_last_set_bit(bitmap), Some(30));
524}