1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
use core::cell::OnceCell;

use super::{
    ByteReader, ByteWriter, Deserializable, DeserializationError, Felt, NonceBytes, NonceElements,
    Polynomial, PublicKeyBytes, Rpo256, Serializable, SignatureBytes, Word, MODULUS, N,
    SIG_L2_BOUND, ZERO,
};
use crate::utils::string::*;

// FALCON SIGNATURE
// ================================================================================================

/// An RPO Falcon512 signature over a message.
///
/// The signature is a pair of polynomials (s1, s2) in (Z_p\[x\]/(phi))^2, where:
/// - p := 12289
/// - phi := x^512 + 1
/// - s1 = c - s2 * h
/// - h is a polynomial representing the public key and c is a polynomial that is the hash-to-point
///   of the message being signed.
///
/// The signature  verifies if and only if:
/// 1. s1 = c - s2 * h
/// 2. |s1|^2 + |s2|^2 <= SIG_L2_BOUND
///
/// where |.| is the norm.
///
/// [Signature] also includes the extended public key which is serialized as:
/// 1. 1 byte representing the log2(512) i.e., 9.
/// 2. 896 bytes for the public key. This is decoded into the `h` polynomial above.
///
/// The actual signature is serialized as:
/// 1. A header byte specifying the algorithm used to encode the coefficients of the `s2` polynomial
///    together with the degree of the irreducible polynomial phi.
///    The general format of this byte is 0b0cc1nnnn where:
///     a. cc is either 01 when the compressed encoding algorithm is used and 10 when the
///     uncompressed algorithm is used.
///     b. nnnn is log2(N) where N is the degree of the irreducible polynomial phi.
///    The current implementation works always with cc equal to 0b01 and nnnn equal to 0b1001 and
///    thus the header byte is always equal to 0b00111001.
/// 2. 40 bytes for the nonce.
/// 3. 625 bytes encoding the `s2` polynomial above.
///
/// The total size of the signature (including the extended public key) is 1563 bytes.
#[derive(Debug, Clone)]
pub struct Signature {
    pub(super) pk: PublicKeyBytes,
    pub(super) sig: SignatureBytes,

    // Cached polynomial decoding for public key and signatures
    pub(super) pk_polynomial: OnceCell<Polynomial>,
    pub(super) sig_polynomial: OnceCell<Polynomial>,
}

impl Signature {
    // PUBLIC ACCESSORS
    // --------------------------------------------------------------------------------------------

    /// Returns the public key polynomial h.
    pub fn pub_key_poly(&self) -> Polynomial {
        *self.pk_polynomial.get_or_init(|| {
            // we assume that the signature was constructed with a valid public key, and thus
            // expect() is OK here.
            Polynomial::from_pub_key(&self.pk).expect("invalid public key")
        })
    }

    /// Returns the nonce component of the signature represented as field elements.
    ///
    /// Nonce bytes are converted to field elements by taking consecutive 5 byte chunks
    /// of the nonce and interpreting them as field elements.
    pub fn nonce(&self) -> NonceElements {
        // we assume that the signature was constructed with a valid signature, and thus
        // expect() is OK here.
        let nonce = self.sig[1..41].try_into().expect("invalid signature");
        decode_nonce(nonce)
    }

    // Returns the polynomial representation of the signature in Z_p[x]/(phi).
    pub fn sig_poly(&self) -> Polynomial {
        *self.sig_polynomial.get_or_init(|| {
            // we assume that the signature was constructed with a valid signature, and thus
            // expect() is OK here.
            Polynomial::from_signature(&self.sig).expect("invalid signature")
        })
    }

    // HASH-TO-POINT
    // --------------------------------------------------------------------------------------------

    /// Returns a polynomial in Z_p\[x\]/(phi) representing the hash of the provided message.
    pub fn hash_to_point(&self, message: Word) -> Polynomial {
        hash_to_point(message, &self.nonce())
    }

    // SIGNATURE VERIFICATION
    // --------------------------------------------------------------------------------------------
    /// Returns true if this signature is a valid signature for the specified message generated
    /// against key pair matching the specified public key commitment.
    pub fn verify(&self, message: Word, pubkey_com: Word) -> bool {
        // Make sure the expanded public key matches the provided public key commitment
        let h = self.pub_key_poly();
        let h_digest: Word = Rpo256::hash_elements(&h.to_elements()).into();
        if h_digest != pubkey_com {
            return false;
        }

        // Make sure the signature is valid
        let s2 = self.sig_poly();
        let c = self.hash_to_point(message);

        let s1 = c - s2 * h;

        let sq_norm = s1.sq_norm() + s2.sq_norm();
        sq_norm <= SIG_L2_BOUND
    }
}

// SERIALIZATION / DESERIALIZATION
// ================================================================================================

impl Serializable for Signature {
    fn write_into<W: ByteWriter>(&self, target: &mut W) {
        target.write_bytes(&self.pk);
        target.write_bytes(&self.sig);
    }
}

impl Deserializable for Signature {
    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
        let pk: PublicKeyBytes = source.read_array()?;
        let sig: SignatureBytes = source.read_array()?;

