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