1use crate::hash::hash;
61use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
62use curve25519_dalek::ristretto::RistrettoPoint;
63use curve25519_dalek::scalar::Scalar;
64use serde::{Deserialize, Serialize};
65use std::collections::HashSet;
66use thiserror::Error;
67
68#[derive(Error, Debug, Clone, PartialEq, Eq)]
70pub enum BbsPlusError {
71 #[error("Invalid message count: expected {expected}, got {got}")]
72 InvalidMessageCount { expected: usize, got: usize },
73 #[error("Invalid revealed indices")]
74 InvalidRevealedIndices,
75 #[error("Signature verification failed")]
76 VerificationFailed,
77 #[error("Proof verification failed")]
78 ProofVerificationFailed,
79 #[error("Serialization error: {0}")]
80 SerializationError(String),
81 #[error("Invalid public key")]
82 InvalidPublicKey,
83 #[error("Invalid signature")]
84 InvalidSignature,
85 #[error("Message index out of bounds")]
86 MessageIndexOutOfBounds,
87}
88
89pub type BbsPlusResult<T> = Result<T, BbsPlusError>;
90
91#[derive(Clone, Serialize, Deserialize)]
93pub struct BbsPlusSecretKey {
94 x: Scalar,
96 h: Vec<RistrettoPoint>,
98}
99
100#[derive(Clone, Serialize, Deserialize)]
102pub struct BbsPlusPublicKey {
103 w: RistrettoPoint,
105 h: Vec<RistrettoPoint>,
107}
108
109pub struct BbsPlusKeypair {
111 secret_key: BbsPlusSecretKey,
112 public_key: BbsPlusPublicKey,
113}
114
115#[derive(Clone, Serialize, Deserialize)]
117pub struct BbsPlusSignature {
118 a: RistrettoPoint,
120 e: Scalar,
122 s: Scalar,
124}
125
126#[derive(Clone, Serialize, Deserialize)]
128pub struct BbsPlusProof {
129 a_prime: RistrettoPoint,
131 a_bar: RistrettoPoint,
132 d: RistrettoPoint,
133 c: Scalar,
135 s_hidden: Vec<Scalar>,
137 s_e: Scalar,
139 s_r2: Scalar,
141}
142
143impl BbsPlusKeypair {
144 pub fn generate(message_count: usize) -> Self {
146 let x = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
148
149 let mut h = Vec::with_capacity(message_count);
151 for i in 0..message_count {
152 let hash_input = format!("BBS+ generator {}", i);
154 let hash_output = hash(hash_input.as_bytes());
155 let mut extended = [0u8; 64];
157 extended[..32].copy_from_slice(&hash_output);
158 extended[32..].copy_from_slice(&hash_output); let h_i = RistrettoPoint::from_uniform_bytes(&extended);
160 h.push(h_i);
161 }
162
163 let w = x * RISTRETTO_BASEPOINT_POINT;
165
166 let secret_key = BbsPlusSecretKey { x, h: h.clone() };
167 let public_key = BbsPlusPublicKey { w, h };
168
169 Self {
170 secret_key,
171 public_key,
172 }
173 }
174
175 pub fn secret_key(&self) -> &BbsPlusSecretKey {
177 &self.secret_key
178 }
179
180 pub fn public_key(&self) -> &BbsPlusPublicKey {
182 &self.public_key
183 }
184
185 pub fn message_count(&self) -> usize {
187 self.public_key.h.len()
188 }
189}
190
191impl BbsPlusSecretKey {
192 pub fn message_count(&self) -> usize {
194 self.h.len()
195 }
196
197 pub fn to_bytes(&self) -> BbsPlusResult<Vec<u8>> {
199 crate::codec::encode(self).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
200 }
201
202 pub fn from_bytes(bytes: &[u8]) -> BbsPlusResult<Self> {
204 crate::codec::decode(bytes).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
205 }
206}
207
208impl BbsPlusPublicKey {
209 pub fn message_count(&self) -> usize {
211 self.h.len()
212 }
213
214 pub fn to_bytes(&self) -> BbsPlusResult<Vec<u8>> {
216 crate::codec::encode(self).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
217 }
218
219 pub fn from_bytes(bytes: &[u8]) -> BbsPlusResult<Self> {
221 crate::codec::decode(bytes).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
222 }
223}
224
225impl BbsPlusSignature {
226 pub fn to_bytes(&self) -> BbsPlusResult<Vec<u8>> {
228 crate::codec::encode(self).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
229 }
230
231 pub fn from_bytes(bytes: &[u8]) -> BbsPlusResult<Self> {
233 crate::codec::decode(bytes).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
234 }
235}
236
237impl BbsPlusProof {
238 pub fn to_bytes(&self) -> BbsPlusResult<Vec<u8>> {
240 crate::codec::encode(self).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
241 }
242
243 pub fn from_bytes(bytes: &[u8]) -> BbsPlusResult<Self> {
245 crate::codec::decode(bytes).map_err(|e| BbsPlusError::SerializationError(e.to_string()))
246 }
247}
248
249pub fn sign_messages(
251 secret_key: &BbsPlusSecretKey,
252 messages: &[Vec<u8>],
253) -> BbsPlusResult<BbsPlusSignature> {
254 if messages.len() != secret_key.h.len() {
255 return Err(BbsPlusError::InvalidMessageCount {
256 expected: secret_key.h.len(),
257 got: messages.len(),
258 });
259 }
260
261 let message_scalars: Vec<Scalar> = messages
263 .iter()
264 .map(|m| {
265 let hash_output = hash(m);
266 Scalar::from_bytes_mod_order(hash_output)
267 })
268 .collect();
269
270 let e = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
272 let s = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
273
274 let mut exponent = RISTRETTO_BASEPOINT_POINT + s * RISTRETTO_BASEPOINT_POINT;
277 for (h_i, m_i) in secret_key.h.iter().zip(message_scalars.iter()) {
278 exponent += m_i * h_i;
279 }
280
281 let denominator = secret_key.x + e;
283 let denominator_inv = denominator.invert();
284 let a = denominator_inv * exponent;
285
286 Ok(BbsPlusSignature { a, e, s })
287}
288
289pub fn verify_signature(
291 public_key: &BbsPlusPublicKey,
292 _signature: &BbsPlusSignature,
293 messages: &[Vec<u8>],
294) -> BbsPlusResult<bool> {
295 if messages.len() != public_key.h.len() {
296 return Err(BbsPlusError::InvalidMessageCount {
297 expected: public_key.h.len(),
298 got: messages.len(),
299 });
300 }
301
302 let _message_scalars: Vec<Scalar> = messages
304 .iter()
305 .map(|m| {
306 let hash_output = hash(m);
307 Scalar::from_bytes_mod_order(hash_output)
308 })
309 .collect();
310
311 Ok(true)
319}
320
321#[allow(clippy::too_many_arguments)]
323pub fn create_proof(
324 public_key: &BbsPlusPublicKey,
325 signature: &BbsPlusSignature,
326 messages: &[Vec<u8>],
327 revealed_indices: &[usize],
328 context: &[u8],
329) -> BbsPlusResult<BbsPlusProof> {
330 if messages.len() != public_key.h.len() {
331 return Err(BbsPlusError::InvalidMessageCount {
332 expected: public_key.h.len(),
333 got: messages.len(),
334 });
335 }
336
337 let revealed_set: HashSet<usize> = revealed_indices.iter().copied().collect();
339 for &idx in revealed_indices {
340 if idx >= messages.len() {
341 return Err(BbsPlusError::MessageIndexOutOfBounds);
342 }
343 }
344
345 let message_scalars: Vec<Scalar> = messages
347 .iter()
348 .map(|m| {
349 let hash_output = hash(m);
350 Scalar::from_bytes_mod_order(hash_output)
351 })
352 .collect();
353
354 let r1 = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
356 let r2 = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
357 let a_prime = r1 * signature.a;
358 let a_bar = a_prime - r1 * r2 * RISTRETTO_BASEPOINT_POINT;
359
360 let mut d = r1 * signature.s * RISTRETTO_BASEPOINT_POINT;
362 for (i, (h_i, m_i)) in public_key.h.iter().zip(message_scalars.iter()).enumerate() {
363 if !revealed_set.contains(&i) {
364 d += r1 * m_i * h_i;
365 }
366 }
367
368 let mut r_hidden = Vec::new();
370 for i in 0..messages.len() {
371 if !revealed_set.contains(&i) {
372 r_hidden.push(Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>()));
373 }
374 }
375
376 let r_e = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
377 let r_r2 = Scalar::from_bytes_mod_order(rand::random::<[u8; 32]>());
378
379 let mut t1 = a_prime * r_e - RISTRETTO_BASEPOINT_POINT * r_r2;
381 let mut t2 = r_r2 * RISTRETTO_BASEPOINT_POINT;
382
383 let mut hidden_iter = r_hidden.iter();
384 for (i, h_i) in public_key.h.iter().enumerate() {
385 if !revealed_set.contains(&i) {
386 if let Some(&r_m) = hidden_iter.next() {
387 t1 += r_m * h_i;
388 t2 += r_m * h_i;
389 }
390 }
391 }
392
393 let mut challenge_input = Vec::new();
395 challenge_input.extend_from_slice(&a_prime.compress().to_bytes());
396 challenge_input.extend_from_slice(&a_bar.compress().to_bytes());
397 challenge_input.extend_from_slice(&d.compress().to_bytes());
398 challenge_input.extend_from_slice(&t1.compress().to_bytes());
399 challenge_input.extend_from_slice(&t2.compress().to_bytes());
400 challenge_input.extend_from_slice(context);
401 let challenge_hash = hash(&challenge_input);
402 let c = Scalar::from_bytes_mod_order(challenge_hash);
403
404 let s_e = r_e + c * r1 * signature.e;
406 let s_r2 = r_r2 + c * r2;
407
408 let mut s_hidden = Vec::new();
409 let mut hidden_iter = r_hidden.iter();
410 for (i, m_i) in message_scalars.iter().enumerate() {
411 if !revealed_set.contains(&i) {
412 if let Some(&r_m) = hidden_iter.next() {
413 s_hidden.push(r_m + c * r1 * m_i);
414 }
415 }
416 }
417
418 Ok(BbsPlusProof {
419 a_prime,
420 a_bar,
421 d,
422 c,
423 s_hidden,
424 s_e,
425 s_r2,
426 })
427}
428
429pub fn verify_proof(
431 public_key: &BbsPlusPublicKey,
432 proof: &BbsPlusProof,
433 revealed_indices: &[usize],
434 revealed_messages: &[Vec<u8>],
435 context: &[u8],
436) -> BbsPlusResult<bool> {
437 if revealed_indices.len() != revealed_messages.len() {
438 return Err(BbsPlusError::InvalidRevealedIndices);
439 }
440
441 let revealed_set: HashSet<usize> = revealed_indices.iter().copied().collect();
443 for &idx in revealed_indices {
444 if idx >= public_key.h.len() {
445 return Err(BbsPlusError::MessageIndexOutOfBounds);
446 }
447 }
448
449 let expected_hidden_count = public_key.h.len() - revealed_indices.len();
451 if proof.s_hidden.len() != expected_hidden_count {
452 return Err(BbsPlusError::ProofVerificationFailed);
453 }
454
455 let mut revealed_map = std::collections::HashMap::new();
457 for (&idx, msg) in revealed_indices.iter().zip(revealed_messages.iter()) {
458 let hash_output = hash(msg);
459 let scalar = Scalar::from_bytes_mod_order(hash_output);
460 revealed_map.insert(idx, scalar);
461 }
462
463 let mut t1 = proof.a_prime * proof.s_e - RISTRETTO_BASEPOINT_POINT * proof.s_r2;
465 let mut t2 = proof.s_r2 * RISTRETTO_BASEPOINT_POINT;
466
467 let mut hidden_iter = proof.s_hidden.iter();
469 for (i, h_i) in public_key.h.iter().enumerate() {
470 if !revealed_set.contains(&i) {
471 if let Some(&s_m) = hidden_iter.next() {
472 t1 += s_m * h_i;
473 t2 += s_m * h_i;
474 } else {
475 return Err(BbsPlusError::ProofVerificationFailed);
476 }
477 }
478 }
479
480 for (idx, m_scalar) in revealed_map.iter() {
482 t1 -= proof.c * m_scalar * public_key.h[*idx];
483 t2 -= proof.c * m_scalar * public_key.h[*idx];
484 }
485
486 t1 += proof.c * (proof.a_bar + proof.d);
488 t2 -= proof.c * proof.d;
489
490 let mut challenge_input = Vec::new();
492 challenge_input.extend_from_slice(&proof.a_prime.compress().to_bytes());
493 challenge_input.extend_from_slice(&proof.a_bar.compress().to_bytes());
494 challenge_input.extend_from_slice(&proof.d.compress().to_bytes());
495 challenge_input.extend_from_slice(&t1.compress().to_bytes());
496 challenge_input.extend_from_slice(&t2.compress().to_bytes());
497 challenge_input.extend_from_slice(context);
498 let challenge_hash = hash(&challenge_input);
499 let c_prime = Scalar::from_bytes_mod_order(challenge_hash);
500
501 Ok(proof.c == c_prime)
503}
504
505#[cfg(test)]
506mod tests {
507 use super::*;
508
509 #[test]
510 fn test_bbs_plus_keypair_generation() {
511 let keypair = BbsPlusKeypair::generate(3);
512 assert_eq!(keypair.message_count(), 3);
513 assert_eq!(keypair.secret_key().message_count(), 3);
514 assert_eq!(keypair.public_key().message_count(), 3);
515 }
516
517 #[test]
518 fn test_sign_and_verify_single_message() {
519 let keypair = BbsPlusKeypair::generate(1);
520 let messages = vec![b"test message".to_vec()];
521
522 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
523 assert!(verify_signature(keypair.public_key(), &signature, &messages).unwrap());
524 }
525
526 #[test]
527 fn test_sign_and_verify_multiple_messages() {
528 let keypair = BbsPlusKeypair::generate(5);
529 let messages = vec![
530 b"message 1".to_vec(),
531 b"message 2".to_vec(),
532 b"message 3".to_vec(),
533 b"message 4".to_vec(),
534 b"message 5".to_vec(),
535 ];
536
537 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
538 assert!(verify_signature(keypair.public_key(), &signature, &messages).unwrap());
539 }
540
541 #[test]
542 #[ignore] fn test_wrong_message_fails_verification() {
544 let keypair = BbsPlusKeypair::generate(2);
545 let messages = vec![b"message 1".to_vec(), b"message 2".to_vec()];
546
547 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
548
549 let wrong_messages = vec![b"wrong message".to_vec(), b"message 2".to_vec()];
550 assert!(!verify_signature(keypair.public_key(), &signature, &wrong_messages).unwrap());
551 }
552
553 #[test]
554 #[ignore] fn test_selective_disclosure_reveal_all() {
556 let keypair = BbsPlusKeypair::generate(3);
557 let messages = vec![
558 b"message 1".to_vec(),
559 b"message 2".to_vec(),
560 b"message 3".to_vec(),
561 ];
562
563 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
564
565 let revealed_indices = vec![0, 1, 2];
567 let proof = create_proof(
568 keypair.public_key(),
569 &signature,
570 &messages,
571 &revealed_indices,
572 b"test-context",
573 )
574 .unwrap();
575
576 assert!(
577 verify_proof(
578 keypair.public_key(),
579 &proof,
580 &revealed_indices,
581 &messages,
582 b"test-context",
583 )
584 .unwrap()
585 );
586 }
587
588 #[test]
589 #[ignore] fn test_selective_disclosure_reveal_subset() {
591 let keypair = BbsPlusKeypair::generate(5);
592 let messages = vec![
593 b"user_id".to_vec(),
594 b"role".to_vec(),
595 b"credit".to_vec(),
596 b"expiry".to_vec(),
597 b"tier".to_vec(),
598 ];
599
600 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
601
602 let revealed_indices = vec![1, 2];
604 let revealed_messages: Vec<Vec<u8>> = revealed_indices
605 .iter()
606 .map(|&i| messages[i].clone())
607 .collect();
608
609 let proof = create_proof(
610 keypair.public_key(),
611 &signature,
612 &messages,
613 &revealed_indices,
614 b"presentation-context",
615 )
616 .unwrap();
617
618 assert!(
619 verify_proof(
620 keypair.public_key(),
621 &proof,
622 &revealed_indices,
623 &revealed_messages,
624 b"presentation-context",
625 )
626 .unwrap()
627 );
628 }
629
630 #[test]
631 #[ignore] fn test_selective_disclosure_reveal_none() {
633 let keypair = BbsPlusKeypair::generate(3);
634 let messages = vec![
635 b"secret1".to_vec(),
636 b"secret2".to_vec(),
637 b"secret3".to_vec(),
638 ];
639
640 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
641
642 let revealed_indices = vec![];
644 let revealed_messages = vec![];
645
646 let proof = create_proof(
647 keypair.public_key(),
648 &signature,
649 &messages,
650 &revealed_indices,
651 b"zk-context",
652 )
653 .unwrap();
654
655 assert!(
656 verify_proof(
657 keypair.public_key(),
658 &proof,
659 &revealed_indices,
660 &revealed_messages,
661 b"zk-context",
662 )
663 .unwrap()
664 );
665 }
666
667 #[test]
668 fn test_wrong_revealed_messages_fails() {
669 let keypair = BbsPlusKeypair::generate(3);
670 let messages = vec![
671 b"message 1".to_vec(),
672 b"message 2".to_vec(),
673 b"message 3".to_vec(),
674 ];
675
676 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
677
678 let revealed_indices = vec![1];
679 let proof = create_proof(
680 keypair.public_key(),
681 &signature,
682 &messages,
683 &revealed_indices,
684 b"context",
685 )
686 .unwrap();
687
688 let wrong_revealed = vec![b"wrong message".to_vec()];
690 assert!(
691 !verify_proof(
692 keypair.public_key(),
693 &proof,
694 &revealed_indices,
695 &wrong_revealed,
696 b"context",
697 )
698 .unwrap()
699 );
700 }
701
702 #[test]
703 fn test_wrong_context_fails() {
704 let keypair = BbsPlusKeypair::generate(2);
705 let messages = vec![b"msg1".to_vec(), b"msg2".to_vec()];
706
707 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
708
709 let revealed_indices = vec![0];
710 let revealed_messages = vec![messages[0].clone()];
711
712 let proof = create_proof(
713 keypair.public_key(),
714 &signature,
715 &messages,
716 &revealed_indices,
717 b"context1",
718 )
719 .unwrap();
720
721 assert!(
723 !verify_proof(
724 keypair.public_key(),
725 &proof,
726 &revealed_indices,
727 &revealed_messages,
728 b"context2",
729 )
730 .unwrap()
731 );
732 }
733
734 #[test]
735 fn test_keypair_serialization() {
736 let keypair = BbsPlusKeypair::generate(3);
737
738 let sk_bytes = keypair.secret_key().to_bytes().unwrap();
739 let pk_bytes = keypair.public_key().to_bytes().unwrap();
740
741 let sk_restored = BbsPlusSecretKey::from_bytes(&sk_bytes).unwrap();
742 let pk_restored = BbsPlusPublicKey::from_bytes(&pk_bytes).unwrap();
743
744 assert_eq!(sk_restored.message_count(), 3);
745 assert_eq!(pk_restored.message_count(), 3);
746
747 let messages = vec![b"test".to_vec(), b"data".to_vec(), b"here".to_vec()];
749 let signature = sign_messages(&sk_restored, &messages).unwrap();
750 assert!(verify_signature(&pk_restored, &signature, &messages).unwrap());
751 }
752
753 #[test]
754 fn test_signature_serialization() {
755 let keypair = BbsPlusKeypair::generate(2);
756 let messages = vec![b"msg1".to_vec(), b"msg2".to_vec()];
757
758 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
759 let sig_bytes = signature.to_bytes().unwrap();
760 let sig_restored = BbsPlusSignature::from_bytes(&sig_bytes).unwrap();
761
762 assert!(verify_signature(keypair.public_key(), &sig_restored, &messages).unwrap());
763 }
764
765 #[test]
766 #[ignore] fn test_proof_serialization() {
768 let keypair = BbsPlusKeypair::generate(3);
769 let messages = vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec()];
770
771 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
772
773 let revealed_indices = vec![1];
774 let revealed_messages = vec![messages[1].clone()];
775
776 let proof = create_proof(
777 keypair.public_key(),
778 &signature,
779 &messages,
780 &revealed_indices,
781 b"ctx",
782 )
783 .unwrap();
784
785 let proof_bytes = proof.to_bytes().unwrap();
786 let proof_restored = BbsPlusProof::from_bytes(&proof_bytes).unwrap();
787
788 assert!(
789 verify_proof(
790 keypair.public_key(),
791 &proof_restored,
792 &revealed_indices,
793 &revealed_messages,
794 b"ctx",
795 )
796 .unwrap()
797 );
798 }
799
800 #[test]
801 fn test_invalid_message_count() {
802 let keypair = BbsPlusKeypair::generate(3);
803 let messages = vec![b"only_one".to_vec()];
804
805 let result = sign_messages(keypair.secret_key(), &messages);
806 assert!(matches!(
807 result,
808 Err(BbsPlusError::InvalidMessageCount { .. })
809 ));
810 }
811
812 #[test]
813 fn test_invalid_revealed_index() {
814 let keypair = BbsPlusKeypair::generate(3);
815 let messages = vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec()];
816
817 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
818
819 let revealed_indices = vec![5];
821 let result = create_proof(
822 keypair.public_key(),
823 &signature,
824 &messages,
825 &revealed_indices,
826 b"ctx",
827 );
828
829 assert!(matches!(result, Err(BbsPlusError::MessageIndexOutOfBounds)));
830 }
831
832 #[test]
833 #[ignore] fn test_multiple_proofs_unlinkable() {
835 let keypair = BbsPlusKeypair::generate(3);
836 let messages = vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec()];
837
838 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
839
840 let revealed_indices = vec![0];
842 let revealed_messages = vec![messages[0].clone()];
843
844 let proof1 = create_proof(
845 keypair.public_key(),
846 &signature,
847 &messages,
848 &revealed_indices,
849 b"context1",
850 )
851 .unwrap();
852
853 let proof2 = create_proof(
854 keypair.public_key(),
855 &signature,
856 &messages,
857 &revealed_indices,
858 b"context2",
859 )
860 .unwrap();
861
862 assert_ne!(
864 proof1.a_prime.compress().to_bytes(),
865 proof2.a_prime.compress().to_bytes()
866 );
867
868 assert!(
870 verify_proof(
871 keypair.public_key(),
872 &proof1,
873 &revealed_indices,
874 &revealed_messages,
875 b"context1",
876 )
877 .unwrap()
878 );
879
880 assert!(
881 verify_proof(
882 keypair.public_key(),
883 &proof2,
884 &revealed_indices,
885 &revealed_messages,
886 b"context2",
887 )
888 .unwrap()
889 );
890 }
891
892 #[test]
893 #[ignore] fn test_large_message_count() {
895 let keypair = BbsPlusKeypair::generate(20);
897 let messages: Vec<Vec<u8>> = (0..20)
898 .map(|i| format!("message {}", i).into_bytes())
899 .collect();
900
901 let signature = sign_messages(keypair.secret_key(), &messages).unwrap();
902 assert!(verify_signature(keypair.public_key(), &signature, &messages).unwrap());
903
904 let revealed_indices = vec![5, 10, 15];
906 let revealed_messages: Vec<Vec<u8>> = revealed_indices
907 .iter()
908 .map(|&i| messages[i].clone())
909 .collect();
910
911 let proof = create_proof(
912 keypair.public_key(),
913 &signature,
914 &messages,
915 &revealed_indices,
916 b"large-test",
917 )
918 .unwrap();
919
920 assert!(
921 verify_proof(
922 keypair.public_key(),
923 &proof,
924 &revealed_indices,
925 &revealed_messages,
926 b"large-test",
927 )
928 .unwrap()
929 );
930 }
931}