        // make sure public key and signature can be decoded correctly
        let pk_polynomial = Polynomial::from_pub_key(&pk)
            .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?
            .into();
        let sig_polynomial = Polynomial::from_signature(&sig)
            .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?
            .into();

        Ok(Self { pk, sig, pk_polynomial, sig_polynomial })
    }
}

// HELPER FUNCTIONS
// ================================================================================================

/// Returns a polynomial in Z_p[x]/(phi) representing the hash of the provided message and
/// nonce.
fn hash_to_point(message: Word, nonce: &NonceElements) -> Polynomial {
    let mut state = [ZERO; Rpo256::STATE_WIDTH];

    // absorb the nonce into the state
    for (&n, s) in nonce.iter().zip(state[Rpo256::RATE_RANGE].iter_mut()) {
        *s = n;
    }
    Rpo256::apply_permutation(&mut state);

    // absorb message into the state
    for (&m, s) in message.iter().zip(state[Rpo256::RATE_RANGE].iter_mut()) {
        *s = m;
    }

    // squeeze the coefficients of the polynomial
    let mut i = 0;
    let mut res = [0_u16; N];
    for _ in 0..64 {
        Rpo256::apply_permutation(&mut state);
        for a in &state[Rpo256::RATE_RANGE] {
            res[i] = (a.as_int() % MODULUS as u64) as u16;
            i += 1;
        }
    }

    // using the raw constructor is OK here because we reduce all coefficients by the modulus above
    unsafe { Polynomial::new(res) }
}

/// Converts byte representation of the nonce into field element representation.
fn decode_nonce(nonce: &NonceBytes) -> NonceElements {
    let mut buffer = [0_u8; 8];
    let mut result = [ZERO; 8];
    for (i, bytes) in nonce.chunks(5).enumerate() {
        buffer[..5].copy_from_slice(bytes);
        // we can safely (without overflow) create a new Felt from u64 value here since this value
        // contains at most 5 bytes
        result[i] = Felt::new(u64::from_le_bytes(buffer));
    }

    result
}

// TESTS
// ================================================================================================

#[cfg(all(test, feature = "std"))]
mod tests {
    use libc::c_void;
    use rand_utils::rand_vector;

    use super::{
        super::{ffi::*, KeyPair},
        *,
    };

    // Wrappers for unsafe functions
    impl Rpo128Context {
        /// Initializes the RPO state.
        pub fn init() -> Self {
            let mut ctx = Rpo128Context { content: [0u64; 13] };
            unsafe {
                rpo128_init(&mut ctx as *mut Rpo128Context);
            }
            ctx
        }

        /// Absorbs data into the RPO state.
        pub fn absorb(&mut self, data: &[u8]) {
            unsafe {
                rpo128_absorb(
                    self as *mut Rpo128Context,
                    data.as_ptr() as *const c_void,
                    data.len(),
                )
            }
        }

        /// Finalizes the RPO state to prepare for squeezing.
        pub fn finalize(&mut self) {
            unsafe { rpo128_finalize(self as *mut Rpo128Context) }
        }
    }

    #[test]
    fn test_hash_to_point() {
        // Create a random message and transform it into a u8 vector
        let msg_felts: Word = rand_vector::<Felt>(4).try_into().unwrap();
        let msg_bytes = msg_felts.iter().flat_map(|e| e.as_int().to_le_bytes()).collect::<Vec<_>>();

        // Create a nonce i.e. a [u8; 40] array and pack into a [Felt; 8] array.
        let nonce: [u8; 40] = rand_vector::<u8>(40).try_into().unwrap();

        let mut buffer = [0_u8; 64];
        for i in 0..8 {
            buffer[8 * i] = nonce[5 * i];
            buffer[8 * i + 1] = nonce[5 * i + 1];
            buffer[8 * i + 2] = nonce[5 * i + 2];
            buffer[8 * i + 3] = nonce[5 * i + 3];
            buffer[8 * i + 4] = nonce[5 * i + 4];
        }

        // Initialize the RPO state
        let mut rng = Rpo128Context::init();

        // Absorb the nonce and message into the RPO state
        rng.absorb(&buffer);
        rng.absorb(&msg_bytes);
        rng.finalize();

        // Generate the coefficients of the hash-to-point polynomial.
        let mut res: [u16; N] = [0; N];

        unsafe {
            PQCLEAN_FALCON512_CLEAN_hash_to_point_rpo(
                &mut rng as *mut Rpo128Context,
                res.as_mut_ptr(),
                9,
            );
        }

        // Check that the coefficients are correct
        let nonce = decode_nonce(&nonce);
        assert_eq!(res, hash_to_point(msg_felts, &nonce).inner());
    }

    #[test]
    fn test_serialization_round_trip() {
        let key = KeyPair::new().unwrap();
        let signature = key.sign(Word::default()).unwrap();
        let serialized = signature.to_bytes();
        let deserialized = Signature::read_from_bytes(&serialized).unwrap();
        assert_eq!(signature.sig_poly(), deserialized.sig_poly());
        assert_eq!(signature.pub_key_poly(), deserialized.pub_key_poly());
    }
}