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
  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}