pub mod bge;
pub mod bpp;
pub mod chacha8;
pub mod clsag;
pub mod consts;
pub mod derive;
pub mod field;
pub mod hash;
pub mod hashtoec;
pub mod maths;
pub mod zarcanum;
use crate::error::{Error, Result};
use crate::rng::RngCore;
pub use purecrypto::ec::edwards25519::hazmat::{EdwardsPoint as Point, Scalar};
pub use bge::generate_bge_proof;
pub use bpp::{TRAIT_ZARCANUM, TRAIT_ZC_OUT, Trait};
pub use chacha8::{chacha8, chacha8_generate_key};
pub use clsag::{ClsagGgxInputRef, generate_clsag_ggx, verify_clsag_ggx};
pub use consts::*;
pub use derive::{
compute_key_image, derivation_hint, derive_public_key, derive_secret_key,
generate_key_derivation,
};
pub use hash::{HashHelper, hash_to_scalar, hs_bytes};
pub use hashtoec::{hash_to_ec, hash_to_point, hp};
pub use zarcanum::{generate_double_schnorr_sig, generate_vector_ug_aggregation_proof};
pub fn point_from_bytes(b: &[u8]) -> Result<Point> {
let arr: [u8; 32] = b.try_into().map_err(|_| Error::InvalidPoint)?;
Point::decompress(&arr).ok_or(Error::InvalidPoint)
}
pub fn scalar_from_canonical(b: &[u8]) -> Result<Scalar> {
let arr: [u8; 32] = b.try_into().map_err(|_| Error::InvalidScalar)?;
Scalar::from_bytes_canonical(&arr).ok_or(Error::InvalidScalar)
}
pub fn scalar_from_wide(b: &[u8]) -> Scalar {
let mut wide = [0u8; 64];
let n = b.len().min(64);
wide[..n].copy_from_slice(&b[..n]);
Scalar::from_bytes_mod_order(&wide)
}
pub fn scalar_int(v: u64) -> Scalar {
let mut b = [0u8; 32];
b[..8].copy_from_slice(&v.to_le_bytes());
Scalar::from_bytes_canonical(&b).expect("u64 is always a canonical scalar")
}
pub fn mul8(p: &Point) -> Point {
p.mul_by_cofactor()
}
pub fn random_scalar(rnd: &mut dyn RngCore) -> Scalar {
let mut buf = [0u8; 64];
rnd.fill_bytes(&mut buf);
Scalar::from_bytes_mod_order(&buf)
}
pub fn pub_from_priv(s: &Scalar) -> Point {
Point::mul_base(s)
}
pub fn generate_key_scalar(rnd: &mut dyn RngCore) -> Scalar {
use purecrypto::hash::{Digest, Sha512};
let mut seed = [0u8; 32];
rnd.fill_bytes(&mut seed);
let digest = Sha512::digest(&seed);
let mut lower = [0u8; 32];
lower.copy_from_slice(&digest[..32]);
lower[0] &= 248;
lower[31] &= 63;
lower[31] |= 64;
let mut wide = [0u8; 64];
wide[..32].copy_from_slice(&lower);
Scalar::from_bytes_mod_order(&wide)
}
pub fn double_scalar_base_mult(a: &Scalar, big_a: &Point, b: &Scalar) -> Point {
big_a.mul(a).add(&Point::mul_base(b))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn scalar_int_round_trips() {
let s = scalar_int(0x0102030405060708);
assert_eq!(&s.to_bytes()[..8], &0x0102030405060708u64.to_le_bytes());
}
#[test]
fn mul8_matches_three_doublings() {
let p = Point::mul_base(&scalar_int(1234567));
let manual = p.add(&p);
let manual = manual.add(&manual);
let manual = manual.add(&manual);
assert_eq!(mul8(&p), manual);
}
}