use crate::fp512bn::big;
use crate::fp512bn::big::BIG;
use crate::fp512bn::fp::FP;
use crate::fp512bn::ecp;
use crate::fp512bn::ecp::ECP;
use crate::fp512bn::dbig::DBIG;
use crate::fp512bn::ecp2::ECP2;
use crate::fp512bn::fp4::FP4;
use crate::fp512bn::pair;
use crate::fp512bn::rom;
use crate::hmac;
pub const BFS: usize = big::MODBYTES as usize;
pub const BGS: usize = big::MODBYTES as usize;
pub const BLS_OK: isize = 0;
pub const BLS_FAIL: isize = -1;
static mut G2_TAB: [FP4; ecp::G2_TABLE] = [FP4::new(); ecp::G2_TABLE];
fn ceil(a: usize,b: usize) -> usize {
return (a-1)/b+1;
}
fn hash_to_field(hash: usize,hlen: usize ,u: &mut [FP], dst: &[u8],m: &[u8],ctr: usize) {
let q = BIG::new_ints(&rom::MODULUS);
let el = ceil(q.nbits()+ecp::AESKEY*8,8);
let mut okm: [u8;256]=[0;256];
let mut fd: [u8;128]=[0;128];
hmac::xmd_expand(hash,hlen,&mut okm,el*ctr,&dst,&m);
for i in 0..ctr {
for j in 0..el {
fd[j]=okm[el*i+j];
}
u[i]=FP::new_big(&DBIG::frombytes(&fd[0 .. el]).dmod(&q));
}
}
#[allow(non_snake_case)]
pub fn bls_hash_to_point(m: &[u8]) -> ECP {
let dst= String::from("BLS_SIG_ZZZG1_XMD:SHA256-SVDW-RO-_NUL_".to_ascii_uppercase());
let mut u: [FP; 2] = [
FP::new(),
FP::new(),
];
hash_to_field(hmac::MC_SHA2,ecp::HASH_TYPE,&mut u,dst.as_bytes(),m,2);
let mut P=ECP::map2point(&u[0]);
let P1=ECP::map2point(&u[1]);
P.add(&P1);
P.cfp();
P.affine();
return P;
}
pub fn init() -> isize {
let g = ECP2::generator();
if g.is_infinity() {
return BLS_FAIL;
}
unsafe {
pair::precomp(&mut G2_TAB, &g);
}
return BLS_OK;
}
pub fn key_pair_generate(ikm: &[u8], s: &mut [u8], w: &mut [u8]) -> isize {
let r = BIG::new_ints(&rom::CURVE_ORDER);
let el = ceil(3*ceil(r.nbits(),8),2);
let g = ECP2::generator();
let mut len: [u8; 2] = [0; 2];
hmac::inttobytes(el,&mut len);
let salt=String::from("BLS-SIG-KEYGEN-SALT-");
let mut prk: [u8;64]=[0;64];
let mut okm: [u8;128]=[0;128];
let mut aikm: [u8;65]=[0;65];
let likm=ikm.len();
for i in 0..likm {
aikm[i]=ikm[i];
}
aikm[likm]=0;
let hlen=ecp::HASH_TYPE;
hmac::hkdf_extract(hmac::MC_SHA2,hlen,&mut prk,Some(&salt.as_bytes()),&aikm[0 .. likm+1]);
hmac::hkdf_expand(hmac::MC_SHA2,hlen,&mut okm,el,&prk[0 .. hlen],&len);
let mut dx = DBIG::frombytes(&okm[0 .. el]);
let mut sc = dx.dmod(&r);
sc.tobytes(s);
pair::g2mul(&g, &sc).tobytes(w,true); return BLS_OK;
}
pub fn core_sign(sig: &mut [u8], m: &[u8], s: &[u8]) -> isize {
let d = bls_hash_to_point(m);
let sc = BIG::frombytes(&s);
pair::g1mul(&d, &sc).tobytes(sig, true);
return BLS_OK;
}
pub fn core_verify(sig: &[u8], m: &[u8], w: &[u8]) -> isize {
let hm = bls_hash_to_point(m);
let mut d = ECP::frombytes(&sig);
if !pair::g1member(&d) {
return BLS_FAIL;
}
d.neg();
let pk = ECP2::frombytes(&w);
if !pair::g2member(&pk) {
return BLS_FAIL;
}
let mut r = pair::initmp();
unsafe {
pair::another_pc(&mut r, &G2_TAB, &d);
}
pair::another(&mut r, &pk, &hm);
let mut v = pair::miller(&mut r);
v = pair::fexp(&v);
if v.isunity() {
return BLS_OK;
}
return BLS_FAIL;
}