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 = 0;
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 auth_scheme(&self) -> AuthScheme {
128 match self {
129 AuthSecretKey::Falcon512Rpo(_) => AuthScheme::Falcon512Rpo,
130 AuthSecretKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
131 }
132 }
133
134 pub fn public_key(&self) -> PublicKey {
136 match self {
137 AuthSecretKey::Falcon512Rpo(key) => PublicKey::Falcon512Rpo(key.public_key()),
138 AuthSecretKey::EcdsaK256Keccak(key) => PublicKey::EcdsaK256Keccak(key.public_key()),
139 }
140 }
141
142 pub fn sign(&self, message: Word) -> Signature {
144 match self {
145 AuthSecretKey::Falcon512Rpo(key) => Signature::Falcon512Rpo(key.sign(message)),
146 AuthSecretKey::EcdsaK256Keccak(key) => Signature::EcdsaK256Keccak(key.sign(message)),
147 }
148 }
149}
150
151impl Serializable for AuthSecretKey {
152 fn write_into<W: ByteWriter>(&self, target: &mut W) {
153 self.auth_scheme().write_into(target);
154 match self {
155 AuthSecretKey::Falcon512Rpo(key) => key.write_into(target),
156 AuthSecretKey::EcdsaK256Keccak(key) => key.write_into(target),
157 }
158 }
159}
160
161impl Deserializable for AuthSecretKey {
162 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
163 match source.read::<AuthScheme>()? {
164 AuthScheme::Falcon512Rpo => {
165 let secret_key = falcon512_rpo::SecretKey::read_from(source)?;
166 Ok(AuthSecretKey::Falcon512Rpo(secret_key))
167 },
168 AuthScheme::EcdsaK256Keccak => {
169 let secret_key = ecdsa_k256_keccak::SecretKey::read_from(source)?;
170 Ok(AuthSecretKey::EcdsaK256Keccak(secret_key))
171 },
172 }
173 }
174}
175
176#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
181pub struct PublicKeyCommitment(Word);
182
183impl core::fmt::Display for PublicKeyCommitment {
184 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
185 write!(f, "{}", self.0)
186 }
187}
188
189impl From<falcon512_rpo::PublicKey> for PublicKeyCommitment {
190 fn from(value: falcon512_rpo::PublicKey) -> Self {
191 Self(value.to_commitment())
192 }
193}
194
195impl From<PublicKeyCommitment> for Word {
196 fn from(value: PublicKeyCommitment) -> Self {
197 value.0
198 }
199}
200
201impl From<Word> for PublicKeyCommitment {
202 fn from(value: Word) -> Self {
203 Self(value)
204 }
205}
206
207#[derive(Clone, Debug)]
209#[non_exhaustive]
210pub enum PublicKey {
211 Falcon512Rpo(falcon512_rpo::PublicKey),
212 EcdsaK256Keccak(ecdsa_k256_keccak::PublicKey),
213}
214
215impl PublicKey {
216 pub fn auth_scheme(&self) -> AuthScheme {
218 match self {
219 PublicKey::Falcon512Rpo(_) => AuthScheme::Falcon512Rpo,
220 PublicKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
221 }
222 }
223
224 pub fn to_commitment(&self) -> PublicKeyCommitment {
226 match self {
227 PublicKey::Falcon512Rpo(key) => key.to_commitment().into(),
228 PublicKey::EcdsaK256Keccak(key) => key.to_commitment().into(),
229 }
230 }
231
232 pub fn verify(&self, message: Word, signature: Signature) -> bool {
234 match (self, signature) {
235 (PublicKey::Falcon512Rpo(key), Signature::Falcon512Rpo(sig)) => {
236 key.verify(message, &sig)
237 },
238 (PublicKey::EcdsaK256Keccak(key), Signature::EcdsaK256Keccak(sig)) => {
239 key.verify(message, &sig)
240 },
241 _ => false,
242 }
243 }
244}
245
246impl Serializable for PublicKey {
247 fn write_into<W: ByteWriter>(&self, target: &mut W) {
248 self.auth_scheme().write_into(target);
249 match self {
250 PublicKey::Falcon512Rpo(pub_key) => pub_key.write_into(target),
251 PublicKey::EcdsaK256Keccak(pub_key) => pub_key.write_into(target),
252 }
253 }
254}
255
256impl Deserializable for PublicKey {
257 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
258 match source.read::<AuthScheme>()? {
259 AuthScheme::Falcon512Rpo => {
260 let pub_key = falcon512_rpo::PublicKey::read_from(source)?;
261 Ok(PublicKey::Falcon512Rpo(pub_key))
262 },
263 AuthScheme::EcdsaK256Keccak => {
264 let pub_key = ecdsa_k256_keccak::PublicKey::read_from(source)?;
265 Ok(PublicKey::EcdsaK256Keccak(pub_key))
266 },
267 }
268 }
269}
270
271#[derive(Clone, Debug)]
290#[repr(u8)]
291pub enum Signature {
292 Falcon512Rpo(falcon512_rpo::Signature) = FALCON_512_RPO,
293 EcdsaK256Keccak(ecdsa_k256_keccak::Signature) = ECDSA_K256_KECCAK,
294}
295
296impl Signature {
297 pub fn auth_scheme(&self) -> AuthScheme {
299 match self {
300 Signature::Falcon512Rpo(_) => AuthScheme::Falcon512Rpo,
301 Signature::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
302 }
303 }
304
305 pub fn to_prepared_signature(&self, msg: Word) -> Vec<Felt> {
311 let mut result = match self {
314 Signature::Falcon512Rpo(sig) => prepare_falcon512_rpo_signature(sig),
315 Signature::EcdsaK256Keccak(sig) => {
316 let pk = ecdsa_k256_keccak::PublicKey::recover_from(msg, sig)
317 .expect("inferring public key from signature and message should succeed");
318 miden_core_lib::dsa::ecdsa_k256_keccak::encode_signature(&pk, sig)
319 },
320 };
321
322 result.reverse();
325 result
326 }
327}
328
329impl From<falcon512_rpo::Signature> for Signature {
330 fn from(signature: falcon512_rpo::Signature) -> Self {
331 Signature::Falcon512Rpo(signature)
332 }
333}
334
335impl Serializable for Signature {
336 fn write_into<W: ByteWriter>(&self, target: &mut W) {
337 self.auth_scheme().write_into(target);
338 match self {
339 Signature::Falcon512Rpo(signature) => signature.write_into(target),
340 Signature::EcdsaK256Keccak(signature) => signature.write_into(target),
341 }
342 }
343}
344
345impl Deserializable for Signature {
346 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
347 match source.read::<AuthScheme>()? {
348 AuthScheme::Falcon512Rpo => {
349 let signature = falcon512_rpo::Signature::read_from(source)?;
350 Ok(Signature::Falcon512Rpo(signature))
351 },
352 AuthScheme::EcdsaK256Keccak => {
353 let signature = ecdsa_k256_keccak::Signature::read_from(source)?;
354 Ok(Signature::EcdsaK256Keccak(signature))
355 },
356 }
357 }
358}
359
360fn prepare_falcon512_rpo_signature(sig: &falcon512_rpo::Signature) -> Vec<Felt> {
375 use falcon512_rpo::Polynomial;
376
377 let nonce = sig.nonce();
380 let s2 = sig.sig_poly();
382 let h = sig.public_key();
385 let pi = Polynomial::mul_modulo_p(h, s2);
389
390 let mut polynomials: Vec<Felt> =
396 h.coefficients.iter().map(|a| Felt::from(a.value() as u32)).collect();
397 polynomials.extend(s2.coefficients.iter().map(|a| Felt::from(a.value() as u32)));
398 polynomials.extend(pi.iter().map(|a| Felt::new(*a)));
399
400 let digest_polynomials = Hasher::hash_elements(&polynomials);
401 let challenge = (digest_polynomials[0], digest_polynomials[1]);
402
403 let mut result: Vec<Felt> = vec![challenge.0, challenge.1];
404 result.extend_from_slice(&polynomials);
405 result.extend_from_slice(&nonce.to_elements());
406
407 result
408}