picnic_bindings/
lib.rs

1//! # Bindings for Picnic: Post-Quantum Signatures
2//!
3//! The Picnic signature scheme is a family of digital signature schemes secure against attacks by
4//! quantum computers. This crate provides bindings that implements the traits from the [signature]
5//! crate.
6//!
7//! More information on Picnic is available on the project website:
8//! <https://microsoft.github.io/Picnic/>
9//!
10//! Serialization and deserialization is implemented via the `serde` crate. By enabling the
11//! `serialization` feature, all public structs implement the `Serialize` and `Deserialize` traits.
12//!
13//! ## Usage
14//!
15//! Key generation, signing and verification can be implemented as follows:
16//! ```
17//! # #[cfg(feature="picnic")] {
18//! use picnic_bindings::{PicnicL1FSSigningKey, Signer, Verifier};
19//!
20//! let (signing_key, verification_key) = PicnicL1FSSigningKey::random().expect("Key generation failed");
21//! let msg = "some message".as_bytes();
22//! let signature = signing_key.sign(msg);
23//! verification_key.verify(msg, &signature).expect("Verification failed");
24//! # }
25//! ```
26//!
27//! Keys and signatures support conversions to and from `&[u8]`. The following code example
28//! demonstrates the necessary steps for [SigningKey]:
29//! ```
30//! # #[cfg(feature="picnic")] {
31//! use picnic_bindings::{PicnicL1FSSigningKey};
32//! use std::convert::TryFrom;
33//!
34//! let (signing_key, verification_key) = PicnicL1FSSigningKey::random().expect("Key generation failed");
35//! let signing_key_2 = PicnicL1FSSigningKey::try_from(signing_key.as_ref()).expect("Deserialization failed");
36//! assert_eq!(signing_key, signing_key_2);
37//! # }
38//! ```
39//!
40//! Alternatively:
41//! ```
42//! # #[cfg(feature="picnic")] {
43//! use picnic_bindings::{DynamicSigningKey, PicnicL1FS, Parameters, Signer, Verifier};
44//!
45//! let (signing_key, verification_key) = DynamicSigningKey::random(PicnicL1FS::PARAM).expect("Key generation failed");
46//! let msg = "some message".as_bytes();
47//! let signature = signing_key.sign(msg);
48//! verification_key.verify(msg, &signature).expect("Verification failed");
49//! # }
50//! ```
51//!
52//! In case a signature as only available as `&[u8]` and taking ownership is not desired, the
53//! [RawVerifier] trait offers a method to verify the signature without first converting it into an
54//! instance of [DynamicSignature].
55//! ```
56//! # #[cfg(feature="picnic")] {
57//! use picnic_bindings::{PicnicL1FSSigningKey, Signer, RawVerifier};
58//!
59//! let (signing_key, verification_key) = PicnicL1FSSigningKey::random().expect("Key generation failed");
60//! let msg = "some message".as_bytes();
61//! let signature = signing_key.sign(msg);
62//! // assume that this is the actual signature
63//! let signature = signature.as_ref();
64//! verification_key.verify_raw(msg, signature).expect("Verification failed");
65//! # }
66//! ```
67
68#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
69#![warn(missing_docs)]
70
71// If neither is specified, the crate is essentially empty.
72#[cfg(all(not(feature = "picnic"), not(feature = "picnic3")))]
73compile_error!("One of the features \"picnic\" and \"picnic3\" is required.");
74
75#[cfg(not(feature = "std"))]
76extern crate alloc;
77
78#[cfg(not(feature = "std"))]
79use alloc::{format, vec, vec::Vec};
80
81use core::fmt::{self, Debug};
82use core::marker::PhantomData;
83use libpicnic_sys::*;
84use paste::paste;
85pub use signature::{self, Error, Signer, Verifier};
86
87#[cfg(feature = "serialization")]
88use serde::{Deserialize, Deserializer, Serialize, Serializer};
89
90#[cfg(feature = "zeroize")]
91use zeroize::{Zeroize, ZeroizeOnDrop};
92
93#[cfg(feature = "subtle")]
94use subtle::{Choice, ConstantTimeEq};
95
96mod wrapper;
97use crate::wrapper::*;
98
99#[cfg(feature = "serialization")]
100mod serialization;
101
102#[cfg(feature = "serialization")]
103use serialization::{deserialize, serialize};
104
105/// Trait to describe Picnic parameters
106pub trait Parameters: Clone {
107    /// Internal parameter
108    const PARAM: picnic_params_t;
109    /// Max size of a signature
110    const MAX_SIGNATURE_SIZE: usize;
111    /// Size of the serialized private key
112    const PRIVATE_KEY_SIZE: usize;
113    /// Size of the serialized public key
114    const PUBLIC_KEY_SIZE: usize;
115
116    /// Retrieve name of the parameter set
117    fn parameter_name() -> &'static str;
118}
119
120/// Trait that allows to directly verify a signature from a `&[u8]`
121///
122/// With this trait verifiers are able to verify a signature without first storing it in a
123/// [DynamicSignature] to satisfy the [Verifier] interface.
124pub trait RawVerifier {
125    /// Verify a "raw" signature.
126    fn verify_raw(&self, msg: &[u8], signature: &[u8]) -> Result<(), Error>;
127}
128
129/// Define a parameters set and its associated implementations and types
130macro_rules! define_params {
131    ($name:ident, $param:ident) => {
132        paste! {
133            #[doc = $name " parameters"]
134            #[derive(Clone, Debug, PartialEq, Eq)]
135            #[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
136            pub struct $name {}
137
138            impl Parameters for $name {
139                const PARAM: picnic_params_t = picnic_params_t::$param;
140                const MAX_SIGNATURE_SIZE: usize = [<PICNIC_SIGNATURE_SIZE_ $param>];
141                const PRIVATE_KEY_SIZE: usize = [<PICNIC_PRIVATE_KEY_SIZE_ $param>];
142                const PUBLIC_KEY_SIZE: usize = [<PICNIC_PUBLIC_KEY_SIZE_ $param>];
143
144                #[inline(always)]
145                fn parameter_name() -> &'static str {
146                    "$param"
147                }
148            }
149
150            #[doc = "Signing key for " $name]
151            pub type [<$name SigningKey>] = SigningKey<$name>;
152            #[doc = "Verification key for " $name]
153            pub type [<$name VerificationKey>] = VerificationKey<$name>;
154        }
155    };
156}
157
158#[cfg(feature = "picnic")]
159define_params!(PicnicL1FS, Picnic_L1_FS);
160#[cfg(feature = "unruh-transform")]
161define_params!(PicnicL1UR, Picnic_L1_UR);
162#[cfg(feature = "picnic")]
163define_params!(PicnicL1Full, Picnic_L1_full);
164#[cfg(feature = "picnic3")]
165define_params!(Picnic3L1, Picnic3_L1);
166
167#[cfg(feature = "picnic")]
168define_params!(PicnicL3FS, Picnic_L3_FS);
169#[cfg(feature = "unruh-transform")]
170define_params!(PicnicL3UR, Picnic_L3_UR);
171#[cfg(feature = "picnic")]
172define_params!(PicnicL3Full, Picnic_L3_full);
173#[cfg(feature = "picnic3")]
174define_params!(Picnic3L3, Picnic3_L3);
175
176#[cfg(feature = "picnic")]
177define_params!(PicnicL5FS, Picnic_L5_FS);
178#[cfg(feature = "unruh-transform")]
179define_params!(PicnicL5UR, Picnic_L5_UR);
180#[cfg(feature = "picnic")]
181define_params!(PicnicL5Full, Picnic_L5_full);
182#[cfg(feature = "picnic3")]
183define_params!(Picnic3L5, Picnic3_L5);
184
185/// Signature stored in a `Vec`
186///
187/// While storing signatures in arrays is possible, their size varies even for the same parameter
188/// set.
189#[derive(Debug, Clone, Eq, PartialEq)]
190#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
191pub struct DynamicSignature(
192    #[cfg_attr(feature = "serialization", serde(with = "serde_bytes"))] Vec<u8>,
193);
194
195impl AsRef<[u8]> for DynamicSignature {
196    fn as_ref(&self) -> &[u8] {
197        self.0.as_ref()
198    }
199}
200
201impl From<&[u8]> for DynamicSignature {
202    fn from(bytes: &[u8]) -> Self {
203        Self(bytes.into())
204    }
205}
206
207/// Signing key generic over the parameters
208#[derive(Clone)]
209#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
210pub struct SigningKey<P: Parameters> {
211    data: PrivateKey,
212    #[cfg_attr(feature = "zeroize", zeroize(skip))]
213    phantom_data: PhantomData<P>,
214}
215
216impl<P> SigningKey<P>
217where
218    P: Parameters,
219{
220    /// Sample a new random signing key and the corresponding verification key.
221    /// This operation may fail if the Picnic library is not built with support
222    /// for the given parameter set.
223    pub fn random() -> Result<(Self, VerificationKey<P>), Error> {
224        PrivateKey::random(P::PARAM).map(|(sk, vk)| {
225            (
226                Self {
227                    data: sk,
228                    phantom_data: PhantomData,
229                },
230                VerificationKey {
231                    data: vk,
232                    phantom_data: PhantomData,
233                },
234            )
235        })
236    }
237}
238
239impl<P> Signer<DynamicSignature> for SigningKey<P>
240where
241    P: Parameters,
242{
243    fn try_sign(&self, msg: &[u8]) -> Result<DynamicSignature, Error> {
244        let mut signature = vec![0; P::MAX_SIGNATURE_SIZE];
245
246        let length = self.data.try_sign(msg, signature.as_mut_slice())?;
247        signature.resize(length, 0);
248        Ok(DynamicSignature(signature))
249    }
250}
251
252impl<P> Verifier<DynamicSignature> for SigningKey<P>
253where
254    P: Parameters,
255{
256    fn verify(&self, msg: &[u8], signature: &DynamicSignature) -> Result<(), Error> {
257        self.data
258            .public_key()
259            .and_then(|pk| pk.verify(msg, signature.as_ref()))
260    }
261}
262
263impl<P> PicnicKey for SigningKey<P>
264where
265    P: Parameters,
266{
267    #[inline(always)]
268    fn param(&self) -> picnic_params_t {
269        P::PARAM
270    }
271
272    #[inline(always)]
273    fn serialized_size(&self) -> usize {
274        P::PRIVATE_KEY_SIZE
275    }
276}
277
278impl<P> AsRef<[u8]> for SigningKey<P>
279where
280    P: Parameters,
281{
282    fn as_ref(&self) -> &[u8] {
283        // FIXME: this breaks the abstraction layer; this should be a call to picnic_write_private_key
284        &self.data.as_ref().data[0..P::PRIVATE_KEY_SIZE]
285    }
286}
287
288impl<P> TryFrom<&[u8]> for SigningKey<P>
289where
290    P: Parameters,
291{
292    type Error = Error;
293
294    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
295        let sk = PrivateKey::try_from(value)?;
296        match sk.param() == P::PARAM {
297            true => Ok(Self {
298                data: sk,
299                phantom_data: PhantomData,
300            }),
301            false => Err(Self::Error::new()),
302        }
303    }
304}
305
306impl<P> Debug for SigningKey<P>
307where
308    P: Parameters,
309{
310    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
311        fmt.debug_struct(&format!("SigningKey<{}>", P::parameter_name()))
312            .field("data", &"[...]")
313            .finish()
314    }
315}
316
317impl<P> PartialEq for SigningKey<P>
318where
319    P: Parameters,
320{
321    fn eq(&self, other: &Self) -> bool {
322        self.as_ref() == other.as_ref()
323    }
324}
325
326impl<P> Eq for SigningKey<P> where P: Parameters {}
327
328#[cfg(feature = "subtle")]
329impl<P> ConstantTimeEq for SigningKey<P>
330where
331    P: Parameters,
332{
333    fn ct_eq(&self, other: &Self) -> Choice {
334        self.as_ref().ct_eq(other.as_ref())
335    }
336}
337
338#[cfg(feature = "serialization")]
339impl<P> Serialize for SigningKey<P>
340where
341    P: Parameters,
342{
343    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
344    where
345        S: Serializer,
346    {
347        serialize(self, serializer)
348    }
349}
350
351#[cfg(feature = "serialization")]
352impl<'de, P> Deserialize<'de> for SigningKey<P>
353where
354    P: Parameters,
355{
356    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
357    where
358        D: Deserializer<'de>,
359    {
360        deserialize(deserializer)
361    }
362}
363
364/// Verification key generic over the parameters
365#[derive(Clone)]
366pub struct VerificationKey<P: Parameters> {
367    data: PublicKey,
368    phantom_data: PhantomData<P>,
369}
370
371impl<P> Verifier<DynamicSignature> for VerificationKey<P>
372where
373    P: Parameters,
374{
375    fn verify(&self, msg: &[u8], signature: &DynamicSignature) -> Result<(), Error> {
376        self.verify_raw(msg, &signature.0)
377    }
378}
379
380impl<P> RawVerifier for VerificationKey<P>
381where
382    P: Parameters,
383{
384    fn verify_raw(&self, msg: &[u8], signature: &[u8]) -> Result<(), Error> {
385        self.data.verify(msg, signature)
386    }
387}
388
389impl<P> PicnicKey for VerificationKey<P>
390where
391    P: Parameters,
392{
393    #[inline(always)]
394    fn param(&self) -> picnic_params_t {
395        P::PARAM
396    }
397
398    #[inline(always)]
399    fn serialized_size(&self) -> usize {
400        P::PUBLIC_KEY_SIZE
401    }
402}
403
404impl<P> AsRef<[u8]> for VerificationKey<P>
405where
406    P: Parameters,
407{
408    fn as_ref(&self) -> &[u8] {
409        // FIXME: this breaks the abstraction layer; this should be a call to picnic_write_public_key
410        &self.data.as_ref().data[0..P::PUBLIC_KEY_SIZE]
411    }
412}
413
414impl<P> TryFrom<&[u8]> for VerificationKey<P>
415where
416    P: Parameters,
417{
418    type Error = Error;
419
420    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
421        let vk = PublicKey::try_from(value)?;
422        match vk.param() == P::PARAM {
423            true => Ok(Self {
424                data: vk,
425                phantom_data: PhantomData,
426            }),
427            false => Err(Self::Error::new()),
428        }
429    }
430}
431
432impl<P> TryFrom<&SigningKey<P>> for VerificationKey<P>
433where
434    P: Parameters,
435{
436    type Error = Error;
437
438    fn try_from(sk: &SigningKey<P>) -> Result<Self, Self::Error> {
439        sk.data.public_key().map(|vk| Self {
440            data: vk,
441            phantom_data: PhantomData,
442        })
443    }
444}
445
446impl<P> Debug for VerificationKey<P>
447where
448    P: Parameters,
449{
450    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
451        fmt.debug_struct(&format!("VerificationKey<{}>", P::parameter_name()))
452            .field("data", &self.data)
453            .finish()
454    }
455}
456
457impl<P> PartialEq for VerificationKey<P>
458where
459    P: Parameters,
460{
461    fn eq(&self, other: &Self) -> bool {
462        self.as_ref() == other.as_ref()
463    }
464}
465
466impl<P> Eq for VerificationKey<P> where P: Parameters {}
467
468#[cfg(feature = "serialization")]
469impl<P> Serialize for VerificationKey<P>
470where
471    P: Parameters,
472{
473    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
474    where
475        S: Serializer,
476    {
477        serialize(self, serializer)
478    }
479}
480
481#[cfg(feature = "serialization")]
482impl<'de, P> Deserialize<'de> for VerificationKey<P>
483where
484    P: Parameters,
485{
486    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
487    where
488        D: Deserializer<'de>,
489    {
490        deserialize(deserializer)
491    }
492}
493
494/// Signing key
495#[derive(Clone)]
496#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
497pub struct DynamicSigningKey {
498    data: PrivateKey,
499}
500
501impl Debug for DynamicSigningKey {
502    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
503        fmt.debug_struct("DynamicSigningKey")
504            .field("param", &self.param())
505            .field("data", &"[...]")
506            .finish()
507    }
508}
509
510impl DynamicSigningKey {
511    /// Sample a new random signing key and the corresponding verification key.
512    /// This operation may fail if the Picnic library is not built with support
513    /// for the given parameter set.
514    pub fn random(params: picnic_params_t) -> Result<(Self, DynamicVerificationKey), Error> {
515        PrivateKey::random(params)
516            .map(|(sk, vk)| (Self { data: sk }, DynamicVerificationKey { data: vk }))
517    }
518}
519
520impl Signer<DynamicSignature> for DynamicSigningKey {
521    fn try_sign(&self, msg: &[u8]) -> Result<DynamicSignature, Error> {
522        let mut signature = vec![0; signature_size(self.param())];
523        let length = self.data.try_sign(msg, signature.as_mut_slice())?;
524        signature.resize(length, 0);
525        Ok(DynamicSignature(signature))
526    }
527}
528
529impl Verifier<DynamicSignature> for DynamicSigningKey {
530    fn verify(&self, msg: &[u8], signature: &DynamicSignature) -> Result<(), Error> {
531        self.data
532            .public_key()
533            .and_then(|pk| pk.verify(msg, signature.as_ref()))
534    }
535}
536
537impl PicnicKey for DynamicSigningKey {
538    #[inline(always)]
539    fn param(&self) -> picnic_params_t {
540        self.data.param()
541    }
542
543    #[inline(always)]
544    fn serialized_size(&self) -> usize {
545        self.data.serialized_size()
546    }
547}
548
549impl AsRef<[u8]> for DynamicSigningKey {
550    fn as_ref(&self) -> &[u8] {
551        // FIXME: this breaks the abstraction layer; this should be a call to picnic_write_private_key
552        &self.data.as_ref().data[0..self.serialized_size()]
553    }
554}
555
556impl TryFrom<&[u8]> for DynamicSigningKey {
557    type Error = Error;
558
559    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
560        let sk = PrivateKey::try_from(value)?;
561        match sk.param() != picnic_params_t::PARAMETER_SET_INVALID {
562            true => Ok(DynamicSigningKey { data: sk }),
563            false => Err(Self::Error::new()),
564        }
565    }
566}
567
568impl PartialEq for DynamicSigningKey {
569    fn eq(&self, other: &Self) -> bool {
570        self.param() == other.param() && {
571            let size = self.serialized_size();
572            self.data.as_ref().data[..size] == other.data.as_ref().data[..size]
573        }
574    }
575}
576
577impl Eq for DynamicSigningKey {}
578
579#[cfg(feature = "serialization")]
580impl Serialize for DynamicSigningKey {
581    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
582    where
583        S: Serializer,
584    {
585        serialize(self, serializer)
586    }
587}
588
589#[cfg(feature = "serialization")]
590impl<'de> Deserialize<'de> for DynamicSigningKey {
591    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
592    where
593        D: Deserializer<'de>,
594    {
595        deserialize(deserializer)
596    }
597}
598
599/// Verification key
600#[derive(Clone, Debug)]
601pub struct DynamicVerificationKey {
602    data: PublicKey,
603}
604
605impl Verifier<DynamicSignature> for DynamicVerificationKey {
606    fn verify(&self, msg: &[u8], signature: &DynamicSignature) -> Result<(), Error> {
607        self.verify_raw(msg, &signature.0)
608    }
609}
610
611impl RawVerifier for DynamicVerificationKey {
612    fn verify_raw(&self, msg: &[u8], signature: &[u8]) -> Result<(), Error> {
613        self.data.verify(msg, signature)
614    }
615}
616
617impl PicnicKey for DynamicVerificationKey {
618    #[inline(always)]
619    fn param(&self) -> picnic_params_t {
620        self.data.param()
621    }
622
623    #[inline(always)]
624    fn serialized_size(&self) -> usize {
625        self.data.serialized_size()
626    }
627}
628
629impl AsRef<[u8]> for DynamicVerificationKey {
630    fn as_ref(&self) -> &[u8] {
631        // FIXME: this breaks the abstraction layer; this should be a call to picnic_write_public_key
632        &self.data.as_ref().data[0..self.serialized_size()]
633    }
634}
635
636impl TryFrom<&[u8]> for DynamicVerificationKey {
637    type Error = Error;
638
639    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
640        let vk = PublicKey::try_from(value)?;
641        match vk.param() != picnic_params_t::PARAMETER_SET_INVALID {
642            true => Ok(DynamicVerificationKey { data: vk }),
643            false => Err(Self::Error::new()),
644        }
645    }
646}
647
648impl TryFrom<&DynamicSigningKey> for DynamicVerificationKey {
649    type Error = Error;
650
651    fn try_from(sk: &DynamicSigningKey) -> Result<Self, Self::Error> {
652        sk.data.public_key().map(|vk| Self { data: vk })
653    }
654}
655
656impl PartialEq for DynamicVerificationKey {
657    fn eq(&self, other: &Self) -> bool {
658        self.param() == other.param() && {
659            let size = self.serialized_size();
660            self.data.as_ref().data[..size] == other.data.as_ref().data[..size]
661        }
662    }
663}
664
665impl Eq for DynamicVerificationKey {}
666
667#[cfg(feature = "serialization")]
668impl Serialize for DynamicVerificationKey {
669    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
670    where
671        S: Serializer,
672    {
673        serialize(self, serializer)
674    }
675}
676
677#[cfg(feature = "serialization")]
678impl<'de> Deserialize<'de> for DynamicVerificationKey {
679    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
680    where
681        D: Deserializer<'de>,
682    {
683        deserialize(deserializer)
684    }
685}
686
687#[cfg(test)]
688mod test {
689    #[cfg(feature = "picnic")]
690    use crate::{PicnicL1FSSigningKey, PicnicL1FullSigningKey, PicnicL1FullVerificationKey};
691
692    #[cfg(feature = "picnic")]
693    #[test]
694    fn serialization_param_mismatch() {
695        let (sk1, vk1) = PicnicL1FSSigningKey::random().expect("unable to generate keys");
696        PicnicL1FullSigningKey::try_from(sk1.as_ref()).expect_err("deserialization did not fail");
697        PicnicL1FullVerificationKey::try_from(vk1.as_ref())
698            .expect_err("deserialization did not fail");
699    }
700}