pqcrypto_rainbow/
rainbowvcircumzenithal.rs

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