miden_tx/auth/
tx_authenticator.rs1use alloc::{collections::BTreeMap, string::ToString, sync::Arc, vec::Vec};
2
3use miden_lib::utils::sync::RwLock;
4use miden_objects::account::{AccountDelta, AuthSecretKey};
5use rand::Rng;
6use vm_processor::{Digest, Felt, Word};
7
8use super::signatures::get_falcon_signature;
9use crate::errors::AuthenticationError;
10
11pub trait TransactionAuthenticator {
22 fn get_signature(
34 &self,
35 pub_key: Word,
36 message: Word,
37 account_delta: &AccountDelta,
38 ) -> Result<Vec<Felt>, AuthenticationError>;
39}
40
41impl<T> TransactionAuthenticator for &T
44where
45 T: TransactionAuthenticator + ?Sized,
46{
47 fn get_signature(
48 &self,
49 pub_key: Word,
50 message: Word,
51 account_delta: &AccountDelta,
52 ) -> Result<Vec<Felt>, AuthenticationError> {
53 TransactionAuthenticator::get_signature(*self, pub_key, message, account_delta)
54 }
55}
56
57#[derive(Clone, Debug)]
61pub struct BasicAuthenticator<R> {
63 keys: BTreeMap<Digest, AuthSecretKey>,
65 rng: Arc<RwLock<R>>,
66}
67
68impl<R: Rng> BasicAuthenticator<R> {
69 #[cfg(feature = "std")]
70 pub fn new(keys: &[(Word, AuthSecretKey)]) -> BasicAuthenticator<rand::rngs::StdRng> {
71 use rand::{SeedableRng, rngs::StdRng};
72
73 let rng = StdRng::from_os_rng();
74 BasicAuthenticator::<StdRng>::new_with_rng(keys, rng)
75 }
76
77 pub fn new_with_rng(keys: &[(Word, AuthSecretKey)], rng: R) -> Self {
78 let mut key_map = BTreeMap::new();
79 for (word, secret_key) in keys {
80 key_map.insert(word.into(), secret_key.clone());
81 }
82
83 BasicAuthenticator {
84 keys: key_map,
85 rng: Arc::new(RwLock::new(rng)),
86 }
87 }
88}
89
90impl<R: Rng> TransactionAuthenticator for BasicAuthenticator<R> {
91 fn get_signature(
101 &self,
102 pub_key: Word,
103 message: Word,
104 account_delta: &AccountDelta,
105 ) -> Result<Vec<Felt>, AuthenticationError> {
106 let _ = account_delta;
107 let mut rng = self.rng.write();
108
109 match self.keys.get(&pub_key.into()) {
110 Some(key) => match key {
111 AuthSecretKey::RpoFalcon512(falcon_key) => {
112 get_falcon_signature(falcon_key, message, &mut *rng)
113 },
114 },
115 None => Err(AuthenticationError::UnknownPublicKey(format!(
116 "public key {} is not contained in the authenticator's keys",
117 Digest::from(pub_key)
118 ))),
119 }
120 }
121}
122
123impl TransactionAuthenticator for () {
127 fn get_signature(
128 &self,
129 _pub_key: Word,
130 _message: Word,
131 _account_delta: &AccountDelta,
132 ) -> Result<Vec<Felt>, AuthenticationError> {
133 Err(AuthenticationError::RejectedSignature(
134 "default authenticator cannot provide signatures".to_string(),
135 ))
136 }
137}
138
139#[cfg(test)]
140mod test {
141 use miden_lib::utils::{Deserializable, Serializable};
142 use miden_objects::{account::AuthSecretKey, crypto::dsa::rpo_falcon512::SecretKey};
143
144 #[test]
145 fn serialize_auth_key() {
146 let secret_key = SecretKey::new();
147 let auth_key = AuthSecretKey::RpoFalcon512(secret_key.clone());
148 let serialized = auth_key.to_bytes();
149 let deserialized = AuthSecretKey::read_from_bytes(&serialized).unwrap();
150
151 match deserialized {
152 AuthSecretKey::RpoFalcon512(key) => assert_eq!(secret_key.to_bytes(), key.to_bytes()),
153 }
154 }
155}