use rand::{CryptoRng, RngCore};
use crate::keys::{Verkey, Sigkey, MasterSecret, ProofOfPossession, Keypair};
use amcl_wrapper::field_elem::{FieldElement, FieldElementVector};
use amcl_wrapper::group_elem::{GroupElement, GroupElementVector};
use secret_sharing::polynomial::Polynomial;
use secret_sharing::shamir_secret_sharing::get_shared_secret;
use crate::{VerkeyGroup, SignatureGroup, VerkeyGroupVec, SignatureGroupVec};
use std::collections::{HashMap, HashSet};
use std::mem;
use crate::errors::PixelError;
use crate::signature::Signature;
pub struct Signer {
pub id: usize,
pub sigkey_initial: Sigkey,
pub verkey: Verkey,
pub pop: ProofOfPossession,
}
fn keygen_from_shares<R: RngCore + CryptoRng>(
num_signers: usize,
mut master_secret_shares: HashMap<usize, FieldElement>,
rng: &mut R,
gen: &VerkeyGroup,
gens: &[SignatureGroup],
) -> Result<Vec<Signer>, PixelError> {
let mut signers = vec![];
for i in 0..num_signers {
let id = i + 1;
let x_i = master_secret_shares.remove(&id).unwrap();
let master_secret = MasterSecret {value: x_i};
let verkey = Verkey::from_master_secret(&master_secret, gen);
let pop = Keypair::gen_pop(&verkey, &master_secret);
let sigkey_initial = Sigkey::initial_secret_key(
gen,
gens,
&master_secret,
rng,
)?;
mem::drop(master_secret);
signers.push(Signer {
id,
sigkey_initial,
verkey,
pop
})
}
Ok(signers)
}
pub fn trusted_party_SSS_keygen<R: RngCore + CryptoRng>(
threshold: usize,
total: usize,
rng: &mut R,
gen: &VerkeyGroup,
gens: &[SignatureGroup],
) -> Result<(FieldElement, Vec<Signer>), PixelError> {
let (secret_x, x_shares) = get_shared_secret(threshold, total);
Ok((secret_x, keygen_from_shares(total, x_shares, rng, gen, gens)?))
}
pub struct ThresholdScheme {}
impl ThresholdScheme {
pub fn aggregate_sigs(threshold: usize, sigs: Vec<(usize, Signature)>) -> Signature {
assert!(sigs.len() >= threshold);
let mut sigma_1_bases = SignatureGroupVec::with_capacity(threshold);
let mut sigma_1_exps = FieldElementVector::with_capacity(threshold);
let mut sigma_2_bases = VerkeyGroupVec::with_capacity(threshold);
let mut sigma_2_exps = FieldElementVector::with_capacity(threshold);
let signer_ids = sigs
.iter()
.take(threshold)
.map(|(i, _)| *i)
.collect::<HashSet<usize>>();
for (id, sig) in sigs.into_iter().take(threshold) {
let l = Polynomial::lagrange_basis_at_0(signer_ids.clone(), id);
sigma_1_bases.push(sig.sigma_1.clone());
sigma_1_exps.push(l.clone());
sigma_2_bases.push(sig.sigma_2.clone());
sigma_2_exps.push(l);
}
Signature {
sigma_1: sigma_1_bases.multi_scalar_mul_const_time(sigma_1_exps.as_ref()).unwrap(),
sigma_2: sigma_2_bases.multi_scalar_mul_const_time(sigma_2_exps.as_ref()).unwrap(),
}
}
pub fn aggregate_vk(threshold: usize, keys: Vec<(usize, &Verkey)>) -> Verkey {
assert!(keys.len() >= threshold);
let mut vk_bases = VerkeyGroupVec::with_capacity(threshold);
let mut vk_exps = FieldElementVector::with_capacity(threshold);
let signer_ids = keys
.iter()
.take(threshold)
.map(|(i, _)| *i)
.collect::<HashSet<usize>>();
for (id, vk) in keys.into_iter().take(threshold) {
let l = Polynomial::lagrange_basis_at_0(signer_ids.clone(), id);
vk_bases.push(vk.value.clone());
vk_exps.push(l.clone());
}
Verkey {
value: vk_bases.multi_scalar_mul_var_time(vk_exps.as_ref()).unwrap(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use rand::rngs::ThreadRng;
use crate::util::{GeneratorSet, calculate_l};
use crate::signature::Signature;
use crate::keys::{InMemorySigKeyDb, SigkeyManager};
fn check_threshold_key_gen(
threshold: usize,
secret_x: FieldElement,
signers: &[Signer],
gen: &VerkeyGroup,
) {
let threshold_vk = ThresholdScheme::aggregate_vk(
threshold,
signers
.iter()
.take(threshold)
.map(|s| (s.id, &s.verkey))
.collect::<Vec<(usize, &Verkey)>>(),
);
let expected_vk = gen * &secret_x;
assert_eq!(expected_vk, threshold_vk.value);
}
fn check_threshold_key_gen_gaps_in_ids(
threshold: usize,
secret_x: FieldElement,
keys_to_aggr: Vec<(usize, &Verkey)>,
gen: &VerkeyGroup,
) {
let threshold_vk = ThresholdScheme::aggregate_vk(threshold, keys_to_aggr);
let expected_vk = gen * &secret_x;
assert_eq!(expected_vk, threshold_vk.value);
}
fn check_signing_on_random_msgs(threshold: usize, signers: &[Signer], mut sigkey_dbs: Vec<InMemorySigKeyDb>, mut sk_managers: Vec<SigkeyManager>, T: u128, l: u8, gens: &GeneratorSet) {
let mut rng = rand::thread_rng();
for t in 1..=T {
let msg = FieldElement::random().to_bytes();
let mut sigs = vec![];
for i in 0..threshold {
let sk = sk_managers[i].get_current_key(&sigkey_dbs[i]).unwrap();
let sig = Signature::new(&msg, t, l, &gens, sk, &mut rng).unwrap();
assert!(sig.verify(&msg, t, l, gens, &signers[i].verkey).unwrap());
sigs.push((signers[i].id, sig));
}
let threshold_sig = ThresholdScheme::aggregate_sigs(threshold, sigs);
let threshold_vk = ThresholdScheme::aggregate_vk(
threshold,
signers
.iter()
.map(|s| (s.id, &s.verkey))
.collect::<Vec<(usize, &Verkey)>>(),
);
assert!(threshold_sig.verify(&msg, t, l, gens, &threshold_vk).unwrap());
for i in 0..threshold {
sk_managers[i].simple_update(&gens, &mut rng, &mut sigkey_dbs[i]).unwrap();
}
}
}
#[test]
fn test_verkey_aggregation_shamir_secret_sharing_keygen() {
let mut rng = rand::thread_rng();
let T = 7;
let generators = GeneratorSet::new(T, "test_pixel").unwrap();
let threshold = 3;
let total = 5;
let (secret_x, signers) = trusted_party_SSS_keygen(threshold, total, &mut rng, &generators.0, &generators.1).unwrap();
check_threshold_key_gen(threshold, secret_x, &signers, &generators.0)
}
#[test]
fn test_verkey_aggregation_gaps_in_ids_shamir_secret_sharing_keygen() {
let mut rng = rand::thread_rng();
let T = 7;
let generators = GeneratorSet::new(T, "test_pixel").unwrap();
let threshold = 3;
let total = 5;
let (secret_x, signers) = trusted_party_SSS_keygen(threshold, total, &mut rng, &generators.0, &generators.1).unwrap();
let mut keys = vec![];
keys.push((signers[0].id, &signers[0].verkey));
keys.push((signers[2].id, &signers[2].verkey));
keys.push((signers[4].id, &signers[4].verkey));
check_threshold_key_gen_gaps_in_ids(threshold, secret_x, keys, &generators.0);
}
#[test]
fn test_sign_verify_shamir_secret_sharing_keygen() {
let mut rng = rand::thread_rng();
let T = 7;
let l = calculate_l(T).unwrap();
let generators = GeneratorSet::new(T, "test_pixel").unwrap();
let threshold = 3;
let total = 5;
let (secret_x, signers) = trusted_party_SSS_keygen(threshold, total, &mut rng, &generators.0, &generators.1).unwrap();
let mut sk_managers = Vec::<SigkeyManager>::new();
let mut sigkey_dbs = Vec::<InMemorySigKeyDb>::new();
for i in 0..total {
let mut db = InMemorySigKeyDb::new();
let sk_manager = SigkeyManager::new(T, l, signers[i].sigkey_initial.clone(), &mut db).unwrap();
sigkey_dbs.push(db);
sk_managers.push(sk_manager);
}
check_signing_on_random_msgs(threshold, &signers, sigkey_dbs, sk_managers, T, l, &generators)
}
}