arnaucube
arnaucube/arkeddsaPublic Self-hosted repository
arkeddsa/src/eddsa.rs
src/eddsa.rsRaw
  1use crate::{signature::Signature, Error};
  2use ark_crypto_primitives::sponge::{
  3    poseidon::{PoseidonConfig, PoseidonSponge},
  4    Absorb, CryptographicSponge,
  5};
  6use ark_ec::{
  7    twisted_edwards::{Affine, TECurveConfig},
  8    AffineRepr, CurveGroup,
  9};
 10use ark_ff::{BigInteger, PrimeField};
 11use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
 12use digest::Digest;
 13use digest::OutputSizeUser;
 14use rand_core::CryptoRngCore;
 15
 16fn prune_buffer<F: PrimeField>(mut bytes: [u8; 32]) -> F {
 17    bytes[0] &= 0b1111_1000;
 18    bytes[31] &= 0b0111_1111;
 19    bytes[31] |= 0b0100_0000;
 20    F::from_le_bytes_mod_order(&bytes[..])
 21}
 22
 23#[derive(Copy, Clone, Debug)]
 24/// EdDSA secret key is 32 byte data
 25pub struct SecretKey([u8; 32]);
 26
 27impl SecretKey {
 28    fn expand<F: PrimeField, D: Digest>(&self) -> (F, [u8; 32]) {
 29        let hash = D::new().chain_update(self.0).finalize();
 30        let (buffer, hash_prefix) = hash.split_at(32);
 31        let buffer: [u8; 32] = buffer.try_into().unwrap();
 32        let hash_prefix: [u8; 32] = hash_prefix.try_into().unwrap();
 33        let x = prune_buffer(buffer);
 34        (x, hash_prefix)
 35    }
 36
 37    pub fn to_bytes(&self) -> [u8; 32] {
 38        self.0
 39    }
 40
 41    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
 42        Self(bytes.clone())
 43    }
 44}
 45
 46/// `PublicKey` is EdDSA signature verification key
 47#[derive(Copy, Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize)]
 48pub struct PublicKey<C: CurveGroup>(pub C::Affine);
 49
 50impl<C: CurveGroup> PublicKey<C> {
 51    pub fn xy(&self) -> Result<(C::BaseField, C::BaseField), Error> {
 52        self.as_ref().xy().ok_or(Error::Coordinates)
 53    }
 54
 55    pub fn to_bytes(&self) -> Vec<u8> {
 56        let mut bytes = Vec::new();
 57        self.serialize_compressed(&mut bytes).unwrap();
 58        bytes
 59    }
 60
 61    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Box<dyn ark_std::error::Error>> {
 62        let point = C::Affine::deserialize_compressed(bytes)?;
 63        Ok(Self(point))
 64    }
 65}
 66
 67// impl<C: CurveGroup> From<C::Affine> for PublicKey<C> {
 68//     fn from(affine: C::Affine) -> Self {
 69//         Self(affine)
 70//     }
 71// }
 72// impl<C: CurveGroup> From<C> for PublicKey<C> {
 73//     fn from(proj: C) -> Self {
 74//         PublicKey(proj.into_affine())
 75//     }
 76// }
 77// impl<C: CurveGroup> From<C::Affine> for PublicKey<C> {
 78//     fn from(affine: C::Affine) -> Self {
 79//         PublicKey(affine)
 80//     }
 81// }
 82
 83impl<C: CurveGroup> AsRef<C::Affine> for PublicKey<C> {
 84    fn as_ref(&self) -> &C::Affine {
 85        &self.0
 86    }
 87}
 88
 89#[derive(Copy, Clone, Debug)]
 90/// `SigningKey` produces EdDSA signatures for given message
 91pub struct SigningKey<C: CurveGroup> {
 92    secret_key: SecretKey,
 93    public_key: PublicKey<C>,
 94}
 95
 96impl<C: CurveGroup + Clone> SigningKey<C>
 97where
 98    C::BaseField: PrimeField + Absorb,
 99{
100    pub fn new<D: Digest>(secret_key: &SecretKey) -> Result<Self, Error> {
101        (<D as OutputSizeUser>::output_size() == 64)
102            .then_some(())
103            .ok_or(Error::BadDigestOutput)?;
104
105        let (x, _) = secret_key.expand::<C::ScalarField, D>();
106        let public_key: C::Affine = (C::Affine::generator() * x).into();
107        let signing_key = Self {
108            secret_key: *secret_key,
109            public_key: PublicKey(public_key),
110        };
111
112        Ok(signing_key)
113    }
114
115    pub fn from_bytes<D: Digest>(bytes: &[u8; 32]) -> Result<Self, Error> {
116        let secret_key = SecretKey::from_bytes(bytes);
117        Self::new::<D>(&secret_key)
118    }
119
120    pub fn to_bytes(&self) -> [u8; 32] {
121        self.secret_key.to_bytes()
122    }
123
124    pub fn generate<D: Digest>(rng: &mut impl CryptoRngCore) -> Result<Self, Error> {
125        let mut secret_key = SecretKey([0; 32]);
126        rng.fill_bytes(&mut secret_key.0);
127        Self::new::<D>(&secret_key)
128    }
129
130    pub fn public_key(&self) -> &PublicKey<C> {
131        &self.public_key
132    }
133
134    pub fn sign<D: Digest>(
135        &self,
136        poseidon: &PoseidonConfig<C::BaseField>,
137        message: &C::BaseField,
138    ) -> Result<Signature<C>, Error> {
139        let (x, prefix) = self.secret_key.expand::<C::ScalarField, D>();
140
141        let mut h = D::new();
142        h.update(prefix);
143        let msg_bytes = message.into_bigint().to_bytes_le();
144        let mut msg32: [u8; 32] = [0; 32];
145        msg32[..msg_bytes.len()].copy_from_slice(&msg_bytes[..]);
146        h.update(msg32);
147
148        let r: C::ScalarField = crate::from_digest(h);
149        let sig_r: C::Affine = (C::Affine::generator() * r).into();
150
151        let mut poseidon = PoseidonSponge::new(poseidon);
152
153        let (sig_r_x, sig_r_y) = sig_r.xy().ok_or(Error::Coordinates)?;
154        poseidon.absorb(&sig_r_x);
155        poseidon.absorb(&sig_r_y);
156        let (pk_x, pk_y) = self.public_key.0.xy().ok_or(Error::Coordinates)?;
157        poseidon.absorb(&pk_x);
158        poseidon.absorb(&pk_y);
159        poseidon.absorb(message);
160
161        // use poseidon over Fq, so that it can be done too in-circuit
162        let k = poseidon.squeeze_field_elements::<C::BaseField>(1);
163        let k = k.first().ok_or(Error::BadDigestOutput)?;
164        let k = C::ScalarField::from_le_bytes_mod_order(&k.into_bigint().to_bytes_le());
165
166        let sig_s = (x * k) + r;
167
168        Ok(Signature::new(sig_r, sig_s))
169    }
170}
171
172impl<C: CurveGroup> SigningKey<C> {
173    pub fn shared_key<D: Digest>(&self, recipient: &PublicKey<C>) -> [u8; 32] {
174        let (x, _) = self.secret_key.expand::<C::ScalarField, D>();
175        let shared_key: C::Affine = (recipient.0 * x).into();
176        let mut data = Vec::new();
177        shared_key.serialize_compressed(&mut data).unwrap();
178        data[00..32].try_into().unwrap()
179    }
180}
181
182impl<C: CurveGroup + Clone> PublicKey<C>
183where
184    C::BaseField: PrimeField + Absorb,
185{
186    pub fn verify(
187        &self,
188        poseidon: &PoseidonConfig<C::BaseField>,
189        message: &C::BaseField,
190        signature: &Signature<C>,
191    ) -> Result<(), Error> {
192        let mut poseidon = PoseidonSponge::new(poseidon);
193
194        let (sig_r_x, sig_r_y) = signature.r().xy().ok_or(Error::Coordinates)?;
195        poseidon.absorb(&sig_r_x);
196        poseidon.absorb(&sig_r_y);
197        let (pk_x, pk_y) = self.0.xy().ok_or(Error::Coordinates)?;
198        poseidon.absorb(&pk_x);
199        poseidon.absorb(&pk_y);
200        poseidon.absorb(message);
201
202        // use poseidon over Fq, so that it can be done too in-circuit
203        let k = poseidon.squeeze_field_elements::<C::BaseField>(1);
204        let k = k.first().ok_or(Error::BadDigestOutput)?;
205
206        let kx_b = self.0.mul_bigint(k.into_bigint());
207        let s_b = C::Affine::generator() * signature.s();
208        let r_rec: C::Affine = (s_b - kx_b).into();
209
210        (signature.r() == &r_rec).then_some(()).ok_or(Error::Verify)
211    }
212}