use crate::error::{Error, check};
use crate::ffi;
use crate::types::{BLS_PUBKEY_LEN, BLS_SIG_LEN};
use std::fmt;
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct BlsPubkey(pub [u8; BLS_PUBKEY_LEN]);
impl Default for BlsPubkey {
fn default() -> Self {
BlsPubkey([0u8; BLS_PUBKEY_LEN])
}
}
impl fmt::Debug for BlsPubkey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BlsPubkey({})", hex::encode_bytes(&self.0))
}
}
impl From<ffi::nwep_bls_pubkey> for BlsPubkey {
fn from(p: ffi::nwep_bls_pubkey) -> Self {
BlsPubkey(p.data)
}
}
impl From<BlsPubkey> for ffi::nwep_bls_pubkey {
fn from(p: BlsPubkey) -> Self {
ffi::nwep_bls_pubkey { data: p.0 }
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct BlsSig(pub [u8; BLS_SIG_LEN]);
impl Default for BlsSig {
fn default() -> Self {
BlsSig([0u8; BLS_SIG_LEN])
}
}
impl fmt::Debug for BlsSig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BlsSig([{} bytes])", BLS_SIG_LEN)
}
}
impl From<ffi::nwep_bls_sig> for BlsSig {
fn from(s: ffi::nwep_bls_sig) -> Self {
BlsSig(s.data)
}
}
impl From<BlsSig> for ffi::nwep_bls_sig {
fn from(s: BlsSig) -> Self {
ffi::nwep_bls_sig { data: s.0 }
}
}
pub struct BlsKeypair {
inner: ffi::nwep_bls_keypair,
}
impl BlsKeypair {
pub fn generate() -> Result<Self, Error> {
let mut kp = ffi::nwep_bls_keypair {
pubkey: [0u8; BLS_PUBKEY_LEN],
privkey: [0u8; 32],
};
check(unsafe { ffi::nwep_bls_keypair_generate(&mut kp) })?;
Ok(BlsKeypair { inner: kp })
}
pub fn from_seed(ikm: &[u8]) -> Result<Self, Error> {
let mut kp = ffi::nwep_bls_keypair {
pubkey: [0u8; BLS_PUBKEY_LEN],
privkey: [0u8; 32],
};
check(unsafe { ffi::nwep_bls_keypair_from_seed(&mut kp, ikm.as_ptr(), ikm.len()) })?;
Ok(BlsKeypair { inner: kp })
}
pub fn pubkey(&self) -> BlsPubkey {
BlsPubkey(self.inner.pubkey)
}
pub(crate) fn as_ffi(&self) -> &ffi::nwep_bls_keypair {
&self.inner
}
}
pub fn bls_pubkey_serialize(pk: &BlsPubkey) -> Result<[u8; BLS_PUBKEY_LEN], Error> {
let ffi_pk = ffi::nwep_bls_pubkey { data: pk.0 };
let mut out = [0u8; BLS_PUBKEY_LEN];
check(unsafe { ffi::nwep_bls_pubkey_serialize(out.as_mut_ptr(), &ffi_pk) })?;
Ok(out)
}
pub fn bls_pubkey_deserialize(data: &[u8; BLS_PUBKEY_LEN]) -> Result<BlsPubkey, Error> {
let mut pk = ffi::nwep_bls_pubkey {
data: [0u8; BLS_PUBKEY_LEN],
};
check(unsafe { ffi::nwep_bls_pubkey_deserialize(&mut pk, data.as_ptr()) })?;
Ok(BlsPubkey(pk.data))
}
pub fn bls_sign(kp: &BlsKeypair, msg: &[u8]) -> Result<BlsSig, Error> {
let mut sig = ffi::nwep_bls_sig {
data: [0u8; BLS_SIG_LEN],
};
check(unsafe { ffi::nwep_bls_sign(&mut sig, kp.as_ffi(), msg.as_ptr(), msg.len()) })?;
Ok(BlsSig(sig.data))
}
pub fn bls_verify(pk: &BlsPubkey, sig: &BlsSig, msg: &[u8]) -> Result<(), Error> {
let ffi_pk = ffi::nwep_bls_pubkey { data: pk.0 };
let ffi_sig = ffi::nwep_bls_sig { data: sig.0 };
check(unsafe { ffi::nwep_bls_verify(&ffi_pk, &ffi_sig, msg.as_ptr(), msg.len()) })
}
pub fn bls_aggregate_sigs(sigs: &[BlsSig]) -> Result<BlsSig, Error> {
let ffi_sigs: Vec<ffi::nwep_bls_sig> = sigs
.iter()
.map(|s| ffi::nwep_bls_sig { data: s.0 })
.collect();
let mut out = ffi::nwep_bls_sig {
data: [0u8; BLS_SIG_LEN],
};
check(unsafe { ffi::nwep_bls_aggregate_sigs(&mut out, ffi_sigs.as_ptr(), ffi_sigs.len()) })?;
Ok(BlsSig(out.data))
}
pub fn bls_verify_aggregate(pks: &[BlsPubkey], sig: &BlsSig, msg: &[u8]) -> Result<(), Error> {
let ffi_pks: Vec<ffi::nwep_bls_pubkey> = pks
.iter()
.map(|p| ffi::nwep_bls_pubkey { data: p.0 })
.collect();
let ffi_sig = ffi::nwep_bls_sig { data: sig.0 };
check(unsafe {
ffi::nwep_bls_verify_aggregate(
ffi_pks.as_ptr(),
ffi_pks.len(),
&ffi_sig,
msg.as_ptr(),
msg.len(),
)
})
}
mod hex {
pub fn encode_bytes(b: &[u8]) -> String {
b.iter().map(|x| format!("{:02x}", x)).collect()
}
}