pqcrypto_qtesla/
qteslapiii.rs

1//! qtesla-p-III
2//!
3//! These bindings use the clean version from [PQClean][pqc]
4//!
5//! # Example
6//! ```
7//! use pqcrypto_qtesla::qteslapiii::*;
8//! let message = vec![0, 1, 2, 3, 4, 5];
9//! let (pk, sk) = keypair();
10//! let sm = sign(&message, &sk);
11//! let verifiedmsg = open(&sm, &pk).unwrap();
12//! assert!(verifiedmsg == message);
13//! ```
14//!
15//! [pqc]: https://github.com/pqclean/pqclean/
16
17// This file is generated.
18
19use crate::ffi;
20use pqcrypto_traits::sign as primitive;
21use pqcrypto_traits::{Error, Result};
22
23macro_rules! simple_struct {
24    ($type: ident, $size: expr) => {
25        #[derive(Clone, Copy)]
26        pub struct $type([u8; $size]);
27
28        impl $type {
29            /// Generates an uninitialized object
30            ///
31            /// Used to pass to ``ffi`` interfaces.
32            ///
33            /// Internal use only!
34            fn new() -> Self {
35                $type([0u8; $size])
36            }
37        }
38
39        impl primitive::$type for $type {
40            /// Get this object as a byte slice
41            #[inline]
42            fn as_bytes(&self) -> &[u8] {
43                &self.0
44            }
45
46            /// Construct this object from a byte slice
47            fn from_bytes(bytes: &[u8]) -> Result<Self> {
48                if bytes.len() != $size {
49                    Err(Error::BadLength {
50                        name: stringify!($type),
51                        actual: bytes.len(),
52                        expected: $size,
53                    })
54                } else {
55                    let mut array = [0u8; $size];
56                    array.copy_from_slice(bytes);
57                    Ok($type(array))
58                }
59            }
60        }
61
62        impl PartialEq for $type {
63            /// By no means constant time comparison
64            fn eq(&self, other: &Self) -> bool {
65                self.0
66                    .iter()
67                    .zip(other.0.iter())
68                    .try_for_each(|(a, b)| if a == b { Ok(()) } else { Err(()) })
69                    .is_ok()
70            }
71        }
72    };
73}
74
75simple_struct!(
76    PublicKey,
77    ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_PUBLICKEYBYTES
78);
79simple_struct!(
80    SecretKey,
81    ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_SECRETKEYBYTES
82);
83#[derive(Clone, Copy)]
84pub struct DetachedSignature([u8; ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES], usize);
85
86// for internal use
87impl DetachedSignature {
88    fn new() -> Self {
89        DetachedSignature([0u8; ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES], 0)
90    }
91}
92
93impl primitive::DetachedSignature for DetachedSignature {
94    /// Get this object as a byte slice
95    #[inline]
96    fn as_bytes(&self) -> &[u8] {
97        &self.0[..self.1]
98    }
99
100    #[inline]
101    fn from_bytes(bytes: &[u8]) -> Result<Self> {
102        let actual = bytes.len();
103        let expected = ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES;
104        if actual > expected {
105            return Err(Error::BadLength {
106                name: "DetachedSignature",
107                actual,
108                expected,
109            });
110        }
111        let mut array = [0u8; ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES];
112        array[..bytes.len()].copy_from_slice(bytes);
113        Ok(DetachedSignature(array, actual))
114    }
115}
116
117#[derive(Clone)]
118pub struct SignedMessage(Vec<u8>);
119impl primitive::SignedMessage for SignedMessage {
120    /// Get this object as a byte slice
121    #[inline]
122    fn as_bytes(&self) -> &[u8] {
123        &self.0.as_slice()
124    }
125
126    /// Construct this object from a byte slice
127    #[inline]
128    fn from_bytes(bytes: &[u8]) -> Result<Self> {
129        Ok(SignedMessage(bytes.to_vec()))
130    }
131}
132
133impl SignedMessage {
134    pub fn len(&self) -> usize {
135        self.0.len()
136    }
137}
138
139/// Get the number of bytes for a public key
140pub const fn public_key_bytes() -> usize {
141    ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_PUBLICKEYBYTES
142}
143
144/// Get the number of bytes for a secret key
145pub const fn secret_key_bytes() -> usize {
146    ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_SECRETKEYBYTES
147}
148
149/// Get the number of bytes that a signature occupies
150pub const fn signature_bytes() -> usize {
151    ffi::PQCLEAN_QTESLAPIII_CLEAN_CRYPTO_BYTES
152}
153
154/// Generate a qtesla-p-III keypair
155pub fn keypair() -> (PublicKey, SecretKey) {
156    keypair_portable()
157}
158
159#[inline]
160fn keypair_portable() -> (PublicKey, SecretKey) {
161    let mut pk = PublicKey::new();
162    let mut sk = SecretKey::new();
163    assert_eq!(
164        unsafe {
165            ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_keypair(pk.0.as_mut_ptr(), sk.0.as_mut_ptr())
166        },
167        0
168    );
169    (pk, sk)
170}
171
172/// Sign the message and return the signed message.
173pub fn sign(msg: &[u8], sk: &SecretKey) -> SignedMessage {
174    sign_portable(msg, sk)
175}
176
177#[inline]
178fn sign_portable(msg: &[u8], sk: &SecretKey) -> SignedMessage {
179    let max_len = msg.len() + signature_bytes();
180    let mut signed_msg = Vec::with_capacity(max_len);
181    let mut smlen: usize = 0;
182    unsafe {
183        ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign(
184            signed_msg.as_mut_ptr(),
185            &mut smlen as *mut usize,
186            msg.as_ptr(),
187            msg.len(),
188            sk.0.as_ptr(),
189        );
190        debug_assert!(smlen <= max_len, "exceeded Vec capacity");
191        signed_msg.set_len(smlen);
192    }
193    SignedMessage(signed_msg)
194}
195
196#[must_use]
197pub fn open(
198    sm: &SignedMessage,
199    pk: &PublicKey,
200) -> std::result::Result<Vec<u8>, primitive::VerificationError> {
201    open_portable(sm, pk)
202}
203
204#[inline]
205fn open_portable(
206    sm: &SignedMessage,
207    pk: &PublicKey,
208) -> std::result::Result<Vec<u8>, primitive::VerificationError> {
209    let mut m: Vec<u8> = Vec::with_capacity(sm.len());
210    let mut mlen: usize = 0;
211    match unsafe {
212        ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_open(
213            m.as_mut_ptr(),
214            &mut mlen as *mut usize,
215            sm.0.as_ptr(),
216            sm.len(),
217            pk.0.as_ptr(),
218        )
219    } {
220        0 => {
221            unsafe { m.set_len(mlen) };
222            Ok(m)
223        }
224        -1 => Err(primitive::VerificationError::InvalidSignature),
225        _ => Err(primitive::VerificationError::UnknownVerificationError),
226    }
227}
228
229pub fn detached_sign(msg: &[u8], sk: &SecretKey) -> DetachedSignature {
230    detached_sign_portable(msg, sk)
231}
232
233#[inline]
234fn detached_sign_portable(msg: &[u8], sk: &SecretKey) -> DetachedSignature {
235    let mut sig = DetachedSignature::new();
236    unsafe {
237        ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_signature(
238            sig.0.as_mut_ptr(),
239            &mut sig.1 as *mut usize,
240            msg.as_ptr(),
241            msg.len(),
242            sk.0.as_ptr(),
243        );
244    }
245    sig
246}
247
248#[must_use]
249pub fn verify_detached_signature(
250    sig: &DetachedSignature,
251    msg: &[u8],
252    pk: &PublicKey,
253) -> std::result::Result<(), primitive::VerificationError> {
254    verify_detached_signature_portable(sig, msg, pk)
255}
256
257fn verify_detached_signature_portable(
258    sig: &DetachedSignature,
259    msg: &[u8],
260    pk: &PublicKey,
261) -> std::result::Result<(), primitive::VerificationError> {
262    let res = unsafe {
263        ffi::PQCLEAN_QTESLAPIII_CLEAN_crypto_sign_verify(
264            sig.0.as_ptr(),
265            sig.1,
266            msg.as_ptr(),
267            msg.len(),
268            pk.0.as_ptr(),
269        )
270    };
271    match res {
272        0 => Ok(()),
273        -1 => Err(primitive::VerificationError::InvalidSignature),
274        _ => Err(primitive::VerificationError::UnknownVerificationError),
275    }
276}
277
278#[cfg(test)]
279mod test {
280    use super::*;
281    use rand::prelude::*;
282
283    #[test]
284    pub fn test_sign() {
285        let mut rng = rand::thread_rng();
286        let len: u16 = rng.gen();
287
288        let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
289        let (pk, sk) = keypair();
290        let sm = sign(&message, &sk);
291        let verifiedmsg = open(&sm, &pk).unwrap();
292        assert!(verifiedmsg == message);
293    }
294
295    #[test]
296    pub fn test_sign_detached() {
297        let mut rng = rand::thread_rng();
298        let len: u16 = rng.gen();
299        let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
300
301        let (pk, sk) = keypair();
302        let sig = detached_sign(&message, &sk);
303        assert!(verify_detached_signature(&sig, &message, &pk).is_ok());
304        assert!(!verify_detached_signature(&sig, &message[..message.len() - 1], &pk).is_ok());
305    }
306}