mirror of
https://github.com/arnaucube/arkeddsa.git
synced 2026-01-11 16:01:27 +01:00
better bounds
reuse ark-error
This commit is contained in:
94
src/eddsa.rs
94
src/eddsa.rs
@@ -3,7 +3,10 @@ use ark_crypto_primitives::sponge::{
|
||||
poseidon::{PoseidonConfig, PoseidonSponge},
|
||||
Absorb, CryptographicSponge,
|
||||
};
|
||||
use ark_ec::{twisted_edwards::TECurveConfig, AffineRepr, CurveGroup};
|
||||
use ark_ec::{
|
||||
twisted_edwards::{Affine, TECurveConfig},
|
||||
AffineRepr,
|
||||
};
|
||||
use ark_ff::PrimeField;
|
||||
use digest::Digest;
|
||||
use digest::OutputSizeUser;
|
||||
@@ -41,41 +44,48 @@ impl SecretKey {
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// `PublicKey` is EdDSA signature verification key
|
||||
pub struct PublicKey<A: AffineRepr>(A)
|
||||
where
|
||||
A::Config: TECurveConfig;
|
||||
pub struct PublicKey<TE: TECurveConfig>(Affine<TE>);
|
||||
|
||||
impl<A: AffineRepr> PublicKey<A>
|
||||
where
|
||||
A::Config: TECurveConfig,
|
||||
{
|
||||
pub fn xy(&self) -> (&A::BaseField, &A::BaseField) {
|
||||
self.0.xy().unwrap()
|
||||
impl<TE: TECurveConfig> PublicKey<TE> {
|
||||
pub fn point(&self) -> &Affine<TE> {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn xy(&self) -> (&TE::BaseField, &TE::BaseField) {
|
||||
self.as_ref().xy().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<TE: TECurveConfig> From<Affine<TE>> for PublicKey<TE> {
|
||||
fn from(affine: Affine<TE>) -> Self {
|
||||
Self(affine)
|
||||
}
|
||||
}
|
||||
|
||||
impl<TE: TECurveConfig> AsRef<Affine<TE>> for PublicKey<TE> {
|
||||
fn as_ref(&self) -> &Affine<TE> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
/// `SigningKey` produces EdDSA signatures for given message
|
||||
pub struct SigningKey<A: AffineRepr>
|
||||
where
|
||||
A::Config: TECurveConfig,
|
||||
{
|
||||
pub struct SigningKey<TE: TECurveConfig> {
|
||||
secret_key: SecretKey,
|
||||
public_key: PublicKey<A>,
|
||||
public_key: PublicKey<TE>,
|
||||
}
|
||||
|
||||
impl<A: AffineRepr> SigningKey<A>
|
||||
impl<TE: TECurveConfig> SigningKey<TE>
|
||||
where
|
||||
A::Config: TECurveConfig,
|
||||
A::BaseField: PrimeField + Absorb,
|
||||
TE::BaseField: PrimeField + Absorb,
|
||||
{
|
||||
pub fn new<D: Digest>(secret_key: &SecretKey) -> Result<Self, Error> {
|
||||
(<D as OutputSizeUser>::output_size() == 64)
|
||||
.then_some(())
|
||||
.ok_or(Error::BadOutputSize)?;
|
||||
.ok_or(Error::BadDigestOutput)?;
|
||||
|
||||
let (x, _) = secret_key.expand::<A::ScalarField, D>();
|
||||
let public_key: A = (A::generator() * x).into_affine();
|
||||
let (x, _) = secret_key.expand::<TE::ScalarField, D>();
|
||||
let public_key: Affine<TE> = (Affine::<TE>::generator() * x).into();
|
||||
let signing_key = Self {
|
||||
secret_key: *secret_key,
|
||||
public_key: PublicKey(public_key),
|
||||
@@ -90,35 +100,36 @@ where
|
||||
Self::new::<D>(&secret_key)
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> &PublicKey<A> {
|
||||
pub fn public_key(&self) -> &PublicKey<TE> {
|
||||
&self.public_key
|
||||
}
|
||||
|
||||
pub fn sign<D: Digest, E: Absorb>(
|
||||
&self,
|
||||
poseidon: &PoseidonConfig<A::BaseField>,
|
||||
poseidon: &PoseidonConfig<TE::BaseField>,
|
||||
message: &[E],
|
||||
) -> Signature<A> {
|
||||
let (x, prefix) = self.secret_key.expand::<A::ScalarField, D>();
|
||||
) -> Signature<TE> {
|
||||
let (x, prefix) = self.secret_key.expand::<TE::ScalarField, D>();
|
||||
|
||||
let mut h = D::new();
|
||||
h.update(prefix);
|
||||
message
|
||||
.iter()
|
||||
.for_each(|m| h.update(m.to_sponge_bytes_as_vec()));
|
||||
let r: A::ScalarField = crate::from_digest(h);
|
||||
let sig_r = (A::generator() * r).into_affine();
|
||||
let r: TE::ScalarField = crate::from_digest(h);
|
||||
let sig_r: Affine<TE> = (Affine::<TE>::generator() * r).into();
|
||||
|
||||
let mut poseidon = PoseidonSponge::new(poseidon);
|
||||
|
||||
let (sig_r_x, sig_r_y) = sig_r.xy().unwrap();
|
||||
poseidon.absorb(sig_r_x);
|
||||
poseidon.absorb(sig_r_y);
|
||||
let (vk_x, vk_y) = self.public_key.0.xy().unwrap();
|
||||
poseidon.absorb(vk_x);
|
||||
poseidon.absorb(vk_y);
|
||||
let (pk_x, pk_y) = self.public_key.0.xy().unwrap();
|
||||
poseidon.absorb(pk_x);
|
||||
poseidon.absorb(pk_y);
|
||||
message.iter().for_each(|m| poseidon.absorb(m));
|
||||
|
||||
let k = poseidon.squeeze_field_elements::<A::ScalarField>(1);
|
||||
let k = poseidon.squeeze_field_elements::<TE::ScalarField>(1);
|
||||
let k = k.first().unwrap();
|
||||
|
||||
let sig_s = (x * k) + r;
|
||||
@@ -127,33 +138,32 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: AffineRepr> PublicKey<A>
|
||||
impl<TE: TECurveConfig> PublicKey<TE>
|
||||
where
|
||||
A::Config: TECurveConfig,
|
||||
A::BaseField: PrimeField + Absorb,
|
||||
TE::BaseField: PrimeField + Absorb,
|
||||
{
|
||||
pub fn verify<E: Absorb>(
|
||||
&self,
|
||||
poseidon: &PoseidonConfig<A::BaseField>,
|
||||
poseidon: &PoseidonConfig<TE::BaseField>,
|
||||
message: &[E],
|
||||
signature: &Signature<A>,
|
||||
signature: &Signature<TE>,
|
||||
) -> Result<(), Error> {
|
||||
let mut poseidon = PoseidonSponge::new(poseidon);
|
||||
|
||||
let (sig_r_x, sig_r_y) = signature.r().xy().unwrap();
|
||||
poseidon.absorb(sig_r_x);
|
||||
poseidon.absorb(sig_r_y);
|
||||
let (vk_x, vk_y) = self.0.xy().unwrap();
|
||||
poseidon.absorb(vk_x);
|
||||
poseidon.absorb(vk_y);
|
||||
let (pk_x, pk_y) = self.0.xy().unwrap();
|
||||
poseidon.absorb(pk_x);
|
||||
poseidon.absorb(pk_y);
|
||||
message.iter().for_each(|m| poseidon.absorb(m));
|
||||
|
||||
let k = poseidon.squeeze_field_elements::<A::ScalarField>(1);
|
||||
let k = poseidon.squeeze_field_elements::<TE::ScalarField>(1);
|
||||
let k = k.first().unwrap();
|
||||
|
||||
let kx_b = self.0 * k;
|
||||
let s_b = A::generator() * signature.s();
|
||||
let r_rec: A = (s_b - kx_b).into();
|
||||
let s_b = Affine::<TE>::generator() * signature.s();
|
||||
let r_rec: Affine<TE> = (s_b - kx_b).into();
|
||||
|
||||
(signature.r() == &r_rec).then_some(()).ok_or(Error::Verify)
|
||||
}
|
||||
|
||||
33
src/lib.rs
33
src/lib.rs
@@ -14,17 +14,27 @@ pub(crate) fn from_digest<F: PrimeField, D: Digest>(digest: D) -> F {
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Error {
|
||||
Verify,
|
||||
BadOutputSize,
|
||||
InvalidData,
|
||||
BadDigestOutput,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
match *self {
|
||||
Error::Verify => write!(f, "Signature verification failed"),
|
||||
Error::BadDigestOutput => write!(f, "Bad digest output size"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ark_std::error::Error for Error {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use crate::SigningKey;
|
||||
use ark_crypto_primitives::sponge::poseidon::{find_poseidon_ark_and_mds, PoseidonConfig};
|
||||
use ark_crypto_primitives::sponge::Absorb;
|
||||
use ark_ec::{twisted_edwards::TECurveConfig, AffineRepr};
|
||||
use ark_ec::twisted_edwards::TECurveConfig;
|
||||
use ark_ff::PrimeField;
|
||||
use digest::Digest;
|
||||
use rand_core::OsRng;
|
||||
@@ -46,13 +56,12 @@ mod test {
|
||||
PoseidonConfig::new(full_rounds, partial_rounds, 5, mds, ark, rate, 1)
|
||||
}
|
||||
|
||||
fn run_test<A: AffineRepr, D: Digest>()
|
||||
fn run_test<TE: TECurveConfig, D: Digest>()
|
||||
where
|
||||
A::BaseField: Absorb + PrimeField,
|
||||
A::Config: TECurveConfig,
|
||||
TE::BaseField: Absorb + PrimeField,
|
||||
{
|
||||
let poseidon = poseidon_config(4, 8, 55);
|
||||
let signing_key = SigningKey::<A>::generate::<D>(&mut OsRng).unwrap();
|
||||
let signing_key = SigningKey::<TE>::generate::<D>(&mut OsRng).unwrap();
|
||||
let message = b"xxx yyy <<< zzz >>> bunny";
|
||||
let signature = signing_key.sign::<D, _>(&poseidon, &message[..]);
|
||||
let public_key = signing_key.public_key();
|
||||
@@ -63,10 +72,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_eddsa() {
|
||||
run_test::<ark_ed_on_bn254::EdwardsAffine, sha2::Sha512>();
|
||||
run_test::<ark_ed_on_bn254::EdwardsAffine, blake2::Blake2b512>();
|
||||
run_test::<crate::ed_on_bn254_twist::EdwardsAffine, sha2::Sha512>();
|
||||
run_test::<ark_ed_on_bls12_381::EdwardsAffine, sha2::Sha512>();
|
||||
run_test::<ark_ed_on_bls12_381_bandersnatch::EdwardsAffine, sha2::Sha512>();
|
||||
run_test::<ark_ed_on_bn254::EdwardsConfig, sha2::Sha512>();
|
||||
run_test::<ark_ed_on_bn254::EdwardsConfig, blake2::Blake2b512>();
|
||||
run_test::<crate::ed_on_bn254_twist::EdwardsConfig, sha2::Sha512>();
|
||||
run_test::<ark_ed_on_bls12_381::EdwardsConfig, sha2::Sha512>();
|
||||
run_test::<ark_ed_on_bls12_381_bandersnatch::EdwardsConfig, sha2::Sha512>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
use crate::Error;
|
||||
use ark_ec::twisted_edwards::Affine;
|
||||
use ark_ec::twisted_edwards::TECurveConfig;
|
||||
use ark_ec::AffineRepr;
|
||||
use ark_serialize::CanonicalDeserialize;
|
||||
use ark_serialize::CanonicalSerialize;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
/// `SignatureComponents` contains the realized parts of a signature
|
||||
pub struct Signature<A: AffineRepr> {
|
||||
r: A,
|
||||
s: A::ScalarField,
|
||||
pub struct Signature<TE: TECurveConfig> {
|
||||
r: Affine<TE>,
|
||||
s: TE::ScalarField,
|
||||
}
|
||||
|
||||
impl<A: AffineRepr> Signature<A>
|
||||
where
|
||||
A::Config: TECurveConfig,
|
||||
{
|
||||
impl<TE: TECurveConfig> Signature<TE> {
|
||||
/// Serializes the signature components to bytes as uncompressed.
|
||||
/// Expect output size to be `size_of(A::BaseField) * 2 + size_of(A::ScalarField)`
|
||||
/// Expect output size to be `size_of(TE::BaseField) * 2 + size_of(TE::ScalarField)`
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
self.r.serialize_uncompressed(&mut bytes).unwrap();
|
||||
@@ -25,32 +21,30 @@ where
|
||||
}
|
||||
|
||||
/// Checked deserialization of the signature components from bytes.
|
||||
/// Expects input size to be `size_of(A::BaseField) * 2 + size_of(A::ScalarField)`
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Signature<A>, Error> {
|
||||
let point_size = A::Config::serialized_size(ark_serialize::Compress::No);
|
||||
(bytes.len() == 32 + A::Config::serialized_size(ark_serialize::Compress::No))
|
||||
/// Expects input size to be `size_of(TE::BaseField) * 2 + size_of(TE::ScalarField)`
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, Box<dyn ark_std::error::Error>> {
|
||||
let point_size = TE::serialized_size(ark_serialize::Compress::No);
|
||||
(bytes.len() == 32 + TE::serialized_size(ark_serialize::Compress::No))
|
||||
.then_some(true)
|
||||
.ok_or(Error::InvalidData)?;
|
||||
.ok_or(ark_serialize::SerializationError::InvalidData)?;
|
||||
|
||||
let off1 = point_size;
|
||||
let off2 = off1 + 32;
|
||||
|
||||
let r =
|
||||
A::deserialize_uncompressed(&bytes[00..off1]).map_err(|_| crate::Error::InvalidData)?;
|
||||
let s = A::ScalarField::deserialize_uncompressed(&bytes[off1..off2])
|
||||
.map_err(|_| crate::Error::InvalidData)?;
|
||||
let r = Affine::<TE>::deserialize_uncompressed(&bytes[00..off1])?;
|
||||
let s = TE::ScalarField::deserialize_uncompressed(&bytes[off1..off2])?;
|
||||
Ok(Signature { r, s })
|
||||
}
|
||||
|
||||
pub fn new(r: A, s: A::ScalarField) -> Self {
|
||||
pub fn new(r: Affine<TE>, s: TE::ScalarField) -> Self {
|
||||
Self { r, s }
|
||||
}
|
||||
|
||||
pub(crate) fn r(&self) -> &A {
|
||||
pub fn r(&self) -> &Affine<TE> {
|
||||
&self.r
|
||||
}
|
||||
|
||||
pub(crate) fn s(&self) -> &A::ScalarField {
|
||||
pub fn s(&self) -> &TE::ScalarField {
|
||||
&self.s
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user