bbs_plus/
setup.rs

1#![allow(non_snake_case)]
2
3//! Keys and setup parameters
4//! # Examples
5//!
6//! Creating signature parameters and keypair:
7//!
8//! ```
9//! use ark_bls12_381::Bls12_381;
10//! use blake2::Blake2b512;
11//! use bbs_plus::setup::{SignatureParamsG1, SignatureParamsG2, KeypairG1, KeypairG2, PublicKeyG2, SignatureParams23G1};
12//!
13//! // For BBS+ signatures
14//!
15//! let params_g1 = SignatureParamsG1::<Bls12_381>::generate_using_rng(&mut rng, 5);
16//! let params_g2 = SignatureParamsG2::<Bls12_381>::generate_using_rng(&mut rng, 5);
17//! let params_g1_1 = SignatureParamsG1::<Bls12_381>::new::<Blake2b512>(&[1, 2, 3, 4], 5);
18//! let params_g2_1 = SignatureParamsG2::<Bls12_381>::new::<Blake2b512>(&[1, 2, 3, 4], 5);
19//!
20//! let keypair_g2 = KeypairG2::<Bls12_381>::generate_using_rng(&mut rng, &params_g1);
21//! let keypair_g1 = KeypairG1::<Bls12_381>::generate_using_rng(&mut rng, &params_g2);
22//!
23//! // Generate keypair using a secret `seed`. The same seed will return same keypair. The seed
24//! // is hashed (along with other things) using the given hash function, the example below use Blake2b512
25//! // let seed: &[u8] = <Some secret seed>
26//! let keypair_g21 = KeypairG2::<Bls12_381>::generate_using_seed::<Blake2b512>(seed, &params_g1);
27//!
28//! // public and secret key from `Keypair`
29//! let sk = keypair_g2.secret_key;
30//! let pk = keypair_g2.public_key;
31//!
32//! // Another way to generate keypair is
33//! let sk = SecretKey::generate_using_seed::<Blake2b512>(&seed);
34//! let pk = PublicKeyG2::public_key_from_secret_key(&sk, &params_g1);
35//! KeypairG2 {secret_key: sk, public_key: pk}
36//!
37//! // For BBS signatures
38//!
39//! // For BBS, sig params are `SignatureParams23G1` but public key is `PublicKeyG2`
40//! let params = SignatureParams23G1::<Bls12_381>::generate_using_rng(&mut rng, 5);
41//! let params_1 = SignatureParams23G1::<Bls12_381>::new::<Blake2b512>(&[1, 2, 3, 4], 5);
42//!
43//! let keypair = KeypairG2::<Bls12_381>::generate_using_rng_and_bbs23_params(&mut rng, &params);
44//! let keypair_1 = KeypairG2::<Bls12_381>::generate_using_seed_and_bbs23_params::<Blake2b512>(seed, &params);
45//!
46//! let pk = PublicKeyG2::generate_using_secret_key_and_bbs23_params(&sk, &params);
47//! KeypairG2 {secret_key: sk, public_key: pk}
48//! ```
49
50use crate::error::BBSPlusError;
51use ark_ec::{pairing::Pairing, AffineRepr, CurveGroup, VariableBaseMSM};
52use ark_ff::PrimeField;
53use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
54use ark_std::{cfg_iter, fmt::Debug, rand::RngCore, vec::Vec, UniformRand};
55use digest::{Digest, DynDigest};
56
57use zeroize::{Zeroize, ZeroizeOnDrop};
58
59use core::iter::once;
60use dock_crypto_utils::{
61    affine_group_element_from_byte_slices,
62    aliases::*,
63    concat_slices,
64    hashing_utils::{hash_to_field, projective_group_elem_from_try_and_incr},
65    iter::*,
66    join,
67    misc::{n_projective_group_elements, seq_pairs_satisfy},
68    serde_utils::*,
69    signature::MultiMessageSignatureParams,
70    try_iter::CheckLeft,
71};
72use itertools::process_results;
73
74#[cfg(feature = "parallel")]
75use rayon::prelude::*;
76
77use serde::{Deserialize, Serialize};
78use serde_with::serde_as;
79
80/// Secret key used by the signer to sign messages
81#[serde_as]
82#[derive(
83    Clone,
84    PartialEq,
85    Eq,
86    Debug,
87    CanonicalSerialize,
88    CanonicalDeserialize,
89    Serialize,
90    Deserialize,
91    Zeroize,
92    ZeroizeOnDrop,
93)]
94pub struct SecretKey<F: PrimeField>(#[serde_as(as = "ArkObjectBytes")] pub F);
95
96impl<F: PrimeField> SecretKey<F> {
97    pub const DST: &'static [u8] = b"BBS-SIG-KEYGEN-SALT";
98    pub fn generate_using_seed<D>(seed: &[u8]) -> Self
99    where
100        F: PrimeField,
101        D: Default + DynDigest + Clone,
102    {
103        Self(hash_to_field::<F, D>(Self::DST, seed))
104    }
105}
106
107macro_rules! impl_multi_msg_sig_params {
108    ($name: ident) => {
109        impl<E: Pairing> MultiMessageSignatureParams for $name<E> {
110            fn supported_message_count(&self) -> usize {
111                self.h.len()
112            }
113        }
114
115        impl<E: Pairing> MultiMessageSignatureParams for &$name<E> {
116            fn supported_message_count(&self) -> usize {
117                self.h.len()
118            }
119        }
120    };
121}
122
123macro_rules! impl_sig_params_prepared {
124    ( $group_affine:ident, $group_projective:ident) => {
125        /// Commit to given messages using the parameters and the given blinding as a Pedersen commitment.
126        /// `indexed_messages_sorted_by_index` must produce items sorted by unique indices, otherwise,
127        /// an error will be returned.
128        /// Eg. if given messages `m_i`, `m_j`, and `m_k` in the iterator, the commitment converts messages to
129        /// scalars and multiplies them by the parameter curve points:
130        /// `params.h_0 * blinding + params.h_i * m_i + params.h_j * m_j + params.h_k * m_k`
131        /// Computes using multi-scalar multiplication
132        pub fn commit_to_messages<'a, MI>(
133            &self,
134            indexed_messages_sorted_by_index: MI,
135            blinding: &'a E::ScalarField,
136        ) -> Result<E::$group_affine, BBSPlusError>
137        where
138            MI: IntoIterator<Item = (usize, &'a E::ScalarField)>,
139        {
140            let (bases, scalars): (Vec<_>, Vec<_>) = process_results(
141                pair_valid_items_with_slice::<_, _, _, BBSPlusError, _>(
142                    indexed_messages_sorted_by_index,
143                    CheckLeft(seq_pairs_satisfy(|a, b| a < b)),
144                    &self.h,
145                ),
146                |iter| iter.chain(once((&self.h_0, blinding))).unzip(),
147            )?;
148
149            Ok(E::$group_projective::msm_unchecked(&bases, &scalars).into_affine())
150        }
151
152        /// Compute `b` from the paper (equivalently 'A*{e+x}').
153        /// `indexed_messages_sorted_by_index` must produce items sorted by unique indices, otherwise,
154        /// an error will be returned.
155        /// Commits to the given messages and adds `self.g1` to it,
156        /// `b = g_1 + h_0 * s + sum(h_i * m_i)` for all indices `i` in the map.
157        pub fn b<'a, MI>(
158            &self,
159            indexed_messages_sorted_by_index: MI,
160            s: &'a E::ScalarField,
161        ) -> Result<E::$group_projective, BBSPlusError>
162        where
163            MI: IntoIterator<Item = (usize, &'a E::ScalarField)>,
164        {
165            let commitment = self.commit_to_messages(indexed_messages_sorted_by_index, s)?;
166            Ok(commitment + self.g1)
167        }
168    };
169}
170
171macro_rules! impl_sig_params_prepared_bbs23 {
172    ( $group_affine:ident, $group_projective:ident) => {
173        /// Commit to given messages using the parameters and the given blinding as a Pedersen commitment.
174        /// `indexed_messages_sorted_by_index` must produce items sorted by unique indices, otherwise,
175        /// an error will be returned.
176        /// Eg. if given messages `m_i`, `m_j`, and `m_k` in the iterator, the commitment converts messages to
177        /// scalars and multiplies them by the parameter curve points:
178        /// `params.h_i * m_i + params.h_j * m_j + params.h_k * m_k`
179        /// Computes using multi-scalar multiplication
180        pub fn commit_to_messages<'a, MI>(
181            &self,
182            indexed_messages_sorted_by_index: MI,
183        ) -> Result<E::$group_affine, BBSPlusError>
184        where
185            MI: IntoIterator<Item = (usize, &'a E::ScalarField)>,
186        {
187            let (bases, scalars): (Vec<_>, Vec<_>) = process_results(
188                pair_valid_items_with_slice::<_, _, _, BBSPlusError, _>(
189                    indexed_messages_sorted_by_index,
190                    CheckLeft(seq_pairs_satisfy(|a, b| a < b)),
191                    &self.h,
192                ),
193                |iter| iter.unzip(),
194            )?;
195
196            Ok(E::$group_projective::msm_unchecked(&bases, &scalars).into_affine())
197        }
198
199        /// Compute `b` from the paper (equivalently 'A*{e+x}').
200        /// `indexed_messages_sorted_by_index` must produce items sorted by unique indices, otherwise,
201        /// an error will be returned.
202        /// Commits to the given messages and adds `self.g1` to it,
203        /// `b = g_1 + + sum(h_i * m_i)` for all indices `i` in the map.
204        pub fn b<'a, MI>(
205            &self,
206            indexed_messages_sorted_by_index: MI,
207        ) -> Result<E::$group_projective, BBSPlusError>
208        where
209            MI: IntoIterator<Item = (usize, &'a E::ScalarField)>,
210        {
211            let commitment = self.commit_to_messages(indexed_messages_sorted_by_index)?;
212            Ok(commitment + self.g1)
213        }
214    };
215}
216
217macro_rules! impl_sig_params {
218    ( $name:ident, $group_affine:ident, $group_projective:ident, $other_group_affine:ident, $other_group_projective:ident ) => {
219        /// BBS+ signature params used while signing and verifying. Also used when proving knowledge of signature.
220        /// Every signer _can_ create his own params but several signers _can_ share the same parameters if
221        /// signing messages of the same size and still have their own public keys.
222        /// Size of parameters is proportional to the number of messages
223        #[serde_as]
224        #[derive(
225            Clone,
226            PartialEq,
227            Eq,
228            Debug,
229            CanonicalSerialize,
230            CanonicalDeserialize,
231            Serialize,
232            Deserialize,
233        )]
234        pub struct $name<E: Pairing> {
235            #[serde_as(as = "ArkObjectBytes")]
236            pub g1: E::$group_affine,
237            #[serde_as(as = "ArkObjectBytes")]
238            pub g2: E::$other_group_affine,
239            #[serde_as(as = "ArkObjectBytes")]
240            pub h_0: E::$group_affine,
241            /// Vector of size same as the size of multi-message that needs to be signed.
242            #[serde_as(as = "Vec<ArkObjectBytes>")]
243            pub h: Vec<E::$group_affine>,
244        }
245
246        impl<E: Pairing> $name<E> {
247            /// Generate params by hashing a known string. The hash function is vulnerable to timing
248            /// attack but since all this is public knowledge, it is fine.
249            /// This is useful if people need to be convinced that the discrete log of group elements wrt each other is not known.
250            pub fn new<D: Digest>(label: &[u8], message_count: u32) -> Self {
251                assert_ne!(message_count, 0);
252
253                let ((h, [g1, h_0]), g2) = join!(
254                    {
255                        let g1 = projective_group_elem_from_try_and_incr::<E::$group_affine, D>(
256                            &concat_slices!(label, b" : g1"),
257                        );
258                        let h_bytes = concat_slices!(label, b" : h_");
259                        // h_i for i in 0 to message_count
260                        let h = n_projective_group_elements::<E::$group_affine, D>(
261                            0..message_count + 1,
262                            &h_bytes,
263                        );
264                        let g1_and_h: Vec<_> = iter::once(g1).chain(h).collect();
265
266                        // Convert all to affine
267                        let mut normalized_g1_and_h =
268                            E::$group_projective::normalize_batch(&g1_and_h);
269
270                        (
271                            normalized_g1_and_h.split_off(2),
272                            <[_; 2]>::try_from(normalized_g1_and_h).unwrap(),
273                        )
274                    },
275                    affine_group_element_from_byte_slices!(label, b" : g2")
276                );
277
278                Self { g1, g2, h_0, h }
279            }
280
281            /// Generate params using a random number generator
282            pub fn generate_using_rng<R>(rng: &mut R, message_count: u32) -> Self
283            where
284                R: RngCore,
285            {
286                assert_ne!(message_count, 0);
287                let h = (0..message_count)
288                    .into_iter()
289                    .map(|_| E::$group_projective::rand(rng))
290                    .collect::<Vec<E::$group_projective>>();
291                Self {
292                    g1: E::$group_affine::rand(rng),
293                    g2: E::$other_group_affine::rand(rng),
294                    h_0: E::$group_affine::rand(rng),
295                    h: E::$group_projective::normalize_batch(&h),
296                }
297            }
298
299            /// Check that all group elements are non-zero (returns false if any element is zero).
300            /// A verifier on receiving these parameters must first check that they are valid and only
301            /// then use them for any signature or proof of knowledge of signature verification.
302            pub fn is_valid(&self) -> bool {
303                !(self.g1.is_zero()
304                    || self.g2.is_zero()
305                    || self.h_0.is_zero()
306                    || cfg_iter!(self.h).any(|v| v.is_zero()))
307            }
308
309            impl_sig_params_prepared!($group_affine, $group_projective);
310        }
311    };
312}
313
314macro_rules! impl_public_key_generation {
315    ($gen_function_name: ident, $params:ident) => {
316        /// Generate public key from given secret key and signature parameter g_2
317        pub fn $gen_function_name(
318            secret_key: &SecretKey<E::ScalarField>,
319            params: &$params<E>,
320        ) -> Self {
321            Self(params.g2.mul_bigint(secret_key.0.into_bigint()).into())
322        }
323    };
324}
325
326macro_rules! impl_public_key {
327    ( $name:ident, $group:ident, $params:ident ) => {
328        /// Public key of the signer. The signer can use the same public key with different
329        /// signature parameters to sign different multi-messages, provided that parameter
330        /// `g2` is consistent with the 'g2' used to generate the public key.
331        #[serde_as]
332        #[derive(
333            Clone,
334            PartialEq,
335            Eq,
336            Debug,
337            CanonicalSerialize,
338            CanonicalDeserialize,
339            Serialize,
340            Deserialize,
341        )]
342        pub struct $name<E: Pairing>(#[serde_as(as = "ArkObjectBytes")] pub <E as Pairing>::$group);
343
344        impl<E: Pairing> $name<E>
345        where
346            E: Pairing,
347        {
348            impl_public_key_generation!(generate_using_secret_key, $params);
349
350            /// Public key shouldn't be 0. A verifier on receiving this must first check that its
351            /// valid and only then use it for any signature or proof of knowledge of signature verification.
352            pub fn is_valid(&self) -> bool {
353                !self.0.is_zero()
354            }
355        }
356    };
357}
358
359macro_rules! impl_keypair_generation {
360    ( $gen_using_seed_fn_name:ident, $gen_using_rng_fn_name:ident, $gen_using_sk_fn_name:ident, $pk: ident, $params:ident ) => {
361        pub fn $gen_using_seed_fn_name<D>(seed: &[u8], params: &$params<E>) -> Self
362        where
363            D: DynDigest + Default + Clone,
364        {
365            let secret_key = SecretKey::<E::ScalarField>::generate_using_seed::<D>(seed);
366            let public_key = $pk::$gen_using_sk_fn_name(&secret_key, params);
367            Self {
368                secret_key,
369                public_key,
370            }
371        }
372
373        pub fn $gen_using_rng_fn_name<R: RngCore>(rng: &mut R, params: &$params<E>) -> Self {
374            let secret_key = SecretKey(E::ScalarField::rand(rng));
375            let public_key = $pk::$gen_using_sk_fn_name(&secret_key, params);
376            Self {
377                secret_key,
378                public_key,
379            }
380        }
381    };
382}
383
384macro_rules! impl_keypair {
385    ( $name:ident, $group:ident, $pk: ident, $params:ident ) => {
386        #[derive(
387            Clone,
388            Debug,
389            Eq,
390            PartialEq,
391            CanonicalSerialize,
392            CanonicalDeserialize,
393            Serialize,
394            Deserialize,
395            Zeroize,
396            ZeroizeOnDrop,
397        )]
398        #[serde(bound = "")]
399        pub struct $name<E: Pairing> {
400            pub secret_key: SecretKey<E::ScalarField>,
401            #[zeroize(skip)]
402            pub public_key: $pk<E>,
403        }
404
405        /// Create a secret key and corresponding public key
406        impl<E: Pairing> $name<E> {
407            impl_keypair_generation!(
408                generate_using_seed,
409                generate_using_rng,
410                generate_using_secret_key,
411                $pk,
412                $params
413            );
414        }
415    };
416}
417
418impl_sig_params!(SignatureParamsG1, G1Affine, G1, G2Affine, G2);
419impl_multi_msg_sig_params!(SignatureParamsG1);
420impl_sig_params!(SignatureParamsG2, G2Affine, G2, G1Affine, G1);
421impl_multi_msg_sig_params!(SignatureParamsG2);
422impl_public_key!(PublicKeyG2, G2Affine, SignatureParamsG1);
423impl_public_key!(PublicKeyG1, G1Affine, SignatureParamsG2);
424impl_keypair!(KeypairG2, G2Projective, PublicKeyG2, SignatureParamsG1);
425impl_keypair!(KeypairG1, G1Projective, PublicKeyG1, SignatureParamsG2);
426
427#[serde_as]
428#[derive(
429    Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
430)]
431pub struct PreparedSignatureParamsG1<E: Pairing> {
432    #[serde_as(as = "ArkObjectBytes")]
433    pub g1: E::G1Affine,
434    #[serde_as(as = "ArkObjectBytes")]
435    pub g2: E::G2Prepared,
436    #[serde_as(as = "ArkObjectBytes")]
437    pub h_0: E::G1Affine,
438    /// Vector of size same as the size of multi-message that needs to be signed.
439    #[serde_as(as = "Vec<ArkObjectBytes>")]
440    pub h: Vec<E::G1Affine>,
441}
442
443#[serde_as]
444#[derive(
445    Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
446)]
447pub struct PreparedPublicKeyG2<E: Pairing>(#[serde_as(as = "ArkObjectBytes")] pub E::G2Prepared);
448
449impl<E: Pairing> From<SignatureParamsG1<E>> for PreparedSignatureParamsG1<E> {
450    fn from(params: SignatureParamsG1<E>) -> Self {
451        Self {
452            g1: params.g1,
453            g2: E::G2Prepared::from(params.g2),
454            h_0: params.h_0,
455            h: params.h,
456        }
457    }
458}
459
460impl_multi_msg_sig_params!(PreparedSignatureParamsG1);
461
462impl<E: Pairing> PreparedSignatureParamsG1<E> {
463    impl_sig_params_prepared!(G1Affine, G1);
464}
465
466impl<E: Pairing> From<PublicKeyG2<E>> for PreparedPublicKeyG2<E> {
467    fn from(pk: PublicKeyG2<E>) -> Self {
468        Self(E::G2Prepared::from(pk.0))
469    }
470}
471
472/// BBS signature params used for signing, verifying and proving knowledge of signature.
473#[serde_as]
474#[derive(
475    Clone, PartialEq, Eq, Debug, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
476)]
477pub struct SignatureParams23G1<E: Pairing> {
478    #[serde_as(as = "ArkObjectBytes")]
479    pub g1: E::G1Affine,
480    #[serde_as(as = "ArkObjectBytes")]
481    pub g2: E::G2Affine,
482    /// Vector of size same as the size of multi-message that needs to be signed.
483    #[serde_as(as = "Vec<ArkObjectBytes>")]
484    pub h: Vec<E::G1Affine>,
485}
486
487/// Signature params for BBS signatures with G2 element prepared for pairing
488#[serde_as]
489#[derive(
490    Clone, Debug, PartialEq, CanonicalSerialize, CanonicalDeserialize, Serialize, Deserialize,
491)]
492pub struct PreparedSignatureParams23G1<E: Pairing> {
493    #[serde_as(as = "ArkObjectBytes")]
494    pub g1: E::G1Affine,
495    #[serde_as(as = "ArkObjectBytes")]
496    pub g2: E::G2Prepared,
497    /// Vector of size same as the size of multi-message that needs to be signed.
498    #[serde_as(as = "Vec<ArkObjectBytes>")]
499    pub h: Vec<E::G1Affine>,
500}
501
502impl<E: Pairing> SignatureParams23G1<E> {
503    /// Generate params by hashing a known string. The hash function is vulnerable to timing
504    /// attack but since all this is public knowledge, it is fine.
505    /// This is useful if people need to be convinced that the discrete log of group elements wrt each other is not known.
506    pub fn new<D: Digest>(label: &[u8], message_count: u32) -> Self {
507        assert_ne!(message_count, 0);
508        // Group element by hashing `label`||`g1`, `label`||`g2` and `label`||`h_i` for i in 1 to message_count.
509        let (g1, g2, h) = join!(
510            affine_group_element_from_byte_slices!(label, b" : g1"),
511            affine_group_element_from_byte_slices!(label, b" : g2"),
512            {
513                let h: Vec<_> = n_projective_group_elements::<E::G1Affine, D>(
514                    1..message_count + 1,
515                    &concat_slices!(label, b" : h_"),
516                )
517                .collect();
518                E::G1::normalize_batch(&h)
519            }
520        );
521
522        Self { g1, g2, h }
523    }
524
525    /// Generate params using a random number generator
526    pub fn generate_using_rng<R>(rng: &mut R, message_count: u32) -> Self
527    where
528        R: RngCore,
529    {
530        assert_ne!(message_count, 0);
531        let h = (0..message_count)
532            .map(|_| E::G1::rand(rng))
533            .collect::<Vec<E::G1>>();
534        Self {
535            g1: E::G1::rand(rng).into(),
536            g2: E::G2::rand(rng).into(),
537            h: E::G1::normalize_batch(&h),
538        }
539    }
540
541    /// Check that all group elements are non-zero (returns false if any element is zero).
542    /// A verifier on receiving these parameters must first check that they are valid and only
543    /// then use them for any signature or proof of knowledge of signature verification.
544    pub fn is_valid(&self) -> bool {
545        !(self.g1.is_zero() || self.g2.is_zero() || cfg_iter!(self.h).any(|v| v.is_zero()))
546    }
547
548    impl_sig_params_prepared_bbs23!(G1Affine, G1);
549}
550
551impl_multi_msg_sig_params!(SignatureParams23G1);
552
553impl<E: Pairing> From<SignatureParams23G1<E>> for PreparedSignatureParams23G1<E> {
554    fn from(params: SignatureParams23G1<E>) -> Self {
555        Self {
556            g1: params.g1,
557            g2: E::G2Prepared::from(params.g2),
558            h: params.h,
559        }
560    }
561}
562
563impl<E: Pairing> PreparedSignatureParams23G1<E> {
564    impl_sig_params_prepared_bbs23!(G1Affine, G1);
565}
566
567impl_multi_msg_sig_params!(PreparedSignatureParams23G1);
568
569impl<E: Pairing> PublicKeyG2<E> {
570    impl_public_key_generation!(
571        generate_using_secret_key_and_bbs23_params,
572        SignatureParams23G1
573    );
574}
575
576impl<E: Pairing> KeypairG2<E> {
577    impl_keypair_generation!(
578        generate_using_seed_and_bbs23_params,
579        generate_using_rng_and_bbs23_params,
580        generate_using_secret_key_and_bbs23_params,
581        PublicKeyG2,
582        SignatureParams23G1
583    );
584}
585
586#[cfg(test)]
587mod tests {
588    use super::*;
589    use crate::test_serialization;
590    use ark_bls12_381::Bls12_381;
591    use ark_std::rand::{rngs::StdRng, SeedableRng};
592    use blake2::Blake2b512;
593    use schnorr_pok::{
594        compute_random_oracle_challenge,
595        discrete_log::{PokDiscreteLog, PokDiscreteLogProtocol},
596    };
597
598    type Fr = <Bls12_381 as Pairing>::ScalarField;
599
600    macro_rules! test_serz_des {
601        ($keypair:ident, $public_key:ident, $params:ident, $rng:ident, $message_count: ident, $fn_name: ident) => {
602            let params = $params::<Bls12_381>::generate_using_rng(&mut $rng, $message_count);
603            test_serialization!($params<Bls12_381>, params);
604
605            let keypair = $keypair::<Bls12_381>::$fn_name(&mut $rng, &params);
606            test_serialization!($keypair<Bls12_381>, keypair);
607
608            let pk = keypair.public_key.clone();
609            let sk = keypair.secret_key.clone();
610            test_serialization!($public_key<Bls12_381>, pk);
611            test_serialization!(SecretKey<<Bls12_381 as Pairing>::ScalarField>, sk);
612        };
613    }
614
615    macro_rules! test_params {
616        ($params:ident, $message_count: ident) => {
617            let label_1 = "test1".as_bytes();
618            let params_1 = $params::<Bls12_381>::new::<Blake2b512>(&label_1, $message_count);
619            assert!(params_1.is_valid());
620            assert_eq!(params_1.h.len(), $message_count as usize);
621
622            // Same label should generate same params
623            let params_1_again = $params::<Bls12_381>::new::<Blake2b512>(&label_1, $message_count);
624            assert_eq!(params_1_again, params_1);
625
626            // Different label should generate different params
627            let label_2 = "test2".as_bytes();
628            let params_2 = $params::<Bls12_381>::new::<Blake2b512>(&label_2, $message_count);
629            assert_ne!(params_1, params_2);
630        };
631    }
632
633    macro_rules! test_keypair {
634        ($keypair:ident, $public_key:ident, $params:ident, $seed_fn_name: ident, $sk_fn_name: ident) => {
635            let params = $params::<Bls12_381>::new::<Blake2b512>("test".as_bytes(), 5);
636            let seed = [0, 1, 2, 10, 11];
637
638            let sk = SecretKey::generate_using_seed::<Blake2b512>(&seed);
639            assert_eq!(sk, SecretKey::generate_using_seed::<Blake2b512>(&seed));
640
641            let pk = $public_key::<Bls12_381>::$sk_fn_name(&sk, &params);
642
643            let keypair = $keypair::<Bls12_381>::$seed_fn_name::<Blake2b512>(&seed, &params);
644            assert_eq!(
645                keypair,
646                $keypair {
647                    secret_key: sk.clone(),
648                    public_key: pk
649                }
650            );
651            drop(sk);
652            drop(keypair);
653        };
654    }
655
656    #[test]
657    fn keypair() {
658        test_keypair!(
659            KeypairG2,
660            PublicKeyG2,
661            SignatureParamsG1,
662            generate_using_seed,
663            generate_using_secret_key
664        );
665        test_keypair!(
666            KeypairG1,
667            PublicKeyG1,
668            SignatureParamsG2,
669            generate_using_seed,
670            generate_using_secret_key
671        );
672        test_keypair!(
673            KeypairG2,
674            PublicKeyG2,
675            SignatureParams23G1,
676            generate_using_seed_and_bbs23_params,
677            generate_using_secret_key_and_bbs23_params
678        );
679    }
680
681    #[test]
682    fn serz_deserz() {
683        // Test serialization of keypair, secret key, public key and signature params
684        let mut rng = StdRng::seed_from_u64(0u64);
685        let message_count = 10;
686        test_serz_des!(
687            KeypairG2,
688            PublicKeyG2,
689            SignatureParamsG1,
690            rng,
691            message_count,
692            generate_using_rng
693        );
694        test_serz_des!(
695            KeypairG1,
696            PublicKeyG1,
697            SignatureParamsG2,
698            rng,
699            message_count,
700            generate_using_rng
701        );
702        test_serz_des!(
703            KeypairG2,
704            PublicKeyG2,
705            SignatureParams23G1,
706            rng,
707            message_count,
708            generate_using_rng_and_bbs23_params
709        );
710    }
711
712    #[test]
713    fn params_deterministically() {
714        // Test generation of signature params deterministically.
715        let message_count = 10;
716        test_params!(SignatureParamsG1, message_count);
717        test_params!(SignatureParamsG2, message_count);
718        test_params!(SignatureParams23G1, message_count);
719    }
720
721    #[test]
722    fn proof_of_knowledge_of_public_key() {
723        macro_rules! check {
724            ($group_affine:ident, $public_key:ident, $params:ident) => {
725                let mut rng = StdRng::seed_from_u64(0u64);
726                let params = $params::<Bls12_381>::new::<Blake2b512>("test".as_bytes(), 5);
727                let seed = [0, 1, 2, 10, 11];
728                let sk = SecretKey::generate_using_seed::<Blake2b512>(&seed);
729                let pk = $public_key::<Bls12_381>::generate_using_secret_key(&sk, &params);
730
731                let base = &params.g2;
732                let witness = sk.0.clone();
733                let blinding = Fr::rand(&mut rng);
734
735                let protocol =
736                    PokDiscreteLogProtocol::<<Bls12_381 as Pairing>::$group_affine>::init(
737                        witness, blinding, base,
738                    );
739
740                let mut chal_contrib_prover = vec![];
741                protocol
742                    .challenge_contribution(base, &pk.0, &mut chal_contrib_prover)
743                    .unwrap();
744
745                test_serialization!(
746                    PokDiscreteLogProtocol<<Bls12_381 as Pairing>::$group_affine>,
747                    protocol
748                );
749
750                let challenge_prover =
751                    compute_random_oracle_challenge::<Fr, Blake2b512>(&chal_contrib_prover);
752                let proof = protocol.gen_proof(&challenge_prover);
753
754                let mut chal_contrib_verifier = vec![];
755                proof
756                    .challenge_contribution(base, &pk.0, &mut chal_contrib_verifier)
757                    .unwrap();
758
759                let challenge_verifier =
760                    compute_random_oracle_challenge::<Fr, Blake2b512>(&chal_contrib_verifier);
761                assert!(proof.verify(&pk.0, base, &challenge_verifier));
762                assert_eq!(chal_contrib_prover, chal_contrib_verifier);
763                assert_eq!(challenge_prover, challenge_verifier);
764
765                test_serialization!(PokDiscreteLog<<Bls12_381 as Pairing>::$group_affine>, proof);
766            };
767        }
768
769        check!(G2Affine, PublicKeyG2, SignatureParamsG1);
770        check!(G1Affine, PublicKeyG1, SignatureParamsG2);
771    }
772}