1use alloc::borrow::ToOwned;
2use alloc::string::ToString;
3use alloc::vec::Vec;
4use core::str::FromStr;
5
6use rand::{CryptoRng, Rng};
7
8use crate::crypto::dsa::{ecdsa_k256_keccak, falcon512_poseidon2};
9use crate::errors::AuthSchemeError;
10use crate::utils::serde::{
11 ByteReader,
12 ByteWriter,
13 Deserializable,
14 DeserializationError,
15 Serializable,
16};
17use crate::{Felt, Word};
18
19const FALCON512_POSEIDON2: u8 = 2;
24const ECDSA_K256_KECCAK: u8 = 1;
25
26const FALCON512_POSEIDON2_STR: &str = "Falcon512Poseidon2";
27const ECDSA_K256_KECCAK_STR: &str = "EcdsaK256Keccak";
28
29#[derive(Copy, Clone, Debug, PartialEq, Eq)]
32#[non_exhaustive]
33#[repr(u8)]
34pub enum AuthScheme {
35 Falcon512Poseidon2 = FALCON512_POSEIDON2,
41
42 EcdsaK256Keccak = ECDSA_K256_KECCAK,
60}
61
62impl AuthScheme {
63 pub fn as_u8(&self) -> u8 {
65 *self as u8
66 }
67}
68
69impl core::fmt::Display for AuthScheme {
70 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
71 match self {
72 Self::Falcon512Poseidon2 => f.write_str(FALCON512_POSEIDON2_STR),
73 Self::EcdsaK256Keccak => f.write_str(ECDSA_K256_KECCAK_STR),
74 }
75 }
76}
77
78impl TryFrom<u8> for AuthScheme {
79 type Error = AuthSchemeError;
80
81 fn try_from(value: u8) -> Result<Self, Self::Error> {
82 match value {
83 FALCON512_POSEIDON2 => Ok(Self::Falcon512Poseidon2),
84 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
85 value => Err(AuthSchemeError::InvalidAuthSchemeIdentifier(value.to_string())),
86 }
87 }
88}
89
90impl FromStr for AuthScheme {
91 type Err = AuthSchemeError;
92
93 fn from_str(input: &str) -> Result<Self, Self::Err> {
94 match input {
95 FALCON512_POSEIDON2_STR => Ok(AuthScheme::Falcon512Poseidon2),
96 ECDSA_K256_KECCAK_STR => Ok(AuthScheme::EcdsaK256Keccak),
97 other => Err(AuthSchemeError::InvalidAuthSchemeIdentifier(other.to_owned())),
98 }
99 }
100}
101
102impl Serializable for AuthScheme {
103 fn write_into<W: ByteWriter>(&self, target: &mut W) {
104 target.write_u8(*self as u8);
105 }
106
107 fn get_size_hint(&self) -> usize {
108 size_of::<u8>()
110 }
111}
112
113impl Deserializable for AuthScheme {
114 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
115 match source.read_u8()? {
116 FALCON512_POSEIDON2 => Ok(Self::Falcon512Poseidon2),
117 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
118 value => Err(DeserializationError::InvalidValue(format!(
119 "auth scheme identifier `{value}` is not valid"
120 ))),
121 }
122 }
123}
124
125#[derive(Clone, Debug, PartialEq, Eq)]
130#[non_exhaustive]
131#[repr(u8)]
132pub enum AuthSecretKey {
133 Falcon512Poseidon2(falcon512_poseidon2::SecretKey) = FALCON512_POSEIDON2,
134 EcdsaK256Keccak(ecdsa_k256_keccak::SigningKey) = ECDSA_K256_KECCAK,
135}
136
137impl AuthSecretKey {
138 #[cfg(feature = "std")]
140 pub fn new_falcon512_poseidon2() -> Self {
141 Self::Falcon512Poseidon2(falcon512_poseidon2::SecretKey::new())
142 }
143
144 pub fn new_falcon512_poseidon2_with_rng<R: Rng>(rng: &mut R) -> Self {
146 Self::Falcon512Poseidon2(falcon512_poseidon2::SecretKey::with_rng::<R>(rng))
147 }
148
149 #[cfg(feature = "std")]
155 pub fn new_ecdsa_k256_keccak() -> Self {
156 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SigningKey::new())
157 }
158
159 pub fn new_ecdsa_k256_keccak_with_rng<R: Rng + CryptoRng>(rng: &mut R) -> Self {
165 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SigningKey::with_rng::<R>(rng))
166 }
167
168 pub fn with_scheme_and_rng<R: Rng + CryptoRng>(
173 scheme: AuthScheme,
174 rng: &mut R,
175 ) -> Result<Self, AuthSchemeError> {
176 match scheme {
177 AuthScheme::Falcon512Poseidon2 => Ok(Self::new_falcon512_poseidon2_with_rng(rng)),
178 AuthScheme::EcdsaK256Keccak => Ok(Self::new_ecdsa_k256_keccak_with_rng(rng)),
179 }
180 }
181
182 #[cfg(feature = "std")]
187 pub fn with_scheme(scheme: AuthScheme) -> Result<Self, AuthSchemeError> {
188 match scheme {
189 AuthScheme::Falcon512Poseidon2 => Ok(Self::new_falcon512_poseidon2()),
190 AuthScheme::EcdsaK256Keccak => Ok(Self::new_ecdsa_k256_keccak()),
191 }
192 }
193
194 pub fn auth_scheme(&self) -> AuthScheme {
196 match self {
197 AuthSecretKey::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
198 AuthSecretKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
199 }
200 }
201
202 pub fn public_key(&self) -> PublicKey {
204 match self {
205 AuthSecretKey::Falcon512Poseidon2(key) => {
206 PublicKey::Falcon512Poseidon2(key.public_key())
207 },
208 AuthSecretKey::EcdsaK256Keccak(key) => PublicKey::EcdsaK256Keccak(key.public_key()),
209 }
210 }
211
212 pub fn sign(&self, message: Word) -> Signature {
214 match self {
215 AuthSecretKey::Falcon512Poseidon2(key) => {
216 Signature::Falcon512Poseidon2(key.sign(message))
217 },
218 AuthSecretKey::EcdsaK256Keccak(key) => Signature::EcdsaK256Keccak(key.sign(message)),
219 }
220 }
221}
222
223impl Serializable for AuthSecretKey {
224 fn write_into<W: ByteWriter>(&self, target: &mut W) {
225 self.auth_scheme().write_into(target);
226 match self {
227 AuthSecretKey::Falcon512Poseidon2(key) => key.write_into(target),
228 AuthSecretKey::EcdsaK256Keccak(key) => key.write_into(target),
229 }
230 }
231}
232
233impl Deserializable for AuthSecretKey {
234 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
235 match source.read::<AuthScheme>()? {
236 AuthScheme::Falcon512Poseidon2 => {
237 let secret_key = falcon512_poseidon2::SecretKey::read_from(source)?;
238 Ok(AuthSecretKey::Falcon512Poseidon2(secret_key))
239 },
240 AuthScheme::EcdsaK256Keccak => {
241 let secret_key = ecdsa_k256_keccak::SigningKey::read_from(source)?;
242 Ok(AuthSecretKey::EcdsaK256Keccak(secret_key))
243 },
244 }
245 }
246}
247
248#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
253pub struct PublicKeyCommitment(Word);
254
255impl core::fmt::Display for PublicKeyCommitment {
256 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
257 write!(f, "{}", self.0)
258 }
259}
260
261impl From<falcon512_poseidon2::PublicKey> for PublicKeyCommitment {
262 fn from(value: falcon512_poseidon2::PublicKey) -> Self {
263 Self(value.to_commitment())
264 }
265}
266
267impl From<ecdsa_k256_keccak::PublicKey> for PublicKeyCommitment {
268 fn from(value: ecdsa_k256_keccak::PublicKey) -> Self {
269 Self(value.to_commitment())
270 }
271}
272
273impl From<PublicKeyCommitment> for Word {
274 fn from(value: PublicKeyCommitment) -> Self {
275 value.0
276 }
277}
278
279impl From<Word> for PublicKeyCommitment {
280 fn from(value: Word) -> Self {
281 Self(value)
282 }
283}
284
285#[derive(Clone, Debug)]
287#[non_exhaustive]
288pub enum PublicKey {
289 Falcon512Poseidon2(falcon512_poseidon2::PublicKey),
290 EcdsaK256Keccak(ecdsa_k256_keccak::PublicKey),
291}
292
293impl PublicKey {
294 pub fn auth_scheme(&self) -> AuthScheme {
296 match self {
297 PublicKey::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
298 PublicKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
299 }
300 }
301
302 pub fn to_commitment(&self) -> PublicKeyCommitment {
304 match self {
305 PublicKey::Falcon512Poseidon2(key) => key.to_commitment().into(),
306 PublicKey::EcdsaK256Keccak(key) => key.to_commitment().into(),
307 }
308 }
309
310 pub fn verify(&self, message: Word, signature: Signature) -> bool {
312 match (self, signature) {
313 (PublicKey::Falcon512Poseidon2(key), Signature::Falcon512Poseidon2(sig)) => {
314 key.verify(message, &sig)
315 },
316 (PublicKey::EcdsaK256Keccak(key), Signature::EcdsaK256Keccak(sig)) => {
317 key.verify(message, &sig)
318 },
319 _ => false,
320 }
321 }
322}
323
324impl Serializable for PublicKey {
325 fn write_into<W: ByteWriter>(&self, target: &mut W) {
326 self.auth_scheme().write_into(target);
327 match self {
328 PublicKey::Falcon512Poseidon2(pub_key) => pub_key.write_into(target),
329 PublicKey::EcdsaK256Keccak(pub_key) => pub_key.write_into(target),
330 }
331 }
332}
333
334impl Deserializable for PublicKey {
335 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
336 match source.read::<AuthScheme>()? {
337 AuthScheme::Falcon512Poseidon2 => {
338 let pub_key = falcon512_poseidon2::PublicKey::read_from(source)?;
339 Ok(PublicKey::Falcon512Poseidon2(pub_key))
340 },
341 AuthScheme::EcdsaK256Keccak => {
342 let pub_key = ecdsa_k256_keccak::PublicKey::read_from(source)?;
343 Ok(PublicKey::EcdsaK256Keccak(pub_key))
344 },
345 }
346 }
347}
348
349#[derive(Clone, Debug)]
368#[repr(u8)]
369pub enum Signature {
370 Falcon512Poseidon2(falcon512_poseidon2::Signature) = FALCON512_POSEIDON2,
371 EcdsaK256Keccak(ecdsa_k256_keccak::Signature) = ECDSA_K256_KECCAK,
372}
373
374impl Signature {
375 pub fn auth_scheme(&self) -> AuthScheme {
377 match self {
378 Signature::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
379 Signature::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
380 }
381 }
382
383 pub fn to_prepared_signature(&self, msg: Word) -> Vec<Felt> {
389 match self {
392 Signature::Falcon512Poseidon2(sig) => {
393 miden_core_lib::dsa::falcon512_poseidon2::encode_signature(sig.public_key(), sig)
394 },
395 Signature::EcdsaK256Keccak(sig) => {
396 let pk = ecdsa_k256_keccak::PublicKey::recover_from(msg, sig)
397 .expect("inferring public key from signature and message should succeed");
398 miden_core_lib::dsa::ecdsa_k256_keccak::encode_signature(&pk, sig)
399 },
400 }
401 }
402}
403
404impl From<falcon512_poseidon2::Signature> for Signature {
405 fn from(signature: falcon512_poseidon2::Signature) -> Self {
406 Signature::Falcon512Poseidon2(signature)
407 }
408}
409
410impl Serializable for Signature {
411 fn write_into<W: ByteWriter>(&self, target: &mut W) {
412 self.auth_scheme().write_into(target);
413 match self {
414 Signature::Falcon512Poseidon2(signature) => signature.write_into(target),
415 Signature::EcdsaK256Keccak(signature) => signature.write_into(target),
416 }
417 }
418}
419
420impl Deserializable for Signature {
421 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
422 match source.read::<AuthScheme>()? {
423 AuthScheme::Falcon512Poseidon2 => {
424 let signature = falcon512_poseidon2::Signature::read_from(source)?;
425 Ok(Signature::Falcon512Poseidon2(signature))
426 },
427 AuthScheme::EcdsaK256Keccak => {
428 let signature = ecdsa_k256_keccak::Signature::read_from(source)?;
429 Ok(Signature::EcdsaK256Keccak(signature))
430 },
431 }
432 }
433}