Remove `as` keyword when not needed, use `Scalar`/`Element` shortcuts (#159)
* use Identifier instead of index * remove pub(crate) from the Identifier index * Refreshed Identifier newtype of Scalar with traits * Remove commented out lines * add test vectors with indices larger than 1 byte * add little_endian_serialize to implement Ord for Identifier * remove 'as' keyword when not needed * use Scalar shortcut * use Element shortcut * remove more instances of 'as' keyword when not needed * rustfmt Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com>
This commit is contained in:
parent
278630e183
commit
33b01a7d6f
|
@ -110,13 +110,13 @@ where
|
|||
let mut VKs = Vec::with_capacity(n);
|
||||
let mut R_coeffs = Vec::with_capacity(self.signatures.len());
|
||||
let mut Rs = Vec::with_capacity(self.signatures.len());
|
||||
let mut P_coeff_acc = <<C::Group as Group>::Field as Field>::zero();
|
||||
let mut P_coeff_acc = <<C::Group as Group>::Field>::zero();
|
||||
|
||||
for item in self.signatures.iter() {
|
||||
let z = item.sig.z;
|
||||
let R = item.sig.R;
|
||||
|
||||
let blind = <<C::Group as Group>::Field as Field>::random(&mut rng);
|
||||
let blind = <<C::Group as Group>::Field>::random(&mut rng);
|
||||
|
||||
let P_coeff = blind * z;
|
||||
P_coeff_acc = P_coeff_acc - P_coeff;
|
||||
|
@ -124,7 +124,7 @@ where
|
|||
R_coeffs.push(blind);
|
||||
Rs.push(R);
|
||||
|
||||
VK_coeffs.push(<<C::Group as Group>::Field as Field>::zero() + (blind * item.c.0));
|
||||
VK_coeffs.push(<<C::Group as Group>::Field>::zero() + (blind * item.c.0));
|
||||
VKs.push(item.vk.element);
|
||||
}
|
||||
|
||||
|
@ -132,13 +132,13 @@ where
|
|||
.chain(VK_coeffs.iter())
|
||||
.chain(R_coeffs.iter());
|
||||
|
||||
let basepoints = [<C::Group as Group>::generator()];
|
||||
let basepoints = [C::Group::generator()];
|
||||
let points = basepoints.iter().chain(VKs.iter()).chain(Rs.iter());
|
||||
|
||||
let check: Element<C> =
|
||||
VartimeMultiscalarMul::<C>::vartime_multiscalar_mul(scalars, points);
|
||||
|
||||
if (check * <C::Group as Group>::cofactor()) == <C::Group as Group>::identity() {
|
||||
if (check * <C::Group>::cofactor()) == <C::Group>::identity() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::InvalidSignature)
|
||||
|
|
|
@ -24,7 +24,7 @@ pub mod keys;
|
|||
pub mod round1;
|
||||
pub mod round2;
|
||||
|
||||
use crate::{Ciphersuite, Error, Field, Group, Signature};
|
||||
use crate::{Ciphersuite, Element, Error, Field, Group, Scalar, Signature};
|
||||
|
||||
pub use self::identifier::Identifier;
|
||||
|
||||
|
@ -35,7 +35,7 @@ pub use self::identifier::Identifier;
|
|||
///
|
||||
/// <https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md>
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct BindingFactor<C: Ciphersuite>(<<C::Group as Group>::Field as Field>::Scalar);
|
||||
pub struct BindingFactor<C: Ciphersuite>(Scalar<C>);
|
||||
|
||||
impl<C> BindingFactor<C>
|
||||
where
|
||||
|
@ -45,12 +45,12 @@ where
|
|||
pub fn from_bytes(
|
||||
bytes: <<C::Group as Group>::Field as Field>::Serialization,
|
||||
) -> Result<Self, Error> {
|
||||
<<C::Group as Group>::Field as Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
<<C::Group as Group>::Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
}
|
||||
|
||||
/// Serializes [`BindingFactor`] to bytes.
|
||||
pub fn to_bytes(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
|
||||
<<C::Group as Group>::Field as Field>::serialize(&self.0)
|
||||
<<C::Group as Group>::Field>::serialize(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,11 +145,11 @@ where
|
|||
fn derive_lagrange_coeff<C: Ciphersuite>(
|
||||
signer_id: &Identifier<C>,
|
||||
signing_package: &SigningPackage<C>,
|
||||
) -> Result<<<C::Group as Group>::Field as Field>::Scalar, &'static str> {
|
||||
let zero = <<C::Group as Group>::Field as Field>::zero();
|
||||
) -> Result<Scalar<C>, &'static str> {
|
||||
let zero = <<C::Group as Group>::Field>::zero();
|
||||
|
||||
let mut num = <<C::Group as Group>::Field as Field>::one();
|
||||
let mut den = <<C::Group as Group>::Field as Field>::one();
|
||||
let mut num = <<C::Group as Group>::Field>::one();
|
||||
let mut den = <<C::Group as Group>::Field>::one();
|
||||
|
||||
// Ala the sorting of B, just always sort by identifier in ascending order
|
||||
//
|
||||
|
@ -169,7 +169,7 @@ fn derive_lagrange_coeff<C: Ciphersuite>(
|
|||
}
|
||||
|
||||
// TODO(dconnolly): return this error if the inversion result == zero
|
||||
let lagrange_coeff = num * <<C::Group as Group>::Field as Field>::invert(&den).unwrap();
|
||||
let lagrange_coeff = num * <<C::Group as Group>::Field>::invert(&den).unwrap();
|
||||
|
||||
Ok(lagrange_coeff)
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ where
|
|||
/// The product of all signers' individual commitments, published as part of the
|
||||
/// final signature.
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct GroupCommitment<C: Ciphersuite>(pub(super) <C::Group as Group>::Element);
|
||||
pub struct GroupCommitment<C: Ciphersuite>(pub(super) Element<C>);
|
||||
|
||||
// impl<C> Debug for GroupCommitment<C> where C: Ciphersuite {
|
||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -276,9 +276,9 @@ where
|
|||
fn try_from(signing_package: &SigningPackage<C>) -> Result<GroupCommitment<C>, &'static str> {
|
||||
let binding_factor_list: BindingFactorList<C> = signing_package.into();
|
||||
|
||||
let identity = <C::Group as Group>::identity();
|
||||
let identity = <C::Group>::identity();
|
||||
|
||||
let mut group_commitment = <C::Group as Group>::identity();
|
||||
let mut group_commitment = <C::Group>::identity();
|
||||
|
||||
// Ala the sorting of B, just always sort by identifier in ascending order
|
||||
//
|
||||
|
@ -369,8 +369,8 @@ where
|
|||
//
|
||||
// Implements [`aggregate`] from the spec.
|
||||
//
|
||||
// [`aggregate`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#section-5.3
|
||||
let mut z = <<C::Group as Group>::Field as Field>::zero();
|
||||
// [`aggregate`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-5.3
|
||||
let mut z = <<C::Group as Group>::Field>::zero();
|
||||
|
||||
for signature_share in signature_shares {
|
||||
z = z + signature_share.signature.z_share;
|
||||
|
|
|
@ -21,7 +21,7 @@ where
|
|||
{
|
||||
// Serialize the underlying scalar.
|
||||
pub(crate) fn serialize(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
|
||||
<<C::Group as Group>::Field as Field>::serialize(&self.0)
|
||||
<<C::Group as Group>::Field>::serialize(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ where
|
|||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_tuple("Identifier")
|
||||
.field(&<<C::Group as Group>::Field as Field>::serialize(&self.0).as_ref())
|
||||
.field(&<<C::Group as Group>::Field>::serialize(&self.0).as_ref())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
<<C::Group as Group>::Field as Field>::serialize(&self.0)
|
||||
<<C::Group as Group>::Field>::serialize(&self.0)
|
||||
.as_ref()
|
||||
.hash(state)
|
||||
}
|
||||
|
@ -55,10 +55,8 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
let serialized_self =
|
||||
<<C::Group as Group>::Field as Field>::little_endian_serialize(&self.0);
|
||||
let serialized_other =
|
||||
<<C::Group as Group>::Field as Field>::little_endian_serialize(&other.0);
|
||||
let serialized_self = <<C::Group as Group>::Field>::little_endian_serialize(&self.0);
|
||||
let serialized_other = <<C::Group as Group>::Field>::little_endian_serialize(&other.0);
|
||||
serialized_self.as_ref().cmp(serialized_other.as_ref())
|
||||
}
|
||||
}
|
||||
|
@ -68,10 +66,8 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
let serialized_self =
|
||||
<<C::Group as Group>::Field as Field>::little_endian_serialize(&self.0);
|
||||
let serialized_other =
|
||||
<<C::Group as Group>::Field as Field>::little_endian_serialize(&other.0);
|
||||
let serialized_self = <<C::Group as Group>::Field>::little_endian_serialize(&self.0);
|
||||
let serialized_other = <<C::Group as Group>::Field>::little_endian_serialize(&other.0);
|
||||
serialized_self
|
||||
.as_ref()
|
||||
.partial_cmp(serialized_other.as_ref())
|
||||
|
@ -121,8 +117,8 @@ where
|
|||
} else {
|
||||
// Classic left-to-right double-and-add algorithm that skips the first bit 1 (since
|
||||
// identifiers are never zero, there is always a bit 1), thus `sum` starts with 1 too.
|
||||
let one = <<C::Group as Group>::Field as Field>::one();
|
||||
let mut sum = <<C::Group as Group>::Field as Field>::one();
|
||||
let one = <<C::Group as Group>::Field>::one();
|
||||
let mut sum = <<C::Group as Group>::Field>::one();
|
||||
|
||||
let bits = (n.to_be_bytes().len() as u32) * 8;
|
||||
for i in (0..(bits - n.leading_zeros() - 1)).rev() {
|
||||
|
|
|
@ -12,7 +12,7 @@ use hex::FromHex;
|
|||
use rand_core::{CryptoRng, RngCore};
|
||||
use zeroize::{DefaultIsZeroes, Zeroize};
|
||||
|
||||
use crate::{frost::Identifier, Ciphersuite, Error, Field, Group, Scalar, VerifyingKey};
|
||||
use crate::{frost::Identifier, Ciphersuite, Element, Error, Field, Group, Scalar, VerifyingKey};
|
||||
|
||||
pub mod dkg;
|
||||
|
||||
|
@ -20,8 +20,8 @@ pub mod dkg;
|
|||
pub(crate) fn generate_coefficients<C: Ciphersuite, R: RngCore + CryptoRng>(
|
||||
size: usize,
|
||||
rng: &mut R,
|
||||
) -> Vec<<<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar> {
|
||||
iter::repeat_with(|| <<C::Group as Group>::Field as Field>::random(rng))
|
||||
) -> Vec<Scalar<C>> {
|
||||
iter::repeat_with(|| <<C::Group as Group>::Field>::random(rng))
|
||||
.take(size)
|
||||
.collect()
|
||||
}
|
||||
|
@ -42,12 +42,12 @@ where
|
|||
pub fn from_bytes(
|
||||
bytes: <<C::Group as Group>::Field as Field>::Serialization,
|
||||
) -> Result<Self, Error> {
|
||||
<<C::Group as Group>::Field as Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
<<C::Group as Group>::Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
}
|
||||
|
||||
/// Serialize to bytes
|
||||
pub fn to_bytes(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
|
||||
<<C::Group as Group>::Field as Field>::serialize(&self.0)
|
||||
<<C::Group as Group>::Field>::serialize(&self.0)
|
||||
}
|
||||
|
||||
/// Generates a new uniformly random secret value using the provided RNG.
|
||||
|
@ -56,9 +56,7 @@ where
|
|||
where
|
||||
R: CryptoRng + RngCore,
|
||||
{
|
||||
Self(<<C::Group as Group>::Field as Field>::random_nonzero(
|
||||
&mut rng,
|
||||
))
|
||||
Self(<<C::Group as Group>::Field>::random_nonzero(&mut rng))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +76,7 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self(<<C::Group as Group>::Field as Field>::zero())
|
||||
Self(<<C::Group as Group>::Field>::zero())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +88,7 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn from(secret: &SharedSecret<C>) -> Self {
|
||||
let element = <C::Group as Group>::generator() * secret.0;
|
||||
let element = <C::Group>::generator() * secret.0;
|
||||
|
||||
VerifyingKey { element }
|
||||
}
|
||||
|
@ -123,12 +121,12 @@ where
|
|||
pub fn from_bytes(
|
||||
bytes: <<C::Group as Group>::Field as Field>::Serialization,
|
||||
) -> Result<Self, Error> {
|
||||
<<C::Group as Group>::Field as Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
<<C::Group as Group>::Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
}
|
||||
|
||||
/// Serialize to bytes
|
||||
pub fn to_bytes(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
|
||||
<<C::Group as Group>::Field as Field>::serialize(&self.0)
|
||||
<<C::Group as Group>::Field>::serialize(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,7 +146,7 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self(<<C::Group as Group>::Field as Field>::zero())
|
||||
Self(<<C::Group as Group>::Field>::zero())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +170,7 @@ where
|
|||
|
||||
/// A public group element that represents a single signer's public verification share.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct VerifyingShare<C>(pub(super) <C::Group as Group>::Element)
|
||||
pub struct VerifyingShare<C>(pub(super) Element<C>)
|
||||
where
|
||||
C: Ciphersuite;
|
||||
|
||||
|
@ -207,7 +205,7 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn from(secret: SigningShare<C>) -> VerifyingShare<C> {
|
||||
VerifyingShare(<C::Group as Group>::generator() * secret.0 as Scalar<C>)
|
||||
VerifyingShare(<C::Group>::generator() * secret.0 as Scalar<C>)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +214,7 @@ where
|
|||
/// This is a (public) commitment to one coefficient of a secret polynomial used for performing
|
||||
/// verifiable secret sharing for a Shamir secret share.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub(super) struct CoefficientCommitment<C: Ciphersuite>(pub(super) <C::Group as Group>::Element);
|
||||
pub(super) struct CoefficientCommitment<C: Ciphersuite>(pub(super) Element<C>);
|
||||
|
||||
/// Contains the commitments to the coefficients for our secret polynomial _f_,
|
||||
/// used to generate participants' key shares.
|
||||
|
@ -280,7 +278,7 @@ where
|
|||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#appendix-C.2-4
|
||||
pub fn verify(&self) -> Result<(VerifyingShare<C>, VerifyingKey<C>), &'static str> {
|
||||
let f_result = <C::Group as Group>::generator() * self.value.0;
|
||||
let f_result = <C::Group>::generator() * self.value.0;
|
||||
let result = evaluate_vss(&self.commitment, self.identifier)?;
|
||||
|
||||
if !(f_result == result) {
|
||||
|
@ -347,8 +345,9 @@ pub fn keygen_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
|
|||
fn evaluate_polynomial<C: Ciphersuite>(
|
||||
identifier: Identifier<C>,
|
||||
coefficients: &[Scalar<C>],
|
||||
) -> Result<<<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar, &'static str> {
|
||||
let mut value = <<C::Group as Group>::Field as Field>::zero();
|
||||
) -> Result<Scalar<C>, &'static str> {
|
||||
let mut value = <<C::Group as Group>::Field>::zero();
|
||||
|
||||
let ell_scalar = identifier;
|
||||
for coeff in coefficients.iter().skip(1).rev() {
|
||||
value = value + *coeff;
|
||||
|
@ -364,14 +363,11 @@ fn evaluate_polynomial<C: Ciphersuite>(
|
|||
fn evaluate_vss<C: Ciphersuite>(
|
||||
commitment: &VerifiableSecretSharingCommitment<C>,
|
||||
identifier: Identifier<C>,
|
||||
) -> Result<<<C as Ciphersuite>::Group as Group>::Element, &'static str> {
|
||||
) -> Result<Element<C>, &'static str> {
|
||||
let i = identifier;
|
||||
|
||||
let (_, result) = commitment.0.iter().fold(
|
||||
(
|
||||
<<C::Group as Group>::Field as Field>::one(),
|
||||
<C::Group as Group>::identity(),
|
||||
),
|
||||
(<<C::Group as Group>::Field>::one(), <C::Group>::identity()),
|
||||
|(i_to_the_k, sum_so_far), comm_k| (i * i_to_the_k, sum_so_far + comm_k.0 * i_to_the_k),
|
||||
);
|
||||
Ok(result)
|
||||
|
@ -560,12 +556,12 @@ pub fn reconstruct_secret<C: Ciphersuite>(
|
|||
.map(|share| (share.identifier, share))
|
||||
.collect();
|
||||
|
||||
let mut secret = <<C::Group as Group>::Field as Field>::zero();
|
||||
let mut secret = <<C::Group as Group>::Field>::zero();
|
||||
|
||||
// Compute the Lagrange coefficients
|
||||
for (i, secret_share) in secret_share_map.clone() {
|
||||
let mut num = <<C::Group as Group>::Field as Field>::one();
|
||||
let mut den = <<C::Group as Group>::Field as Field>::one();
|
||||
let mut num = <<C::Group as Group>::Field>::one();
|
||||
let mut den = <<C::Group as Group>::Field>::one();
|
||||
|
||||
for j in secret_share_map.clone().into_keys() {
|
||||
if j == i {
|
||||
|
@ -581,20 +577,16 @@ pub fn reconstruct_secret<C: Ciphersuite>(
|
|||
|
||||
// If at this step, the denominator is zero in the scalar field, there must be a duplicate
|
||||
// secret share.
|
||||
if den == <<C::Group as Group>::Field as Field>::zero() {
|
||||
if den == <<C::Group as Group>::Field>::zero() {
|
||||
return Err("Duplicate shares provided");
|
||||
}
|
||||
|
||||
// Save numerator * 1/denomintor in the scalar field
|
||||
let lagrange_coefficient =
|
||||
num * <<C::Group as Group>::Field as Field>::invert(&den).unwrap();
|
||||
let lagrange_coefficient = num * <<C::Group as Group>::Field>::invert(&den).unwrap();
|
||||
|
||||
// Compute y = f(0) via polynomial interpolation of these t-of-n solutions ('points) of f
|
||||
secret = secret + (lagrange_coefficient * secret_share.value.0);
|
||||
}
|
||||
|
||||
Ok(
|
||||
SharedSecret::from_bytes(<<C::Group as Group>::Field as Field>::serialize(&secret))
|
||||
.unwrap(),
|
||||
)
|
||||
Ok(SharedSecret::from_bytes(<<C::Group as Group>::Field>::serialize(&secret)).unwrap())
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ use std::{collections::HashMap, iter};
|
|||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use crate::{
|
||||
frost::Identifier, Challenge, Ciphersuite, Field, Group, Scalar, Signature, VerifyingKey,
|
||||
frost::Identifier, Challenge, Ciphersuite, Element, Field, Group, Scalar, Signature,
|
||||
VerifyingKey,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
@ -112,8 +113,8 @@ pub fn keygen_part1<C: Ciphersuite, R: RngCore + CryptoRng>(
|
|||
// > c_i = H(i, Φ, g^{a_{i0}} , R_i), μ_i = k + a_{i0} · c_i, with Φ being
|
||||
// > a context string to prevent replay attacks.
|
||||
|
||||
let k = <<C::Group as Group>::Field as Field>::random(&mut rng);
|
||||
let R_i = <C::Group as Group>::generator() * k;
|
||||
let k = <<C::Group as Group>::Field>::random(&mut rng);
|
||||
let R_i = <C::Group>::generator() * k;
|
||||
let c_i = challenge::<C>(identifier, &R_i, &commitment.0[0].0)
|
||||
.ok_or("DKG not supported by ciphersuite")?;
|
||||
let mu_i = k + coefficients[0] * c_i.0;
|
||||
|
@ -136,8 +137,8 @@ pub fn keygen_part1<C: Ciphersuite, R: RngCore + CryptoRng>(
|
|||
/// Generates the challenge for the proof of knowledge to a secret for the DKG.
|
||||
fn challenge<C>(
|
||||
identifier: Identifier<C>,
|
||||
R: &<C::Group as Group>::Element,
|
||||
verifying_key: &<C::Group as Group>::Element,
|
||||
R: &Element<C>,
|
||||
verifying_key: &Element<C>,
|
||||
) -> Option<Challenge<C>>
|
||||
where
|
||||
C: Ciphersuite,
|
||||
|
@ -145,8 +146,8 @@ where
|
|||
let mut preimage = vec![];
|
||||
|
||||
preimage.extend_from_slice(identifier.serialize().as_ref());
|
||||
preimage.extend_from_slice(<C::Group as Group>::serialize(R).as_ref());
|
||||
preimage.extend_from_slice(<C::Group as Group>::serialize(verifying_key).as_ref());
|
||||
preimage.extend_from_slice(<C::Group>::serialize(R).as_ref());
|
||||
preimage.extend_from_slice(<C::Group>::serialize(verifying_key).as_ref());
|
||||
|
||||
Some(Challenge(C::HDKG(&preimage[..])?))
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ pub fn keygen_part2<C: Ciphersuite>(
|
|||
let c_ell =
|
||||
challenge::<C>(ell, &R_ell, &phi_ell0).ok_or("DKG not supported by ciphersuite")?;
|
||||
|
||||
if R_ell != <C::Group as Group>::generator() * mu_ell - phi_ell0 * c_ell.0 {
|
||||
if R_ell != <C::Group>::generator() * mu_ell - phi_ell0 * c_ell.0 {
|
||||
return Err("Invalid proof of knowledge");
|
||||
}
|
||||
|
||||
|
@ -226,7 +227,7 @@ fn compute_verifying_keys<C: Ciphersuite>(
|
|||
// Note that in this loop, "i" refers to the other participant whose public verification share
|
||||
// we are computing, and not the current participant.
|
||||
for i in round2_packages.iter().map(|p| p.sender_identifier) {
|
||||
let mut y_i = <C::Group as Group>::identity();
|
||||
let mut y_i = <C::Group>::identity();
|
||||
|
||||
// We need to iterate through all commitment vectors, including our own,
|
||||
// so chain it manually
|
||||
|
@ -274,8 +275,8 @@ pub fn keygen_part3<C: Ciphersuite>(
|
|||
return Err("inconsistent number of packages");
|
||||
}
|
||||
|
||||
let mut signing_share: Scalar<C> = <<C::Group as Group>::Field as Field>::zero();
|
||||
let mut group_public: <C::Group as Group>::Element = <C::Group as Group>::identity();
|
||||
let mut signing_share = <<C::Group as Group>::Field>::zero();
|
||||
let mut group_public = <C::Group>::identity();
|
||||
|
||||
let round1_packages_map: HashMap<Identifier<C>, &Round1Package<C>> = round1_packages
|
||||
.iter()
|
||||
|
|
|
@ -6,13 +6,13 @@ use hex::FromHex;
|
|||
use rand_core::{CryptoRng, RngCore};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
use crate::{frost, Ciphersuite, Error, Field, Group};
|
||||
use crate::{frost, Ciphersuite, Element, Error, Field, Group, Scalar};
|
||||
|
||||
use super::{keys::SigningShare, Identifier};
|
||||
|
||||
/// A scalar that is a signing nonce.
|
||||
#[derive(Clone, PartialEq, Eq, Zeroize)]
|
||||
pub struct Nonce<C: Ciphersuite>(pub(super) <<C::Group as Group>::Field as Field>::Scalar);
|
||||
pub struct Nonce<C: Ciphersuite>(pub(super) Scalar<C>);
|
||||
|
||||
impl<C> Nonce<C>
|
||||
where
|
||||
|
@ -43,7 +43,7 @@ where
|
|||
secret: &SigningShare<C>,
|
||||
random_bytes: [u8; 32],
|
||||
) -> Self {
|
||||
let secret_enc = <<C::Group as Group>::Field as Field>::serialize(&secret.0);
|
||||
let secret_enc = <<C::Group as Group>::Field>::serialize(&secret.0);
|
||||
|
||||
let input: Vec<u8> = random_bytes
|
||||
.iter()
|
||||
|
@ -58,12 +58,12 @@ where
|
|||
pub fn from_bytes(
|
||||
bytes: <<C::Group as Group>::Field as Field>::Serialization,
|
||||
) -> Result<Self, Error> {
|
||||
<<C::Group as Group>::Field as Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
<<C::Group as Group>::Field>::deserialize(&bytes).map(|scalar| Self(scalar))
|
||||
}
|
||||
|
||||
/// Serialize [`Nonce`] to bytes
|
||||
pub fn to_bytes(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
|
||||
<<C::Group as Group>::Field as Field>::serialize(&self.0)
|
||||
<<C::Group as Group>::Field>::serialize(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ where
|
|||
|
||||
/// A Ristretto point that is a commitment to a signing nonce share.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct NonceCommitment<C: Ciphersuite>(pub(super) <C::Group as Group>::Element);
|
||||
pub struct NonceCommitment<C: Ciphersuite>(pub(super) Element<C>);
|
||||
|
||||
impl<C> NonceCommitment<C>
|
||||
where
|
||||
|
@ -101,12 +101,12 @@ where
|
|||
{
|
||||
/// Deserialize [`NonceCommitment`] from bytes
|
||||
pub fn from_bytes(bytes: <C::Group as Group>::Serialization) -> Result<Self, Error> {
|
||||
<C::Group as Group>::deserialize(&bytes).map(|element| Self(element))
|
||||
<C::Group>::deserialize(&bytes).map(|element| Self(element))
|
||||
}
|
||||
|
||||
/// Serialize [`NonceCommitment`] to bytes
|
||||
pub fn to_bytes(&self) -> <C::Group as Group>::Serialization {
|
||||
<C::Group as Group>::serialize(&self.0)
|
||||
<C::Group>::serialize(&self.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ where
|
|||
C: Ciphersuite,
|
||||
{
|
||||
fn from(nonce: &Nonce<C>) -> Self {
|
||||
Self(<C::Group as Group>::generator() * nonce.0)
|
||||
Self(<C::Group>::generator() * nonce.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ where
|
|||
/// One signer's share of the group commitment, derived from their individual signing commitments
|
||||
/// and the binding factor _rho_.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct GroupCommitmentShare<C: Ciphersuite>(pub(super) <C::Group as Group>::Element);
|
||||
pub struct GroupCommitmentShare<C: Ciphersuite>(pub(super) Element<C>);
|
||||
|
||||
/// Encode the list of group signing commitments.
|
||||
///
|
||||
|
@ -282,8 +282,8 @@ pub(super) fn encode_group_commitments<C: Ciphersuite>(
|
|||
|
||||
for item in sorted_signing_commitments {
|
||||
bytes.extend_from_slice(item.identifier.serialize().as_ref());
|
||||
bytes.extend_from_slice(<C::Group as Group>::serialize(&item.hiding.0).as_ref());
|
||||
bytes.extend_from_slice(<C::Group as Group>::serialize(&item.binding.0).as_ref());
|
||||
bytes.extend_from_slice(<C::Group>::serialize(&item.hiding.0).as_ref());
|
||||
bytes.extend_from_slice(<C::Group>::serialize(&item.binding.0).as_ref());
|
||||
}
|
||||
|
||||
bytes
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
|||
#[derive(Clone, Copy)]
|
||||
pub struct SignatureResponse<C: Ciphersuite> {
|
||||
/// The scalar contribution to the group signature.
|
||||
pub z_share: <<C::Group as Group>::Field as Field>::Scalar,
|
||||
pub z_share: Scalar<C>,
|
||||
}
|
||||
|
||||
impl<C> SignatureResponse<C>
|
||||
|
@ -23,13 +23,12 @@ where
|
|||
pub fn from_bytes(
|
||||
bytes: <<C::Group as Group>::Field as Field>::Serialization,
|
||||
) -> Result<Self, Error> {
|
||||
<<C::Group as Group>::Field as Field>::deserialize(&bytes)
|
||||
.map(|scalar| Self { z_share: scalar })
|
||||
<<C::Group as Group>::Field>::deserialize(&bytes).map(|scalar| Self { z_share: scalar })
|
||||
}
|
||||
|
||||
/// Serialize [`SignatureResponse`] to bytes
|
||||
pub fn to_bytes(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
|
||||
<<C::Group as Group>::Field as Field>::serialize(&self.z_share)
|
||||
<<C::Group as Group>::Field>::serialize(&self.z_share)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,10 +84,10 @@ where
|
|||
&self,
|
||||
group_commitment_share: &round1::GroupCommitmentShare<C>,
|
||||
public_key: &frost::keys::VerifyingShare<C>,
|
||||
lambda_i: <<C::Group as Group>::Field as Field>::Scalar,
|
||||
lambda_i: Scalar<C>,
|
||||
challenge: &Challenge<C>,
|
||||
) -> Result<(), &'static str> {
|
||||
if (<C::Group as Group>::generator() * self.signature.z_share)
|
||||
if (<C::Group>::generator() * self.signature.z_share)
|
||||
!= (group_commitment_share.0 + (public_key.0 * challenge.0 * lambda_i))
|
||||
{
|
||||
return Err("Invalid signature share");
|
||||
|
@ -153,7 +152,7 @@ pub fn sign<C: Ciphersuite>(
|
|||
);
|
||||
|
||||
// Compute the Schnorr signature share.
|
||||
let z_share: <<C::Group as Group>::Field as Field>::Scalar = signer_nonces.hiding.0
|
||||
let z_share = signer_nonces.hiding.0
|
||||
+ (signer_nonces.binding.0 * binding_factor.0)
|
||||
+ (lambda_i * key_package.secret_share.0 * challenge.0);
|
||||
|
||||
|
|
|
@ -254,7 +254,7 @@ where
|
|||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("Secret")
|
||||
.field(&hex::encode(
|
||||
<<<C as Ciphersuite>::Group as Group>::Field as Field>::serialize(&self.0),
|
||||
<<<C as Ciphersuite>::Group as Group>::Field>::serialize(&self.0),
|
||||
))
|
||||
.finish()
|
||||
}
|
||||
|
@ -267,20 +267,16 @@ where
|
|||
///
|
||||
/// This is the only invocation of the H2 hash function from the [RFC].
|
||||
///
|
||||
/// [FROST]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#name-signature-challenge-computa
|
||||
/// [RFC]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#section-3.2
|
||||
fn challenge<C>(
|
||||
R: &<C::Group as Group>::Element,
|
||||
verifying_key: &<C::Group as Group>::Element,
|
||||
msg: &[u8],
|
||||
) -> Challenge<C>
|
||||
/// [FROST]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-signature-challenge-computa
|
||||
/// [RFC]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.2
|
||||
fn challenge<C>(R: &Element<C>, verifying_key: &Element<C>, msg: &[u8]) -> Challenge<C>
|
||||
where
|
||||
C: Ciphersuite,
|
||||
{
|
||||
let mut preimage = vec![];
|
||||
|
||||
preimage.extend_from_slice(<C::Group as Group>::serialize(R).as_ref());
|
||||
preimage.extend_from_slice(<C::Group as Group>::serialize(verifying_key).as_ref());
|
||||
preimage.extend_from_slice(<C::Group>::serialize(R).as_ref());
|
||||
preimage.extend_from_slice(<C::Group>::serialize(verifying_key).as_ref());
|
||||
preimage.extend_from_slice(msg);
|
||||
|
||||
Challenge(C::H2(&preimage[..]))
|
||||
|
|
|
@ -38,7 +38,7 @@ where
|
|||
|
||||
let mut x_u64 = [0u64; 5];
|
||||
LittleEndian::read_u64_into(
|
||||
<<C::Group as Group>::Field as Field>::serialize(self).as_ref(),
|
||||
<<C::Group as Group>::Field>::serialize(self).as_ref(),
|
||||
&mut x_u64[0..4],
|
||||
);
|
||||
|
||||
|
@ -147,7 +147,7 @@ where
|
|||
.map(|P_opt| P_opt.map(|P| LookupTable5::<C, Element<C>>::from(&P)))
|
||||
.collect::<Option<Vec<_>>>()?;
|
||||
|
||||
let mut r = <C::Group as Group>::identity();
|
||||
let mut r = <C::Group>::identity();
|
||||
|
||||
for i in (0..256).rev() {
|
||||
let mut t = r + r;
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
use debugless_unwrap::DebuglessUnwrap;
|
||||
|
||||
use crate::{Ciphersuite, Error, Field, Group};
|
||||
use crate::{Ciphersuite, Element, Error, Field, Group, Scalar};
|
||||
|
||||
/// A Schnorr signature over some prime order group (or subgroup).
|
||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||
pub struct Signature<C: Ciphersuite> {
|
||||
/// The commitment `R` to the signature nonce.
|
||||
pub(crate) R: <C::Group as Group>::Element,
|
||||
pub(crate) R: Element<C>,
|
||||
/// The response `z` to the challenge computed from the commitment `R`, the verifying key, and
|
||||
/// the message.
|
||||
pub(crate) z: <<C::Group as Group>::Field as Field>::Scalar,
|
||||
pub(crate) z: Scalar<C>,
|
||||
}
|
||||
|
||||
impl<C> Signature<C>
|
||||
|
@ -25,8 +25,8 @@ where
|
|||
// To compute the expected length of the encoded point, encode the generator
|
||||
// and get its length. Note that we can't use the identity because it can be encoded
|
||||
// shorter in some cases (e.g. P-256, which uses SEC1 encoding).
|
||||
let generator = <C::Group as Group>::generator();
|
||||
let mut R_bytes = Vec::from(<C::Group as Group>::serialize(&generator).as_ref());
|
||||
let generator = <C::Group>::generator();
|
||||
let mut R_bytes = Vec::from(<C::Group>::serialize(&generator).as_ref());
|
||||
|
||||
let R_bytes_len = R_bytes.len();
|
||||
|
||||
|
@ -45,8 +45,8 @@ where
|
|||
let z_serialization = &z_bytes.try_into().map_err(|_| Error::MalformedSignature)?;
|
||||
|
||||
Ok(Self {
|
||||
R: <C::Group as Group>::deserialize(R_serialization)?,
|
||||
z: <<C::Group as Group>::Field as Field>::deserialize(z_serialization)?,
|
||||
R: <C::Group>::deserialize(R_serialization)?,
|
||||
z: <<C::Group as Group>::Field>::deserialize(z_serialization)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,8 @@ where
|
|||
pub fn to_bytes(&self) -> C::SignatureSerialization {
|
||||
let mut bytes = vec![];
|
||||
|
||||
bytes.extend(<C::Group as Group>::serialize(&self.R).as_ref());
|
||||
bytes.extend(<<C::Group as Group>::Field as Field>::serialize(&self.z).as_ref());
|
||||
bytes.extend(<C::Group>::serialize(&self.R).as_ref());
|
||||
bytes.extend(<<C::Group as Group>::Field>::serialize(&self.z).as_ref());
|
||||
|
||||
bytes.try_into().debugless_unwrap()
|
||||
}
|
||||
|
@ -64,13 +64,10 @@ where
|
|||
impl<C: Ciphersuite> std::fmt::Debug for Signature<C> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_struct("Signature")
|
||||
.field(
|
||||
"R",
|
||||
&hex::encode(<C::Group as Group>::serialize(&self.R).as_ref()),
|
||||
)
|
||||
.field("R", &hex::encode(<C::Group>::serialize(&self.R).as_ref()))
|
||||
.field(
|
||||
"z",
|
||||
&hex::encode(<<C::Group as Group>::Field as Field>::serialize(&self.z).as_ref()),
|
||||
&hex::encode(<<C::Group as Group>::Field>::serialize(&self.z).as_ref()),
|
||||
)
|
||||
.finish()
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use crate::{Ciphersuite, Error, Field, Group, Signature, VerifyingKey};
|
||||
use crate::{Ciphersuite, Error, Field, Group, Scalar, Signature, VerifyingKey};
|
||||
|
||||
/// A signing key for a Schnorr signature on a FROST [`Ciphersuite::Group`].
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -10,7 +10,7 @@ pub struct SigningKey<C>
|
|||
where
|
||||
C: Ciphersuite,
|
||||
{
|
||||
pub(crate) scalar: <<C::Group as Group>::Field as Field>::Scalar,
|
||||
pub(crate) scalar: Scalar<C>,
|
||||
}
|
||||
|
||||
impl<C> SigningKey<C>
|
||||
|
@ -19,7 +19,7 @@ where
|
|||
{
|
||||
/// Generate a new signing key.
|
||||
pub fn new<R: RngCore + CryptoRng>(mut rng: R) -> SigningKey<C> {
|
||||
let scalar = <<C::Group as Group>::Field as Field>::random_nonzero(&mut rng);
|
||||
let scalar = <<C::Group as Group>::Field>::random_nonzero(&mut rng);
|
||||
|
||||
SigningKey { scalar }
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ where
|
|||
|
||||
/// Create a signature `msg` using this `SigningKey`.
|
||||
pub fn sign<R: RngCore + CryptoRng>(&self, mut rng: R, msg: &[u8]) -> Signature<C> {
|
||||
let k = <<C::Group as Group>::Field as Field>::random_nonzero(&mut rng);
|
||||
let k = <<C::Group as Group>::Field>::random_nonzero(&mut rng);
|
||||
|
||||
let R = <C::Group as Group>::generator() * k;
|
||||
let R = <C::Group>::generator() * k;
|
||||
|
||||
// Generate Schnorr challenge
|
||||
let c = crate::challenge::<C>(&R, &VerifyingKey::<C>::from(*self).element, msg);
|
||||
|
|
|
@ -46,8 +46,7 @@ pub fn parse_test_vectors<C: Ciphersuite>(json_vectors: &Value) -> TestVectors<C
|
|||
.iter()
|
||||
.map(|v| {
|
||||
let vec = hex::decode(v.as_str().unwrap()).unwrap();
|
||||
<<C::Group as Group>::Field as Field>::deserialize(&vec.try_into().debugless_unwrap())
|
||||
.unwrap()
|
||||
<<C::Group as Group>::Field>::deserialize(&vec.try_into().debugless_unwrap()).unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -152,7 +151,7 @@ pub fn parse_test_vectors<C: Ciphersuite>(json_vectors: &Value) -> TestVectors<C
|
|||
let signature_share = SignatureShare::<C> {
|
||||
identifier: u16::from_str(i).unwrap().try_into().unwrap(),
|
||||
signature: SignatureResponse {
|
||||
z_share: <<C::Group as Group>::Field as Field>::deserialize(&sig_share).unwrap(),
|
||||
z_share: <<C::Group as Group>::Field>::deserialize(&sig_share).unwrap(),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt::{self, Debug};
|
|||
|
||||
use hex::FromHex;
|
||||
|
||||
use crate::{Challenge, Ciphersuite, Error, Group, Signature};
|
||||
use crate::{Challenge, Ciphersuite, Element, Error, Group, Signature};
|
||||
|
||||
/// A valid verifying key for Schnorr signatures over a FROST [`Ciphersuite::Group`].
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
@ -10,7 +10,7 @@ pub struct VerifyingKey<C>
|
|||
where
|
||||
C: Ciphersuite,
|
||||
{
|
||||
pub(crate) element: <C::Group as Group>::Element,
|
||||
pub(crate) element: Element<C>,
|
||||
}
|
||||
|
||||
impl<C> VerifyingKey<C>
|
||||
|
@ -25,12 +25,12 @@ where
|
|||
|
||||
/// Deserialize from bytes
|
||||
pub fn from_bytes(bytes: <C::Group as Group>::Serialization) -> Result<VerifyingKey<C>, Error> {
|
||||
<C::Group as Group>::deserialize(&bytes).map(|element| VerifyingKey { element })
|
||||
<C::Group>::deserialize(&bytes).map(|element| VerifyingKey { element })
|
||||
}
|
||||
|
||||
/// Serialize `VerifyingKey` to bytes
|
||||
pub fn to_bytes(&self) -> <C::Group as Group>::Serialization {
|
||||
<C::Group as Group>::serialize(&self.element)
|
||||
<C::Group>::serialize(&self.element)
|
||||
}
|
||||
|
||||
/// Verify a purported `signature` with a pre-hashed [`Challenge`] made by this verification
|
||||
|
|
Loading…
Reference in New Issue