pqcrypto_picnic/
lib.rs

1//! # Picnic bindings for `pqcrypto`
2//!
3//! This crate implements the traits from [pqcrypto_traits] for the Picnic bindings available in
4//! [picnic_bindings].
5//!
6//! ## Usage
7//!
8//! ```
9//! # #[cfg(feature = "picnic")] {
10//! use pqcrypto_picnic::{picnic_l1_fs_keypair, picnic_l1_fs_open, picnic_l1_fs_sign};
11//!
12//! let (sk, pk) = picnic_l1_fs_keypair();
13//! let sm = picnic_l1_fs_sign(b"a message", &sk);
14//! let opened_msg = picnic_l1_fs_open(&sm, &pk).expect("signature did not verify");
15//! assert_eq!(opened_msg, b"a message");
16//! # }
17
18#![cfg_attr(not(feature = "std"), no_std)]
19
20#[cfg(not(feature = "std"))]
21extern crate alloc;
22
23#[cfg(not(feature = "std"))]
24use alloc::vec::Vec;
25
26use core::{marker::PhantomData, mem};
27use paste::paste;
28pub use picnic_bindings::{self, Parameters};
29use picnic_bindings::{
30    signature::{Signer, Verifier},
31    DynamicSignature, RawVerifier, SigningKey, VerificationKey,
32};
33pub use pqcrypto_traits::{
34    sign::{self, VerificationError},
35    Error,
36};
37
38#[cfg(feature = "serialization")]
39use serde::{Deserialize, Serialize};
40
41#[cfg(feature = "zeroize")]
42use zeroize::{Zeroize, ZeroizeOnDrop};
43
44const LENGTH_SIZE: usize = mem::size_of::<u32>();
45
46/// A Picnic secret key
47#[derive(Debug, Clone, Eq, PartialEq)]
48#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
49#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
50#[repr(transparent)]
51pub struct SecretKey<P>(SigningKey<P>)
52where
53    P: Parameters;
54
55impl<P> sign::SecretKey for SecretKey<P>
56where
57    P: Parameters,
58{
59    #[inline(always)]
60    fn as_bytes(&self) -> &[u8] {
61        self.0.as_ref()
62    }
63
64    fn from_bytes(bytes: &[u8]) -> pqcrypto_traits::Result<Self>
65    where
66        Self: Sized,
67    {
68        match SigningKey::<P>::try_from(bytes) {
69            Ok(sk) => Ok(Self(sk)),
70            Err(_) => Err(Error::BadLength {
71                name: "SecretKey",
72                actual: bytes.len(),
73                expected: P::PRIVATE_KEY_SIZE,
74            }),
75        }
76    }
77}
78
79/// A Picnic public key
80#[derive(Debug, Clone, Eq, PartialEq)]
81#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
82#[repr(transparent)]
83pub struct PublicKey<P>(VerificationKey<P>)
84where
85    P: Parameters;
86
87impl<P> sign::PublicKey for PublicKey<P>
88where
89    P: Parameters,
90{
91    #[inline]
92    fn as_bytes(&self) -> &[u8] {
93        self.0.as_ref()
94    }
95
96    fn from_bytes(bytes: &[u8]) -> pqcrypto_traits::Result<Self>
97    where
98        Self: Sized,
99    {
100        match VerificationKey::<P>::try_from(bytes) {
101            Ok(pk) => Ok(Self(pk)),
102            Err(_) => Err(Error::BadLength {
103                name: "PublicKey",
104                actual: bytes.len(),
105                expected: P::PUBLIC_KEY_SIZE,
106            }),
107        }
108    }
109}
110
111/// A signed message
112///
113/// The message and its signature are encoded in the same way as for the NIST submission of Picnic.
114/// The length of the signature (u32 in little endian) is followed the message and then the signature.
115#[derive(Debug, Clone, Eq, PartialEq)]
116#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
117#[repr(transparent)]
118pub struct SignedMessage<P>(
119    #[cfg_attr(feature = "serialization", serde(with = "serde_bytes"))] Vec<u8>,
120    #[cfg_attr(feature = "serialization", serde(skip))] PhantomData<P>,
121)
122where
123    P: Parameters;
124
125/// Pack message and a signature into a signed message
126fn pack(msg: &[u8], sig: DynamicSignature) -> Vec<u8> {
127    let sig_data = sig.as_ref();
128
129    let mut data = Vec::with_capacity(LENGTH_SIZE + msg.len() + sig_data.len());
130    data.extend_from_slice(&(sig_data.len() as u32).to_le_bytes());
131    data.extend_from_slice(msg);
132    data.extend_from_slice(sig_data);
133    data
134}
135
136/// Unpack message and signature from the signed message
137fn unpack(data: &[u8]) -> pqcrypto_traits::Result<(&[u8], &[u8])> {
138    let sm_len = data.len();
139    if sm_len < LENGTH_SIZE {
140        return Err(Error::BadLength {
141            name: "signature (signature length)",
142            actual: sm_len,
143            expected: LENGTH_SIZE,
144        });
145    }
146
147    let len = u32::from_le_bytes(data[..4].try_into().unwrap()) as usize;
148    if sm_len < len + LENGTH_SIZE {
149        return Err(Error::BadLength {
150            name: "signature (signature length and signature)",
151            actual: sm_len,
152            expected: len + LENGTH_SIZE,
153        });
154    }
155
156    let sig_offset = sm_len - len;
157    let message = &data[LENGTH_SIZE..sig_offset];
158    let signature = &data[sig_offset..];
159
160    Ok((message, signature))
161}
162
163impl<P> sign::SignedMessage for SignedMessage<P>
164where
165    P: Parameters,
166{
167    #[inline]
168    fn as_bytes(&self) -> &[u8] {
169        self.0.as_slice()
170    }
171
172    #[inline]
173    fn from_bytes(bytes: &[u8]) -> pqcrypto_traits::Result<Self> {
174        unpack(bytes).map(|_| SignedMessage(bytes.to_vec(), PhantomData))
175    }
176}
177
178/// A detached signature
179#[derive(Debug, Clone, Eq, PartialEq)]
180#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
181#[repr(transparent)]
182pub struct DetachedSignature<P>(
183    DynamicSignature,
184    #[cfg_attr(feature = "serialization", serde(skip))] PhantomData<P>,
185)
186where
187    P: Parameters;
188
189impl<P> sign::DetachedSignature for DetachedSignature<P>
190where
191    P: Parameters,
192{
193    #[inline]
194    fn as_bytes(&self) -> &[u8] {
195        self.0.as_ref()
196    }
197
198    #[inline]
199    fn from_bytes(bytes: &[u8]) -> pqcrypto_traits::Result<Self>
200    where
201        Self: Sized,
202    {
203        Ok(DetachedSignature(
204            DynamicSignature::from(bytes),
205            PhantomData,
206        ))
207    }
208}
209
210/// Generate a new Picnic key pair
211#[inline]
212pub(crate) fn keypair<P>() -> (SecretKey<P>, PublicKey<P>)
213where
214    P: Parameters,
215{
216    // the pqcrypto-* crates all provide infallible key generation; if the parameters are not
217    // implemented, random will fail
218    SigningKey::<P>::random()
219        .map(|(sk, pk)| (SecretKey(sk), PublicKey(pk)))
220        .expect("parameters not supported")
221}
222
223/// Sign a message
224#[inline]
225pub(crate) fn sign<P>(msg: &[u8], sk: &SecretKey<P>) -> SignedMessage<P>
226where
227    P: Parameters,
228{
229    let sig = sk.0.sign(msg);
230    SignedMessage(pack(msg, sig), PhantomData)
231}
232
233/// Verify a signed message and return the message on success
234#[inline]
235pub(crate) fn open<'a, P>(
236    sm: &'a SignedMessage<P>,
237    pk: &PublicKey<P>,
238) -> Result<&'a [u8], VerificationError>
239where
240    P: Parameters,
241{
242    let (message, signature) = unpack(&sm.0).map_err(|_| VerificationError::InvalidSignature)?;
243    match pk.0.verify_raw(message, signature) {
244        Ok(_) => Ok(message),
245        Err(_) => Err(VerificationError::InvalidSignature),
246    }
247}
248
249/// Generate a detached signature
250#[inline]
251pub(crate) fn detached_sign<P>(msg: &[u8], sk: &SecretKey<P>) -> DetachedSignature<P>
252where
253    P: Parameters,
254{
255    DetachedSignature(sk.0.sign(msg), PhantomData)
256}
257
258/// Verify a detached signature
259#[inline]
260pub(crate) fn verify_detached_signature<P>(
261    sig: &DetachedSignature<P>,
262    msg: &[u8],
263    pk: &PublicKey<P>,
264) -> Result<(), VerificationError>
265where
266    P: Parameters,
267{
268    pk.0.verify(msg, &sig.0)
269        .map_err(|_| VerificationError::InvalidSignature)
270}
271
272/// Get the number of bytes for a public key
273#[inline(always)]
274pub(crate) fn public_key_bytes<P>() -> usize
275where
276    P: Parameters,
277{
278    P::PUBLIC_KEY_SIZE
279}
280
281/// Get the number of bytes for a secret key
282#[inline(always)]
283pub(crate) fn secret_key_bytes<P>() -> usize
284where
285    P: Parameters,
286{
287    P::PRIVATE_KEY_SIZE
288}
289
290/// Get the maximum number of bytes a signature occupies
291#[inline(always)]
292pub(crate) fn signature_bytes<P>() -> usize
293where
294    P: Parameters,
295{
296    P::MAX_SIGNATURE_SIZE
297}
298
299macro_rules! define_implementation {
300    ($name:ident, $parameters:ident) => {
301        paste! {
302            #[doc = "Implementations of [pqcrypto_traits] for Picnic parameter set " $parameters]
303            pub mod $name {
304                pub use crate::{Error, VerificationError};
305                use picnic_bindings::$parameters;
306
307                /// A Picnic secret key
308                pub type SecretKey = crate::SecretKey<$parameters>;
309                /// A Picnic public key
310                pub type PublicKey = crate::PublicKey<$parameters>;
311                /// A message signed with Picnic
312                pub type SignedMessage = crate::SignedMessage<$parameters>;
313                /// A detached Picnic signature
314                pub type DetachedSignature = crate::DetachedSignature<$parameters>;
315
316                /// Generate a new Picnic key pair.
317                #[inline(always)]
318                pub fn keypair() -> (SecretKey, PublicKey) {
319                    crate::keypair::<$parameters>()
320                }
321
322                /// Sign a message.
323                #[inline(always)]
324                pub fn sign(msg: &[u8], sk: &SecretKey) -> SignedMessage {
325                    crate::sign(msg, sk)
326                }
327
328                /// Verify a signed message and return the message on success.
329                #[inline(always)]
330                pub fn open<'a>(sm: &'a SignedMessage, pk: &PublicKey) -> Result<&'a [u8], VerificationError> {
331                    crate::open(sm, pk)
332                }
333
334                /// Sign a message and generate a detached signature.
335                #[inline(always)]
336                pub fn detached_sign(msg: &[u8], sk: &SecretKey) -> DetachedSignature {
337                    crate::detached_sign(msg, sk)
338                }
339
340                /// Verify a detached signature.
341                #[inline(always)]
342                pub fn verify_detached_signature(
343                    sig: &DetachedSignature,
344                    msg: &[u8],
345                    pk: &PublicKey,
346                ) -> Result<(), VerificationError> {
347                    crate::verify_detached_signature(sig, msg, pk)
348                }
349
350                /// Get the number of bytes for a public key.
351                #[inline(always)]
352                pub fn public_key_bytes() -> usize {
353                    crate::public_key_bytes::<$parameters>()
354                }
355
356                /// Get the number of bytes for a secret key.
357                #[inline(always)]
358                pub fn secret_key_bytes() -> usize {
359                    crate::secret_key_bytes::<$parameters>()
360                }
361
362                /// Get the maximum number of bytes a signature occupies.
363                #[inline(always)]
364                pub fn signature_bytes() -> usize {
365                    crate::signature_bytes::<$parameters>()
366                }
367
368                #[cfg(test)]
369                mod test {
370                    #[cfg(not(feature = "std"))]
371                    extern crate alloc;
372
373                    #[cfg(not(feature = "std"))]
374                    use alloc::vec::Vec;
375
376                    use pqcrypto_traits::sign::{DetachedSignature as _, PublicKey as _, SecretKey as _, SignedMessage as _};
377
378                    pub(crate) const MSG: &[u8] = b"test message";
379
380                    #[test]
381                    fn keypair() {
382                        let (sk, pk) = super::keypair();
383                        assert_eq!(sk.as_bytes().len(), super::secret_key_bytes());
384                        assert_eq!(pk.as_bytes().len(), super::public_key_bytes());
385                    }
386
387                    #[test]
388                    fn sign() {
389                        let (sk, pk) = super::keypair();
390                        let sig = super::sign(MSG, &sk);
391                        assert_eq!(super::open(&sig, &pk).unwrap(), MSG);
392                        assert!(sig.as_bytes().len() <= super::signature_bytes() + MSG.len() + crate::LENGTH_SIZE)
393                    }
394
395                    #[test]
396                    fn detached_sign() {
397                        let (sk, pk) = super::keypair();
398                        let sig = super::detached_sign(MSG, &sk);
399                        assert!(super::verify_detached_signature(&sig, MSG, &pk).is_ok());
400                        assert!(sig.as_bytes().len() <= super::signature_bytes());
401                        assert!(super::verify_detached_signature(&sig, b"other msg", &pk).is_err());
402                    }
403
404                    #[test]
405                    fn sizes() {
406                        assert!(super::public_key_bytes() > 0);
407                        assert!(super::secret_key_bytes() > 0);
408                        assert!(super::signature_bytes() > 0);
409                    }
410
411                    #[test]
412                    fn signature_from_bytes() {
413                        assert!(super::SignedMessage::from_bytes(b"").is_err());
414                        assert!(super::SignedMessage::from_bytes(b"\xff\xff\xff").is_err());
415
416                        let bytes = 1234u32.to_le_bytes();
417                        assert!(super::SignedMessage::from_bytes(&bytes).is_err());
418
419                        let mut bytes = Vec::default();
420                        bytes.extend_from_slice(&(14u32.to_le_bytes()));
421                        bytes.extend_from_slice(b"some message");
422                        bytes.extend_from_slice(b"some signature");
423                        assert!(super::SignedMessage::from_bytes(&bytes).is_ok());
424                    }
425                }
426
427                #[cfg(all(test, feature = "serialization"))]
428                mod serialization_tests {
429                    use super::test::MSG;
430                    use serde::{Deserialize, Serialize};
431                    use serde_bytes_repr::{ByteFmtSerializer, ByteFmtDeserializer};
432
433                    #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
434                    struct KeyPair {
435                        sk: super::SecretKey,
436                        pk: super::PublicKey,
437                    }
438
439                    #[test]
440                    fn serialize() {
441                        let (sk, pk) = super::keypair();
442                        let kp1 = KeyPair { sk, pk };
443
444                        let mut out = vec![];
445                        let mut ser = serde_json::Serializer::new(&mut out);
446                        let ser = ByteFmtSerializer::hex(&mut ser);
447
448                        kp1.serialize(ser).unwrap();
449                        let serialized = String::from_utf8(out).unwrap();
450
451                        let mut json_de = serde_json::Deserializer::from_str(&serialized);
452                        let bytefmt_json_de = ByteFmtDeserializer::new_hex(&mut json_de);
453
454                        let kp2 = KeyPair::deserialize(bytefmt_json_de).unwrap();
455                        assert_eq!(kp1, kp2);
456                    }
457
458                    #[test]
459                    fn serialize_signed_msg() {
460                        let (sk, pk) = super::keypair();
461                        let sm1 = super::sign(MSG, &sk);
462
463                        let mut out = vec![];
464                        let mut ser = serde_json::Serializer::new(&mut out);
465                        let ser = ByteFmtSerializer::hex(&mut ser);
466
467                        sm1.serialize(ser).unwrap();
468                        let serialized = String::from_utf8(out).unwrap();
469
470                        let mut json_de = serde_json::Deserializer::from_str(&serialized);
471                        let bytefmt_json_de = ByteFmtDeserializer::new_hex(&mut json_de);
472
473                        let sm2 = crate::SignedMessage::deserialize(bytefmt_json_de).unwrap();
474                        assert_eq!(sm1, sm2);
475                        assert_eq!(MSG, super::open(&sm2, &pk).unwrap());
476                    }
477
478                    #[test]
479                    fn serialize_detached_signature() {
480                        let (sk, pk) = super::keypair();
481                        let sig1 = super::detached_sign(MSG, &sk);
482
483                        let mut out = vec![];
484                        let mut ser = serde_json::Serializer::new(&mut out);
485                        let ser = ByteFmtSerializer::hex(&mut ser);
486
487                        sig1.serialize(ser).unwrap();
488                        let serialized = String::from_utf8(out).unwrap();
489
490                        let mut json_de = serde_json::Deserializer::from_str(&serialized);
491                        let bytefmt_json_de = ByteFmtDeserializer::new_hex(&mut json_de);
492
493                        let sig2 = crate::DetachedSignature::deserialize(bytefmt_json_de).unwrap();
494                        assert_eq!(sig1, sig2);
495                        assert!(super::verify_detached_signature(&sig2, MSG, &pk).is_ok());
496                    }
497                }
498            }
499
500            pub use $name::{
501                detached_sign as [<$name _detached_sign>],
502                keypair as [<$name _keypair>],
503                open as [<$name _open>],
504                public_key_bytes as [<$name _public_key_bytes>],
505                secret_key_bytes as [<$name _secret_key_bytes>],
506                sign as [<$name _sign>],
507                signature_bytes as [<$name _signature_bytes>],
508                verify_detached_signature as [<$name _verify_detached_signature>],
509            };
510        }
511    };
512}
513
514#[cfg(feature = "picnic")]
515
516define_implementation!(picnic_l1_fs, PicnicL1FS);
517#[cfg(feature = "unruh-transform")]
518define_implementation!(picnic_l1_ur, PicnicL1UR);
519#[cfg(feature = "picnic")]
520define_implementation!(picnic_l1_full, PicnicL1Full);
521#[cfg(feature = "picnic3")]
522define_implementation!(picnic3_l1, Picnic3L1);
523
524#[cfg(feature = "picnic")]
525define_implementation!(picnic_l3_fs, PicnicL3FS);
526#[cfg(feature = "unruh-transform")]
527define_implementation!(picnic_l3_ur, PicnicL3UR);
528#[cfg(feature = "picnic")]
529define_implementation!(picnic_l3_full, PicnicL3Full);
530#[cfg(feature = "picnic3")]
531define_implementation!(picnic3_l3, Picnic3L3);
532
533#[cfg(feature = "picnic")]
534define_implementation!(picnic_l5_fs, PicnicL5FS);
535#[cfg(feature = "unruh-transform")]
536define_implementation!(picnic_l5_ur, PicnicL5UR);
537#[cfg(feature = "picnic")]
538define_implementation!(picnic_l5_full, PicnicL5Full);
539#[cfg(feature = "picnic3")]
540define_implementation!(picnic3_l5, Picnic3L5);