use ff::Field;
use hkdf::Hkdf;
use pairing_plus::bls12_381::{Bls12, Fq12, Fr, G1, G2};
use pairing_plus::hash_to_curve::HashToCurve;
use pairing_plus::hash_to_field::BaseFromRO;
use pairing_plus::serdes::SerDes;
use pairing_plus::{CurveAffine, CurveProjective, Engine};
use sha2::digest::generic_array::typenum::{U48, U96};
use sha2::digest::generic_array::{ArrayLength, GenericArray};
use sha2::Sha256;
use std::collections::HashSet;
use std::io::Cursor;
use std::vec::Vec;
pub fn xprime_from_sk<B: AsRef<[u8]>>(msg: B) -> Fr {
const SALT: &[u8] = &[
66, 76, 83, 45, 83, 73, 71, 45, 75, 69, 89, 71, 69, 78, 45, 83, 65, 76, 84, 45,
];
let mut result = GenericArray::<u8, U48>::default();
assert!(Hkdf::<Sha256>::new(Some(SALT), msg.as_ref())
.expand(&[], &mut result)
.is_ok());
Fr::from_okm(&result)
}
fn _agg_help<T: CurveProjective>(ins: &[T]) -> T {
let mut ret = T::zero();
for inv in ins {
ret.add_assign(inv);
}
ret
}
type ScalarT<PtT> = <PtT as CurveProjective>::Scalar;
pub trait BLSSigCore: CurveProjective {
type PKType: CurveProjective<Engine = <Self as CurveProjective>::Engine, Scalar = ScalarT<Self>>
+ SerDes;
fn keygen<B: AsRef<[u8]>>(sk: B) -> (ScalarT<Self>, Self::PKType);
fn core_sign<B: AsRef<[u8]>, C: AsRef<[u8]>>(
x_prime: ScalarT<Self>,
msg: B,
ciphersuite: C,
) -> Self;
fn core_verify<B: AsRef<[u8]>, C: AsRef<[u8]>>(
pk: Self::PKType,
sig: Self,
msg: B,
ciphersuite: C,
) -> bool;
fn aggregate(sigs: &[Self]) -> Self {
_agg_help(sigs)
}
fn core_aggregate_verify<B: AsRef<[u8]>, C: AsRef<[u8]>>(
pks: &[Self::PKType],
msgs: &[B],
sig: Self,
ciphersuite: C,
) -> bool;
}
pub trait BLSSignatureBasic: BLSSigCore {
const CSUITE: &'static [u8];
fn sign<B: AsRef<[u8]>>(x_prime: ScalarT<Self>, msg: B) -> Self {
<Self as BLSSigCore>::core_sign(x_prime, msg, Self::CSUITE)
}
fn verify<B: AsRef<[u8]>>(pk: Self::PKType, sig: Self, msg: B) -> bool {
<Self as BLSSigCore>::core_verify(pk, sig, msg, Self::CSUITE)
}
fn aggregate_verify<B: AsRef<[u8]>>(pks: &[Self::PKType], msgs: &[B], sig: Self) -> bool {
let mut msg_set = HashSet::<&[u8]>::with_capacity(msgs.len());
for msg in msgs {
msg_set.insert(msg.as_ref());
}
if msg_set.len() != msgs.len() {
return false;
}
<Self as BLSSigCore>::core_aggregate_verify(pks, msgs, sig, Self::CSUITE)
}
}
pub trait BLSSignatureAug: BLSSigCore {
const CSUITE: &'static [u8];
const PK_LEN: usize;
fn pk_bytes(pk: &Self::PKType, size_hint: usize) -> Vec<u8> {
let mut cur = Cursor::new(Vec::<u8>::with_capacity(size_hint + Self::PK_LEN));
assert!(pk.serialize(&mut cur, true).is_ok());
cur.into_inner()
}
fn sign<B: AsRef<[u8]>>(x_prime: ScalarT<Self>, msg: B) -> Self {
let pk = {
let mut tmp = <Self::PKType as CurveProjective>::one();
tmp.mul_assign(x_prime);
tmp
};
let mut pk_msg_vec = Self::pk_bytes(&pk, msg.as_ref().len());
pk_msg_vec.extend_from_slice(msg.as_ref());
<Self as BLSSigCore>::core_sign(x_prime, &pk_msg_vec, Self::CSUITE)
}
fn verify<B: AsRef<[u8]>>(pk: Self::PKType, sig: Self, msg: B) -> bool {
let mut pk_msg_vec = Self::pk_bytes(&pk, msg.as_ref().len());
pk_msg_vec.extend_from_slice(msg.as_ref());
<Self as BLSSigCore>::core_verify(pk, sig, &pk_msg_vec, Self::CSUITE)
}
fn aggregate_verify<B: AsRef<[u8]>>(pks: &[Self::PKType], msgs: &[B], sig: Self) -> bool {
let mut pks_msgs_vec = Vec::<Vec<u8>>::with_capacity(msgs.len());
for (msg, pk) in msgs.as_ref().iter().zip(pks) {
let mut pk_msg_vec = Self::pk_bytes(&pk, msg.as_ref().len());
pk_msg_vec.extend_from_slice(msg.as_ref());
pks_msgs_vec.push(pk_msg_vec);
}
<Self as BLSSigCore>::core_aggregate_verify(pks, &pks_msgs_vec[..], sig, Self::CSUITE)
}
}
pub trait BLSSignaturePop: BLSSigCore {
const CSUITE: &'static [u8];
const CSUITE_POP: &'static [u8];
type Length: ArrayLength<u8>;
fn sign<B: AsRef<[u8]>>(x_prime: ScalarT<Self>, msg: B) -> Self {
<Self as BLSSigCore>::core_sign(x_prime, msg, Self::CSUITE)
}
fn verify<B: AsRef<[u8]>>(pk: Self::PKType, sig: Self, msg: B) -> bool {
<Self as BLSSigCore>::core_verify(pk, sig, msg, Self::CSUITE)
}
fn aggregate_verify<B: AsRef<[u8]>>(pks: &[Self::PKType], msgs: &[B], sig: Self) -> bool {
<Self as BLSSigCore>::core_aggregate_verify(pks, msgs, sig, Self::CSUITE)
}
fn multisig_verify<B: AsRef<[u8]>>(pks: &[Self::PKType], sig: Self, msg: B) -> bool {
let apk = _agg_help(pks);
<Self as BLSSigCore>::core_verify(apk, sig, msg, Self::CSUITE)
}
fn pop_prove<B: AsRef<[u8]>>(sk: B) -> Self {
let (x_prime, pk) = <Self as BLSSigCore>::keygen(sk);
let pk_bytes = {
let mut buf = GenericArray::<u8, Self::Length>::default();
let mut cur = Cursor::new(&mut buf[..]);
assert!(pk.serialize(&mut cur, true).is_ok());
buf
};
<Self as BLSSigCore>::core_sign(x_prime, &pk_bytes[..], Self::CSUITE_POP)
}
fn pop_verify(pk: <Self as BLSSigCore>::PKType, sig: Self) -> bool {
let pk_bytes = {
let mut buf = GenericArray::<u8, Self::Length>::default();
let mut cur = Cursor::new(&mut buf[..]);
assert!(pk.serialize(&mut cur, true).is_ok());
buf
};
<Self as BLSSigCore>::core_verify(pk, sig, &pk_bytes[..], Self::CSUITE_POP)
}
}
impl BLSSigCore for G1 {
type PKType = G2;
fn keygen<B: AsRef<[u8]>>(sk: B) -> (Fr, G2) {
let x_prime = xprime_from_sk(sk);
let mut pk = G2::one();
pk.mul_assign(x_prime);
(x_prime, pk)
}
fn core_sign<B: AsRef<[u8]>, C: AsRef<[u8]>>(x_prime: Fr, msg: B, ciphersuite: C) -> G1 {
let mut p = G1::hash_to_curve(msg, ciphersuite);
p.mul_assign(x_prime);
p
}
fn core_verify<B: AsRef<[u8]>, C: AsRef<[u8]>>(
pk: G2,
sig: G1,
msg: B,
ciphersuite: C,
) -> bool {
let p = G1::hash_to_curve(msg, ciphersuite).into_affine().prepare();
let g2gen = {
let mut tmp = G2::one();
tmp.negate();
tmp.into_affine().prepare()
};
match Bls12::final_exponentiation(&Bls12::miller_loop(&[
(&p, &pk.into_affine().prepare()),
(&sig.into_affine().prepare(), &g2gen),
])) {
None => false,
Some(pairingproduct) => pairingproduct == Fq12::one(),
}
}
fn core_aggregate_verify<B: AsRef<[u8]>, C: AsRef<[u8]>>(
pks: &[G2],
msgs: &[B],
sig: G1,
ciphersuite: C,
) -> bool {
let pvec = {
let mut ret =
Vec::<<<G1 as CurveProjective>::Affine as CurveAffine>::Prepared>::with_capacity(
msgs.len() + 1,
);
for msg in msgs {
ret.push(
G1::hash_to_curve(msg, ciphersuite.as_ref())
.into_affine()
.prepare(),
);
}
ret.push(sig.into_affine().prepare());
ret
};
let qvec = {
let mut ret =
Vec::<<<G2 as CurveProjective>::Affine as CurveAffine>::Prepared>::with_capacity(
pks.len() + 1,
);
for pk in pks {
ret.push(pk.into_affine().prepare());
}
let mut tmp = G2::one();
tmp.negate();
ret.push(tmp.into_affine().prepare());
ret
};
let pqz: Vec<_> = pvec.as_slice().iter().zip(qvec.as_slice()).collect();
match Bls12::final_exponentiation(&Bls12::miller_loop(&pqz[..])) {
None => false,
Some(pairingproduct) => pairingproduct == Fq12::one(),
}
}
}
impl BLSSignatureBasic for G1 {
const CSUITE: &'static [u8] = &[
66, 76, 83, 95, 83, 73, 71, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 49, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 78, 85, 76, 95,
];
}
impl BLSSignatureAug for G1 {
const CSUITE: &'static [u8] = &[
66, 76, 83, 95, 83, 73, 71, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 49, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 65, 85, 71, 95,
];
const PK_LEN: usize = 96;
}
impl BLSSignaturePop for G1 {
const CSUITE: &'static [u8] = &[
66, 76, 83, 95, 83, 73, 71, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 49, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 80, 79, 80, 95,
];
const CSUITE_POP: &'static [u8] = &[
66, 76, 83, 95, 80, 79, 80, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 49, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 80, 79, 80, 95,
];
type Length = U96;
}
impl BLSSigCore for G2 {
type PKType = G1;
fn keygen<B: AsRef<[u8]>>(sk: B) -> (Fr, G1) {
let x_prime = xprime_from_sk(sk);
let mut pk = G1::one();
pk.mul_assign(x_prime);
(x_prime, pk)
}
fn core_sign<B: AsRef<[u8]>, C: AsRef<[u8]>>(x_prime: Fr, msg: B, ciphersuite: C) -> G2 {
let mut p = G2::hash_to_curve(msg, ciphersuite);
p.mul_assign(x_prime);
p
}
fn core_verify<B: AsRef<[u8]>, C: AsRef<[u8]>>(
pk: G1,
sig: G2,
msg: B,
ciphersuite: C,
) -> bool {
let p = G2::hash_to_curve(msg, ciphersuite).into_affine().prepare();
let g1gen = {
let mut tmp = G1::one();
tmp.negate();
tmp.into_affine().prepare()
};
match Bls12::final_exponentiation(&Bls12::miller_loop(&[
(&pk.into_affine().prepare(), &p),
(&g1gen, &sig.into_affine().prepare()),
])) {
None => false,
Some(pairingproduct) => pairingproduct == Fq12::one(),
}
}
fn core_aggregate_verify<B: AsRef<[u8]>, C: AsRef<[u8]>>(
pks: &[G1],
msgs: &[B],
sig: G2,
ciphersuite: C,
) -> bool {
let pvec = {
let mut ret =
Vec::<<<G1 as CurveProjective>::Affine as CurveAffine>::Prepared>::with_capacity(
pks.len() + 1,
);
for pk in pks {
ret.push(pk.into_affine().prepare());
}
let mut tmp = G1::one();
tmp.negate();
ret.push(tmp.into_affine().prepare());
ret
};
let qvec = {
let mut ret =
Vec::<<<G2 as CurveProjective>::Affine as CurveAffine>::Prepared>::with_capacity(
msgs.len() + 1,
);
for msg in msgs {
ret.push(
G2::hash_to_curve(msg, ciphersuite.as_ref())
.into_affine()
.prepare(),
);
}
ret.push(sig.into_affine().prepare());
ret
};
let pqz: Vec<_> = pvec.as_slice().iter().zip(qvec.as_slice()).collect();
match Bls12::final_exponentiation(&Bls12::miller_loop(&pqz[..])) {
None => false,
Some(pairingproduct) => pairingproduct == Fq12::one(),
}
}
}
impl BLSSignatureBasic for G2 {
const CSUITE: &'static [u8] = &[
66, 76, 83, 95, 83, 73, 71, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 50, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 78, 85, 76, 95,
];
}
impl BLSSignatureAug for G2 {
const CSUITE: &'static [u8] = &[
66, 76, 83, 95, 83, 73, 71, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 50, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 65, 85, 71, 95,
];
const PK_LEN: usize = 48;
}
impl BLSSignaturePop for G2 {
const CSUITE: &'static [u8] = &[
66, 76, 83, 95, 83, 73, 71, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 50, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 80, 79, 80, 95,
];
const CSUITE_POP: &'static [u8] = &[
66, 76, 83, 95, 80, 79, 80, 95, 66, 76, 83, 49, 50, 51, 56, 49, 71, 50, 45, 83, 72, 65, 50,
53, 54, 45, 83, 83, 87, 85, 45, 82, 79, 45, 95, 80, 79, 80, 95,
];
type Length = U48;
}