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::derived_hash_with_manual_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 pub fn get_signers<T: Clone>(&self, all_signers: &[T]) -> Result<Vec<T>> {
339 let mut signers = Vec::with_capacity(all_signers.len());
340 if let Some(last_bit_index) = bitmap_last_set_bit(self.bitmap) {
341 if last_bit_index as usize >= all_signers.len() {
342 return Err(anyhow!(
343 "{}",
344 CryptoMaterialError::BitVecError(
345 "Signature index is out of range".to_string()
346 )
347 ));
348 }
349 }
350 if all_signers.len() > self.bitmap.len() * 8 {
351 return Err(anyhow!(
352 "{}",
353 CryptoMaterialError::BitVecError(
354 "signer index is out of range".to_string()
355 )
356 ));
357 }
358 for i in 0..all_signers.len() {
359 if bitmap_get_bit(self.bitmap, i) {
360 signers.push(all_signers[i].clone());
361 }
362 }
363 Ok(signers)
364 }
365}
366
367impl Eq for MultiBLSSignature {}
372
373impl TryFrom<&[u8]> for MultiBLSSignature {
374 type Error = CryptoMaterialError;
375
376 fn try_from(
379 bytes: &[u8],
380 ) -> std::result::Result<MultiBLSSignature, CryptoMaterialError> {
381 if bytes.len() < BITMAP_NUM_OF_BYTES {
382 return Err(CryptoMaterialError::DeserializationError);
383 }
384 let mut bitmap = [0u8; BITMAP_NUM_OF_BYTES];
385 for i in 0..BITMAP_NUM_OF_BYTES {
386 bitmap[i] = bytes[i];
387 }
388 let signature =
389 match RawSignature::from_bytes(&bytes[BITMAP_NUM_OF_BYTES..]) {
390 Ok(signature) => signature,
391 Err(_) => {
392 return Err(CryptoMaterialError::DeserializationError)
393 }
394 };
395 Ok(Self { bitmap, signature })
396 }
397}
398
399#[allow(clippy::derived_hash_with_manual_eq)]
400impl std::hash::Hash for MultiBLSSignature {
401 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
402 let encoded_signature = self.to_bytes();
403 state.write(&encoded_signature);
404 }
405}
406
407impl fmt::Display for MultiBLSSignature {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 write!(f, "{}", hex::encode(&self.to_bytes()[..]))
410 }
411}
412
413impl fmt::Debug for MultiBLSSignature {
414 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
415 write!(f, "MultiBLSSignature({})", self)
416 }
417}
418
419impl ValidCryptoMaterial for MultiBLSSignature {
420 fn to_bytes(&self) -> Vec<u8> { self.to_bytes() }
421}
422
423impl Signature for MultiBLSSignature {
424 type SigningKeyMaterial = MultiBLSPrivateKey;
425 type VerifyingKeyMaterial = MultiBLSPublicKey;
426
427 fn verify<T: CryptoHash + Serialize>(
428 &self, message: &T, public_key: &MultiBLSPublicKey,
429 ) -> Result<()> {
430 precondition!(has_tag!(public_key, ValidatedPublicKeyTag));
433 let mut bytes = <T as CryptoHash>::Hasher::seed().to_vec();
434 bcs::serialize_into(&mut bytes, &message)
435 .map_err(|_| CryptoMaterialError::SerializationError)?;
436 Self::verify_arbitrary_msg(self, &bytes, public_key)
437 }
438
439 fn verify_arbitrary_msg(
443 &self, message: &[u8], public_key: &MultiBLSPublicKey,
444 ) -> Result<()> {
445 precondition!(has_tag!(public_key, ValidatedPublicKeyTag));
446 match bitmap_last_set_bit(self.bitmap) {
447 Some(last_bit)
448 if last_bit as usize <= public_key.public_keys().len() =>
449 {
450 ()
451 }
452 _ => {
453 return Err(anyhow!(
454 "{}",
455 CryptoMaterialError::BitVecError(
456 "Signature index is out of range".to_string()
457 )
458 ))
459 }
460 };
461
462 let mut raw_public_keys: Vec<RawPublicKey> = vec![];
463 for i in 0..public_key.public_keys().len() {
464 if bitmap_get_bit(self.bitmap, i) {
465 raw_public_keys.push(public_key.public_keys()[i].clone().raw())
466 }
467 }
468 match bls_signatures::verify_same_message(
469 &self.signature,
470 message,
471 &raw_public_keys,
472 ) {
473 true => Ok(()),
474 false => Err(anyhow!("Invalid BLS signature!")),
475 }
476 }
477}
478
479impl From<BLSSignature> for MultiBLSSignature {
480 fn from(bls_signature: BLSSignature) -> Self {
481 let mut bitmap = [0u8; BITMAP_NUM_OF_BYTES];
482 bitmap[0] = 1;
483 MultiBLSSignature {
484 bitmap,
485 signature: bls_signature.raw(),
486 }
487 }
488}
489
490fn to_bytes<T: ValidCryptoMaterial>(keys: &[T]) -> Vec<u8> {
496 let bytes: Vec<u8> = keys
497 .iter()
498 .flat_map(ValidCryptoMaterial::to_bytes)
499 .collect();
500 bytes
501}
502
503fn bitmap_set_bit(input: &mut [u8; BITMAP_NUM_OF_BYTES], index: usize) {
504 let bucket = index / 8;
505 let bucket_pos = index - (bucket * 8);
508 input[bucket] |= 128 >> bucket_pos as u8;
509}
510
511fn bitmap_get_bit(input: [u8; BITMAP_NUM_OF_BYTES], index: usize) -> bool {
513 let bucket = index / 8;
514 let bucket_pos = index - (bucket * 8);
517 (input[bucket] & (128 >> bucket_pos as u8)) != 0
518}
519
520fn bitmap_last_set_bit(input: [u8; BITMAP_NUM_OF_BYTES]) -> Option<u8> {
522 input
523 .iter()
524 .rev()
525 .enumerate()
526 .find(|(_, byte)| byte != &&0u8)
527 .map(|(i, byte)| {
528 (8 * (BITMAP_NUM_OF_BYTES - i) - byte.trailing_zeros() as usize - 1)
529 as u8
530 })
531}
532
533#[test]
534fn bitmap_tests() {
535 let mut bitmap = [0u8; BITMAP_NUM_OF_BYTES];
536 bitmap[0] = 0b0100_0000u8;
537 bitmap[1] = 0b1111_1111u8;
538 bitmap[3] = 0b1000_0000u8;
539 assert!(!bitmap_get_bit(bitmap, 0));
540 assert!(bitmap_get_bit(bitmap, 1));
541 for i in 8..16 {
542 assert!(bitmap_get_bit(bitmap, i));
543 }
544 for i in 16..24 {
545 assert!(!bitmap_get_bit(bitmap, i));
546 }
547 assert!(bitmap_get_bit(bitmap, 24));
548 assert!(!bitmap_get_bit(bitmap, 31));
549 assert_eq!(bitmap_last_set_bit(bitmap), Some(24));
550
551 bitmap_set_bit(&mut bitmap, 30);
552 assert!(bitmap_get_bit(bitmap, 30));
553 assert_eq!(bitmap_last_set_bit(bitmap), Some(30));
554}