Update to FROST v11

Ensures random functions never return zero. This, combined with a check 
commitments aren't 0, causes no serialized elements to be 0.

Also directly reads their vectors.
This commit is contained in:
Luke Parker
2022-10-13 00:38:36 -04:00
parent b334c96906
commit a0a54eb0de
19 changed files with 491 additions and 257 deletions

View File

@@ -74,7 +74,7 @@ dalek_curve!(
IetfRistrettoHram,
RistrettoPoint,
b"ristretto",
b"FROST-RISTRETTO255-SHA512-v10",
b"FROST-RISTRETTO255-SHA512-v11",
b"chal",
);
@@ -85,6 +85,6 @@ dalek_curve!(
IetfEd25519Hram,
EdwardsPoint,
b"edwards25519",
b"FROST-ED25519-SHA512-v10",
b"FROST-ED25519-SHA512-v11",
b"",
);

View File

@@ -7,7 +7,7 @@ use minimal_ed448::{scalar::Scalar, point::Point};
use crate::{curve::Curve, algorithm::Hram};
const CONTEXT: &[u8] = b"FROST-ED448-SHAKE256-v10";
const CONTEXT: &[u8] = b"FROST-ED448-SHAKE256-v11";
#[derive(Clone, Copy, PartialEq, Eq, Debug, Zeroize)]
pub struct Ed448;
@@ -53,8 +53,8 @@ impl Ietf8032Ed448Hram {
}
#[derive(Copy, Clone)]
pub struct NonIetfEd448Hram;
impl Hram<Ed448> for NonIetfEd448Hram {
pub struct IetfEd448Hram;
impl Hram<Ed448> for IetfEd448Hram {
#[allow(non_snake_case)]
fn hram(R: &Point, A: &Point, m: &[u8]) -> Scalar {
Ietf8032Ed448Hram::hram(&[], R, A, m)

View File

@@ -92,7 +92,7 @@ macro_rules! kp_curve {
}
#[cfg(feature = "p256")]
kp_curve!("p256", p256, P256, IetfP256Hram, b"P-256", b"FROST-P256-SHA256-v10");
kp_curve!("p256", p256, P256, IetfP256Hram, b"P-256", b"FROST-P256-SHA256-v11");
#[cfg(feature = "secp256k1")]
kp_curve!(
@@ -101,5 +101,5 @@ kp_curve!(
Secp256k1,
IetfSecp256k1Hram,
b"secp256k1",
b"FROST-secp256k1-SHA256-v10"
b"FROST-secp256k1-SHA256-v11"
);

View File

@@ -6,8 +6,9 @@ use thiserror::Error;
use rand_core::{RngCore, CryptoRng};
use zeroize::Zeroize;
use subtle::ConstantTimeEq;
use ff::{PrimeField, PrimeFieldBits};
use ff::{Field, PrimeField, PrimeFieldBits};
use group::{Group, GroupOps, GroupEncoding, prime::PrimeGroup};
#[cfg(any(test, feature = "dalek"))]
@@ -27,7 +28,7 @@ pub use kp256::{P256, IetfP256Hram};
#[cfg(feature = "ed448")]
mod ed448;
#[cfg(feature = "ed448")]
pub use ed448::{Ed448, Ietf8032Ed448Hram, NonIetfEd448Hram};
pub use ed448::{Ed448, Ietf8032Ed448Hram, IetfEd448Hram};
/// Set of errors for curve-related operations, namely encoding and decoding.
#[derive(Clone, Error, Debug)]
@@ -49,7 +50,7 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
// This is available via G::Scalar yet `C::G::Scalar` is ambiguous, forcing horrific accesses
type F: PrimeField + PrimeFieldBits + Zeroize;
/// Group element type.
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup + Zeroize;
type G: Group<Scalar = Self::F> + GroupOps + PrimeGroup + Zeroize + ConstantTimeEq;
/// ID for this curve.
const ID: &'static [u8];
@@ -81,6 +82,16 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
Self::hash_to_F(b"rho", binding)
}
#[allow(non_snake_case)]
fn random_F<R: RngCore + CryptoRng>(rng: &mut R) -> Self::F {
let mut res;
while {
res = Self::F::random(&mut *rng);
res.ct_eq(&Self::F::zero()).into()
} {}
res
}
/// Securely generate a random nonce. H3 from the IETF draft.
fn random_nonce<R: RngCore + CryptoRng>(mut secret: Self::F, rng: &mut R) -> Self::F {
let mut seed = vec![0; 32];
@@ -89,12 +100,18 @@ pub trait Curve: Clone + Copy + PartialEq + Eq + Debug + Zeroize {
let mut repr = secret.to_repr();
secret.zeroize();
seed.extend(repr.as_ref());
let mut res;
while {
seed.extend(repr.as_ref());
res = Self::hash_to_F(b"nonce", &seed);
res.ct_eq(&Self::F::zero()).into()
} {
rng.fill_bytes(&mut seed);
}
for i in repr.as_mut() {
i.zeroize();
}
let res = Self::hash_to_F(b"nonce", &seed);
seed.zeroize();
res
}