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