use crate::bn254cx::big;
use crate::bn254cx::big::BIG;
use crate::bn254cx::fp::FP;
use crate::bn254cx::ecp;
use crate::bn254cx::ecp::ECP;
use crate::bn254cx::dbig::DBIG;
use crate::bn254cx::ecp2::ECP2;
use crate::bn254cx::pair;
use crate::bn254cx::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;
fn ceil(a: usize,b: usize) -> usize {
(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 nbq=q.nbits();
let el = ceil(nbq+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]).ctdmod(&q,8*el-nbq));
}
}
#[allow(non_snake_case)]
pub fn bls_hash_to_point(m: &[u8]) -> ECP {
let dst= "BLS_SIG_BN254CXG1_XMD:SHA-256_SVDW_RO_NUL_";
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();
P
}
pub fn init() -> isize {
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 nbr=r.nbits();
let el = ceil(3*ceil(nbr,8),2);
let g = ECP2::generator();
let mut len: [u8; 2] = [0; 2];
hmac::inttobytes(el,&mut len);
let salt="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 sc = dx.ctdmod(&r,8*el-nbr);
sc.tobytes(s);
pair::g2mul(&g, &sc).tobytes(w,true); 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);
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 g = ECP2::generator();
let mut v = pair::ate2(&g, &d, &pk, &hm);
v = pair::fexp(&v);
if v.isunity() {
return BLS_OK;
}
BLS_FAIL
}