arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
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}