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,
44}
45
46impl AuthScheme {
47 pub fn as_u8(&self) -> u8 {
49 *self as u8
50 }
51}
52
53impl core::fmt::Display for AuthScheme {
54 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55 match self {
56 Self::Falcon512Poseidon2 => f.write_str(FALCON512_POSEIDON2_STR),
57 Self::EcdsaK256Keccak => f.write_str(ECDSA_K256_KECCAK_STR),
58 }
59 }
60}
61
62impl TryFrom<u8> for AuthScheme {
63 type Error = AuthSchemeError;
64
65 fn try_from(value: u8) -> Result<Self, Self::Error> {
66 match value {
67 FALCON512_POSEIDON2 => Ok(Self::Falcon512Poseidon2),
68 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
69 value => Err(AuthSchemeError::InvalidAuthSchemeIdentifier(value.to_string())),
70 }
71 }
72}
73
74impl FromStr for AuthScheme {
75 type Err = AuthSchemeError;
76
77 fn from_str(input: &str) -> Result<Self, Self::Err> {
78 match input {
79 FALCON512_POSEIDON2_STR => Ok(AuthScheme::Falcon512Poseidon2),
80 ECDSA_K256_KECCAK_STR => Ok(AuthScheme::EcdsaK256Keccak),
81 other => Err(AuthSchemeError::InvalidAuthSchemeIdentifier(other.to_owned())),
82 }
83 }
84}
85
86impl Serializable for AuthScheme {
87 fn write_into<W: ByteWriter>(&self, target: &mut W) {
88 target.write_u8(*self as u8);
89 }
90
91 fn get_size_hint(&self) -> usize {
92 size_of::<u8>()
94 }
95}
96
97impl Deserializable for AuthScheme {
98 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
99 match source.read_u8()? {
100 FALCON512_POSEIDON2 => Ok(Self::Falcon512Poseidon2),
101 ECDSA_K256_KECCAK => Ok(Self::EcdsaK256Keccak),
102 value => Err(DeserializationError::InvalidValue(format!(
103 "auth scheme identifier `{value}` is not valid"
104 ))),
105 }
106 }
107}
108
109#[derive(Clone, Debug, PartialEq, Eq)]
114#[non_exhaustive]
115#[repr(u8)]
116pub enum AuthSecretKey {
117 Falcon512Poseidon2(falcon512_poseidon2::SecretKey) = FALCON512_POSEIDON2,
118 EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey) = ECDSA_K256_KECCAK,
119}
120
121impl AuthSecretKey {
122 #[cfg(feature = "std")]
124 pub fn new_falcon512_poseidon2() -> Self {
125 Self::Falcon512Poseidon2(falcon512_poseidon2::SecretKey::new())
126 }
127
128 pub fn new_falcon512_poseidon2_with_rng<R: Rng>(rng: &mut R) -> Self {
130 Self::Falcon512Poseidon2(falcon512_poseidon2::SecretKey::with_rng(rng))
131 }
132
133 #[cfg(feature = "std")]
135 pub fn new_ecdsa_k256_keccak() -> Self {
136 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey::new())
137 }
138
139 pub fn new_ecdsa_k256_keccak_with_rng<R: Rng + CryptoRng>(rng: &mut R) -> Self {
141 Self::EcdsaK256Keccak(ecdsa_k256_keccak::SecretKey::with_rng(rng))
142 }
143
144 pub fn with_scheme_and_rng<R: Rng + CryptoRng>(
149 scheme: AuthScheme,
150 rng: &mut R,
151 ) -> Result<Self, AuthSchemeError> {
152 match scheme {
153 AuthScheme::Falcon512Poseidon2 => Ok(Self::new_falcon512_poseidon2_with_rng(rng)),
154 AuthScheme::EcdsaK256Keccak => Ok(Self::new_ecdsa_k256_keccak_with_rng(rng)),
155 }
156 }
157
158 #[cfg(feature = "std")]
163 pub fn with_scheme(scheme: AuthScheme) -> Result<Self, AuthSchemeError> {
164 match scheme {
165 AuthScheme::Falcon512Poseidon2 => Ok(Self::new_falcon512_poseidon2()),
166 AuthScheme::EcdsaK256Keccak => Ok(Self::new_ecdsa_k256_keccak()),
167 }
168 }
169
170 pub fn auth_scheme(&self) -> AuthScheme {
172 match self {
173 AuthSecretKey::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
174 AuthSecretKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
175 }
176 }
177
178 pub fn public_key(&self) -> PublicKey {
180 match self {
181 AuthSecretKey::Falcon512Poseidon2(key) => {
182 PublicKey::Falcon512Poseidon2(key.public_key())
183 },
184 AuthSecretKey::EcdsaK256Keccak(key) => PublicKey::EcdsaK256Keccak(key.public_key()),
185 }
186 }
187
188 pub fn sign(&self, message: Word) -> Signature {
190 match self {
191 AuthSecretKey::Falcon512Poseidon2(key) => {
192 Signature::Falcon512Poseidon2(key.sign(message))
193 },
194 AuthSecretKey::EcdsaK256Keccak(key) => Signature::EcdsaK256Keccak(key.sign(message)),
195 }
196 }
197}
198
199impl Serializable for AuthSecretKey {
200 fn write_into<W: ByteWriter>(&self, target: &mut W) {
201 self.auth_scheme().write_into(target);
202 match self {
203 AuthSecretKey::Falcon512Poseidon2(key) => key.write_into(target),
204 AuthSecretKey::EcdsaK256Keccak(key) => key.write_into(target),
205 }
206 }
207}
208
209impl Deserializable for AuthSecretKey {
210 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
211 match source.read::<AuthScheme>()? {
212 AuthScheme::Falcon512Poseidon2 => {
213 let secret_key = falcon512_poseidon2::SecretKey::read_from(source)?;
214 Ok(AuthSecretKey::Falcon512Poseidon2(secret_key))
215 },
216 AuthScheme::EcdsaK256Keccak => {
217 let secret_key = ecdsa_k256_keccak::SecretKey::read_from(source)?;
218 Ok(AuthSecretKey::EcdsaK256Keccak(secret_key))
219 },
220 }
221 }
222}
223
224#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
229pub struct PublicKeyCommitment(Word);
230
231impl core::fmt::Display for PublicKeyCommitment {
232 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
233 write!(f, "{}", self.0)
234 }
235}
236
237impl From<falcon512_poseidon2::PublicKey> for PublicKeyCommitment {
238 fn from(value: falcon512_poseidon2::PublicKey) -> Self {
239 Self(value.to_commitment())
240 }
241}
242
243impl From<PublicKeyCommitment> for Word {
244 fn from(value: PublicKeyCommitment) -> Self {
245 value.0
246 }
247}
248
249impl From<Word> for PublicKeyCommitment {
250 fn from(value: Word) -> Self {
251 Self(value)
252 }
253}
254
255#[derive(Clone, Debug)]
257#[non_exhaustive]
258pub enum PublicKey {
259 Falcon512Poseidon2(falcon512_poseidon2::PublicKey),
260 EcdsaK256Keccak(ecdsa_k256_keccak::PublicKey),
261}
262
263impl PublicKey {
264 pub fn auth_scheme(&self) -> AuthScheme {
266 match self {
267 PublicKey::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
268 PublicKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
269 }
270 }
271
272 pub fn to_commitment(&self) -> PublicKeyCommitment {
274 match self {
275 PublicKey::Falcon512Poseidon2(key) => key.to_commitment().into(),
276 PublicKey::EcdsaK256Keccak(key) => key.to_commitment().into(),
277 }
278 }
279
280 pub fn verify(&self, message: Word, signature: Signature) -> bool {
282 match (self, signature) {
283 (PublicKey::Falcon512Poseidon2(key), Signature::Falcon512Poseidon2(sig)) => {
284 key.verify(message, &sig)
285 },
286 (PublicKey::EcdsaK256Keccak(key), Signature::EcdsaK256Keccak(sig)) => {
287 key.verify(message, &sig)
288 },
289 _ => false,
290 }
291 }
292}
293
294impl Serializable for PublicKey {
295 fn write_into<W: ByteWriter>(&self, target: &mut W) {
296 self.auth_scheme().write_into(target);
297 match self {
298 PublicKey::Falcon512Poseidon2(pub_key) => pub_key.write_into(target),
299 PublicKey::EcdsaK256Keccak(pub_key) => pub_key.write_into(target),
300 }
301 }
302}
303
304impl Deserializable for PublicKey {
305 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
306 match source.read::<AuthScheme>()? {
307 AuthScheme::Falcon512Poseidon2 => {
308 let pub_key = falcon512_poseidon2::PublicKey::read_from(source)?;
309 Ok(PublicKey::Falcon512Poseidon2(pub_key))
310 },
311 AuthScheme::EcdsaK256Keccak => {
312 let pub_key = ecdsa_k256_keccak::PublicKey::read_from(source)?;
313 Ok(PublicKey::EcdsaK256Keccak(pub_key))
314 },
315 }
316 }
317}
318
319#[derive(Clone, Debug)]
338#[repr(u8)]
339pub enum Signature {
340 Falcon512Poseidon2(falcon512_poseidon2::Signature) = FALCON512_POSEIDON2,
341 EcdsaK256Keccak(ecdsa_k256_keccak::Signature) = ECDSA_K256_KECCAK,
342}
343
344impl Signature {
345 pub fn auth_scheme(&self) -> AuthScheme {
347 match self {
348 Signature::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
349 Signature::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
350 }
351 }
352
353 pub fn to_prepared_signature(&self, msg: Word) -> Vec<Felt> {
359 match self {
362 Signature::Falcon512Poseidon2(sig) => {
363 miden_core_lib::dsa::falcon512_poseidon2::encode_signature(sig.public_key(), sig)
364 },
365 Signature::EcdsaK256Keccak(sig) => {
366 let pk = ecdsa_k256_keccak::PublicKey::recover_from(msg, sig)
367 .expect("inferring public key from signature and message should succeed");
368 miden_core_lib::dsa::ecdsa_k256_keccak::encode_signature(&pk, sig)
369 },
370 }
371 }
372}
373
374impl From<falcon512_poseidon2::Signature> for Signature {
375 fn from(signature: falcon512_poseidon2::Signature) -> Self {
376 Signature::Falcon512Poseidon2(signature)
377 }
378}
379
380impl Serializable for Signature {
381 fn write_into<W: ByteWriter>(&self, target: &mut W) {
382 self.auth_scheme().write_into(target);
383 match self {
384 Signature::Falcon512Poseidon2(signature) => signature.write_into(target),
385 Signature::EcdsaK256Keccak(signature) => signature.write_into(target),
386 }
387 }
388}
389
390impl Deserializable for Signature {
391 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
392 match source.read::<AuthScheme>()? {
393 AuthScheme::Falcon512Poseidon2 => {
394 let signature = falcon512_poseidon2::Signature::read_from(source)?;
395 Ok(Signature::Falcon512Poseidon2(signature))
396 },
397 AuthScheme::EcdsaK256Keccak => {
398 let signature = ecdsa_k256_keccak::Signature::read_from(source)?;
399 Ok(Signature::EcdsaK256Keccak(signature))
400 },
401 }
402 }
403}