use core::{
fmt::Debug,
ops::{Add, Mul, Sub},
};
use alloc::{borrow::Cow, collections::BTreeMap, vec::Vec};
use rand_core::{CryptoRng, RngCore};
use crate::{
challenge,
keys::{KeyPackage, PublicKeyPackage, SecretShare, VerifyingShare},
random_nonzero,
round1::{self, SigningNonces},
round2::{self, SignatureShare},
BindingFactor, BindingFactorList, Challenge, Error, FieldError, GroupCommitment, GroupError,
Identifier, Signature, SigningKey, SigningPackage, VerifyingKey,
};
pub trait Field: Copy {
type Scalar: Add<Output = Self::Scalar>
+ Copy
+ Clone
+ Eq
+ Mul<Output = Self::Scalar>
+ PartialEq
+ Sub<Output = Self::Scalar>
+ Send
+ Sync;
type Serialization: Clone + AsRef<[u8]> + AsMut<[u8]> + for<'a> TryFrom<&'a [u8]> + Debug;
fn zero() -> Self::Scalar;
fn one() -> Self::Scalar;
fn invert(scalar: &Self::Scalar) -> Result<Self::Scalar, FieldError>;
fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar;
fn serialize(scalar: &Self::Scalar) -> Self::Serialization;
fn little_endian_serialize(scalar: &Self::Scalar) -> Self::Serialization;
fn deserialize(buf: &Self::Serialization) -> Result<Self::Scalar, FieldError>;
}
pub type Scalar<C> = <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar;
pub trait Group: Copy + PartialEq {
type Field: Field;
type Element: Add<Output = Self::Element>
+ Copy
+ Clone
+ Eq
+ Mul<<Self::Field as Field>::Scalar, Output = Self::Element>
+ PartialEq
+ Sub<Output = Self::Element>
+ Send
+ Sync;
type Serialization: Clone + AsRef<[u8]> + AsMut<[u8]> + for<'a> TryFrom<&'a [u8]> + Debug;
fn cofactor() -> <Self::Field as Field>::Scalar;
fn identity() -> Self::Element;
fn generator() -> Self::Element;
fn serialize(element: &Self::Element) -> Result<Self::Serialization, GroupError>;
fn deserialize(buf: &Self::Serialization) -> Result<Self::Element, GroupError>;
}
pub type Element<C> = <<C as Ciphersuite>::Group as Group>::Element;
pub trait Ciphersuite: Copy + PartialEq + Debug + 'static + Send + Sync {
const ID: &'static str;
type Group: Group;
type HashOutput: AsRef<[u8]>;
type SignatureSerialization: Clone
+ AsRef<[u8]>
+ AsMut<[u8]>
+ for<'a> TryFrom<&'a [u8]>
+ Debug;
fn H1(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar;
fn H2(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar;
fn H3(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar;
fn H4(m: &[u8]) -> Self::HashOutput;
fn H5(m: &[u8]) -> Self::HashOutput;
fn HDKG(_m: &[u8]) -> Option<<<Self::Group as Group>::Field as Field>::Scalar> {
None
}
fn HID(_m: &[u8]) -> Option<<<Self::Group as Group>::Field as Field>::Scalar> {
None
}
fn single_sign<R: RngCore + CryptoRng>(
signing_key: &SigningKey<Self>,
rng: R,
message: &[u8],
) -> Signature<Self> {
signing_key.default_sign(rng, message)
}
fn verify_signature(
message: &[u8],
signature: &Signature<Self>,
public_key: &VerifyingKey<Self>,
) -> Result<(), Error<Self>> {
let (message, signature, public_key) = <Self>::pre_verify(message, signature, public_key)?;
let c = <Self>::challenge(&signature.R, &public_key, &message)?;
public_key.verify_prehashed(c, &signature)
}
#[allow(clippy::type_complexity)]
fn pre_sign<'a>(
signing_package: &'a SigningPackage<Self>,
signer_nonces: &'a round1::SigningNonces<Self>,
key_package: &'a KeyPackage<Self>,
) -> Result<
(
Cow<'a, SigningPackage<Self>>,
Cow<'a, round1::SigningNonces<Self>>,
Cow<'a, KeyPackage<Self>>,
),
Error<Self>,
> {
Ok((
Cow::Borrowed(signing_package),
Cow::Borrowed(signer_nonces),
Cow::Borrowed(key_package),
))
}
#[allow(clippy::type_complexity)]
fn pre_aggregate<'a>(
signing_package: &'a SigningPackage<Self>,
signature_shares: &'a BTreeMap<Identifier<Self>, round2::SignatureShare<Self>>,
public_key_package: &'a PublicKeyPackage<Self>,
) -> Result<
(
Cow<'a, SigningPackage<Self>>,
Cow<'a, BTreeMap<Identifier<Self>, round2::SignatureShare<Self>>>,
Cow<'a, PublicKeyPackage<Self>>,
),
Error<Self>,
> {
Ok((
Cow::Borrowed(signing_package),
Cow::Borrowed(signature_shares),
Cow::Borrowed(public_key_package),
))
}
#[allow(clippy::type_complexity)]
fn pre_verify<'a>(
msg: &'a [u8],
signature: &'a Signature<Self>,
public_key: &'a VerifyingKey<Self>,
) -> Result<
(
Cow<'a, [u8]>,
Cow<'a, Signature<Self>>,
Cow<'a, VerifyingKey<Self>>,
),
Error<Self>,
> {
Ok((
Cow::Borrowed(msg),
Cow::Borrowed(signature),
Cow::Borrowed(public_key),
))
}
#[allow(clippy::type_complexity)]
fn pre_commitment_sign<'a>(
signing_package: &'a SigningPackage<Self>,
signing_nonces: &'a SigningNonces<Self>,
_binding_factor_list: &'a BindingFactorList<Self>,
) -> Result<(Cow<'a, SigningPackage<Self>>, Cow<'a, SigningNonces<Self>>), Error<Self>> {
Ok((
Cow::Borrowed(signing_package),
Cow::Borrowed(signing_nonces),
))
}
fn pre_commitment_aggregate<'a>(
signing_package: &'a SigningPackage<Self>,
_binding_factor_list: &'a BindingFactorList<Self>,
) -> Result<Cow<'a, SigningPackage<Self>>, Error<Self>> {
Ok(Cow::Borrowed(signing_package))
}
fn generate_nonce<R: RngCore + CryptoRng>(
rng: &mut R,
) -> (
<<Self::Group as Group>::Field as Field>::Scalar,
<Self::Group as Group>::Element,
) {
let k = random_nonzero::<Self, R>(rng);
let R = <Self::Group>::generator() * k;
(k, R)
}
fn challenge(
R: &Element<Self>,
verifying_key: &VerifyingKey<Self>,
message: &[u8],
) -> Result<Challenge<Self>, Error<Self>> {
challenge(R, verifying_key, message)
}
fn compute_signature_share(
_group_commitment: &GroupCommitment<Self>,
signer_nonces: &round1::SigningNonces<Self>,
binding_factor: BindingFactor<Self>,
lambda_i: <<Self::Group as Group>::Field as Field>::Scalar,
key_package: &KeyPackage<Self>,
challenge: Challenge<Self>,
) -> round2::SignatureShare<Self> {
round2::compute_signature_share(
signer_nonces,
binding_factor,
lambda_i,
key_package,
challenge,
)
}
fn verify_share(
_group_commitment: &GroupCommitment<Self>,
signature_share: &SignatureShare<Self>,
identifier: Identifier<Self>,
group_commitment_share: &round1::GroupCommitmentShare<Self>,
verifying_share: &VerifyingShare<Self>,
lambda_i: Scalar<Self>,
challenge: &Challenge<Self>,
) -> Result<(), Error<Self>> {
signature_share.verify(
identifier,
group_commitment_share,
verifying_share,
lambda_i,
challenge,
)
}
fn serialize_signature(signature: &Signature<Self>) -> Result<Vec<u8>, Error<Self>> {
signature.default_serialize()
}
fn deserialize_signature(bytes: &[u8]) -> Result<Signature<Self>, Error<Self>> {
Signature::<Self>::default_deserialize(bytes)
}
fn post_dkg(
key_package: KeyPackage<Self>,
public_key_package: PublicKeyPackage<Self>,
) -> Result<(KeyPackage<Self>, PublicKeyPackage<Self>), Error<Self>> {
Ok((key_package, public_key_package))
}
#[allow(clippy::type_complexity)]
fn post_generate(
secret_shares: BTreeMap<Identifier<Self>, SecretShare<Self>>,
public_key_package: PublicKeyPackage<Self>,
) -> Result<
(
BTreeMap<Identifier<Self>, SecretShare<Self>>,
PublicKeyPackage<Self>,
),
Error<Self>,
> {
Ok((secret_shares, public_key_package))
}
}