miden-crypto/src/dsa/rpo_falcon512/keys.rs
src/dsa/rpo_falcon512/keys.rsRaw
1use super::{
2 ByteReader, ByteWriter, Deserializable, DeserializationError, FalconError, Polynomial,
3 PublicKeyBytes, Rpo256, SecretKeyBytes, Serializable, Signature, Word,
4};
5#[cfg(feature = "std")]
6use {
7 super::{ffi, NonceBytes, NONCE_LEN, PK_LEN, SIG_LEN, SK_LEN},
8 alloc::vec::Vec,
9};
10
11// PUBLIC KEY
12// ================================================================================================
13
14/// A public key for verifying signatures.
15///
16/// The public key is a [Word] (i.e., 4 field elements) that is the hash of the coefficients of
17/// the polynomial representing the raw bytes of the expanded public key.
18///
19/// For Falcon-512, the first byte of the expanded public key is always equal to log2(512) i.e., 9.
20#[derive(Debug, Clone, Copy, PartialEq)]
21pub struct PublicKey(Word);
22
23impl PublicKey {
24 /// Returns a new [PublicKey] which is a commitment to the provided expanded public key.
25 ///
26 /// # Errors
27 /// Returns an error if the decoding of the public key fails.
28 pub fn new(pk: PublicKeyBytes) -> Result<Self, FalconError> {
29 let h = Polynomial::from_pub_key(&pk)?;
30 let pk_felts = h.to_elements();
31 let pk_digest = Rpo256::hash_elements(&pk_felts).into();
32 Ok(Self(pk_digest))
33 }
34
35 /// Verifies the provided signature against provided message and this public key.
36 pub fn verify(&self, message: Word, signature: &Signature) -> bool {
37 signature.verify(message, self.0)
38 }
39}
40
41impl From<PublicKey> for Word {
42 fn from(key: PublicKey) -> Self {
43 key.0
44 }
45}
46
47// KEY PAIR
48// ================================================================================================
49
50/// A key pair (public and secret keys) for signing messages.
51///
52/// The secret key is a byte array of length [PK_LEN].
53/// The public key is a byte array of length [SK_LEN].
54#[derive(Debug, Clone, Copy, PartialEq)]
55pub struct KeyPair {
56 public_key: PublicKeyBytes,
57 secret_key: SecretKeyBytes,
58}
59
60#[allow(clippy::new_without_default)]
61impl KeyPair {
62 // CONSTRUCTORS
63 // --------------------------------------------------------------------------------------------
64
65 /// Generates a (public_key, secret_key) key pair from OS-provided randomness.
66 ///
67 /// # Errors
68 /// Returns an error if key generation fails.
69 #[cfg(feature = "std")]
70 pub fn new() -> Result<Self, FalconError> {
71 let mut public_key = [0u8; PK_LEN];
72 let mut secret_key = [0u8; SK_LEN];
73
74 let res = unsafe {
75 ffi::PQCLEAN_FALCON512_CLEAN_crypto_sign_keypair_rpo(
76 public_key.as_mut_ptr(),
77 secret_key.as_mut_ptr(),
78 )
79 };
80
81 if res == 0 {
82 Ok(Self { public_key, secret_key })
83 } else {
84 Err(FalconError::KeyGenerationFailed)
85 }
86 }
87
88 /// Generates a (public_key, secret_key) key pair from the provided seed.
89 ///
90 /// # Errors
91 /// Returns an error if key generation fails.
92 #[cfg(feature = "std")]
93 pub fn from_seed(seed: &NonceBytes) -> Result<Self, FalconError> {
94 let mut public_key = [0u8; PK_LEN];
95 let mut secret_key = [0u8; SK_LEN];
96
97 let res = unsafe {
98 ffi::PQCLEAN_FALCON512_CLEAN_crypto_sign_keypair_from_seed_rpo(
99 public_key.as_mut_ptr(),
100 secret_key.as_mut_ptr(),
101 seed.as_ptr(),
102 )
103 };
104
105 if res == 0 {
106 Ok(Self { public_key, secret_key })
107 } else {
108 Err(FalconError::KeyGenerationFailed)
109 }
110 }
111
112 // PUBLIC ACCESSORS
113 // --------------------------------------------------------------------------------------------
114
115 /// Returns the public key corresponding to this key pair.
116 pub fn public_key(&self) -> PublicKey {
117 // TODO: memoize public key commitment as computing it requires quite a bit of hashing.
118 // expect() is fine here because we assume that the key pair was constructed correctly.
119 PublicKey::new(self.public_key).expect("invalid key pair")
120 }
121
122 /// Returns the expanded public key corresponding to this key pair.
123 pub fn expanded_public_key(&self) -> PublicKeyBytes {
124 self.public_key
125 }
126
127 // SIGNATURE GENERATION
128 // --------------------------------------------------------------------------------------------
129
130 /// Signs a message with a secret key and a seed.
131 ///
132 /// # Errors
133 /// Returns an error of signature generation fails.
134 #[cfg(feature = "std")]
135 pub fn sign(&self, message: Word) -> Result<Signature, FalconError> {
136 let msg = message.iter().flat_map(|e| e.as_int().to_le_bytes()).collect::<Vec<_>>();
137 let msg_len = msg.len();
138 let mut sig = [0_u8; SIG_LEN + NONCE_LEN];
139 let mut sig_len: usize = 0;
140
141 let res = unsafe {
142 ffi::PQCLEAN_FALCON512_CLEAN_crypto_sign_signature_rpo(
143 sig.as_mut_ptr(),
144 &mut sig_len as *mut usize,
145 msg.as_ptr(),
146 msg_len,
147 self.secret_key.as_ptr(),
148 )
149 };
150
151 if res == 0 {
152 Ok(Signature {
153 sig,
154 pk: self.public_key,
155 pk_polynomial: Default::default(),
156 sig_polynomial: Default::default(),
157 })
158 } else {
159 Err(FalconError::SigGenerationFailed)
160 }
161 }
162}
163
164// SERIALIZATION / DESERIALIZATION
165// ================================================================================================
166
167impl Serializable for KeyPair {
168 fn write_into<W: ByteWriter>(&self, target: &mut W) {
169 target.write_bytes(&self.public_key);
170 target.write_bytes(&self.secret_key);
171 }
172}
173
174impl Deserializable for KeyPair {
175 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
176 let public_key: PublicKeyBytes = source.read_array()?;
177 let secret_key: SecretKeyBytes = source.read_array()?;
178 Ok(Self { public_key, secret_key })
179 }
180}
181
182// TESTS
183// ================================================================================================
184
185#[cfg(all(test, feature = "std"))]
186mod tests {
187 use rand_utils::{rand_array, rand_vector};
188
189 use super::{super::Felt, KeyPair, NonceBytes, Word};
190
191 #[test]
192 fn test_falcon_verification() {
193 // generate random keys
194 let keys = KeyPair::new().unwrap();
195 let pk = keys.public_key();
196
197 // sign a random message
198 let message: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
199 let signature = keys.sign(message);
200
201 // make sure the signature verifies correctly
202 assert!(pk.verify(message, signature.as_ref().unwrap()));
203
204 // a signature should not verify against a wrong message
205 let message2: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
206 assert!(!pk.verify(message2, signature.as_ref().unwrap()));
207
208 // a signature should not verify against a wrong public key
209 let keys2 = KeyPair::new().unwrap();
210 assert!(!keys2.public_key().verify(message, signature.as_ref().unwrap()))
211 }
212
213 #[test]
214 fn test_falcon_verification_from_seed() {
215 // generate keys from a random seed
216 let seed: NonceBytes = rand_array();
217 let keys = KeyPair::from_seed(&seed).unwrap();
218 let pk = keys.public_key();
219
220 // sign a random message
221 let message: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
222 let signature = keys.sign(message);
223
224 // make sure the signature verifies correctly
225 assert!(pk.verify(message, signature.as_ref().unwrap()));
226
227 // a signature should not verify against a wrong message
228 let message2: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
229 assert!(!pk.verify(message2, signature.as_ref().unwrap()));
230
231 // a signature should not verify against a wrong public key
232 let keys2 = KeyPair::new().unwrap();
233 assert!(!keys2.public_key().verify(message, signature.as_ref().unwrap()))
234 }
235}