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