1use ark_bls12_381::{Bls12_381, Fr as BlsFr, G1Affine as BlsG1Affine};
28use ark_ec::{AffineRepr, CurveGroup, short_weierstrass::Affine};
29use ark_ff::PrimeField;
30use ark_secp256r1::{Affine as SecP256Affine, Fq, Fr as SecP256Fr};
31use ark_serialize::{CanonicalSerialize, Compress, SerializationError};
32use ark_std::{
33 UniformRand,
34 io::Write,
35 rand::{SeedableRng, rngs::StdRng},
36 vec::Vec,
37};
38use base64::prelude::*;
39use bbs_plus::{
40 error::BBSPlusError,
41 prelude::SignatureG1,
42 proof::{PoKOfSignatureG1Proof, PoKOfSignatureG1Protocol},
43 setup::{KeypairG2, PublicKeyG2, SignatureParamsG1},
44};
45use blake2::Blake2b512;
46use bulletproofs_plus_plus::prelude::SetupParams as BppSetupParams;
47use dock_crypto_utils::{
48 commitment::PedersenCommitmentKey,
49 signature::MessageOrBlinding,
50 transcript::{Transcript, new_merlin_transcript},
51};
52use equality_across_groups::{
53 ec::commitments::{
54 PointCommitment, PointCommitmentWithOpening, from_base_field_to_scalar_field,
55 },
56 eq_across_groups::ProofLargeWitness,
57 pok_ecdsa_pubkey::{
58 PoKEcdsaSigCommittedPublicKey, PoKEcdsaSigCommittedPublicKeyProtocol, TransformedEcdsaSig,
59 },
60 tom256::{Affine as Tom256Affine, Config as Tom256Config},
61};
62pub use kvac::bbs_sharp::ecdsa;
63use proof_system::{
64 prelude::{
65 EqualWitnesses, MetaStatement, MetaStatements, Witness, WitnessRef, Witnesses,
66 bbs_plus::{PoKBBSSignatureG1Prover, PoKBBSSignatureG1Verifier},
67 },
68 proof::Proof,
69 proof_spec::ProofSpec,
70 statement::{Statements, ped_comm::PedersenCommitment as PedersenCommitmentStmt},
71 witness::PoKBBSSignatureG1,
72};
73
74use serde::ser::SerializeStruct;
75use serde::{Serialize, Serializer};
76use sha2::{Digest, Sha256};
77use std::{
78 collections::{BTreeMap, BTreeSet, HashMap},
79 fmt,
80};
81
82#[derive(Debug)]
89pub struct Issuer {
90 setup: PublicSetup,
92 keypair: KeypairG2<Bls12_381>,
94}
95
96#[derive(Debug)]
99pub struct Verifier {
100 setup: PublicSetup,
102 certificate: PublicKeyG2<Bls12_381>,
104}
105
106#[derive(Debug)]
113pub struct MobilePhone {
114 setup: PublicSetup,
116 secure_element: SecureElement,
119 swiyu: Option<Swiyu>,
122}
123
124#[derive(CanonicalSerialize, Debug, Clone)]
129pub struct VerifiedCredential {
130 messages: Vec<BlsFr>,
134 signature: SignatureG1<Bls12_381>,
136 message_strings: BTreeMap<usize, String>,
138}
139
140#[derive(Default, Debug)]
146pub struct SecureElement {
147 keys: Vec<SecP256Fr>,
153}
154
155#[derive(Debug)]
161pub struct Swiyu {
162 setup: PublicSetup,
164 key_id: Option<usize>,
166 vcs: Option<VerifiedCredential>,
168}
169
170#[derive(Clone, CanonicalSerialize, Debug)]
174pub struct BBSPresentation {
175 proof: PoKOfSignatureG1Proof<Bls12_381>,
178 revealed: BTreeMap<usize, BlsFr>,
181 message_strings: BTreeMap<usize, String>,
183 commitment_pub_x: PublicCommitment,
185 commitment_pub_y: PublicCommitment,
187}
188
189#[derive(Clone, Debug)]
192pub enum PublicCommitment {
193 Open(BlsFr, BlsG1Affine),
197 Closed(BlsG1Affine),
200}
201
202impl CanonicalSerialize for PublicCommitment {
203 fn serialize_with_mode<W: Write>(
204 &self,
205 mut writer: W,
206 mode: Compress,
207 ) -> Result<(), SerializationError> {
208 match self {
209 PublicCommitment::Open(fp, affine) => {
210 fp.serialize_with_mode(&mut writer, mode)?;
211 affine.serialize_with_mode(&mut writer, mode)?;
212 }
213 PublicCommitment::Closed(affine) => affine.serialize_with_mode(&mut writer, mode)?,
214 }
215 Ok(())
216 }
217
218 fn serialized_size(&self, mode: Compress) -> usize {
219 match self {
220 PublicCommitment::Open(fp, affine) => {
221 fp.serialized_size(mode) + affine.serialized_size(mode)
222 }
223 PublicCommitment::Closed(affine) => affine.serialized_size(mode),
224 }
225 }
226}
227
228#[derive(Clone)]
233pub struct ECDSAProof {
234 comm_pk: PointCommitment<Tom256Config>,
236 proof: PoKEcdsaSigCommittedPublicKey<{ ECDSAProof::NUM_REPS_SCALAR_MULT }>,
238 proof_eq_pk_x: ProofEqDL,
240 proof_eq_pk_y: ProofEqDL,
242 proof_eq_pk_bbs: Proof<Bls12_381>,
245}
246
247impl Issuer {
248 pub fn new(mut setup: PublicSetup) -> Self {
250 Self {
251 keypair: KeypairG2::<Bls12_381>::generate_using_rng(
252 &mut setup.rng,
253 &setup.sig_params_g1,
254 ),
255 setup,
256 }
257 }
258
259 pub fn get_certificate(&self) -> PublicKeyG2<Bls12_381> {
261 self.keypair.public_key.clone()
262 }
263
264 pub fn new_credential(&mut self, key_pub: SecP256Affine) -> VerifiedCredential {
270 let pk_x = from_base_field_to_scalar_field::<Fq, BlsFr>(key_pub.x().unwrap());
271 let pk_y = from_base_field_to_scalar_field::<Fq, BlsFr>(key_pub.y().unwrap());
272 let mut generator = names::Generator::default();
273 let (first, last) = (generator.next().unwrap(), generator.next().unwrap());
274 let message_strings = BTreeMap::from([
275 (VerifiedCredential::FIELD_FIRSTNAME, first.clone()),
276 (VerifiedCredential::FIELD_LASTNAME, last.clone()),
277 ]);
278 let messages = vec![
279 pk_x,
280 pk_y,
281 (&VerifierMessage(first)).into(),
282 (&VerifierMessage(last)).into(),
283 ];
284 VerifiedCredential {
285 signature: SignatureG1::<Bls12_381>::new(
286 &mut self.setup.rng,
287 &messages,
288 &self.keypair.secret_key,
289 &self.setup.sig_params_g1,
290 )
291 .unwrap(),
292 messages,
293 message_strings,
294 }
295 }
296}
297
298impl VerifiedCredential {
300 pub const FIELD_PUB_X: usize = 0;
301 pub const FIELD_PUB_Y: usize = 1;
302 pub const FIELD_FIRSTNAME: usize = 2;
303 pub const FIELD_LASTNAME: usize = 3;
304 pub const FIELD_COUNT: u32 = 4;
305
306 pub fn get_message_str(&self, field: usize) -> Option<String> {
309 return self.message_strings.get(&field).cloned();
310 }
311}
312
313impl Verifier {
314 pub fn new(setup: PublicSetup, certificate: PublicKeyG2<Bls12_381>) -> Self {
317 Self { setup, certificate }
318 }
319
320 pub fn create_message(&mut self) -> VerifierMessage {
322 VerifierMessage::new("Verifier")
323 }
324
325 pub fn check_proof(
331 &self,
332 verifier_message: VerifierMessage,
333 bbs_presentation: BBSPresentation,
334 ecdsa_proof: ECDSAProof,
335 ) {
336 bbs_presentation
337 .verify(
338 self.setup.clone(),
339 self.certificate.clone(),
340 &(&verifier_message).into(),
341 )
342 .expect("Verification of BBS proof failed");
343 ecdsa_proof.verify(
344 self.setup.clone(),
345 (&verifier_message).into(),
346 &bbs_presentation,
347 &self.certificate,
348 );
349 }
350}
351
352#[derive(Debug, Clone)]
357pub struct VerifierMessage(String);
358
359impl VerifierMessage {
360 pub fn new(domain: &str) -> Self {
362 Self(format!(
363 "{domain}: Proof request at {}",
364 chrono::Utc::now().to_rfc3339()
365 ))
366 }
367}
368
369impl Into<BlsFr> for &VerifierMessage {
371 fn into(self) -> BlsFr {
372 let hash = Sha256::digest(self.0.as_bytes());
373 let mut bytes = [0u8; 32];
374 bytes.copy_from_slice(&hash[..32]);
375 BlsFr::from_le_bytes_mod_order(&bytes)
376 }
377}
378
379impl Into<SecP256Fr> for &VerifierMessage {
381 fn into(self) -> SecP256Fr {
382 let hash = Sha256::digest(self.0.as_bytes());
383 let mut bytes = [0u8; 32];
384 bytes.copy_from_slice(&hash[..32]);
385 SecP256Fr::from_le_bytes_mod_order(&bytes)
386 }
387}
388
389impl MobilePhone {
390 pub fn new(setup: PublicSetup) -> Self {
393 Self {
394 setup,
395 secure_element: SecureElement::default(),
396 swiyu: None,
397 }
398 }
399
400 pub fn install_swiyu(&mut self) {
402 if self.swiyu.is_some() {
403 panic!("Swiyu is already installed");
404 }
405 self.swiyu = Some(Swiyu::new(self.setup.clone()))
406 }
407
408 pub fn secure_element(&mut self) -> &mut SecureElement {
411 &mut self.secure_element
412 }
413
414 pub fn swiyu(&mut self) -> &mut Swiyu {
418 match self.swiyu.as_mut() {
419 Some(swiyu) => swiyu,
420 None => panic!("Swiyu is not yet installed"),
421 }
422 }
423}
424
425impl SecureElement {
426 pub fn create_kp(&mut self) -> SEKeypair {
429 let sk = SecP256Fr::rand(&mut StdRng::seed_from_u64(0u64));
430 let key_pub = (ecdsa::Signature::generator() * sk).into_affine();
431 self.keys.push(sk);
432 SEKeypair {
433 id: self.keys.len() - 1,
434 key_pub,
435 }
436 }
437
438 pub fn sign(&self, id: usize, msg: VerifierMessage) -> ecdsa::Signature {
442 ecdsa::Signature::new_prehashed(
443 &mut StdRng::seed_from_u64(0u64),
444 (&msg).into(),
445 self.keys[id],
446 )
447 }
448}
449
450#[derive(Debug)]
453pub struct SEKeypair {
454 pub id: usize,
455 pub key_pub: SecP256Affine,
456}
457
458impl Swiyu {
459 pub fn new(setup: PublicSetup) -> Self {
463 Self {
464 setup,
465 key_id: None,
466 vcs: None,
467 }
468 }
469
470 pub fn add_vc(&mut self, key_id: usize, credential: VerifiedCredential) {
473 if self.vcs.is_some() {
474 panic!("Can only have one credential");
475 }
476 self.key_id = Some(key_id);
477 self.vcs = Some(credential);
478 }
479
480 pub fn bbs_presentation(
489 &mut self,
490 message: VerifierMessage,
491 reveal: Vec<usize>,
492 ) -> BBSPresentation {
493 let vc = self.vcs.as_ref().expect("No credential yet!");
494 let mut messages_and_blindings = vec![
495 MessageOrBlinding::BlindMessageRandomly(&vc.messages[0]),
496 MessageOrBlinding::BlindMessageRandomly(&vc.messages[1]),
497 ];
498
499 let mut message_strings = BTreeMap::new();
501 let mut revealed = BTreeMap::new();
502 for idx in [
503 VerifiedCredential::FIELD_FIRSTNAME,
504 VerifiedCredential::FIELD_LASTNAME,
505 ] {
506 let msg = &vc.messages[idx];
507 if reveal.contains(&idx) {
508 messages_and_blindings.push(MessageOrBlinding::RevealMessage(msg));
509 message_strings.insert(idx, vc.message_strings[&idx].clone());
510 revealed.insert(idx, msg.clone());
511 } else {
512 messages_and_blindings.push(MessageOrBlinding::BlindMessageRandomly(msg));
513 }
514 }
515
516 let proof = PoKOfSignatureG1Protocol::init(
517 &mut self.setup.rng,
518 &vc.signature,
519 &self.setup.sig_params_g1,
520 messages_and_blindings,
521 )
522 .unwrap()
523 .gen_proof(&(&message).into())
524 .unwrap();
525
526 BBSPresentation {
527 proof,
528 revealed,
529 message_strings,
530 commitment_pub_x: PublicCommitment::from_message(
531 &mut self.setup,
532 &vc.messages[VerifiedCredential::FIELD_PUB_X],
533 ),
534 commitment_pub_y: PublicCommitment::from_message(
535 &mut self.setup,
536 &vc.messages[VerifiedCredential::FIELD_PUB_Y],
537 ),
538 }
539 }
540}
541
542impl PublicCommitment {
543 pub fn from_message(setup: &mut PublicSetup, message: &BlsFr) -> Self {
546 let randomness = BlsFr::rand(&mut setup.rng);
547 Self::Open(randomness, setup.comm_key_bls.commit(message, &randomness))
548 }
549
550 pub fn close(self) -> Self {
553 match self {
554 PublicCommitment::Open(_, affine) => PublicCommitment::Closed(affine),
555 _ => self,
556 }
557 }
558
559 pub fn rand(&self) -> BlsFr {
562 match self {
563 PublicCommitment::Open(fp, _) => fp.clone(),
564 _ => panic!("No random value in closed commitment"),
565 }
566 }
567
568 pub fn affine(&self) -> BlsG1Affine {
570 match self {
571 PublicCommitment::Open(_, affine) => affine.clone(),
572 PublicCommitment::Closed(affine) => affine.clone(),
573 }
574 }
575
576 pub fn assert_closed(&self) {
578 if let Self::Open(_, _) = self {
579 panic!("PublicCommitment is open and leaks random value!");
580 }
581 }
582}
583
584#[derive(Clone, Debug)]
587pub struct PublicSetup {
588 rng: StdRng,
590 sig_params_g1: SignatureParamsG1<Bls12_381>,
592 bpp_setup_params: BppSetupParams<Affine<Tom256Config>>,
594 comm_key_tom: PedersenCommitmentKey<Tom256Affine>,
596 comm_key_secp: PedersenCommitmentKey<SecP256Affine>,
598 comm_key_bls: PedersenCommitmentKey<BlsG1Affine>,
600}
601
602impl PublicSetup {
603 const WITNESS_BIT_SIZE: usize = 64;
605 const CHALLENGE_BIT_SIZE: usize = 180;
606 const ABORT_PARAM: usize = 8;
607 const RESPONSE_BYTE_SIZE: usize = 32;
608 const NUM_REPS: usize = 1;
609 const NUM_CHUNKS: usize = 4;
610 const BPP_BASE: u16 = 2;
611
612 pub fn new() -> Self {
614 let comm_key_tom = PedersenCommitmentKey::<Tom256Affine>::new::<Blake2b512>(b"test2");
615
616 let base = PublicSetup::BPP_BASE;
618 let mut bpp_setup_params =
619 BppSetupParams::<Tom256Affine>::new_for_perfect_range_proof::<Blake2b512>(
620 b"test",
621 base,
622 PublicSetup::WITNESS_BIT_SIZE as u16,
623 PublicSetup::NUM_CHUNKS as u32,
624 );
625 bpp_setup_params.G = comm_key_tom.g;
626 bpp_setup_params.H_vec[0] = comm_key_tom.h;
627
628 Self {
629 sig_params_g1: SignatureParamsG1::<Bls12_381>::new::<Blake2b512>(
630 "eid-demo".as_bytes(),
631 VerifiedCredential::FIELD_COUNT,
632 ),
633 rng: StdRng::seed_from_u64(0u64),
634 bpp_setup_params,
635 comm_key_tom,
636 comm_key_secp: PedersenCommitmentKey::<SecP256Affine>::new::<Blake2b512>(b"test1"),
637 comm_key_bls: PedersenCommitmentKey::<BlsG1Affine>::new::<Blake2b512>(b"test3"),
638 }
639 }
640
641 pub fn to_json(&self) -> String {
642 serde_json::to_string(self).expect("JSON conversion error")
643 }
644
645 fn append_transcript<T: Transcript + Clone + Write>(&self, pt: &mut T) {
650 pt.append(b"comm_key_secp", &self.comm_key_secp);
651 pt.append(b"comm_key_tom", &self.comm_key_tom);
652 pt.append(b"comm_key_bls", &self.comm_key_bls);
653 pt.append(b"bpp_setup_params", &self.bpp_setup_params);
654 }
655}
656
657type ProofEqDL = ProofLargeWitness<
659 Tom256Affine,
660 BlsG1Affine,
661 { PublicSetup::NUM_CHUNKS },
662 { PublicSetup::WITNESS_BIT_SIZE },
663 { PublicSetup::CHALLENGE_BIT_SIZE },
664 { PublicSetup::ABORT_PARAM },
665 { PublicSetup::RESPONSE_BYTE_SIZE },
666 { PublicSetup::NUM_REPS },
667>;
668
669impl ECDSAProof {
670 const NUM_REPS_SCALAR_MULT: usize = 128;
671
672 pub fn new(
677 mut setup: PublicSetup,
678 holder_pub: SecP256Affine,
679 vc: VerifiedCredential,
680 bbs_presentation: BBSPresentation,
681 ecdsa_signature: ecdsa::Signature,
682 verifier_message: VerifierMessage,
683 ) -> Self {
684 let comm_pk =
686 PointCommitmentWithOpening::new(&mut setup.rng, &holder_pub, &setup.comm_key_tom)
687 .unwrap();
688
689 let transformed_sig =
690 TransformedEcdsaSig::new(&ecdsa_signature, (&verifier_message).into(), holder_pub)
691 .unwrap();
692 transformed_sig
693 .verify_prehashed((&verifier_message).into(), holder_pub)
694 .unwrap();
695
696 let mut prover_transcript = new_merlin_transcript(b"test");
700 setup.append_transcript(&mut prover_transcript);
701 Self::append_transcript(
702 &mut prover_transcript,
703 &comm_pk.comm,
704 &bbs_presentation,
705 &(&verifier_message).into(),
706 );
707
708 let protocol =
711 PoKEcdsaSigCommittedPublicKeyProtocol::<{ ECDSAProof::NUM_REPS_SCALAR_MULT }>::init(
712 &mut setup.rng,
713 transformed_sig,
714 (&verifier_message).into(),
715 holder_pub,
716 comm_pk.clone(),
717 &setup.comm_key_secp,
718 &setup.comm_key_tom,
719 )
720 .unwrap();
721 protocol
722 .challenge_contribution(&mut prover_transcript)
723 .unwrap();
724 let challenge_prover = prover_transcript.challenge_scalar(b"challenge");
725 let proof = protocol.gen_proof(&challenge_prover);
726
727 let proof_eq_pk_x = ProofEqDL::new(
729 &mut setup.rng,
730 &comm_pk.x,
731 comm_pk.r_x,
732 bbs_presentation.commitment_pub_x.rand(),
733 &setup.comm_key_tom,
734 &setup.comm_key_bls,
735 PublicSetup::BPP_BASE,
736 setup.bpp_setup_params.clone(),
737 &mut prover_transcript,
738 )
739 .unwrap();
740
741 let proof_eq_pk_y = ProofEqDL::new(
743 &mut setup.rng,
744 &comm_pk.y,
745 comm_pk.r_y,
746 bbs_presentation.commitment_pub_y.rand(),
747 &setup.comm_key_tom,
748 &setup.comm_key_bls,
749 PublicSetup::BPP_BASE,
750 setup.bpp_setup_params.clone(),
751 &mut prover_transcript,
752 )
753 .unwrap();
754
755 let mut statements = Statements::<Bls12_381>::new();
757 statements.add(PedersenCommitmentStmt::new_statement_from_params(
758 vec![setup.comm_key_bls.g, setup.comm_key_bls.h],
759 bbs_presentation.commitment_pub_x.affine(),
760 ));
761 statements.add(PedersenCommitmentStmt::new_statement_from_params(
762 vec![setup.comm_key_bls.g, setup.comm_key_bls.h],
763 bbs_presentation.commitment_pub_y.affine(),
764 ));
765 statements.add(
766 PoKBBSSignatureG1Prover::<Bls12_381>::new_statement_from_params(
767 setup.sig_params_g1.clone(),
768 BTreeMap::new(),
769 ),
770 );
771
772 let mut meta_statements = MetaStatements::new();
773 meta_statements.add(MetaStatement::WitnessEquality(EqualWitnesses(
774 vec![(0, 0), (2, 0)]
775 .into_iter()
776 .collect::<BTreeSet<WitnessRef>>(),
777 )));
778 meta_statements.add(MetaStatement::WitnessEquality(EqualWitnesses(
779 vec![(1, 0), (2, 1)]
780 .into_iter()
781 .collect::<BTreeSet<WitnessRef>>(),
782 )));
783
784 let mut witnesses = Witnesses::new();
785 witnesses.add(Witness::PedersenCommitment(vec![
786 vc.messages[0].clone(),
787 bbs_presentation.commitment_pub_x.rand(),
788 ]));
789 witnesses.add(Witness::PedersenCommitment(vec![
790 vc.messages[1].clone(),
791 bbs_presentation.commitment_pub_y.rand(),
792 ]));
793 witnesses.add(PoKBBSSignatureG1::new_as_witness(
794 vc.signature,
795 BTreeMap::from([
796 (0, vc.messages[0]),
797 (1, vc.messages[1]),
798 (2, vc.messages[2]),
799 (3, vc.messages[3]),
800 ]),
801 ));
802
803 let context = Some(b"test".to_vec());
804 let proof_spec = ProofSpec::new(
805 statements.clone(),
806 meta_statements.clone(),
807 vec![],
808 context.clone(),
809 );
810 proof_spec.validate().unwrap();
811
812 let nonce_eq_pk = Some(b"test nonce".to_vec());
813 let proof_eq_pk_bbs = Proof::new::<StdRng, Blake2b512>(
814 &mut setup.rng,
815 proof_spec.clone(),
816 witnesses.clone(),
817 nonce_eq_pk.clone(),
818 Default::default(),
819 )
820 .unwrap()
821 .0;
822
823 Self {
824 comm_pk: comm_pk.comm,
825 proof,
826 proof_eq_pk_x,
827 proof_eq_pk_y,
828 proof_eq_pk_bbs,
829 }
830 }
831
832 pub fn verify(
836 &self,
837 mut setup: PublicSetup,
838 message: SecP256Fr,
839 presentation: &BBSPresentation,
840 issuer_pub: &PublicKeyG2<Bls12_381>,
841 ) {
842 presentation.assert_closed();
843 let mut verifier_transcript = new_merlin_transcript(b"test");
844 setup.append_transcript(&mut verifier_transcript);
845 Self::append_transcript(
846 &mut verifier_transcript,
847 &self.comm_pk,
848 presentation,
849 &message,
850 );
851 self.proof
852 .challenge_contribution(&mut verifier_transcript)
853 .unwrap();
854
855 let challenge_verifier = verifier_transcript.challenge_scalar(b"challenge");
856
857 self.proof
860 .verify(
861 message,
862 &self.comm_pk,
863 &challenge_verifier,
864 &setup.comm_key_secp,
865 &setup.comm_key_tom,
866 )
867 .expect("ECDSA proof failed");
868
869 self.proof_eq_pk_x
872 .verify(
873 &self.comm_pk.x,
874 &presentation.commitment_pub_x.affine(),
875 &setup.comm_key_tom,
876 &setup.comm_key_bls,
877 &setup.bpp_setup_params,
878 &mut verifier_transcript,
879 )
880 .expect("DlEQ proof for x position failed");
881
882 self.proof_eq_pk_y
885 .verify(
886 &self.comm_pk.y,
887 &presentation.commitment_pub_y.affine(),
888 &setup.comm_key_tom,
889 &setup.comm_key_bls,
890 &setup.bpp_setup_params,
891 &mut verifier_transcript,
892 )
893 .expect("DlEQ proff for y position failed");
894
895 let mut verifier_statements = Statements::<Bls12_381>::new();
898 verifier_statements.add(PedersenCommitmentStmt::new_statement_from_params(
899 vec![setup.comm_key_bls.g, setup.comm_key_bls.h],
900 presentation.commitment_pub_x.affine(),
901 ));
902 verifier_statements.add(PedersenCommitmentStmt::new_statement_from_params(
903 vec![setup.comm_key_bls.g, setup.comm_key_bls.h],
904 presentation.commitment_pub_y.affine(),
905 ));
906 verifier_statements.add(PoKBBSSignatureG1Verifier::new_statement_from_params(
907 setup.sig_params_g1.clone(),
908 issuer_pub.clone(),
909 BTreeMap::new(),
910 ));
911
912 let mut meta_statements = MetaStatements::new();
913 meta_statements.add(MetaStatement::WitnessEquality(EqualWitnesses(
914 vec![(0, 0), (2, 0)]
915 .into_iter()
916 .collect::<BTreeSet<WitnessRef>>(),
917 )));
918 meta_statements.add(MetaStatement::WitnessEquality(EqualWitnesses(
919 vec![(1, 0), (2, 1)]
920 .into_iter()
921 .collect::<BTreeSet<WitnessRef>>(),
922 )));
923
924 let context = Some(b"test".to_vec());
925 let verifier_proof_spec = ProofSpec::new(
926 verifier_statements.clone(),
927 meta_statements.clone(),
928 vec![],
929 context.clone(),
930 );
931 verifier_proof_spec.validate().unwrap();
932
933 let nonce_eq_pk = Some(b"test nonce".to_vec());
934 self.proof_eq_pk_bbs
935 .clone()
936 .verify::<StdRng, Blake2b512>(
937 &mut setup.rng,
938 verifier_proof_spec,
939 nonce_eq_pk.clone(),
940 Default::default(),
941 )
942 .expect("Verify Point Equality Proof");
943 }
944
945 pub fn get_sizes(&self) -> HashMap<&str, usize> {
947 HashMap::from([
948 ("proof_add", self.proof.proof_add.compressed_size()),
949 ("proof_scalar", self.proof.proof_minus_zR.compressed_size()),
950 ("proof_eqdl_x", self.proof_eq_pk_x.compressed_size()),
951 ("proof_eqdl_y", self.proof_eq_pk_y.compressed_size()),
952 ("proof_eq_comm_bbs", self.proof_eq_pk_bbs.compressed_size()),
953 ])
954 }
955
956 pub fn to_json(&self) -> String {
958 serde_json::to_string(self).expect("While serializing to JSON")
959 }
960
961 fn append_transcript<T: Transcript + Clone + Write>(
963 pt: &mut T,
964 comm_pk: &PointCommitment<Tom256Config>,
965 presentation: &BBSPresentation,
966 message: &SecP256Fr,
967 ) {
968 pt.append(b"comm_pk", comm_pk);
969 pt.append(b"bls_comm_pk_x", &presentation.commitment_pub_x.affine());
970 pt.append(b"bls_comm_pk_y", &presentation.commitment_pub_y.affine());
971 pt.append(b"message", message);
972 }
973}
974
975impl BBSPresentation {
976 pub fn assert_closed(&self) {
979 self.commitment_pub_x.assert_closed();
980 self.commitment_pub_y.assert_closed();
981 }
982
983 pub fn close(self) -> Self {
985 Self {
986 proof: self.proof,
987 revealed: self.revealed,
988 message_strings: self.message_strings,
989 commitment_pub_x: self.commitment_pub_x.close(),
990 commitment_pub_y: self.commitment_pub_y.close(),
991 }
992 }
993
994 pub fn verify(
1000 &self,
1001 setup: PublicSetup,
1002 issuer_certificate: PublicKeyG2<Bls12_381>,
1003 verifier_message: &BlsFr,
1004 ) -> Result<(), BBSPlusError> {
1005 self.proof.verify(
1007 &self.revealed,
1008 verifier_message,
1009 issuer_certificate,
1010 setup.sig_params_g1.clone(),
1011 )?;
1012
1013 for (rev_id, bbs_msg) in &self.revealed {
1015 match self.message_strings.get(rev_id) {
1016 Some(msg_str) => {
1017 if bbs_msg != &(&VerifierMessage(msg_str.clone())).into() {
1018 return Err(BBSPlusError::InvalidSignature);
1019 }
1020 }
1021 None => return Err(BBSPlusError::IncorrectNoOfShares(*rev_id, 0)),
1022 }
1023 }
1024
1025 Ok(())
1026 }
1027
1028 pub fn message_string(&self, idx: usize) -> Option<String> {
1031 self.message_strings.get(&idx).cloned()
1032 }
1033
1034 pub fn get_sizes(&self) -> HashMap<&str, usize> {
1036 HashMap::from([("proof_bbs", self.proof.compressed_size())])
1037 }
1038
1039 pub fn to_json(&self) -> String {
1041 serde_json::to_string(self).expect("Error while serializing to json")
1042 }
1043}
1044
1045impl Serialize for BBSPresentation {
1047 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1048 where
1049 S: Serializer,
1050 {
1051 fn serialize_ark<T: CanonicalSerialize>(t: &T) -> String {
1053 let mut buf = Vec::new();
1054 t.serialize_compressed(&mut buf).unwrap();
1055 BASE64_STANDARD.encode(buf)
1056 }
1057
1058 let revealed: BTreeMap<usize, String> = self
1060 .revealed
1061 .iter()
1062 .map(|(k, v)| (*k, serialize_ark(v)))
1063 .collect();
1064
1065 let message_strings = &self.message_strings;
1067
1068 fn serialize_commitment(c: &PublicCommitment) -> serde_json::Value {
1070 match c {
1071 PublicCommitment::Open(rand, affine) => {
1072 serde_json::json!({
1073 "type": "open",
1074 "rand": serialize_ark(rand),
1075 "affine": serialize_ark(affine),
1076 })
1077 }
1078 PublicCommitment::Closed(affine) => {
1079 serde_json::json!({
1080 "type": "closed",
1081 "affine": serialize_ark(affine),
1082 })
1083 }
1084 }
1085 }
1086
1087 let proof_bytes = {
1089 let mut buf = Vec::new();
1090 self.proof.serialize_compressed(&mut buf).unwrap();
1091 BASE64_STANDARD.encode(buf)
1092 };
1093
1094 let mut state = serializer.serialize_struct("BBSPresentation", 5)?;
1095 state.serialize_field("proof", &proof_bytes)?;
1096 state.serialize_field("revealed", &revealed)?;
1097 state.serialize_field("message_strings", message_strings)?;
1098 state.serialize_field(
1099 "commitment_pub_x",
1100 &serialize_commitment(&self.commitment_pub_x),
1101 )?;
1102 state.serialize_field(
1103 "commitment_pub_y",
1104 &serialize_commitment(&self.commitment_pub_y),
1105 )?;
1106 state.end()
1107 }
1108}
1109
1110impl Serialize for PublicSetup {
1112 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1113 where
1114 S: Serializer,
1115 {
1116 let mut state = serializer.serialize_struct("PublicSetup", 5)?;
1117 state.serialize_field("sig_params_g1", &self.sig_params_g1)?;
1118 let mut bpp_bytes = Vec::new();
1120 self.bpp_setup_params
1121 .serialize_compressed(&mut bpp_bytes)
1122 .unwrap();
1123 let bpp_base64 = BASE64_STANDARD.encode(bpp_bytes);
1124 state.serialize_field("bpp_setup_params", &bpp_base64)?;
1125 state.serialize_field("comm_key_tom", &self.comm_key_tom)?;
1126 state.serialize_field("comm_key_secp", &self.comm_key_secp)?;
1127 state.serialize_field("comm_key_bls", &self.comm_key_bls)?;
1128 state.end()
1129 }
1130}
1131
1132impl Serialize for ECDSAProof {
1134 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1135 where
1136 S: Serializer,
1137 {
1138 fn serialize_ark<T: CanonicalSerialize>(t: &T) -> String {
1140 let mut buf = Vec::new();
1141 t.serialize_compressed(&mut buf).unwrap();
1142 BASE64_STANDARD.encode(buf)
1143 }
1144
1145 let comm_pk_bytes = serialize_ark(&self.comm_pk);
1146 let proof_bytes = serialize_ark(&self.proof);
1147 let proof_eq_pk_x_bytes = serialize_ark(&self.proof_eq_pk_x);
1148 let proof_eq_pk_y_bytes = serialize_ark(&self.proof_eq_pk_y);
1149
1150 let mut state = serializer.serialize_struct("ECDSAProof", 4)?;
1151 state.serialize_field("comm_pk", &comm_pk_bytes)?;
1152 state.serialize_field("proof", &proof_bytes)?;
1153 state.serialize_field("proof_eq_pk_x", &proof_eq_pk_x_bytes)?;
1154 state.serialize_field("proof_eq_pk_y", &proof_eq_pk_y_bytes)?;
1155 state.end()
1156 }
1157}
1158
1159impl fmt::Display for BBSPresentation {
1160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1161 match serde_json::to_string(self) {
1162 Ok(json) => write!(f, "BBSPresentation: {json}"),
1163 Err(_) => Err(fmt::Error),
1164 }
1165 }
1166}
1167
1168impl fmt::Display for ECDSAProof {
1169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1170 match serde_json::to_string(self) {
1171 Ok(json) => write!(f, "ECDSAProof: {json}"),
1172 Err(_) => Err(fmt::Error),
1173 }
1174 }
1175}
1176
1177impl fmt::Display for Issuer {
1178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1179 write!(f, "Issuer: {:?}", self)
1180 }
1181}
1182
1183impl fmt::Display for MobilePhone {
1184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1185 write!(f, "MobilePhone: {:?}", self)
1186 }
1187}
1188
1189impl fmt::Display for PublicSetup {
1190 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1191 match serde_json::to_string(self) {
1192 Ok(json) => write!(f, "PublicSetup: {json}"),
1193 Err(_) => Err(fmt::Error),
1194 }
1195 }
1196}
1197
1198impl fmt::Display for SecureElement {
1199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1200 write!(f, "SecureElement: {:?}", self)
1201 }
1202}
1203
1204impl fmt::Display for SEKeypair {
1205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1206 write!(f, "SEKeypair: {:?}", self)
1207 }
1208}
1209
1210impl fmt::Display for Swiyu {
1211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1212 write!(f, "Swiyu app: {:?}", self)
1213 }
1214}
1215
1216impl fmt::Display for VerifiedCredential {
1217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1218 write!(f, "VerifiedCredential: {:?}", self)
1219 }
1220}
1221
1222impl fmt::Display for Verifier {
1223 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1224 write!(f, "Verifier: {:?}", self)
1225 }
1226}
1227
1228impl fmt::Display for VerifierMessage {
1229 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1230 write!(f, "VerifierMessage: {:?}", self)
1231 }
1232}
1233
1234#[cfg(test)]
1235mod test {
1236 use std::{
1237 collections::{BTreeMap, BTreeSet},
1238 error::Error,
1239 };
1240
1241 use super::*;
1242 use proof_system::{
1243 prelude::bbs_plus::{PoKBBSSignatureG1Prover, PoKBBSSignatureG1Verifier},
1244 witness::PoKBBSSignatureG1,
1245 };
1246
1247 #[test]
1249 fn sign_verify_msg() -> Result<(), Box<dyn Error>> {
1250 let setup = PublicSetup::new();
1252 let mut issuer = Issuer::new(setup.clone());
1253 let mut holder = MobilePhone::new(setup.clone());
1254 let mut verifier = Verifier::new(setup.clone(), issuer.get_certificate());
1255
1256 holder.install_swiyu();
1258 let se_kp = holder.secure_element().create_kp();
1259 let credential = issuer.new_credential(se_kp.key_pub);
1260 holder.swiyu().add_vc(se_kp.id, credential.clone());
1261
1262 let message = verifier.create_message();
1264
1265 let presentation = holder
1268 .swiyu()
1269 .bbs_presentation(message.clone(), vec![VerifiedCredential::FIELD_FIRSTNAME]);
1270 let signature = holder.secure_element().sign(0, message.clone());
1271 let proof = ECDSAProof::new(
1272 setup,
1273 se_kp.key_pub,
1274 credential.clone(),
1275 presentation.clone(),
1276 signature,
1277 message.clone(),
1278 );
1279 let presentation_closed = presentation.close();
1280
1281 verifier.check_proof(message, presentation_closed.clone(), proof.clone());
1283 assert_eq!(
1284 presentation_closed.message_string(VerifiedCredential::FIELD_FIRSTNAME),
1285 Some(credential.message_strings[&VerifiedCredential::FIELD_FIRSTNAME].clone())
1286 );
1287 assert_eq!(
1288 presentation_closed.message_string(VerifiedCredential::FIELD_LASTNAME),
1289 None
1290 );
1291
1292 Ok(())
1293 }
1294
1295 #[test]
1297 fn verify_bbs() -> Result<(), Box<dyn Error>> {
1298 let mut rng = StdRng::seed_from_u64(0u64);
1299 let holder_sk = SecP256Fr::rand(&mut StdRng::seed_from_u64(0u64));
1300 let holder_pub = (ecdsa::Signature::generator() * holder_sk).into_affine();
1301 let message_pet = (&VerifierMessage(format!("goldfish"))).into();
1302 let message_pk_x = from_base_field_to_scalar_field::<Fq, BlsFr>(holder_pub.x().unwrap());
1303 let message_pk_y = from_base_field_to_scalar_field::<Fq, BlsFr>(holder_pub.y().unwrap());
1304 let messages = vec![message_pk_x, message_pk_y, message_pet];
1305 let sig_params_g1 = SignatureParamsG1::<Bls12_381>::new::<Blake2b512>(
1306 "eid-demo".as_bytes(),
1307 messages.len() as u32,
1308 );
1309 let issuer_keypair = KeypairG2::<Bls12_381>::generate_using_rng(&mut rng, &sig_params_g1);
1310
1311 let signature_issuer = SignatureG1::<Bls12_381>::new(
1312 &mut rng,
1313 &messages,
1314 &issuer_keypair.secret_key,
1315 &sig_params_g1,
1316 )
1317 .unwrap();
1318
1319 let challenge = BlsFr::rand(&mut rng);
1320 let proof_bbs = PoKOfSignatureG1Protocol::init(
1321 &mut rng,
1322 &signature_issuer,
1323 &sig_params_g1,
1324 vec![
1325 MessageOrBlinding::BlindMessageRandomly(&message_pk_x),
1326 MessageOrBlinding::BlindMessageRandomly(&message_pk_y),
1327 MessageOrBlinding::RevealMessage(&message_pet),
1328 ],
1329 )
1330 .unwrap()
1331 .gen_proof(&challenge)
1332 .unwrap();
1333
1334 let comm_key_bls = PedersenCommitmentKey::<BlsG1Affine>::new::<Blake2b512>(b"test3");
1335 let randomness_pub_x = BlsFr::rand(&mut rng);
1336 let commitment_pub_x = comm_key_bls.commit(&message_pk_x, &randomness_pub_x);
1337 let randomness_pub_y = BlsFr::rand(&mut rng);
1338 let commitment_pub_y = comm_key_bls.commit(&message_pk_y, &randomness_pub_y);
1339
1340 let mut statements = Statements::<Bls12_381>::new();
1341 statements.add(PedersenCommitmentStmt::new_statement_from_params(
1342 vec![comm_key_bls.g, comm_key_bls.h],
1343 commitment_pub_x,
1344 ));
1345 statements.add(PedersenCommitmentStmt::new_statement_from_params(
1346 vec![comm_key_bls.g, comm_key_bls.h],
1347 commitment_pub_y,
1348 ));
1349 statements.add(
1350 PoKBBSSignatureG1Prover::<Bls12_381>::new_statement_from_params(
1351 sig_params_g1.clone(),
1352 BTreeMap::from([(2, message_pet)]),
1353 ),
1354 );
1355
1356 let mut meta_statements = MetaStatements::new();
1357 meta_statements.add(MetaStatement::WitnessEquality(EqualWitnesses(
1358 vec![(0, 0), (2, 0)]
1359 .into_iter()
1360 .collect::<BTreeSet<WitnessRef>>(),
1361 )));
1362 meta_statements.add(MetaStatement::WitnessEquality(EqualWitnesses(
1363 vec![(1, 0), (2, 1)]
1364 .into_iter()
1365 .collect::<BTreeSet<WitnessRef>>(),
1366 )));
1367
1368 let mut witnesses = Witnesses::new();
1369 witnesses.add(Witness::PedersenCommitment(vec![
1370 message_pk_x.clone(),
1371 randomness_pub_x,
1372 ]));
1373 witnesses.add(Witness::PedersenCommitment(vec![
1374 message_pk_y.clone(),
1375 randomness_pub_y,
1376 ]));
1377 witnesses.add(PoKBBSSignatureG1::new_as_witness(
1378 signature_issuer,
1379 BTreeMap::from([(0, message_pk_x), (1, message_pk_y)]),
1380 ));
1381
1382 let context = Some(b"test".to_vec());
1383 let proof_spec = ProofSpec::new(
1384 statements.clone(),
1385 meta_statements.clone(),
1386 vec![],
1387 context.clone(),
1388 );
1389 proof_spec.validate().unwrap();
1390
1391 let nonce_eq_pk = Some(b"test nonce".to_vec());
1392 let proof_eq_pk = Proof::new::<StdRng, Blake2b512>(
1393 &mut rng,
1394 proof_spec.clone(),
1395 witnesses.clone(),
1396 nonce_eq_pk.clone(),
1397 Default::default(),
1398 )
1399 .unwrap()
1400 .0;
1401
1402 proof_bbs
1403 .verify(
1404 &BTreeMap::from([(2, message_pet)]),
1405 &challenge,
1406 issuer_keypair.public_key.clone(),
1407 sig_params_g1.clone(),
1408 )
1409 .expect("Verify BBS proof");
1410
1411 let mut verifier_statements = Statements::<Bls12_381>::new();
1412 verifier_statements.add(PedersenCommitmentStmt::new_statement_from_params(
1413 vec![comm_key_bls.g, comm_key_bls.h],
1414 commitment_pub_x,
1415 ));
1416 verifier_statements.add(PedersenCommitmentStmt::new_statement_from_params(
1417 vec![comm_key_bls.g, comm_key_bls.h],
1418 commitment_pub_y,
1419 ));
1420 verifier_statements.add(PoKBBSSignatureG1Verifier::new_statement_from_params(
1421 sig_params_g1.clone(),
1422 issuer_keypair.public_key.clone(),
1423 BTreeMap::from([(2, message_pet)]),
1424 ));
1425 let verifier_proof_spec = ProofSpec::new(
1426 verifier_statements.clone(),
1427 meta_statements.clone(),
1428 vec![],
1429 context.clone(),
1430 );
1431 verifier_proof_spec.validate().unwrap();
1432
1433 proof_eq_pk
1434 .verify::<StdRng, Blake2b512>(
1435 &mut rng,
1436 verifier_proof_spec,
1437 nonce_eq_pk.clone(),
1438 Default::default(),
1439 )
1440 .expect("Verify Point Equality Proof");
1441
1442 Ok(())
1443 }
1444}