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::SigningKey) = 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::SigningKey::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::SigningKey::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::SigningKey::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<ecdsa_k256_keccak::PublicKey> for PublicKeyCommitment {
244 fn from(value: ecdsa_k256_keccak::PublicKey) -> Self {
245 Self(value.to_commitment())
246 }
247}
248
249impl From<PublicKeyCommitment> for Word {
250 fn from(value: PublicKeyCommitment) -> Self {
251 value.0
252 }
253}
254
255impl From<Word> for PublicKeyCommitment {
256 fn from(value: Word) -> Self {
257 Self(value)
258 }
259}
260
261#[derive(Clone, Debug)]
263#[non_exhaustive]
264pub enum PublicKey {
265 Falcon512Poseidon2(falcon512_poseidon2::PublicKey),
266 EcdsaK256Keccak(ecdsa_k256_keccak::PublicKey),
267}
268
269impl PublicKey {
270 pub fn auth_scheme(&self) -> AuthScheme {
272 match self {
273 PublicKey::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
274 PublicKey::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
275 }
276 }
277
278 pub fn to_commitment(&self) -> PublicKeyCommitment {
280 match self {
281 PublicKey::Falcon512Poseidon2(key) => key.to_commitment().into(),
282 PublicKey::EcdsaK256Keccak(key) => key.to_commitment().into(),
283 }
284 }
285
286 pub fn verify(&self, message: Word, signature: Signature) -> bool {
288 match (self, signature) {
289 (PublicKey::Falcon512Poseidon2(key), Signature::Falcon512Poseidon2(sig)) => {
290 key.verify(message, &sig)
291 },
292 (PublicKey::EcdsaK256Keccak(key), Signature::EcdsaK256Keccak(sig)) => {
293 key.verify(message, &sig)
294 },
295 _ => false,
296 }
297 }
298}
299
300impl Serializable for PublicKey {
301 fn write_into<W: ByteWriter>(&self, target: &mut W) {
302 self.auth_scheme().write_into(target);
303 match self {
304 PublicKey::Falcon512Poseidon2(pub_key) => pub_key.write_into(target),
305 PublicKey::EcdsaK256Keccak(pub_key) => pub_key.write_into(target),
306 }
307 }
308}
309
310impl Deserializable for PublicKey {
311 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
312 match source.read::<AuthScheme>()? {
313 AuthScheme::Falcon512Poseidon2 => {
314 let pub_key = falcon512_poseidon2::PublicKey::read_from(source)?;
315 Ok(PublicKey::Falcon512Poseidon2(pub_key))
316 },
317 AuthScheme::EcdsaK256Keccak => {
318 let pub_key = ecdsa_k256_keccak::PublicKey::read_from(source)?;
319 Ok(PublicKey::EcdsaK256Keccak(pub_key))
320 },
321 }
322 }
323}
324
325#[derive(Clone, Debug)]
344#[repr(u8)]
345pub enum Signature {
346 Falcon512Poseidon2(falcon512_poseidon2::Signature) = FALCON512_POSEIDON2,
347 EcdsaK256Keccak(ecdsa_k256_keccak::Signature) = ECDSA_K256_KECCAK,
348}
349
350impl Signature {
351 pub fn auth_scheme(&self) -> AuthScheme {
353 match self {
354 Signature::Falcon512Poseidon2(_) => AuthScheme::Falcon512Poseidon2,
355 Signature::EcdsaK256Keccak(_) => AuthScheme::EcdsaK256Keccak,
356 }
357 }
358
359 pub fn to_prepared_signature(&self, msg: Word) -> Vec<Felt> {
365 match self {
368 Signature::Falcon512Poseidon2(sig) => {
369 miden_core_lib::dsa::falcon512_poseidon2::encode_signature(sig.public_key(), sig)
370 },
371 Signature::EcdsaK256Keccak(sig) => {
372 let pk = ecdsa_k256_keccak::PublicKey::recover_from(msg, sig)
373 .expect("inferring public key from signature and message should succeed");
374 miden_core_lib::dsa::ecdsa_k256_keccak::encode_signature(&pk, sig)
375 },
376 }
377 }
378}
379
380impl From<falcon512_poseidon2::Signature> for Signature {
381 fn from(signature: falcon512_poseidon2::Signature) -> Self {
382 Signature::Falcon512Poseidon2(signature)
383 }
384}
385
386impl Serializable for Signature {
387 fn write_into<W: ByteWriter>(&self, target: &mut W) {
388 self.auth_scheme().write_into(target);
389 match self {
390 Signature::Falcon512Poseidon2(signature) => signature.write_into(target),
391 Signature::EcdsaK256Keccak(signature) => signature.write_into(target),
392 }
393 }
394}
395
396impl Deserializable for Signature {
397 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
398 match source.read::<AuthScheme>()? {
399 AuthScheme::Falcon512Poseidon2 => {
400 let signature = falcon512_poseidon2::Signature::read_from(source)?;
401 Ok(Signature::Falcon512Poseidon2(signature))
402 },
403 AuthScheme::EcdsaK256Keccak => {
404 let signature = ecdsa_k256_keccak::Signature::read_from(source)?;
405 Ok(Signature::EcdsaK256Keccak(signature))
406 },
407 }
408 }
409}