1use alloc::vec::Vec;
2
3use rand::{CryptoRng, Rng};
4
5use crate::crypto::dsa::{ecdsa_k256_keccak, falcon512_rpo};
6use crate::errors::AuthSchemeError;
7use crate::utils::serde::{
8 ByteReader,
9 ByteWriter,
10 Deserializable,
11 DeserializationError,
12 Serializable,
13};
14use crate::{Felt, Hasher, Word};
15
16const FALCON_512_RPO: u8 = 2;
21const ECDSA_K256_KECCAK: u8 = 1;
22
23#[derive(Copy, Clone, Debug, PartialEq, Eq)]
26#[non_exhaustive]
27#[repr(u8)]
28pub enum AuthScheme {
29 Falcon512Rpo = FALCON_512_RPO,
35
36 EcdsaK256Keccak = ECDSA_K256_KECCAK,
38}
39
40impl AuthScheme {
41 pub fn as_u8(&self) -> u8 {
43 *self as u8
44 }
45}
46
47impl core::fmt::Display for AuthScheme {
48 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
49 match self {
50 Self::Falcon512Rpo => f.write_str("Falcon512Rpo"),
51 Self::EcdsaK256Keccak => f.write_str("EcdsaK256Keccak"),
52 }
53 }
54}
55
56impl TryFrom<u8> for AuthScheme {
57 type Error = AuthSchemeError;
58
59 fn try_from(value: u8) -> Result<Self, Self::Error> {
60 match value {
61 FALCON_512_RPO => Ok(Self::Falcon512Rpo),
62 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
63 value => Err(AuthSchemeError::InvalidAuthSchemeIdentifier(value)),
64 }
65 }
66}
67
68impl Serializable for AuthScheme {
69 fn write_into<W: ByteWriter>(&self, target: &mut W) {
70 target.write_u8(*self as u8);
71 }
72
73 fn get_size_hint(&self) -> usize {
74 size_of::<u8>()
76 }
77}
78
79impl Deserializable for AuthScheme {
80 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
81 match source.read_u8()? {
82 FALCON_512_RPO => Ok(Self::Falcon512Rpo),
83 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
84 value => Err(DeserializationError::InvalidValue(format!(
85 "auth scheme identifier `{value}` is not valid"
86 ))),
87 }
88 }
89}
90
91#[derive(Clone, Debug, PartialEq, Eq)]
96#[non_exhaustive]
97#[repr(u8)]
98pub enum AuthSecretKey {
99 Falcon512Rpo(falcon512_rpo::SecretKey) = FALCON_512_RPO,
100 EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey) = ECDSA_K256_KECCAK,
101}
102
103impl AuthSecretKey {
104 #[cfg(feature = "std")]
106 pub fn new_falcon512_rpo() -> Self {
107 Self::Falcon512Rpo(falcon512_rpo::SecretKey::new())
108 }
109
110 pub fn new_falcon512_rpo_with_rng<R: Rng>(rng: &mut R) -> Self {
112 Self::Falcon512Rpo(falcon512_rpo::SecretKey::with_rng(rng))
113 }
114
115 #[cfg(feature = "std")]
117 pub fn new_ecdsa_k256_keccak() -> Self {
118 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey::new())
119 }
120
121 pub fn new_ecdsa_k256_keccak_with_rng<R: Rng + CryptoRng>(rng: &mut R) -> Self {
123 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey::with_rng(rng))
124 }
125
126 pub fn with_scheme_and_rng<R: Rng + CryptoRng>(
131 scheme: AuthScheme,
132 rng: &mut R,
133 ) -> Result<Self, AuthSchemeError> {
134 match scheme {
135 AuthScheme::Falcon512Rpo => Ok(Self::new_falcon512_rpo_with_rng(rng)),
136 AuthScheme::EcdsaK256Keccak => Ok(Self::new_ecdsa_k256_keccak_with_rng(rng)),
137 }
138 }
139
140 #[cfg(feature = "std")]
145 pub fn with_scheme(scheme: AuthScheme) -> Result<Self, AuthSchemeError> {
146 match scheme {
147 AuthScheme::Falcon512Rpo => Ok(Self::new_falcon512_rpo()),
148 AuthScheme::EcdsaK256Keccak => Ok(Self::new_ecdsa_k256_keccak()),
149 }
150 }
151
152 pub fn auth_scheme(&self) -> AuthScheme {
154 match self {
155 AuthSecretKey::Falcon512Rpo(_) => AuthScheme::Falcon512Rpo,
156 AuthSecretKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
157 }
158 }
159
160 pub fn public_key(&self) -> PublicKey {
162 match self {
163 AuthSecretKey::Falcon512Rpo(key) => PublicKey::Falcon512Rpo(key.public_key()),
164 AuthSecretKey::EcdsaK256Keccak(key) => PublicKey::EcdsaK256Keccak(key.public_key()),
165 }
166 }
167
168 pub fn sign(&self, message: Word) -> Signature {
170 match self {
171 AuthSecretKey::Falcon512Rpo(key) => Signature::Falcon512Rpo(key.sign(message)),
172 AuthSecretKey::EcdsaK256Keccak(key) => Signature::EcdsaK256Keccak(key.sign(message)),
173 }
174 }
175}
176
177impl Serializable for AuthSecretKey {
178 fn write_into<W: ByteWriter>(&self, target: &mut W) {
179 self.auth_scheme().write_into(target);
180 match self {
181 AuthSecretKey::Falcon512Rpo(key) => key.write_into(target),
182 AuthSecretKey::EcdsaK256Keccak(key) => key.write_into(target),
183 }
184 }
185}
186
187impl Deserializable for AuthSecretKey {
188 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
189 match source.read::<AuthScheme>()? {
190 AuthScheme::Falcon512Rpo => {
191 let secret_key = falcon512_rpo::SecretKey::read_from(source)?;
192 Ok(AuthSecretKey::Falcon512Rpo(secret_key))
193 },
194 AuthScheme::EcdsaK256Keccak => {
195 let secret_key = ecdsa_k256_keccak::SecretKey::read_from(source)?;
196 Ok(AuthSecretKey::EcdsaK256Keccak(secret_key))
197 },
198 }
199 }
200}
201
202#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
207pub struct PublicKeyCommitment(Word);
208
209impl core::fmt::Display for PublicKeyCommitment {
210 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
211 write!(f, "{}", self.0)
212 }
213}
214
215impl From<falcon512_rpo::PublicKey> for PublicKeyCommitment {
216 fn from(value: falcon512_rpo::PublicKey) -> Self {
217 Self(value.to_commitment())
218 }
219}
220
221impl From<PublicKeyCommitment> for Word {
222 fn from(value: PublicKeyCommitment) -> Self {
223 value.0
224 }
225}
226
227impl From<Word> for PublicKeyCommitment {
228 fn from(value: Word) -> Self {
229 Self(value)
230 }
231}
232
233#[derive(Clone, Debug)]
235#[non_exhaustive]
236pub enum PublicKey {
237 Falcon512Rpo(falcon512_rpo::PublicKey),
238 EcdsaK256Keccak(ecdsa_k256_keccak::PublicKey),
239}
240
241impl PublicKey {
242 pub fn auth_scheme(&self) -> AuthScheme {
244 match self {
245 PublicKey::Falcon512Rpo(_) => AuthScheme::Falcon512Rpo,
246 PublicKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
247 }
248 }
249
250 pub fn to_commitment(&self) -> PublicKeyCommitment {
252 match self {
253 PublicKey::Falcon512Rpo(key) => key.to_commitment().into(),
254 PublicKey::EcdsaK256Keccak(key) => key.to_commitment().into(),
255 }
256 }
257
258 pub fn verify(&self, message: Word, signature: Signature) -> bool {
260 match (self, signature) {
261 (PublicKey::Falcon512Rpo(key), Signature::Falcon512Rpo(sig)) => {
262 key.verify(message, &sig)
263 },
264 (PublicKey::EcdsaK256Keccak(key), Signature::EcdsaK256Keccak(sig)) => {
265 key.verify(message, &sig)
266 },
267 _ => false,
268 }
269 }
270}
271
272impl Serializable for PublicKey {
273 fn write_into<W: ByteWriter>(&self, target: &mut W) {
274 self.auth_scheme().write_into(target);
275 match self {
276 PublicKey::Falcon512Rpo(pub_key) => pub_key.write_into(target),
277 PublicKey::EcdsaK256Keccak(pub_key) => pub_key.write_into(target),
278 }
279 }
280}
281
282impl Deserializable for PublicKey {
283 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
284 match source.read::<AuthScheme>()? {
285 AuthScheme::Falcon512Rpo => {
286 let pub_key = falcon512_rpo::PublicKey::read_from(source)?;
287 Ok(PublicKey::Falcon512Rpo(pub_key))
288 },
289 AuthScheme::EcdsaK256Keccak => {
290 let pub_key = ecdsa_k256_keccak::PublicKey::read_from(source)?;
291 Ok(PublicKey::EcdsaK256Keccak(pub_key))
292 },
293 }
294 }
295}
296
297#[derive(Clone, Debug)]
316#[repr(u8)]
317pub enum Signature {
318 Falcon512Rpo(falcon512_rpo::Signature) = FALCON_512_RPO,
319 EcdsaK256Keccak(ecdsa_k256_keccak::Signature) = ECDSA_K256_KECCAK,
320}
321
322impl Signature {
323 pub fn auth_scheme(&self) -> AuthScheme {
325 match self {
326 Signature::Falcon512Rpo(_) => AuthScheme::Falcon512Rpo,
327 Signature::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
328 }
329 }
330
331 pub fn to_prepared_signature(&self, msg: Word) -> Vec<Felt> {
337 let mut result = match self {
340 Signature::Falcon512Rpo(sig) => prepare_falcon512_rpo_signature(sig),
341 Signature::EcdsaK256Keccak(sig) => {
342 let pk = ecdsa_k256_keccak::PublicKey::recover_from(msg, sig)
343 .expect("inferring public key from signature and message should succeed");
344 miden_core_lib::dsa::ecdsa_k256_keccak::encode_signature(&pk, sig)
345 },
346 };
347
348 result.reverse();
351 result
352 }
353}
354
355impl From<falcon512_rpo::Signature> for Signature {
356 fn from(signature: falcon512_rpo::Signature) -> Self {
357 Signature::Falcon512Rpo(signature)
358 }
359}
360
361impl Serializable for Signature {
362 fn write_into<W: ByteWriter>(&self, target: &mut W) {
363 self.auth_scheme().write_into(target);
364 match self {
365 Signature::Falcon512Rpo(signature) => signature.write_into(target),
366 Signature::EcdsaK256Keccak(signature) => signature.write_into(target),
367 }
368 }
369}
370
371impl Deserializable for Signature {
372 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
373 match source.read::<AuthScheme>()? {
374 AuthScheme::Falcon512Rpo => {
375 let signature = falcon512_rpo::Signature::read_from(source)?;
376 Ok(Signature::Falcon512Rpo(signature))
377 },
378 AuthScheme::EcdsaK256Keccak => {
379 let signature = ecdsa_k256_keccak::Signature::read_from(source)?;
380 Ok(Signature::EcdsaK256Keccak(signature))
381 },
382 }
383 }
384}
385
386fn prepare_falcon512_rpo_signature(sig: &falcon512_rpo::Signature) -> Vec<Felt> {
401 use falcon512_rpo::Polynomial;
402
403 let nonce = sig.nonce();
406 let s2 = sig.sig_poly();
408 let h = sig.public_key();
411 let pi = Polynomial::mul_modulo_p(h, s2);
415
416 let mut polynomials: Vec<Felt> =
422 h.coefficients.iter().map(|a| Felt::from(a.value() as u32)).collect();
423 polynomials.extend(s2.coefficients.iter().map(|a| Felt::from(a.value() as u32)));
424 polynomials.extend(pi.iter().map(|a| Felt::new(*a)));
425
426 let digest_polynomials = Hasher::hash_elements(&polynomials);
427 let challenge = (digest_polynomials[0], digest_polynomials[1]);
428
429 let mut result: Vec<Felt> = vec![challenge.0, challenge.1];
430 result.extend_from_slice(&polynomials);
431 result.extend_from_slice(&nonce.to_elements());
432
433 result
434}