pqcrypto_rainbow/
rainbowiiiclassic.rs

1//! rainbowIII-classic
2//!
3//! These bindings use the clean version from [PQClean][pqc]
4//!
5//! **This algorithm has security problems**
6//!
7//! # Example
8//! ```
9//! use pqcrypto_rainbow::rainbowiiiclassic::*;
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_RAINBOWIIICLASSIC_CLEAN_CRYPTO_PUBLICKEYBYTES
89);
90simple_struct!(
91    SecretKey,
92    ffi::PQCLEAN_RAINBOWIIICLASSIC_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_RAINBOWIIICLASSIC_CLEAN_CRYPTO_BYTES],
100    usize,
101);
102
103// for internal use
104impl DetachedSignature {
105    fn new() -> Self {
106        DetachedSignature([0u8; ffi::PQCLEAN_RAINBOWIIICLASSIC_CLEAN_CRYPTO_BYTES], 0)
107    }
108}
109
110impl primitive::DetachedSignature for DetachedSignature {
111    /// Get this object as a byte slice
112    #[inline]
113    fn as_bytes(&self) -> &[u8] {
114        &self.0[..self.1]
115    }
116
117    #[inline]
118    fn from_bytes(bytes: &[u8]) -> Result<Self> {
119        let actual = bytes.len();
120        let expected = ffi::PQCLEAN_RAINBOWIIICLASSIC_CLEAN_CRYPTO_BYTES;
121        if actual > expected {
122            return Err(Error::BadLength {
123                name: "DetachedSignature",
124                actual,
125                expected,
126            });
127        }
128        let mut array = [0u8; ffi::PQCLEAN_RAINBOWIIICLASSIC_CLEAN_CRYPTO_BYTES];
129        array[..bytes.len()].copy_from_slice(bytes);
130        Ok(DetachedSignature(array, actual))
131    }
132}
133
134#[derive(Clone)]
135#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
136pub struct SignedMessage(Vec<u8>);
137impl primitive::SignedMessage for SignedMessage {
138    /// Get this object as a byte slice
139    #[inline]
140    fn as_bytes(&self) -> &[u8] {
141        self.0.as_slice()
142    }
143
144    /// Construct this object from a byte slice
145    #[inline]
146    fn from_bytes(bytes: &[u8]) -> Result<Self> {
147        Ok(SignedMessage(bytes.to_vec()))
148    }
149}
150
151impl SignedMessage {
152    pub fn len(&self) -> usize {
153        self.0.len()
154    }
155}
156
157/// Get the number of bytes for a public key
158pub const fn public_key_bytes() -> usize {
159    ffi::PQCLEAN_RAINBOWIIICLASSIC_CLEAN_CRYPTO_PUBLICKEYBYTES
160}
161
162/// Get the number of bytes for a secret key
163pub const fn secret_key_bytes() -> usize {
164    ffi::PQCLEAN_RAINBOWIIICLASSIC_CLEAN_CRYPTO_SECRETKEYBYTES
165}
166
167/// Get the number of bytes that a signature occupies
168pub const fn signature_bytes() -> usize {
169    ffi::PQCLEAN_RAINBOWIIICLASSIC_CLEAN_CRYPTO_BYTES
170}
171
172macro_rules! gen_keypair {
173    ($variant:ident) => {{
174        let mut pk = PublicKey::new();
175        let mut sk = SecretKey::new();
176        assert_eq!(
177            unsafe { ffi::$variant(pk.0.as_mut_ptr(), sk.0.as_mut_ptr()) },
178            0
179        );
180        (pk, sk)
181    }};
182}
183
184/// Generate a rainbowIII-classic keypair
185#[deprecated(note = "Insecure cryptography, do not use in production")]
186pub fn keypair() -> (PublicKey, SecretKey) {
187    gen_keypair!(PQCLEAN_RAINBOWIIICLASSIC_CLEAN_crypto_sign_keypair)
188}
189
190macro_rules! gen_signature {
191    ($variant:ident, $msg:ident, $sk:ident) => {{
192        let max_len = $msg.len() + signature_bytes();
193        let mut signed_msg = Vec::with_capacity(max_len);
194        let mut smlen: usize = 0;
195        unsafe {
196            ffi::$variant(
197                signed_msg.as_mut_ptr(),
198                &mut smlen as *mut usize,
199                $msg.as_ptr(),
200                $msg.len(),
201                $sk.0.as_ptr(),
202            );
203            debug_assert!(smlen <= max_len, "exceeded vector capacity");
204            signed_msg.set_len(smlen);
205        }
206        SignedMessage(signed_msg)
207    }};
208}
209
210/// Sign the message and return the signed message.
211#[deprecated(note = "Insecure cryptography, do not use in production")]
212pub fn sign(msg: &[u8], sk: &SecretKey) -> SignedMessage {
213    gen_signature!(PQCLEAN_RAINBOWIIICLASSIC_CLEAN_crypto_sign, msg, sk)
214}
215
216macro_rules! open_signed {
217    ($variant:ident, $sm:ident, $pk:ident) => {{
218        let mut m: Vec<u8> = Vec::with_capacity($sm.len());
219        let mut mlen: usize = 0;
220        match unsafe {
221            ffi::$variant(
222                m.as_mut_ptr(),
223                &mut mlen as *mut usize,
224                $sm.0.as_ptr(),
225                $sm.len(),
226                $pk.0.as_ptr(),
227            )
228        } {
229            0 => {
230                unsafe { m.set_len(mlen) };
231                Ok(m)
232            }
233            -1 => Err(primitive::VerificationError::InvalidSignature),
234            _ => Err(primitive::VerificationError::UnknownVerificationError),
235        }
236    }};
237}
238
239/// Open the signed message and if verification succeeds return the message
240#[deprecated(note = "Insecure cryptography, do not use in production")]
241pub fn open(
242    sm: &SignedMessage,
243    pk: &PublicKey,
244) -> core::result::Result<Vec<u8>, primitive::VerificationError> {
245    open_signed!(PQCLEAN_RAINBOWIIICLASSIC_CLEAN_crypto_sign_open, sm, pk)
246}
247
248macro_rules! detached_signature {
249    ($variant:ident, $msg:ident, $sk:ident) => {{
250        let mut sig = DetachedSignature::new();
251        unsafe {
252            ffi::$variant(
253                sig.0.as_mut_ptr(),
254                &mut sig.1 as *mut usize,
255                $msg.as_ptr(),
256                $msg.len(),
257                $sk.0.as_ptr(),
258            );
259        }
260        sig
261    }};
262}
263
264#[deprecated(note = "Insecure cryptography, do not use in production")]
265/// Create a detached signature on the message
266pub fn detached_sign(msg: &[u8], sk: &SecretKey) -> DetachedSignature {
267    detached_signature!(
268        PQCLEAN_RAINBOWIIICLASSIC_CLEAN_crypto_sign_signature,
269        msg,
270        sk
271    )
272}
273
274macro_rules! verify_detached_sig {
275    ($variant:ident, $sig:ident, $msg:ident, $pk:ident) => {{
276        let res = unsafe {
277            ffi::$variant(
278                $sig.0.as_ptr(),
279                $sig.1,
280                $msg.as_ptr(),
281                $msg.len(),
282                $pk.0.as_ptr(),
283            )
284        };
285        match res {
286            0 => Ok(()),
287            -1 => Err(primitive::VerificationError::InvalidSignature),
288            _ => Err(primitive::VerificationError::UnknownVerificationError),
289        }
290    }};
291}
292
293/// Verify the detached signature
294#[deprecated(note = "Insecure cryptography, do not use in production")]
295pub fn verify_detached_signature(
296    sig: &DetachedSignature,
297    msg: &[u8],
298    pk: &PublicKey,
299) -> core::result::Result<(), primitive::VerificationError> {
300    verify_detached_sig!(
301        PQCLEAN_RAINBOWIIICLASSIC_CLEAN_crypto_sign_verify,
302        sig,
303        msg,
304        pk
305    )
306}
307
308#[cfg(test)]
309mod test {
310    use super::*;
311    use rand::prelude::*;
312
313    #[test]
314    pub fn test_sign() {
315        let mut rng = rand::thread_rng();
316        let len: u16 = rng.gen();
317
318        let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
319        let (pk, sk) = keypair();
320        let sm = sign(&message, &sk);
321        let verifiedmsg = open(&sm, &pk).unwrap();
322        assert!(verifiedmsg == message);
323    }
324
325    #[test]
326    pub fn test_sign_detached() {
327        let mut rng = rand::thread_rng();
328        let len: u16 = rng.gen();
329        let message = (0..len).map(|_| rng.gen::<u8>()).collect::<Vec<_>>();
330
331        let (pk, sk) = keypair();
332        let sig = detached_sign(&message, &sk);
333        assert!(verify_detached_signature(&sig, &message, &pk).is_ok());
334        assert!(!verify_detached_signature(&sig, &message[..message.len() - 1], &pk).is_ok());
335    }
336}