changes required for randomization

This commit is contained in:
Conrado Gouvea 2022-07-11 11:59:52 -03:00
parent 1815280576
commit 1ace998b8b
9 changed files with 123 additions and 35 deletions

View File

@ -25,6 +25,7 @@ hex = { version = "0.4.3", features = ["serde"] }
rand_core = "0.6"
serde = { version = "1", optional = true, features = ["derive"] }
thiserror = "1.0"
visibility = "0.0.1"
zeroize = { version = "1.5.4", default-features = false, features = ["derive"] }
# Test dependencies used with the test-impl feature
@ -46,3 +47,4 @@ nightly = []
default = ["serde"]
# Exposes ciphersuite-generic tests for other crates to use
test-impl = ["proptest", "proptest-derive", "serde_json"]
internals = []

View File

@ -12,7 +12,6 @@
use std::{
collections::{BTreeMap, HashMap},
convert::TryFrom,
fmt::{self, Debug},
ops::Index,
};
@ -41,6 +40,18 @@ impl<C> BindingFactor<C>
where
C: Ciphersuite,
{
/// Create a new [`Rho`] from the given scalar.
#[cfg(feature = "internals")]
pub fn new(scalar: <<C::Group as Group>::Field as Field>::Scalar) -> Self {
Self(scalar)
}
/// Return the underlying scalar.
#[cfg(feature = "internals")]
pub fn to_scalar(self) -> <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar {
self.0
}
/// Deserializes [`BindingFactor`] from bytes.
pub fn from_bytes(
bytes: <<C::Group as Group>::Field as Field>::Serialization,
@ -73,6 +84,12 @@ impl<C> BindingFactorList<C>
where
C: Ciphersuite,
{
/// Create a new [`BindingFactorList`] from a vector of binding factors.
#[cfg(feature = "internals")]
pub fn new(binding_factors: BTreeMap<Identifier<C>, BindingFactor<C>>) -> Self {
Self(binding_factors)
}
/// Return iterator through all factors.
pub fn iter(&self) -> impl Iterator<Item = (&Identifier<C>, &BindingFactor<C>)> {
self.0.iter()
@ -136,6 +153,7 @@ where
// TODO: pub struct Lagrange<C: Ciphersuite>(Scalar);
/// Generates the lagrange coefficient for the i'th participant.
#[cfg_attr(feature = "internals", visibility::make(pub))]
fn derive_lagrange_coeff<C: Ciphersuite>(
signer_id: &Identifier<C>,
signing_package: &SigningPackage<C>,
@ -185,7 +203,7 @@ impl<C> SigningPackage<C>
where
C: Ciphersuite,
{
/// Create a new `SigingPackage`
/// Create a new `SigningPackage`
///
/// The `signing_commitments` are sorted by participant `identifier`.
pub fn new(
@ -244,9 +262,25 @@ where
/// The product of all signers' individual commitments, published as part of the
/// final signature.
#[derive(PartialEq, Eq)]
#[derive(Clone, PartialEq, Eq)]
pub struct GroupCommitment<C: Ciphersuite>(pub(super) Element<C>);
impl<C> GroupCommitment<C>
where
C: Ciphersuite,
{
/// Create a new `GroupCommitment`
pub fn new(element: <C::Group as Group>::Element) -> Self {
Self(element)
}
/// Return the underlying element.
#[cfg(feature = "internals")]
pub fn to_element(self) -> <C::Group as Group>::Element {
self.0
}
}
// impl<C> Debug for GroupCommitment<C> where C: Ciphersuite {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// f.debug_tuple("GroupCommitment")
@ -255,43 +289,41 @@ pub struct GroupCommitment<C: Ciphersuite>(pub(super) Element<C>);
// }
// }
impl<C> TryFrom<&SigningPackage<C>> for GroupCommitment<C>
/// Generates the group commitment which is published as part of the joint
/// Schnorr signature.
///
/// Implements [`compute_group_commitment`] from the spec.
///
/// [`compute_group_commitment`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-4.5
#[cfg_attr(feature = "internals", visibility::make(pub))]
fn compute_group_commitment<C>(
signing_package: &SigningPackage<C>,
binding_factor_list: &BindingFactorList<C>,
) -> Result<GroupCommitment<C>, Error>
where
C: Ciphersuite,
{
type Error = Error;
let identity = <C::Group as Group>::identity();
/// Generates the group commitment which is published as part of the joint
/// Schnorr signature.
///
/// Implements [`compute_group_commitment`] from the spec.
///
/// [`compute_group_commitment`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#section-4.5
fn try_from(signing_package: &SigningPackage<C>) -> Result<GroupCommitment<C>, Error> {
let binding_factor_list: BindingFactorList<C> = signing_package.into();
let mut group_commitment = <C::Group as Group>::identity();
let identity = <C::Group>::identity();
let mut group_commitment = <C::Group>::identity();
// Ala the sorting of B, just always sort by identifier in ascending order
//
// https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#encoding-operations-dep-encoding
for commitment in signing_package.signing_commitments() {
// The following check prevents a party from accidentally revealing their share.
// Note that the '&&' operator would be sufficient.
if identity == commitment.binding.0 || identity == commitment.hiding.0 {
return Err(Error::IdentityCommitment);
}
let binding_factor = binding_factor_list[commitment.identifier].clone();
group_commitment = group_commitment
+ (commitment.hiding.0 + (commitment.binding.0 * binding_factor.0));
// Ala the sorting of B, just always sort by identifier in ascending order
//
// https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#encoding-operations-dep-encoding
for commitment in signing_package.signing_commitments() {
// The following check prevents a party from accidentally revealing their share.
// Note that the '&&' operator would be sufficient.
if identity == commitment.binding.0 || identity == commitment.hiding.0 {
return Err(Error::IdentityCommitment);
}
Ok(GroupCommitment(group_commitment))
let binding_factor = binding_factor_list[commitment.identifier].clone();
group_commitment =
group_commitment + (commitment.hiding.0 + (commitment.binding.0 * binding_factor.0));
}
Ok(GroupCommitment::new(group_commitment))
}
////////////////////////////////////////////////////////////////////////////////
@ -326,7 +358,7 @@ where
let binding_factor_list: BindingFactorList<C> = signing_package.into();
// Compute the group commitment from signing commitments produced in round one.
let group_commitment = GroupCommitment::<C>::try_from(signing_package)?;
let group_commitment = compute_group_commitment(signing_package, &binding_factor_list)?;
// Compute the per-message challenge.
let challenge = crate::challenge::<C>(

View File

@ -19,7 +19,8 @@ impl<C> Identifier<C>
where
C: Ciphersuite,
{
// Serialize the underlying scalar.
/// Serialize the underlying scalar.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn serialize(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
<<C::Group as Group>::Field>::serialize(&self.0)
}

View File

@ -121,6 +121,12 @@ impl<C> SigningShare<C>
where
C: Ciphersuite,
{
/// Return the underlying scalar.
#[cfg(feature = "internals")]
pub fn to_scalar(self) -> <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar {
self.0
}
/// Deserialize from bytes
pub fn from_bytes(
bytes: <<C::Group as Group>::Field as Field>::Serialization,

View File

@ -54,6 +54,12 @@ where
Self(C::H3(input.as_slice()))
}
/// Return the underlying scalar.
#[cfg(feature = "internals")]
pub fn to_scalar(self) -> <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar {
self.0
}
/// Deserialize [`Nonce`] from bytes
pub fn from_bytes(
bytes: <<C::Group as Group>::Field as Field>::Serialization,
@ -100,6 +106,12 @@ impl<C> NonceCommitment<C>
where
C: Ciphersuite,
{
/// Return the underlying element.
#[cfg(feature = "internals")]
pub fn to_element(self) -> <C::Group as Group>::Element {
self.0
}
/// Deserialize [`NonceCommitment`] from bytes
pub fn from_bytes(bytes: <C::Group as Group>::Serialization) -> Result<Self, Error> {
<C::Group>::deserialize(&bytes).map(|element| Self(element))
@ -221,6 +233,7 @@ where
/// Computes the [signature commitment share] from these round one signing commitments.
///
/// [signature commitment share]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#name-signature-share-verificatio
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(super) fn to_group_commitment_share(
self,
binding_factor: &frost::BindingFactor<C>,
@ -271,6 +284,7 @@ pub struct GroupCommitmentShare<C: Ciphersuite>(pub(super) Element<C>);
/// - A byte string containing the serialized representation of B.
///
/// [`encode_group_commitment_list()`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#name-list-operations
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(super) fn encode_group_commitments<C: Ciphersuite>(
signing_commitments: Vec<SigningCommitments<C>>,
) -> Vec<u8> {

View File

@ -139,7 +139,7 @@ pub fn sign<C: Ciphersuite>(
binding_factor_list[key_package.identifier].clone();
// Compute the group commitment from signing commitments produced in round one.
let group_commitment = GroupCommitment::<C>::try_from(signing_package)?;
let group_commitment = compute_group_commitment(signing_package, &binding_factor_list)?;
// Compute Lagrange coefficient.
let lambda_i = frost::derive_lagrange_coeff(key_package.identifier(), signing_package)?;

View File

@ -241,6 +241,17 @@ pub trait Ciphersuite: Copy + Clone + PartialEq {
#[derive(Clone)]
pub struct Challenge<C: Ciphersuite>(pub(crate) <<C::Group as Group>::Field as Field>::Scalar);
impl<C> Challenge<C>
where
C: Ciphersuite,
{
/// Return the underlying scalar.
#[cfg(feature = "internals")]
pub fn to_scalar(self) -> <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar {
self.0
}
}
impl<C> Debug for Challenge<C>
where
C: Ciphersuite,
@ -263,6 +274,7 @@ where
///
/// [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
#[cfg_attr(feature = "internals", visibility::make(pub))]
fn challenge<C>(R: &Element<C>, verifying_key: &Element<C>, msg: &[u8]) -> Challenge<C>
where
C: Ciphersuite,

View File

@ -20,6 +20,15 @@ where
C::Group: Group,
<C::Group as Group>::Field: Field,
{
/// Create a new Signature.
#[cfg(feature = "internals")]
pub fn new(
R: <C::Group as Group>::Element,
z: <<C::Group as Group>::Field as Field>::Scalar,
) -> Self {
Self { R, z }
}
/// Converts bytes as [`Ciphersuite::SignatureSerialization`] into a `Signature<C>`.
pub fn from_bytes(bytes: C::SignatureSerialization) -> Result<Self, Error> {
// To compute the expected length of the encoded point, encode the generator

View File

@ -23,6 +23,18 @@ where
// VerifyingKey { element }
// }
/// Create a new VerifyingKey from the given element.
#[cfg(feature = "internals")]
pub fn new(element: <C::Group as Group>::Element) -> Self {
Self { element }
}
/// Return the underlying element.
#[cfg(feature = "internals")]
pub fn to_element(self) -> <C::Group as Group>::Element {
self.element
}
/// Deserialize from bytes
pub fn from_bytes(bytes: <C::Group as Group>::Serialization) -> Result<VerifyingKey<C>, Error> {
<C::Group>::deserialize(&bytes).map(|element| VerifyingKey { element })