Remove C::F_len, C::G_len for F_len<C> and G_len<C>

Relies on the ff/group API, instead of the custom Curve type.

Also removes GENERATOR_TABLE, only used by dalek, as we should provide 
our own API for that over ff/group instead. This slows down the FROST 
tests, under debug, by about 0.2-0.3s. Ed25519 and Ristretto together 
take ~2.15 seconds now.
This commit is contained in:
Luke Parker
2022-06-30 18:46:18 -04:00
parent 4eafbe2a09
commit 133c1222ad
9 changed files with 46 additions and 84 deletions

View File

@@ -11,29 +11,24 @@ macro_rules! dalek_curve {
$Curve: ident,
$Hram: ident,
$Point: ident,
$Table: ident,
$POINT: ident,
$TABLE: ident,
$ID: literal,
$CONTEXT: literal,
$chal: literal,
$digest: literal,
) => {
use dalek_ff_group::{$Point, $Table, $POINT, $TABLE};
use dalek_ff_group::{$Point, $POINT};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct $Curve;
impl Curve for $Curve {
type F = Scalar;
type G = $Point;
type T = &'static $Table;
const ID: &'static [u8] = $ID;
const GENERATOR: Self::G = $POINT;
const GENERATOR_TABLE: Self::T = &$TABLE;
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F {
let mut seed = vec![0; 32];
@@ -58,14 +53,6 @@ macro_rules! dalek_curve {
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F {
Scalar::from_hash(Sha512::new().chain_update($CONTEXT).chain_update(dst).chain_update(msg))
}
fn F_len() -> usize {
32
}
fn G_len() -> usize {
32
}
}
#[derive(Copy, Clone)]
@@ -84,9 +71,7 @@ dalek_curve!(
Ristretto,
IetfRistrettoHram,
RistrettoPoint,
RistrettoBasepointTable,
RISTRETTO_BASEPOINT_POINT,
RISTRETTO_BASEPOINT_TABLE,
b"ristretto",
b"FROST-RISTRETTO255-SHA512-v5",
b"chal",
@@ -98,9 +83,7 @@ dalek_curve!(
Ed25519,
IetfEd25519Hram,
EdwardsPoint,
EdwardsBasepointTable,
ED25519_BASEPOINT_POINT,
ED25519_BASEPOINT_TABLE,
b"edwards25519",
b"",
b"",

View File

@@ -22,12 +22,9 @@ macro_rules! kp_curve {
impl Curve for $Curve {
type F = $lib::Scalar;
type G = $lib::ProjectivePoint;
type T = $lib::ProjectivePoint;
const ID: &'static [u8] = $ID;
const GENERATOR: Self::G = $lib::ProjectivePoint::GENERATOR;
const GENERATOR_TABLE: Self::G = $lib::ProjectivePoint::GENERATOR;
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F {
let mut seed = vec![0; 32];
@@ -73,14 +70,6 @@ macro_rules! kp_curve {
}).reduce(&modulus).unwrap().to_be_bytes()[16 ..]
).unwrap()
}
fn F_len() -> usize {
32
}
fn G_len() -> usize {
33
}
}
#[derive(Clone)]

View File

@@ -1,11 +1,11 @@
use core::{ops::Mul, fmt::Debug};
use core::fmt::Debug;
use thiserror::Error;
use rand_core::{RngCore, CryptoRng};
use ff::{PrimeField, PrimeFieldBits};
use group::{Group, GroupOps, prime::PrimeGroup};
use group::{Group, GroupOps, GroupEncoding, prime::PrimeGroup};
#[cfg(any(test, feature = "dalek"))]
mod dalek;
@@ -44,20 +44,14 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug {
type F: PrimeField + PrimeFieldBits;
/// Group element type
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup;
/// Precomputed table type
type T: Mul<Self::F, Output = Self::G>;
/// ID for this curve
const ID: &'static [u8];
/// Generator for the group
// While group does provide this in its API, privacy coins will want to use a custom basepoint
// While group does provide this in its API, privacy coins may want to use a custom basepoint
const GENERATOR: Self::G;
/// Table for the generator for the group
/// If there isn't a precomputed table available, the generator itself should be used
const GENERATOR_TABLE: Self::T;
/// Securely generate a random nonce. H4 from the IETF draft
fn random_nonce<R: RngCore + CryptoRng>(secret: Self::F, rng: &mut R) -> Self::F;
@@ -83,20 +77,16 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug {
// hash_msg and hash_binding_factor
#[allow(non_snake_case)]
fn hash_to_F(dst: &[u8], msg: &[u8]) -> Self::F;
}
/// Constant size of a serialized scalar field element
// The alternative way to grab this would be either serializing a junk element and getting its
// length or doing a naive division of its BITS property by 8 and assuming a lack of padding
#[allow(non_snake_case)]
fn F_len() -> usize;
#[allow(non_snake_case)]
pub(crate) fn F_len<C: Curve>() -> usize {
<C::F as PrimeField>::Repr::default().as_ref().len()
}
/// Constant size of a serialized group element
// We could grab the serialization as described above yet a naive developer may use a
// non-constant size encoding, proving yet another reason to force this to be a provided constant
// A naive developer could still provide a constant for a variable length encoding, yet at least
// that is on them
#[allow(non_snake_case)]
fn G_len() -> usize;
#[allow(non_snake_case)]
pub(crate) fn G_len<C: Curve>() -> usize {
<C::G as GroupEncoding>::Repr::default().as_ref().len()
}
/// Field element from slice