use core::fmt::Debug;
use std::io::Read;
use thiserror::Error;
use rand_core::{RngCore, CryptoRng};
use zeroize::Zeroize;
use ff::{PrimeField, PrimeFieldBits};
use group::{Group, GroupOps, GroupEncoding, prime::PrimeGroup};
#[cfg(any(test, feature = "dalek"))]
mod dalek;
#[cfg(any(test, feature = "ristretto"))]
pub use dalek::{Ristretto, IetfRistrettoHram};
#[cfg(feature = "ed25519")]
pub use dalek::{Ed25519, IetfEd25519Hram};
#[cfg(feature = "kp256")]
mod kp256;
#[cfg(feature = "secp256k1")]
pub use kp256::{Secp256k1, IetfSecp256k1Hram};
#[cfg(feature = "p256")]
pub use kp256::{P256, IetfP256Hram};
#[cfg(feature = "ed448")]
mod ed448;
#[cfg(feature = "ed448")]
pub use ed448::{Ed448, Ietf8032Ed448Hram, NonIetfEd448Hram};
#[derive(Clone, Error, Debug)]
pub enum CurveError {
#[error("invalid scalar")]
InvalidScalar,
#[error("invalid point")]
InvalidPoint,
}
pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
type F: PrimeField + PrimeFieldBits + Zeroize;
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup + Zeroize;
const ID: &'static [u8];
fn generator() -> Self::G;
fn hash_to_vec(dst: &[u8], data: &[u8]) -> Vec<u8>;
#[allow(non_snake_case)]
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F;
fn hash_msg(msg: &[u8]) -> Vec<u8> {
Self::hash_to_vec(b"msg", msg)
}
fn hash_commitments(commitments: &[u8]) -> Vec<u8> {
Self::hash_to_vec(b"com", commitments)
}
fn hash_binding_factor(binding: &[u8]) -> Self::F {
Self::hash_to_F(b"rho", binding)
}
fn random_nonce<R: RngCore + CryptoRng>(mut secret: Self::F, rng: &mut R) -> Self::F {
let mut seed = vec![0; 32];
rng.fill_bytes(&mut seed);
let mut repr = secret.to_repr();
secret.zeroize();
seed.extend(repr.as_ref());
for i in repr.as_mut() {
i.zeroize();
}
let res = Self::hash_to_F(b"nonce", &seed);
seed.zeroize();
res
}
#[allow(non_snake_case)]
fn F_len() -> usize {
<Self::F as PrimeField>::Repr::default().as_ref().len()
}
#[allow(non_snake_case)]
fn G_len() -> usize {
<Self::G as GroupEncoding>::Repr::default().as_ref().len()
}
#[allow(non_snake_case)]
fn read_F<R: Read>(r: &mut R) -> Result<Self::F, CurveError> {
let mut encoding = <Self::F as PrimeField>::Repr::default();
r.read_exact(encoding.as_mut()).map_err(|_| CurveError::InvalidScalar)?;
let res =
Option::<Self::F>::from(Self::F::from_repr(encoding)).ok_or(CurveError::InvalidScalar);
for b in encoding.as_mut() {
b.zeroize();
}
res
}
#[allow(non_snake_case)]
fn read_G<R: Read>(r: &mut R) -> Result<Self::G, CurveError> {
let mut encoding = <Self::G as GroupEncoding>::Repr::default();
r.read_exact(encoding.as_mut()).map_err(|_| CurveError::InvalidPoint)?;
let point =
Option::<Self::G>::from(Self::G::from_bytes(&encoding)).ok_or(CurveError::InvalidPoint)?;
if (point.is_identity().into()) || (point.to_bytes().as_ref() != encoding.as_ref()) {
Err(CurveError::InvalidPoint)?;
}
Ok(point)
}
}