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