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}