1use alloc::vec::Vec;
2
3use rand::{CryptoRng, Rng};
4
5use crate::crypto::dsa::{ecdsa_k256_keccak, rpo_falcon512};
6use crate::utils::serde::{
7 ByteReader,
8 ByteWriter,
9 Deserializable,
10 DeserializationError,
11 Serializable,
12};
13use crate::{AuthSchemeError, Felt, Hasher, Word};
14
15const RPO_FALCON_512: u8 = 0;
20const ECDSA_K256_KECCAK: u8 = 1;
21
22#[derive(Copy, Clone, Debug, PartialEq, Eq)]
25#[non_exhaustive]
26#[repr(u8)]
27pub enum AuthScheme {
28 RpoFalcon512 = RPO_FALCON_512,
34
35 EcdsaK256Keccak = ECDSA_K256_KECCAK,
37}
38
39impl AuthScheme {
40 pub fn as_u8(&self) -> u8 {
42 *self as u8
43 }
44}
45
46impl core::fmt::Display for AuthScheme {
47 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
48 match self {
49 Self::RpoFalcon512 => f.write_str("RpoFalcon512"),
50 Self::EcdsaK256Keccak => f.write_str("EcdsaK256Keccak"),
51 }
52 }
53}
54
55impl TryFrom<u8> for AuthScheme {
56 type Error = AuthSchemeError;
57
58 fn try_from(value: u8) -> Result<Self, Self::Error> {
59 match value {
60 RPO_FALCON_512 => Ok(Self::RpoFalcon512),
61 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
62 value => Err(AuthSchemeError::InvalidAuthSchemeIdentifier(value)),
63 }
64 }
65}
66
67impl Serializable for AuthScheme {
68 fn write_into<W: ByteWriter>(&self, target: &mut W) {
69 target.write_u8(*self as u8);
70 }
71
72 fn get_size_hint(&self) -> usize {
73 size_of::<u8>()
75 }
76}
77
78impl Deserializable for AuthScheme {
79 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
80 match source.read_u8()? {
81 RPO_FALCON_512 => Ok(Self::RpoFalcon512),
82 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
83 value => Err(DeserializationError::InvalidValue(format!(
84 "auth scheme identifier `{value}` is not valid"
85 ))),
86 }
87 }
88}
89
90#[derive(Clone, Debug, PartialEq, Eq)]
95#[non_exhaustive]
96#[repr(u8)]
97pub enum AuthSecretKey {
98 RpoFalcon512(rpo_falcon512::SecretKey) = RPO_FALCON_512,
99 EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey) = ECDSA_K256_KECCAK,
100}
101
102impl AuthSecretKey {
103 #[cfg(feature = "std")]
105 pub fn new_rpo_falcon512() -> Self {
106 Self::RpoFalcon512(rpo_falcon512::SecretKey::new())
107 }
108
109 pub fn new_rpo_falcon512_with_rng<R: Rng>(rng: &mut R) -> Self {
111 Self::RpoFalcon512(rpo_falcon512::SecretKey::with_rng(rng))
112 }
113
114 #[cfg(feature = "std")]
116 pub fn new_ecdsa_k256_keccak() -> Self {
117 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey::new())
118 }
119
120 pub fn new_ecdsa_k256_keccak_with_rng<R: Rng + CryptoRng>(rng: &mut R) -> Self {
122 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey::with_rng(rng))
123 }
124
125 pub fn auth_scheme(&self) -> AuthScheme {
127 match self {
128 AuthSecretKey::RpoFalcon512(_) => AuthScheme::RpoFalcon512,
129 AuthSecretKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
130 }
131 }
132
133 pub fn public_key(&self) -> PublicKey {
135 match self {
136 AuthSecretKey::RpoFalcon512(key) => PublicKey::RpoFalcon512(key.public_key()),
137 AuthSecretKey::EcdsaK256Keccak(key) => PublicKey::EcdsaK256Keccak(key.public_key()),
138 }
139 }
140
141 pub fn sign(&self, message: Word) -> Signature {
143 match self {
144 AuthSecretKey::RpoFalcon512(key) => Signature::RpoFalcon512(key.sign(message)),
145 AuthSecretKey::EcdsaK256Keccak(key) => Signature::EcdsaK256Keccak(key.sign(message)),
146 }
147 }
148}
149
150impl Serializable for AuthSecretKey {
151 fn write_into<W: ByteWriter>(&self, target: &mut W) {
152 self.auth_scheme().write_into(target);
153 match self {
154 AuthSecretKey::RpoFalcon512(key) => key.write_into(target),
155 AuthSecretKey::EcdsaK256Keccak(key) => key.write_into(target),
156 }
157 }
158}
159
160impl Deserializable for AuthSecretKey {
161 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
162 match source.read::<AuthScheme>()? {
163 AuthScheme::RpoFalcon512 => {
164 let secret_key = rpo_falcon512::SecretKey::read_from(source)?;
165 Ok(AuthSecretKey::RpoFalcon512(secret_key))
166 },
167 AuthScheme::EcdsaK256Keccak => {
168 let secret_key = ecdsa_k256_keccak::SecretKey::read_from(source)?;
169 Ok(AuthSecretKey::EcdsaK256Keccak(secret_key))
170 },
171 }
172 }
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
180pub struct PublicKeyCommitment(Word);
181
182impl core::fmt::Display for PublicKeyCommitment {
183 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
184 write!(f, "{}", self.0)
185 }
186}
187
188impl From<rpo_falcon512::PublicKey> for PublicKeyCommitment {
189 fn from(value: rpo_falcon512::PublicKey) -> Self {
190 Self(value.to_commitment())
191 }
192}
193
194impl From<PublicKeyCommitment> for Word {
195 fn from(value: PublicKeyCommitment) -> Self {
196 value.0
197 }
198}
199
200impl From<Word> for PublicKeyCommitment {
201 fn from(value: Word) -> Self {
202 Self(value)
203 }
204}
205
206#[derive(Clone, Debug)]
208#[non_exhaustive]
209pub enum PublicKey {
210 RpoFalcon512(rpo_falcon512::PublicKey),
211 EcdsaK256Keccak(ecdsa_k256_keccak::PublicKey),
212}
213
214impl PublicKey {
215 pub fn auth_scheme(&self) -> AuthScheme {
217 match self {
218 PublicKey::RpoFalcon512(_) => AuthScheme::RpoFalcon512,
219 PublicKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
220 }
221 }
222
223 pub fn to_commitment(&self) -> PublicKeyCommitment {
225 match self {
226 PublicKey::RpoFalcon512(key) => key.to_commitment().into(),
227 PublicKey::EcdsaK256Keccak(key) => key.to_commitment().into(),
228 }
229 }
230
231 pub fn verify(&self, message: Word, signature: Signature) -> bool {
233 match (self, signature) {
234 (PublicKey::RpoFalcon512(key), Signature::RpoFalcon512(sig)) => {
235 key.verify(message, &sig)
236 },
237 (PublicKey::EcdsaK256Keccak(key), Signature::EcdsaK256Keccak(sig)) => {
238 key.verify(message, &sig)
239 },
240 _ => false,
241 }
242 }
243}
244
245impl Serializable for PublicKey {
246 fn write_into<W: ByteWriter>(&self, target: &mut W) {
247 self.auth_scheme().write_into(target);
248 match self {
249 PublicKey::RpoFalcon512(pub_key) => pub_key.write_into(target),
250 PublicKey::EcdsaK256Keccak(pub_key) => pub_key.write_into(target),
251 }
252 }
253}
254
255impl Deserializable for PublicKey {
256 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
257 match source.read::<AuthScheme>()? {
258 AuthScheme::RpoFalcon512 => {
259 let pub_key = rpo_falcon512::PublicKey::read_from(source)?;
260 Ok(PublicKey::RpoFalcon512(pub_key))
261 },
262 AuthScheme::EcdsaK256Keccak => {
263 let pub_key = ecdsa_k256_keccak::PublicKey::read_from(source)?;
264 Ok(PublicKey::EcdsaK256Keccak(pub_key))
265 },
266 }
267 }
268}
269
270#[derive(Clone, Debug)]
289#[repr(u8)]
290pub enum Signature {
291 RpoFalcon512(rpo_falcon512::Signature) = RPO_FALCON_512,
292 EcdsaK256Keccak(ecdsa_k256_keccak::Signature) = ECDSA_K256_KECCAK,
293}
294
295impl Signature {
296 pub fn auth_scheme(&self) -> AuthScheme {
298 match self {
299 Signature::RpoFalcon512(_) => AuthScheme::RpoFalcon512,
300 Signature::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
301 }
302 }
303
304 pub fn to_prepared_signature(&self) -> Vec<Felt> {
307 match self {
308 Signature::RpoFalcon512(sig) => prepare_rpo_falcon512_signature(sig),
309 Signature::EcdsaK256Keccak(sig) => prepare_ecdsa_k256_keccak_signature(sig),
310 }
311 }
312}
313
314impl From<rpo_falcon512::Signature> for Signature {
315 fn from(signature: rpo_falcon512::Signature) -> Self {
316 Signature::RpoFalcon512(signature)
317 }
318}
319
320impl Serializable for Signature {
321 fn write_into<W: ByteWriter>(&self, target: &mut W) {
322 self.auth_scheme().write_into(target);
323 match self {
324 Signature::RpoFalcon512(signature) => signature.write_into(target),
325 Signature::EcdsaK256Keccak(signature) => signature.write_into(target),
326 }
327 }
328}
329
330impl Deserializable for Signature {
331 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
332 match source.read::<AuthScheme>()? {
333 AuthScheme::RpoFalcon512 => {
334 let signature = rpo_falcon512::Signature::read_from(source)?;
335 Ok(Signature::RpoFalcon512(signature))
336 },
337 AuthScheme::EcdsaK256Keccak => {
338 let signature = ecdsa_k256_keccak::Signature::read_from(source)?;
339 Ok(Signature::EcdsaK256Keccak(signature))
340 },
341 }
342 }
343}
344
345fn prepare_rpo_falcon512_signature(sig: &rpo_falcon512::Signature) -> Vec<Felt> {
360 use rpo_falcon512::Polynomial;
361
362 let nonce = sig.nonce();
365 let s2 = sig.sig_poly();
367 let h = sig.public_key();
370 let pi = Polynomial::mul_modulo_p(h, s2);
374
375 let mut polynomials: Vec<Felt> =
381 h.coefficients.iter().map(|a| Felt::from(a.value() as u32)).collect();
382 polynomials.extend(s2.coefficients.iter().map(|a| Felt::from(a.value() as u32)));
383 polynomials.extend(pi.iter().map(|a| Felt::new(*a)));
384
385 let digest_polynomials = Hasher::hash_elements(&polynomials);
386 let challenge = (digest_polynomials[0], digest_polynomials[1]);
387
388 let mut result: Vec<Felt> = vec![challenge.0, challenge.1];
389 result.extend_from_slice(&polynomials);
390 result.extend_from_slice(&nonce.to_elements());
391
392 result.reverse();
393 result
394}
395
396fn prepare_ecdsa_k256_keccak_signature(sig: &ecdsa_k256_keccak::Signature) -> Vec<Felt> {
400 const BYTES_PER_U32: usize = size_of::<u32>();
401
402 let bytes = sig.to_bytes();
403 bytes
404 .chunks(BYTES_PER_U32)
405 .map(|chunk| {
406 let mut packed = [0u8; BYTES_PER_U32];
408 packed[..chunk.len()].copy_from_slice(chunk);
409 Felt::from(u32::from_le_bytes(packed))
410 })
411 .collect()
412}