changes required for randomization
This commit is contained in:
parent
1815280576
commit
1ace998b8b
|
@ -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 = []
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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)?;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 })
|
||||
|
|
Loading…
Reference in New Issue