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}