use ark_bls12_381::G1Projective; use concordium_base::{ common::{ types::{KeyIndex, KeyPair, TransactionTime}, *, }, curve_arithmetic::arkworks_instances::ArkGroup, dodis_yampolskiy_prf as prf, elgamal::{PublicKey, SecretKey}, id::{ account_holder::*, anonymity_revoker::*, chain::*, constants::{ArCurve, BaseField, *}, identity_provider::*, secret_sharing::Threshold, types::*, }, }; use criterion::*; use ed25519_dalek as ed25519; use either::Either::Left; use rand::*; use std::{collections::BTreeMap, convert::TryFrom, io::Cursor}; type G1 = ArkGroup; type Bls12 = ark_ec::bls12::Bls12; type ExampleAttribute = AttributeKind; type ExampleAttributeList = AttributeList; const EXPIRY: TransactionTime = TransactionTime { seconds: 111111111111111111, }; fn bench_parts(c: &mut Criterion) { let mut csprng = thread_rng(); let ip_secret_key = concordium_base::ps_sig::SecretKey::::generate(20, &mut csprng); let ip_public_key = concordium_base::ps_sig::PublicKey::from(&ip_secret_key); let keypair = ed25519::SigningKey::generate(&mut csprng); let ah_info = CredentialHolderInfo:: { id_cred: IdCredentials::generate(&mut csprng), }; let global_context = GlobalContext::generate(String::from("genesis_string")); let ar_base = global_context.elgamal_generator(); let ar1_secret_key = SecretKey::generate(ar_base, &mut csprng); let ar1_public_key = PublicKey::from(&ar1_secret_key); let ar_id1 = ArIdentity::try_from(1).unwrap(); let ar1_info = ArInfo:: { ar_identity: ar_id1, ar_description: mk_dummy_description("A good AR".to_string()), ar_public_key: ar1_public_key, }; let ar2_secret_key = SecretKey::generate(ar_base, &mut csprng); let ar2_public_key = PublicKey::from(&ar2_secret_key); let ar_id2 = ArIdentity::try_from(2).unwrap(); let ar2_info = ArInfo:: { ar_identity: ar_id2, ar_description: mk_dummy_description("A nice AR".to_string()), ar_public_key: ar2_public_key, }; let ar3_secret_key = SecretKey::generate(ar_base, &mut csprng); let ar3_public_key = PublicKey::from(&ar3_secret_key); let ar_id3 = ArIdentity::try_from(3).unwrap(); let ar3_info = ArInfo:: { ar_identity: ar_id3, ar_description: mk_dummy_description("Weird AR".to_string()), ar_public_key: ar3_public_key, }; let ar4_secret_key = SecretKey::generate(ar_base, &mut csprng); let ar4_public_key = PublicKey::from(&ar4_secret_key); let ar_id4 = ArIdentity::try_from(4).unwrap(); let ar4_info = ArInfo:: { ar_identity: ar_id4, ar_description: mk_dummy_description("Ok AR".to_string()), ar_public_key: ar4_public_key, }; let ip_info = IpInfo { ip_identity: IpIdentity(88), ip_description: mk_dummy_description("IP88".to_string()), ip_verify_key: ip_public_key, ip_cdi_verify_key: keypair.verifying_key(), }; let prf_key = prf::SecretKey::generate(&mut csprng); let valid_to = YearMonth::new(2021, 1).unwrap(); let created_at = YearMonth::new(2021, 1).unwrap(); let alist = { let mut alist = BTreeMap::new(); alist.insert(AttributeTag::from(0u8), AttributeKind::from(55)); alist.insert(AttributeTag::from(8u8), AttributeKind::from(31)); alist }; let aci = AccCredentialInfo { cred_holder_info: ah_info, prf_key, }; let randomness = concordium_base::ps_sig::SigRetrievalRandomness::generate_non_zero(&mut csprng); let id_use_data = IdObjectUseData { aci, randomness }; let alist = ExampleAttributeList { valid_to, created_at, max_accounts: 255, alist, _phantom: Default::default(), }; let ars_infos = [ (ar_id1, ar1_info), (ar_id2, ar2_info), (ar_id3, ar3_info), (ar_id4, ar4_info), ] .iter() .cloned() .collect::>(); let context = IpContext::new(&ip_info, &ars_infos, &global_context); let initial_acc_data = InitialAccountData { keys: { let mut keys = BTreeMap::new(); keys.insert(KeyIndex(0), KeyPair::generate(&mut csprng)); keys.insert(KeyIndex(1), KeyPair::generate(&mut csprng)); keys.insert(KeyIndex(2), KeyPair::generate(&mut csprng)); keys }, threshold: SignatureThreshold::TWO, }; let (pio, _) = generate_pio(&context, Threshold(2), &id_use_data, &initial_acc_data) .expect("Generating the pre-identity object succeed."); let pio_ser = to_bytes(&pio); let ip_info_ser = to_bytes(&ip_info); let pio_des = from_bytes(&mut Cursor::new(&pio_ser)).unwrap(); let ip_info_des: IpInfo = from_bytes(&mut Cursor::new(&ip_info_ser)).unwrap(); let des_context = IpContext::new(&ip_info_des, &ars_infos, &global_context); let ver_ok = verify_credentials::<_, _, ArCurve>( &pio_des, des_context, &alist, EXPIRY, &ip_secret_key, &keypair.to_bytes(), ); let (ip_sig, initial_cdi) = ver_ok.unwrap(); let policy = Policy { valid_to, created_at, policy_vec: { let mut tree = BTreeMap::new(); tree.insert(AttributeTag::from(8u8), AttributeKind::from(31)); tree }, _phantom: Default::default(), }; let mut keys = BTreeMap::new(); keys.insert(KeyIndex(0), KeyPair::generate(&mut csprng)); keys.insert(KeyIndex(1), KeyPair::generate(&mut csprng)); keys.insert(KeyIndex(2), KeyPair::generate(&mut csprng)); let acc_data = CredentialData { keys, threshold: SignatureThreshold::TWO, }; let id_object = IdentityObject { pre_identity_object: pio, alist, signature: ip_sig, }; let (cdi, _) = create_credential( context, &id_object, &id_use_data, 0, policy.clone(), &acc_data, &SystemAttributeRandomness, &Left(EXPIRY), ) .expect("Should generate the credential successfully."); let ar_2 = ArIdentity::try_from(2).unwrap(); // revoking anonymity let second_ar = cdi.values.ar_data.get(&ar_2).unwrap(); let decrypted_share_ar2 = ( ar_2, ar2_secret_key.decrypt(&second_ar.enc_id_cred_pub_share), ); let ar_4 = ArIdentity::try_from(4).unwrap(); let fourth_ar = cdi.values.ar_data.get(&ar_4).unwrap(); let decrypted_share_ar4 = ( ar_4, ar4_secret_key.decrypt(&fourth_ar.enc_id_cred_pub_share), ); let bench_pio = move |b: &mut Bencher, x: &(_, _, _)| b.iter(|| generate_pio(x.0, Threshold(2), x.1, x.2)); c.bench_with_input( BenchmarkId::new("Generate ID request", ""), &(&context, &id_use_data, &initial_acc_data), bench_pio, ); let bench_verify_initial_cdi = move |b: &mut Bencher, x: &(_, _)| b.iter(|| verify_initial_cdi(x.0, x.1, EXPIRY).unwrap()); c.bench_with_input( BenchmarkId::new("Verify Initial CDI", ""), &(&ip_info, &initial_cdi), bench_verify_initial_cdi, ); let bench_create_credential = move |b: &mut Bencher, x: &(_, _, _, _, Policy, _)| { b.iter(|| { create_credential( x.0, x.1, x.2, x.3, x.4.clone(), x.5, &SystemAttributeRandomness, &Left(EXPIRY), ) .unwrap() }) }; c.bench_with_input( BenchmarkId::new("Generate CDI", ""), &(context, &id_object, &id_use_data, 0, policy, &acc_data), bench_create_credential, ); let bench_verify_cdi = move |b: &mut Bencher, x: &(_, _, _, _)| { b.iter(|| verify_cdi(x.0, x.1, x.2, x.3, &Left(EXPIRY)).unwrap()) }; c.bench_with_input( BenchmarkId::new("Verify CDI", ""), &(&global_context, &ip_info, &ars_infos, &cdi), bench_verify_cdi, ); let share_vec = vec![decrypted_share_ar2, decrypted_share_ar4]; let bench_reveal_id_cred_pub = move |b: &mut Bencher| b.iter(|| reveal_id_cred_pub(&share_vec)); let bench_verify_ip = move |b: &mut Bencher| { b.iter(|| { verify_credentials( &id_object.pre_identity_object, context, &id_object.alist, EXPIRY, &ip_secret_key, &keypair.to_bytes(), ) .unwrap() }) }; c.bench_function("IP verify credentials", bench_verify_ip); c.bench_function("Reveal IdCredPub", bench_reveal_id_cred_pub); } criterion_group! { name = verify_id_interactions; config = Criterion::default(); targets = bench_parts } criterion_main!(verify_id_interactions);