1#[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 fn new() -> Self {
46 $type([0u8; $size])
47 }
48 }
49
50 impl primitive::$type for $type {
51 #[inline]
53 fn as_bytes(&self) -> &[u8] {
54 &self.0
55 }
56
57 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 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
103impl 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 #[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 #[inline]
143 fn as_bytes(&self) -> &[u8] {
144 self.0.as_slice()
145 }
146
147 #[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
160pub const fn public_key_bytes() -> usize {
162 ffi::PQCLEAN_RAINBOWVCIRCUMZENITHAL_CLEAN_CRYPTO_PUBLICKEYBYTES
163}
164
165pub const fn secret_key_bytes() -> usize {
167 ffi::PQCLEAN_RAINBOWVCIRCUMZENITHAL_CLEAN_CRYPTO_SECRETKEYBYTES
168}
169
170pub 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#[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#[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#[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")]
272pub 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#[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}