From b409860439b81179cbfc197bdcc3b335248d1058 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Thu, 28 Nov 2024 22:00:43 +0100 Subject: [PATCH 1/3] add in-circuit EdDSA verification gadget add in-circuit EdDSA verification gadget compatible with the out-circuit logic. --- Cargo.toml | 9 +++- README.md | 5 +++ rust-toolchain | 2 +- src/constraints.rs | 90 ++++++++++++++++++++++++++++++++++++++++ src/ed_on_bn254_twist.rs | 15 +++++++ src/eddsa.rs | 33 ++++++++------- src/lib.rs | 14 ++++--- src/signature.rs | 4 +- 8 files changed, 147 insertions(+), 25 deletions(-) create mode 100644 src/constraints.rs diff --git a/Cargo.toml b/Cargo.toml index 4eb6d9d..c34bbb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,7 @@ rust-version = "1.75.0" version = "0.1.0" [dependencies] - -ark-crypto-primitives = {version = "^0.4.0", default-features = false, features = ["sponge", "crh"]} +ark-crypto-primitives = {version = "^0.4.0", default-features = false, features = ["sponge", "crh", "r1cs"]} ark-ec = "^0.4.0" ark-ed-on-bn254 = {version = "0.4.0"} ark-ff = "^0.4.0" @@ -16,6 +15,11 @@ digest = "0.10" rand = "0.8" rand_core = {version = "0.6", default-features = false} +# r1cs deps related under feature="r1cs" +ark-relations = { version = "^0.4.0", default-features = false, optional = true } +ark-r1cs-std = { version = "0.4.0", default-features = false, features = ["parallel"], optional = true } + + [dev-dependencies] ark-algebra-test-templates = "0.4.2" ark-ed-on-bls12-381 = {version = "0.4.0"} @@ -26,3 +30,4 @@ sha2 = "0.10" [features] default = [] +r1cs = ["ark-r1cs-std", "ark-relations"] diff --git a/README.md b/README.md index b7738c5..4ee7ad5 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,8 @@ Do not use in production. EDDSA signature scheme implementation with Poseidon hasher and ark-works backend. Additionally circom compatible `ed_on_bn254_twist` twist is available. + +The `r1cs` feature enables the in-circuit EdDSA verification. + +## test +To test including the constraints use the `r1cs` feature flag: `cargo test --features=r1cs` diff --git a/rust-toolchain b/rust-toolchain index 7c7053a..71fae54 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.75.0 +1.82.0 diff --git a/src/constraints.rs b/src/constraints.rs new file mode 100644 index 0000000..c8c5ace --- /dev/null +++ b/src/constraints.rs @@ -0,0 +1,90 @@ +/// This file implements the EdDSA verification in-circuit. +use ark_crypto_primitives::sponge::{ + constraints::CryptographicSpongeVar, + poseidon::{constraints::PoseidonSpongeVar, PoseidonConfig}, +}; +use ark_ec::CurveGroup; +use ark_ff::Field; +use ark_relations::r1cs::ConstraintSystemRef; + +use ark_r1cs_std::{ + boolean::Boolean, fields::fp::FpVar, fields::nonnative::NonNativeFieldVar, groups::CurveVar, + ToBitsGadget, ToConstraintFieldGadget, +}; + +use crate::Error; + +/// CF stands for ConstraintField +pub type CF = <::BaseField as Field>::BasePrimeField; + +/// gadget to compute the EdDSA verification in-circuit +pub fn verify( + cs: ConstraintSystemRef>, + poseidon_config: PoseidonConfig>, + pk: GC, + sig: (GC, NonNativeFieldVar>), + msg: FpVar>, +) -> Result>, Error> +where + C: CurveGroup, + GC: CurveVar> + ToConstraintFieldGadget>, +{ + let (r, s): (GC, NonNativeFieldVar>) = sig; + + let r_xy = r.to_constraint_field().unwrap(); + let pk_xy = pk.to_constraint_field().unwrap(); + + let mut poseidon = PoseidonSpongeVar::new(cs.clone(), &poseidon_config); + poseidon.absorb(&r_xy).unwrap(); + poseidon.absorb(&pk_xy).unwrap(); + poseidon.absorb(&msg).unwrap(); + let k = poseidon.squeeze_field_elements(1).unwrap(); + let k = k.first().unwrap(); + + let kx_b = pk.scalar_mul_le(k.to_bits_le().unwrap().iter()).unwrap(); + + let g = GC::new_constant(cs.clone(), C::generator()).unwrap(); + let s_b = g.scalar_mul_le(s.to_bits_le().unwrap().iter()).unwrap(); + let r_rec: GC = s_b - kx_b; + Ok(r_rec.is_eq(&r).unwrap()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::ed_on_bn254_twist::{ + constraints::EdwardsVar as GVar, BaseField as Fq, EdwardsConfig, EdwardsProjective as G, + ScalarField as Fr, + }; + use ark_ff::PrimeField; + use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::nonnative::NonNativeFieldVar}; + use ark_relations::r1cs::ConstraintSystem; + use rand_core::OsRng; + + use crate::test::poseidon_config; + use crate::SigningKey; + + #[test] + fn gadget_verify() { + let poseidon_config = poseidon_config::(4, 8, 60); + let sk = SigningKey::::generate::(&mut OsRng).unwrap(); + let msg_raw = b"xxx yyy <<< zzz >>> bunny"; + let msg = Fq::from_le_bytes_mod_order(msg_raw); + let sig = sk.sign::(&poseidon_config, &msg); + let pk = sk.public_key(); + pk.verify(&poseidon_config, &msg, &sig).unwrap(); + + let cs = ConstraintSystem::::new_ref(); + let pk_var: GVar = GVar::new_witness(cs.clone(), || Ok(pk.0)).unwrap(); + let r_var: GVar = GVar::new_witness(cs.clone(), || Ok(sig.r)).unwrap(); + let s_var = NonNativeFieldVar::::new_witness(cs.clone(), || Ok(sig.s)).unwrap(); + let msg_var = FpVar::::new_witness(cs.clone(), || Ok(msg)).unwrap(); + + let res = verify::(cs.clone(), poseidon_config, pk_var, (r_var, s_var), msg_var) + .unwrap(); + res.enforce_equal(&Boolean::::TRUE).unwrap(); + + dbg!(cs.num_constraints()); + assert!(cs.is_satisfied().unwrap()); + } +} diff --git a/src/ed_on_bn254_twist.rs b/src/ed_on_bn254_twist.rs index 747a61f..11817fd 100644 --- a/src/ed_on_bn254_twist.rs +++ b/src/ed_on_bn254_twist.rs @@ -103,3 +103,18 @@ fn test_twist() { let v2 = untwist(u1); assert_eq!(v1, v2); } + +// constraints related logic +#[cfg(feature = "r1cs")] +pub mod constraints { + use ark_r1cs_std::fields::fp::FpVar; + use ark_r1cs_std::groups::curves::twisted_edwards::AffineVar; + + use crate::ed_on_bn254_twist::{BaseField as Fq, EdwardsConfig}; + + /// A variable that is the R1CS equivalent of `crate::Fq`. + pub type FqVar = FpVar; + + /// A variable that is the R1CS equivalent of `crate::EdwardsAffine`. + pub type EdwardsVar = AffineVar; +} diff --git a/src/eddsa.rs b/src/eddsa.rs index 253d2ab..1fea364 100644 --- a/src/eddsa.rs +++ b/src/eddsa.rs @@ -7,7 +7,7 @@ use ark_ec::{ twisted_edwards::{Affine, TECurveConfig}, AffineRepr, }; -use ark_ff::PrimeField; +use ark_ff::{BigInteger, PrimeField}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; use digest::Digest; use digest::OutputSizeUser; @@ -45,7 +45,7 @@ impl SecretKey { /// `PublicKey` is EdDSA signature verification key #[derive(Copy, Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] -pub struct PublicKey(Affine); +pub struct PublicKey(pub Affine); impl PublicKey { pub fn xy(&self) -> (&TE::BaseField, &TE::BaseField) { @@ -121,18 +121,20 @@ where &self.public_key } - pub fn sign( + pub fn sign( &self, poseidon: &PoseidonConfig, - message: &[E], + message: &TE::BaseField, ) -> Signature { let (x, prefix) = self.secret_key.expand::(); let mut h = D::new(); h.update(prefix); - message - .iter() - .for_each(|m| h.update(m.to_sponge_bytes_as_vec())); + let msg_bytes = message.into_bigint().to_bytes_le(); + let mut msg32: [u8; 32] = [0; 32]; + msg32[..msg_bytes.len()].copy_from_slice(&msg_bytes[..]); + h.update(msg32); + let r: TE::ScalarField = crate::from_digest(h); let sig_r: Affine = (Affine::::generator() * r).into(); @@ -144,10 +146,12 @@ where 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)); + poseidon.absorb(message); - let k = poseidon.squeeze_field_elements::(1); + // use poseidon over Fq, so that it can be done too in-circuit + let k = poseidon.squeeze_field_elements::(1); let k = k.first().unwrap(); + let k = TE::ScalarField::from_le_bytes_mod_order(&k.into_bigint().to_bytes_le()); let sig_s = (x * k) + r; @@ -169,10 +173,10 @@ impl PublicKey where TE::BaseField: PrimeField + Absorb, { - pub fn verify( + pub fn verify( &self, poseidon: &PoseidonConfig, - message: &[E], + message: &TE::BaseField, signature: &Signature, ) -> Result<(), Error> { let mut poseidon = PoseidonSponge::new(poseidon); @@ -183,12 +187,13 @@ where 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)); + poseidon.absorb(message); - let k = poseidon.squeeze_field_elements::(1); + // use poseidon over Fq, so that it can be done too in-circuit + let k = poseidon.squeeze_field_elements::(1); let k = k.first().unwrap(); - let kx_b = self.0 * k; + let kx_b = self.0.mul_bigint(k.into_bigint()); let s_b = Affine::::generator() * signature.s(); let r_rec: Affine = (s_b - kx_b).into(); diff --git a/src/lib.rs b/src/lib.rs index c90c782..190da68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,9 @@ pub mod ed_on_bn254_twist; pub mod eddsa; pub mod signature; +#[cfg(feature = "r1cs")] +pub mod constraints; + use ark_ff::PrimeField; use digest::Digest; pub use eddsa::*; @@ -60,14 +63,13 @@ mod test { where TE::BaseField: Absorb + PrimeField, { - let poseidon = poseidon_config(4, 8, 55); + let poseidon = poseidon_config::(4, 8, 55); let signing_key = SigningKey::::generate::(&mut OsRng).unwrap(); - let message = b"xxx yyy <<< zzz >>> bunny"; - let signature = signing_key.sign::(&poseidon, &message[..]); + let message_raw = b"xxx yyy <<< zzz >>> bunny"; + let message = TE::BaseField::from_le_bytes_mod_order(message_raw); + let signature = signing_key.sign::(&poseidon, &message); let public_key = signing_key.public_key(); - public_key - .verify::<_>(&poseidon, &message[..], &signature) - .unwrap(); + public_key.verify(&poseidon, &message, &signature).unwrap(); } #[test] diff --git a/src/signature.rs b/src/signature.rs index 65ea776..3cc1819 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -6,8 +6,8 @@ use ark_serialize::CanonicalSerialize; /// `SignatureComponents` contains the realized parts of a signature #[derive(Copy, Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] pub struct Signature { - r: Affine, - s: TE::ScalarField, + pub r: Affine, + pub s: TE::ScalarField, } impl Signature { From fccc17a15a94190592872854b99ff5787b2bbe6a Mon Sep 17 00:00:00 2001 From: arnaucube Date: Fri, 29 Nov 2024 08:28:38 +0100 Subject: [PATCH 2/3] move the poseidon_config function outside from tests move the poseidon_config function outside from tests, since when externally using this lib usually the user will also use the poseidon_config helper to generate the poseidon config to be used in the signature --- src/constraints.rs | 13 ++++++------- src/lib.rs | 45 +++++++++++++++++++++++---------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/constraints.rs b/src/constraints.rs index c8c5ace..cbae34b 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -51,18 +51,17 @@ where #[cfg(test)] mod tests { - use super::*; - use crate::ed_on_bn254_twist::{ - constraints::EdwardsVar as GVar, BaseField as Fq, EdwardsConfig, EdwardsProjective as G, - ScalarField as Fr, - }; use ark_ff::PrimeField; use ark_r1cs_std::{alloc::AllocVar, eq::EqGadget, fields::nonnative::NonNativeFieldVar}; use ark_relations::r1cs::ConstraintSystem; use rand_core::OsRng; - use crate::test::poseidon_config; - use crate::SigningKey; + use super::*; + use crate::ed_on_bn254_twist::{ + constraints::EdwardsVar as GVar, BaseField as Fq, EdwardsConfig, EdwardsProjective as G, + ScalarField as Fr, + }; + use crate::{poseidon_config, SigningKey}; #[test] fn gadget_verify() { diff --git a/src/lib.rs b/src/lib.rs index 190da68..acc9157 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,8 @@ +use ark_ff::PrimeField; +use digest::Digest; +impl ark_std::error::Error for Error {} +use ark_crypto_primitives::sponge::poseidon::{find_poseidon_ark_and_mds, PoseidonConfig}; + pub mod ed_on_bn254_twist; pub mod eddsa; pub mod signature; @@ -5,8 +10,6 @@ pub mod signature; #[cfg(feature = "r1cs")] pub mod constraints; -use ark_ff::PrimeField; -use digest::Digest; pub use eddsa::*; pub(crate) fn from_digest(digest: D) -> F { @@ -29,35 +32,33 @@ impl core::fmt::Display for Error { } } -impl ark_std::error::Error for Error {} +/// Generates poseidon constants and returns the config +pub fn poseidon_config( + rate: usize, + full_rounds: usize, + partial_rounds: usize, +) -> PoseidonConfig { + let prime_bits = F::MODULUS_BIT_SIZE as u64; + let (ark, mds) = find_poseidon_ark_and_mds( + prime_bits, + rate, + full_rounds as u64, + partial_rounds as u64, + 0, + ); + PoseidonConfig::new(full_rounds, partial_rounds, 5, mds, ark, rate, 1) +} #[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; use ark_ff::PrimeField; use digest::Digest; use rand_core::OsRng; - /// Generates poseidon constants and returns the config - pub fn poseidon_config( - rate: usize, - full_rounds: usize, - partial_rounds: usize, - ) -> PoseidonConfig { - let prime_bits = F::MODULUS_BIT_SIZE as u64; - let (ark, mds) = find_poseidon_ark_and_mds( - prime_bits, - rate, - full_rounds as u64, - partial_rounds as u64, - 0, - ); - PoseidonConfig::new(full_rounds, partial_rounds, 5, mds, ark, rate, 1) - } + use super::poseidon_config; + use crate::SigningKey; fn run_test() where From 15158474ab0eea56f40aac9a316444b03ff6d4eb Mon Sep 17 00:00:00 2001 From: arnaucube Date: Tue, 3 Dec 2024 12:03:27 +0100 Subject: [PATCH 3/3] rm unwraps inside methods, return params to private --- .gitignore | 3 ++- src/constraints.rs | 41 +++++++++++++++++++++-------------------- src/eddsa.rs | 22 +++++++++++----------- src/lib.rs | 4 +++- src/signature.rs | 4 ++-- 5 files changed, 39 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 6466ebf..2832471 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target -*.py \ No newline at end of file +*.py +Cargo.lock diff --git a/src/constraints.rs b/src/constraints.rs index cbae34b..0a5ddcb 100644 --- a/src/constraints.rs +++ b/src/constraints.rs @@ -5,14 +5,11 @@ use ark_crypto_primitives::sponge::{ }; use ark_ec::CurveGroup; use ark_ff::Field; -use ark_relations::r1cs::ConstraintSystemRef; - use ark_r1cs_std::{ boolean::Boolean, fields::fp::FpVar, fields::nonnative::NonNativeFieldVar, groups::CurveVar, ToBitsGadget, ToConstraintFieldGadget, }; - -use crate::Error; +use ark_relations::r1cs::ConstraintSystemRef; /// CF stands for ConstraintField pub type CF = <::BaseField as Field>::BasePrimeField; @@ -24,29 +21,31 @@ pub fn verify( pk: GC, sig: (GC, NonNativeFieldVar>), msg: FpVar>, -) -> Result>, Error> +) -> ark_relations::r1cs::Result>> where C: CurveGroup, GC: CurveVar> + ToConstraintFieldGadget>, { let (r, s): (GC, NonNativeFieldVar>) = sig; - let r_xy = r.to_constraint_field().unwrap(); - let pk_xy = pk.to_constraint_field().unwrap(); + let r_xy = r.to_constraint_field()?; + let pk_xy = pk.to_constraint_field()?; let mut poseidon = PoseidonSpongeVar::new(cs.clone(), &poseidon_config); - poseidon.absorb(&r_xy).unwrap(); - poseidon.absorb(&pk_xy).unwrap(); - poseidon.absorb(&msg).unwrap(); - let k = poseidon.squeeze_field_elements(1).unwrap(); - let k = k.first().unwrap(); + poseidon.absorb(&r_xy)?; + poseidon.absorb(&pk_xy)?; + poseidon.absorb(&msg)?; + let k = poseidon.squeeze_field_elements(1)?; + let k = k + .first() + .ok_or(ark_relations::r1cs::SynthesisError::Unsatisfiable)?; - let kx_b = pk.scalar_mul_le(k.to_bits_le().unwrap().iter()).unwrap(); + let kx_b = pk.scalar_mul_le(k.to_bits_le()?.iter())?; - let g = GC::new_constant(cs.clone(), C::generator()).unwrap(); - let s_b = g.scalar_mul_le(s.to_bits_le().unwrap().iter()).unwrap(); + let g = GC::new_constant(cs.clone(), C::generator())?; + let s_b = g.scalar_mul_le(s.to_bits_le()?.iter())?; let r_rec: GC = s_b - kx_b; - Ok(r_rec.is_eq(&r).unwrap()) + Ok(r_rec.is_eq(&r)?) } #[cfg(test)] @@ -69,14 +68,16 @@ mod tests { let sk = SigningKey::::generate::(&mut OsRng).unwrap(); let msg_raw = b"xxx yyy <<< zzz >>> bunny"; let msg = Fq::from_le_bytes_mod_order(msg_raw); - let sig = sk.sign::(&poseidon_config, &msg); + let sig = sk + .sign::(&poseidon_config, &msg) + .unwrap(); let pk = sk.public_key(); pk.verify(&poseidon_config, &msg, &sig).unwrap(); let cs = ConstraintSystem::::new_ref(); - let pk_var: GVar = GVar::new_witness(cs.clone(), || Ok(pk.0)).unwrap(); - let r_var: GVar = GVar::new_witness(cs.clone(), || Ok(sig.r)).unwrap(); - let s_var = NonNativeFieldVar::::new_witness(cs.clone(), || Ok(sig.s)).unwrap(); + let pk_var: GVar = GVar::new_witness(cs.clone(), || Ok(*pk.as_ref())).unwrap(); + let r_var: GVar = GVar::new_witness(cs.clone(), || Ok(*sig.r())).unwrap(); + let s_var = NonNativeFieldVar::::new_witness(cs.clone(), || Ok(sig.s())).unwrap(); let msg_var = FpVar::::new_witness(cs.clone(), || Ok(msg)).unwrap(); let res = verify::(cs.clone(), poseidon_config, pk_var, (r_var, s_var), msg_var) diff --git a/src/eddsa.rs b/src/eddsa.rs index 1fea364..810448f 100644 --- a/src/eddsa.rs +++ b/src/eddsa.rs @@ -45,11 +45,11 @@ impl SecretKey { /// `PublicKey` is EdDSA signature verification key #[derive(Copy, Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] -pub struct PublicKey(pub Affine); +pub struct PublicKey(Affine); impl PublicKey { - pub fn xy(&self) -> (&TE::BaseField, &TE::BaseField) { - self.as_ref().xy().unwrap() + pub fn xy(&self) -> Result<(&TE::BaseField, &TE::BaseField), Error> { + self.as_ref().xy().ok_or(Error::Coordinates) } pub fn to_bytes(&self) -> Vec { @@ -125,7 +125,7 @@ where &self, poseidon: &PoseidonConfig, message: &TE::BaseField, - ) -> Signature { + ) -> Result, Error> { let (x, prefix) = self.secret_key.expand::(); let mut h = D::new(); @@ -140,22 +140,22 @@ where let mut poseidon = PoseidonSponge::new(poseidon); - let (sig_r_x, sig_r_y) = sig_r.xy().unwrap(); + let (sig_r_x, sig_r_y) = sig_r.xy().ok_or(Error::Coordinates)?; poseidon.absorb(sig_r_x); poseidon.absorb(sig_r_y); - let (pk_x, pk_y) = self.public_key.0.xy().unwrap(); + let (pk_x, pk_y) = self.public_key.0.xy().ok_or(Error::Coordinates)?; poseidon.absorb(pk_x); poseidon.absorb(pk_y); poseidon.absorb(message); // use poseidon over Fq, so that it can be done too in-circuit let k = poseidon.squeeze_field_elements::(1); - let k = k.first().unwrap(); + let k = k.first().ok_or(Error::BadDigestOutput)?; let k = TE::ScalarField::from_le_bytes_mod_order(&k.into_bigint().to_bytes_le()); let sig_s = (x * k) + r; - Signature::new(sig_r, sig_s) + Ok(Signature::new(sig_r, sig_s)) } } @@ -181,17 +181,17 @@ where ) -> Result<(), Error> { let mut poseidon = PoseidonSponge::new(poseidon); - let (sig_r_x, sig_r_y) = signature.r().xy().unwrap(); + let (sig_r_x, sig_r_y) = signature.r().xy().ok_or(Error::Coordinates)?; poseidon.absorb(sig_r_x); poseidon.absorb(sig_r_y); - let (pk_x, pk_y) = self.0.xy().unwrap(); + let (pk_x, pk_y) = self.0.xy().ok_or(Error::Coordinates)?; poseidon.absorb(pk_x); poseidon.absorb(pk_y); poseidon.absorb(message); // use poseidon over Fq, so that it can be done too in-circuit let k = poseidon.squeeze_field_elements::(1); - let k = k.first().unwrap(); + let k = k.first().ok_or(Error::BadDigestOutput)?; let kx_b = self.0.mul_bigint(k.into_bigint()); let s_b = Affine::::generator() * signature.s(); diff --git a/src/lib.rs b/src/lib.rs index acc9157..e4958ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ pub(crate) fn from_digest(digest: D) -> F { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Error { + Coordinates, Verify, BadDigestOutput, } @@ -26,6 +27,7 @@ pub enum Error { impl core::fmt::Display for Error { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match *self { + Error::Coordinates => write!(f, "Could not obtain the coordinates of a point"), Error::Verify => write!(f, "Signature verification failed"), Error::BadDigestOutput => write!(f, "Bad digest output size"), } @@ -68,7 +70,7 @@ mod test { let signing_key = SigningKey::::generate::(&mut OsRng).unwrap(); let message_raw = b"xxx yyy <<< zzz >>> bunny"; let message = TE::BaseField::from_le_bytes_mod_order(message_raw); - let signature = signing_key.sign::(&poseidon, &message); + let signature = signing_key.sign::(&poseidon, &message).unwrap(); let public_key = signing_key.public_key(); public_key.verify(&poseidon, &message, &signature).unwrap(); } diff --git a/src/signature.rs b/src/signature.rs index 3cc1819..65ea776 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -6,8 +6,8 @@ use ark_serialize::CanonicalSerialize; /// `SignatureComponents` contains the realized parts of a signature #[derive(Copy, Clone, Debug, CanonicalSerialize, CanonicalDeserialize)] pub struct Signature { - pub r: Affine, - pub s: TE::ScalarField, + r: Affine, + s: TE::ScalarField, } impl Signature {