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, StarkField, 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 { sig, pk: self.public_key })
151        } else {
152            Err(FalconError::SigGenerationFailed)
153        }
154    }
155}
156
157// SERIALIZATION / DESERIALIZATION
158// ================================================================================================
159
160impl Serializable for KeyPair {
161    fn write_into<W: ByteWriter>(&self, target: &mut W) {
162        target.write_bytes(&self.public_key);
163        target.write_bytes(&self.secret_key);
164    }
165}
166
167impl Deserializable for KeyPair {
168    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
169        let public_key: PublicKeyBytes = source.read_array()?;
170        let secret_key: SecretKeyBytes = source.read_array()?;
171        Ok(Self { public_key, secret_key })
172    }
173}
174
175// TESTS
176// ================================================================================================
177
178#[cfg(all(test, feature = "std"))]
179mod tests {
180    use super::{super::Felt, KeyPair, NonceBytes, Word};
181    use rand_utils::{rand_array, rand_vector};
182
183    #[test]
184    fn test_falcon_verification() {
185        // generate random keys
186        let keys = KeyPair::new().unwrap();
187        let pk = keys.public_key();
188
189        // sign a random message
190        let message: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
191        let signature = keys.sign(message);
192
193        // make sure the signature verifies correctly
194        assert!(pk.verify(message, signature.as_ref().unwrap()));
195
196        // a signature should not verify against a wrong message
197        let message2: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
198        assert!(!pk.verify(message2, signature.as_ref().unwrap()));
199
200        // a signature should not verify against a wrong public key
201        let keys2 = KeyPair::new().unwrap();
202        assert!(!keys2.public_key().verify(message, signature.as_ref().unwrap()))
203    }
204
205    #[test]
206    fn test_falcon_verification_from_seed() {
207        // generate keys from a random seed
208        let seed: NonceBytes = rand_array();
209        let keys = KeyPair::from_seed(&seed).unwrap();
210        let pk = keys.public_key();
211
212        // sign a random message
213        let message: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
214        let signature = keys.sign(message);
215
216        // make sure the signature verifies correctly
217        assert!(pk.verify(message, signature.as_ref().unwrap()));
218
219        // a signature should not verify against a wrong message
220        let message2: Word = rand_vector::<Felt>(4).try_into().expect("Should not fail.");
221        assert!(!pk.verify(message2, signature.as_ref().unwrap()));
222
223        // a signature should not verify against a wrong public key
224        let keys2 = KeyPair::new().unwrap();
225        assert!(!keys2.public_key().verify(message, signature.as_ref().unwrap()))
226    }
227}