use crate::{Compress, Derive};
use group::{ff::Field, Group, UncompressedEncoding};
use pg_curve::{G1Projective, G2Projective, Gt, Scalar};
use rand::{CryptoRng, RngCore};
use subtle::CtOption;
use tiny_keccak::Hasher;
pub(crate) const GT_BYTES: usize = 288;
pub(crate) const G1_BYTES: usize = 48;
pub(crate) const G2_BYTES: usize = 96;
pub(crate) const SCALAR_BYTES: usize = 32;
pub(crate) const ID_BYTES: usize = 64;
#[inline(always)]
pub fn rand_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Scalar {
Scalar::random(rng)
}
#[inline(always)]
pub fn rand_g1<R: RngCore + CryptoRng>(rng: &mut R) -> G1Projective {
G1Projective::random(rng)
}
#[inline(always)]
pub fn rand_g2<R: RngCore + CryptoRng>(rng: &mut R) -> G2Projective {
G2Projective::random(rng)
}
#[inline(always)]
pub fn rand_gt<R: RngCore + CryptoRng>(rng: &mut R) -> Gt {
Gt::random(rng)
}
pub fn bits<'a>(slice: &'a [u8]) -> impl Iterator<Item = subtle::Choice> + 'a {
slice
.iter()
.rev()
.zip((0..8).rev())
.map(|(x, i)| subtle::Choice::from((*x >> i) & 1))
}
pub fn sha3_256(slice: &[u8]) -> [u8; 32] {
let mut digest = tiny_keccak::Sha3::v256();
digest.update(slice);
let mut buf = [0u8; 32];
digest.finalize(&mut buf);
buf
}
pub fn sha3_512(slice: &[u8]) -> [u8; 64] {
let mut digest = tiny_keccak::Sha3::v512();
digest.update(slice);
let mut buf = [0u8; 64];
digest.finalize(&mut buf);
buf
}
pub fn shake256<const N: usize>(slice: &[u8]) -> [u8; N] {
let mut digest = tiny_keccak::Shake::v256();
digest.update(slice);
let mut buf = [0u8; N];
digest.finalize(&mut buf);
buf
}
pub fn rpc<Gr: UncompressedEncoding>(k: &[u8; 32], gs: &[Gr]) -> Scalar {
let mut digest = tiny_keccak::Sha3::v512();
digest.update(k);
for g in gs.iter() {
digest.update(g.to_uncompressed().as_ref())
}
let mut buf = [0u8; 64];
digest.finalize(&mut buf);
Scalar::from_bytes_wide(&buf)
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Identity(pub [u8; ID_BYTES]);
impl Default for Identity {
fn default() -> Self {
Self([0u8; ID_BYTES])
}
}
impl Derive for Identity {
fn derive(b: &[u8]) -> Identity {
Identity(sha3_512(b))
}
fn derive_str(s: &str) -> Identity {
Self::derive(s.as_bytes())
}
}
impl Identity {
#[allow(unused)]
pub(crate) fn to_scalar(self) -> Scalar {
Scalar::from_bytes_wide(&self.0)
}
}
impl Compress for Gt {
const OUTPUT_SIZE: usize = GT_BYTES;
type Output = [u8; Self::OUTPUT_SIZE];
fn to_bytes(&self) -> [u8; GT_BYTES] {
self.to_compressed()
}
fn from_bytes(bytes: &[u8; GT_BYTES]) -> CtOption<Self> {
Self::from_compressed(bytes)
}
}