use amcl_wrapper::errors::SerzDeserzError;
use amcl_wrapper::extension_field_gt::GT;
use amcl_wrapper::group_elem::{GroupElement, GroupElementVector};
use amcl_wrapper::group_elem_g1::G1;
use amcl_wrapper::group_elem_g2::G2;
use super::common::{SigKey, VerKey};
use amcl_wrapper::field_elem::{FieldElement, FieldElementVector};
use common::{Params, MESSAGE_DOMAIN_PREFIX};
use {ate_2_pairing, SignatureGroup, SignatureGroupVec};
use {ate_multi_pairing, VerkeyGroup};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Signature {
pub point: SignatureGroup,
}
impl Signature {
pub fn new(msg: &[u8], sig_key: &SigKey) -> Self {
let hash_point = Self::hash_message(msg);
let sig = hash_point * &sig_key.x;
Signature { point: sig }
}
pub fn verify(&self, msg: &[u8], ver_key: &VerKey, params: &Params) -> bool {
if self.point.is_identity() {
println!("Signature point at infinity");
return false;
}
let msg_hash_point = Self::hash_message(msg);
ate_2_pairing(
&msg_hash_point,
&ver_key.point,
&self.point,
¶ms.g.negation(),
)
.is_one()
}
pub fn batch_verify(msgs_sigs: Vec<(&[u8], &Signature, &VerKey)>, params: &Params) -> bool {
let r = FieldElement::random();
let r_vec = FieldElementVector::new_vandermonde_vector(&r, msgs_sigs.len());
let mut sigs = SignatureGroupVec::with_capacity(msgs_sigs.len());
let mut hs = vec![];
let mut vs = vec![];
for (i, (msg, sig, vk)) in msgs_sigs.iter().enumerate() {
sigs.push(sig.point.clone());
hs.push(Signature::hash_message(msg));
vs.push(&vk.point * &r_vec[i]);
}
let aggr_sig = sigs.multi_scalar_mul_var_time(&r_vec).unwrap();
let mut pairings = hs
.iter()
.zip(vs.iter())
.map(|(h, v)| (h, v))
.collect::<Vec<(&SignatureGroup, &VerkeyGroup)>>();
let neg_g = params.g.negation();
pairings.push((&aggr_sig, &neg_g));
ate_multi_pairing(pairings).is_one()
}
pub fn batch_verify_distinct_msgs(
msgs_sigs: Vec<(&[u8], &Signature, &VerKey)>,
params: &Params,
) -> bool {
let mut aggr_sig = SignatureGroup::new();
let mut hs = vec![];
let mut vs = vec![];
for (msg, sig, vk) in msgs_sigs {
aggr_sig += &sig.point;
hs.push(Signature::hash_message(msg));
vs.push(vk);
}
let mut pairings = hs
.iter()
.zip(vs)
.map(|(h, v)| (h, &v.point))
.collect::<Vec<(&SignatureGroup, &VerkeyGroup)>>();
let neg_g = params.g.negation();
pairings.push((&aggr_sig, &neg_g));
ate_multi_pairing(pairings).is_one()
}
pub fn from_bytes(sig_bytes: &[u8]) -> Result<Signature, SerzDeserzError> {
SignatureGroup::from_bytes(sig_bytes).map(|point| Signature { point })
}
pub fn to_bytes(&self) -> Vec<u8> {
self.point.to_bytes()
}
pub(crate) fn hash_message(msg: &[u8]) -> SignatureGroup {
SignatureGroup::from_msg_hash(&[&MESSAGE_DOMAIN_PREFIX, msg].concat())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::common::Keypair;
use rand::Rng;
use rand::thread_rng;
use std::time::Instant;
#[test]
fn sign_verify() {
let mut rng = thread_rng();
let params = Params::new("test".as_bytes());
let keypair = Keypair::new(&mut rng, ¶ms);
let sk = keypair.sig_key;
let vk = keypair.ver_key;
let msg = "Small msg";
let msg1 = "121220888888822111212";
let msg2 = "Some message to sign";
let msg3 = "Some message to sign, making it bigger, ......, still bigger........................, not some entropy, hu2jnnddsssiu8921n ckhddss2222";
for m in vec![msg, msg1, msg2, msg3] {
let b = m.as_bytes();
let mut sig = Signature::new(&b, &sk);
assert!(sig.verify(&b, &vk, ¶ms));
let bs = sig.to_bytes();
let sig1 = Signature::from_bytes(&bs).unwrap();
assert_eq!(&sig.point.to_bytes(), &sig1.point.to_bytes());
}
}
#[test]
fn verification_failure() {
let mut rng = thread_rng();
let params = Params::new("test".as_bytes());
let keypair = Keypair::new(&mut rng, ¶ms);
let sk = keypair.sig_key;
let vk = keypair.ver_key;
let mut msg = "Some msg";
let sig = Signature::new(&msg.as_bytes(), &sk);
msg = "Other msg";
assert_eq!(sig.verify(&msg.as_bytes(), &vk, ¶ms), false);
msg = "";
assert_eq!(sig.verify(&msg.as_bytes(), &vk, ¶ms), false);
}
#[test]
fn signature_at_infinity() {
let mut rng = thread_rng();
let params = Params::new("test".as_bytes());
let keypair = Keypair::new(&mut rng, ¶ms);
let vk = keypair.ver_key;
let msg = "Small msg".as_bytes();
let sig = Signature {
point: SignatureGroup::identity(),
};
assert_eq!(sig.verify(&msg, &vk, ¶ms), false);
}
#[test]
fn batch_verify() {
let params = Params::new("test".as_bytes());
let mut keypairs = vec![];
let mut msgs = vec![];
let mut sigs = vec![];
let mut rng = rand::thread_rng();
let count = 5;
for _ in 0..count {
let keypair = Keypair::new(&mut rng, ¶ms);
let msg = (0..10).map(|_| rng.gen_range(1, 100)).collect::<Vec<u8>>();
let sig = Signature::new(&msg, &keypair.sig_key);
sigs.push(sig);
msgs.push(msg);
keypairs.push(keypair);
}
let start = Instant::now();
for i in 0..count {
assert!(sigs[i].verify(&msgs[i], &keypairs[i].ver_key, ¶ms));
}
println!(
"Naive verify for {} sigs takes {:?}",
count,
start.elapsed()
);
let start = Instant::now();
let msgs_sigs = (0..count)
.map(|i| (msgs[i].as_slice(), &sigs[i], &keypairs[i].ver_key))
.collect::<Vec<_>>();
assert!(Signature::batch_verify(msgs_sigs, ¶ms));
println!(
"Batch verify for {} sigs takes {:?}",
count,
start.elapsed()
);
let start = Instant::now();
let msgs_sigs = (0..count)
.map(|i| (msgs[i].as_slice(), &sigs[i], &keypairs[i].ver_key))
.collect::<Vec<_>>();
assert!(Signature::batch_verify_distinct_msgs(msgs_sigs, ¶ms));
println!(
"Batch verify assuming distinct messages for {} sigs takes {:?}",
count,
start.elapsed()
);
}
}