w3f_bls/
double_pop.rs

1//! ## Implementation of ProofofPossion trait for Double BLS public keys using
2//! the scheme described in [https://eprint.iacr.org/2022/1611] which also
3//! complies with the proof of possession proposed in
4//! [draft-irtf-cfrg-bls-signature-05](https://www.ietf.org/archive/id/draft-irtf-cfrg-bls-signature-05.html)
5
6use crate::engine::EngineBLS;
7use crate::{DoubleSignature, Message, ProofOfPossession, ProofOfPossessionGenerator};
8
9use crate::double::{DoublePublicKey, DoublePublicKeyScheme};
10use crate::serialize::SerializableToBytes;
11use crate::single::{Keypair, PublicKey};
12
13use alloc::vec::Vec;
14use digest::DynDigest;
15
16use ark_ec::Group;
17use ark_ff::field_hashers::{DefaultFieldHasher, HashToField};
18use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
19
20/// Proof Of Possession of the secret key as the secret scaler genarting both public
21/// keys in G1 and G2 by generating a BLS Signature of public key (in G2)
22#[derive(CanonicalSerialize, CanonicalDeserialize)]
23pub struct NuggetBLSPoP<E: EngineBLS>(pub E::SignatureGroup);
24
25//The bls proof of possession for single or double public key schemes are the same
26impl<E: EngineBLS, H: DynDigest + Default + Clone>
27    ProofOfPossessionGenerator<E, H, DoublePublicKey<E>, NuggetBLSPoP<E>> for Keypair<E>
28{
29    fn generate_pok(&mut self) -> NuggetBLSPoP<E> {
30        //We simply classicaly BLS sign public key in G2 based on https://eprint.iacr.org/2022/1611
31        let sigma_pop = ProofOfPossessionGenerator::<E, H, DoublePublicKey<E>, NuggetBLSnCPPoP<E>>::generate_pok(self);
32        NuggetBLSPoP::<E>(sigma_pop.0 .0)
33    }
34}
35
36/// Serialization for DoublePublickey
37impl<E: EngineBLS> SerializableToBytes for NuggetBLSPoP<E> {
38    const SERIALIZED_BYTES_SIZE: usize = E::SIGNATURE_SERIALIZED_SIZE;
39}
40
41/// The verification process for verifying both possession of one secret key
42/// for two public key is different.
43impl<E: EngineBLS, H: DynDigest + Default + Clone> ProofOfPossession<E, H, DoublePublicKey<E>>
44    for NuggetBLSPoP<E>
45{
46    /// verify the validity of PoP by performing the following Pairing
47    /// e(H_pop(pk_2) + t.g_1, pk_2) = e(sign(H_pop(pk_2))+ t.pk_1, g_2)
48    /// we verifying by calling the verify_prepared ⎈function from the
49    /// engine.
50    fn verify(&self, public_key_of_prover: &DoublePublicKey<E>) -> bool {
51        //First we need to generate our randomness in a way that
52        //prover is unable to predict. We assume g1 and g2 are fixed.
53
54        let public_key_as_bytes =
55            <E as EngineBLS>::public_key_point_to_byte(&public_key_of_prover.1);
56        let public_key_in_signature_group = public_key_of_prover.0;
57        let public_key_in_signature_group_as_bytes =
58            E::signature_point_to_byte(&public_key_in_signature_group);
59
60        let public_key_hashed_to_signature_group =
61            Message::new_pop_message(b"", &public_key_as_bytes).hash_to_signature_curve::<E>();
62        let public_key_hashed_to_signature_group_as_bytes =
63            E::signature_point_to_byte(&public_key_hashed_to_signature_group);
64        let random_oracle_seed = [
65            public_key_hashed_to_signature_group_as_bytes,
66            public_key_as_bytes,
67            public_key_in_signature_group_as_bytes,
68            E::signature_point_to_byte(&self.0),
69        ]
70        .concat();
71
72        let hasher = <DefaultFieldHasher<H> as HashToField<
73            <<E as EngineBLS>::PublicKeyGroup as Group>::ScalarField,
74        >>::new(&[]);
75
76        let randomization_coefficient: E::Scalar =
77            hasher.hash_to_field(random_oracle_seed.as_slice(), 1)[0];
78
79        let mut randomized_pub_in_g1 = public_key_in_signature_group;
80        randomized_pub_in_g1 *= randomization_coefficient;
81        let signature = E::prepare_signature(self.0 + randomized_pub_in_g1);
82        let prepared_public_key = E::prepare_public_key(public_key_of_prover.1);
83        let prepared = [
84            (
85                prepared_public_key.clone(),
86                E::prepare_signature(public_key_hashed_to_signature_group),
87            ),
88            (
89                prepared_public_key.clone(),
90                E::prepare_signature(E::generator_of_signature_group() * randomization_coefficient),
91            ),
92        ];
93        E::verify_prepared(signature, prepared.iter())
94    }
95}
96
97/// Proof Of Possession of the secret key as the secret scaler genarting both public
98/// keys in G1 and G2 by generating a BLS Signature of public key (in G2) plus proof
99/// of knowledge of the secret key of the chaum-pedersen key (samae secret key)
100#[derive(CanonicalSerialize, CanonicalDeserialize)]
101pub struct NuggetBLSnCPPoP<E: EngineBLS>(pub DoubleSignature<E>);
102
103//The implement the generation of bls proof of possession including  chaum-pederesno PoP for double public key schemes
104impl<E: EngineBLS, H: DynDigest + Default + Clone>
105    ProofOfPossessionGenerator<E, H, DoublePublicKey<E>, NuggetBLSnCPPoP<E>> for Keypair<E>
106{
107    fn generate_pok(&mut self) -> NuggetBLSnCPPoP<E> {
108        //We simply classicaly BLS sign public key in G2 based on https://eprint.iacr.org/2022/1611
109        let public_key_as_bytes = self.public.to_bytes();
110        let sigma_pop = DoublePublicKeyScheme::<E>::sign(
111            self,
112            &Message::new_pop_message(b"", &public_key_as_bytes.as_slice()),
113        );
114
115        NuggetBLSnCPPoP::<E>(sigma_pop)
116    }
117}
118
119/// Serialization for NuggetBLSnCPPoP
120impl<E: EngineBLS> SerializableToBytes for NuggetBLSnCPPoP<E> {
121    const SERIALIZED_BYTES_SIZE: usize =
122        <DoubleSignature<E> as SerializableToBytes>::SERIALIZED_BYTES_SIZE;
123}
124
125/// The verification process for verifying both nugget BLS and CP
126impl<E: EngineBLS, H: DynDigest + Default + Clone> ProofOfPossession<E, H, DoublePublicKey<E>>
127    for NuggetBLSnCPPoP<E>
128{
129    /// verify the validity of PoP by verifying nugget PoP and the CP
130    /// signature
131    fn verify(&self, public_key_of_prover: &DoublePublicKey<E>) -> bool {
132        let public_key_in_public_key_group_as_bytes =
133            PublicKey::<E>(public_key_of_prover.1).to_bytes();
134        //verify double pairing && verify cp
135        <NuggetBLSPoP<E> as ProofOfPossession<E, H, DoublePublicKey<E>>>::verify(
136            &NuggetBLSPoP::<E>(self.0 .0),
137            public_key_of_prover,
138        ) && public_key_of_prover.verify(
139            &Message::new_pop_message(b"", &public_key_in_public_key_group_as_bytes.as_slice()),
140            &self.0,
141        )
142    }
143}
144
145#[cfg(all(test, feature = "std"))]
146mod tests {
147    use crate::double::DoublePublicKeyScheme;
148    use crate::engine::TinyBLS381;
149    use crate::serialize::SerializableToBytes;
150    use crate::single::Keypair;
151    use crate::{double_pop::NuggetBLSPoP, DoublePublicKey};
152    use crate::{ProofOfPossession, ProofOfPossessionGenerator};
153
154    use rand::thread_rng;
155    use sha2::Sha256;
156
157    use super::NuggetBLSnCPPoP;
158
159    fn double_bls_pop_sign<
160        PoPFlavor: ProofOfPossession<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>>,
161    >()
162    where
163        Keypair<TinyBLS381>:
164            ProofOfPossessionGenerator<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>, PoPFlavor>,
165    {
166        let mut keypair = Keypair::<TinyBLS381>::generate(thread_rng());
167        <Keypair<TinyBLS381> as ProofOfPossessionGenerator<
168            TinyBLS381,
169            Sha256,
170            DoublePublicKey<TinyBLS381>,
171            PoPFlavor,
172        >>::generate_pok(&mut keypair);
173    }
174
175    #[test]
176    fn nugget_bls_pop_sign() {
177        double_bls_pop_sign::<NuggetBLSPoP<TinyBLS381>>();
178    }
179
180    #[test]
181    fn nugget_bls_and_cp_pop_sign() {
182        double_bls_pop_sign::<NuggetBLSnCPPoP<TinyBLS381>>();
183    }
184
185    fn double_bls_pop_sign_and_verify<
186        PoPFlavor: ProofOfPossession<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>>,
187    >()
188    where
189        Keypair<TinyBLS381>:
190            ProofOfPossessionGenerator<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>, PoPFlavor>,
191    {
192        let mut keypair = Keypair::<TinyBLS381>::generate(thread_rng());
193        let proof_pair = <dyn ProofOfPossessionGenerator<
194            TinyBLS381,
195            Sha256,
196            DoublePublicKey<TinyBLS381>,
197            PoPFlavor,
198        >>::generate_pok(&mut keypair);
199        assert!(
200            ProofOfPossession::<TinyBLS381, Sha256, DoublePublicKey::<TinyBLS381>>::verify(
201                &proof_pair,
202                &DoublePublicKeyScheme::into_double_public_key(&keypair)
203            ),
204            "valid pok does not verify"
205        );
206    }
207
208    #[test]
209    fn nugget_bls_pop_sign_and_verify() {
210        double_bls_pop_sign_and_verify::<NuggetBLSPoP<TinyBLS381>>();
211    }
212
213    #[test]
214    fn nugget_bls_and_cp_pop_sign_and_verify() {
215        double_bls_pop_sign_and_verify::<NuggetBLSnCPPoP<TinyBLS381>>();
216    }
217
218    fn double_bls_pop_of_random_public_key_should_fail<
219        PoPFlavor: ProofOfPossession<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>>,
220    >()
221    where
222        Keypair<TinyBLS381>:
223            ProofOfPossessionGenerator<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>, PoPFlavor>,
224    {
225        let mut keypair_good = Keypair::<TinyBLS381>::generate(thread_rng());
226        let proof_pair = <dyn ProofOfPossessionGenerator<
227            TinyBLS381,
228            Sha256,
229            DoublePublicKey<TinyBLS381>,
230            PoPFlavor,
231        >>::generate_pok(&mut keypair_good);
232        let keypair_bad = Keypair::<TinyBLS381>::generate(thread_rng());
233        assert!(
234            !ProofOfPossession::<TinyBLS381, Sha256, DoublePublicKey::<TinyBLS381>>::verify(
235                &proof_pair,
236                &DoublePublicKeyScheme::into_double_public_key(&keypair_bad)
237            ),
238            "invalid pok of unrelated public key should not verify"
239        );
240    }
241
242    #[test]
243    fn nugget_bls_pop_of_random_public_key_should_fail() {
244        double_bls_pop_of_random_public_key_should_fail::<NuggetBLSPoP<TinyBLS381>>();
245    }
246
247    #[test]
248    fn nugget_bls_and_cp_pop_of_random_public_key_should_fail() {
249        double_bls_pop_of_random_public_key_should_fail::<NuggetBLSnCPPoP<TinyBLS381>>();
250    }
251
252    fn pop_of_a_double_public_key_should_serialize_and_deserialize_for_bls12_381<
253        PoPFlavor: ProofOfPossession<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>> + SerializableToBytes,
254    >()
255    where
256        Keypair<TinyBLS381>:
257            ProofOfPossessionGenerator<TinyBLS381, Sha256, DoublePublicKey<TinyBLS381>, PoPFlavor>,
258    {
259        let mut keypair = Keypair::<TinyBLS381>::generate(thread_rng());
260
261        let proof_pair = <dyn ProofOfPossessionGenerator<
262            TinyBLS381,
263            Sha256,
264            DoublePublicKey<TinyBLS381>,
265            PoPFlavor,
266        >>::generate_pok(&mut keypair);
267
268        let serialized_proof = proof_pair.to_bytes();
269        let deserialized_proof = PoPFlavor::from_bytes(&serialized_proof).unwrap();
270
271        assert!(
272            ProofOfPossession::<TinyBLS381, Sha256, DoublePublicKey::<TinyBLS381>>::verify(
273                &deserialized_proof,
274                &DoublePublicKeyScheme::into_double_public_key(&keypair)
275            ),
276            "valid pok does not verify"
277        );
278    }
279
280    #[test]
281    fn nugget_bls_pop_should_serialize_and_deserialize_for_bls12_381() {
282        pop_of_a_double_public_key_should_serialize_and_deserialize_for_bls12_381::<
283            NuggetBLSPoP<TinyBLS381>,
284        >();
285    }
286
287    #[test]
288    fn nugget_bls_and_cp_pop_should_serialize_and_deserialize_for_bls12_381() {
289        pop_of_a_double_public_key_should_serialize_and_deserialize_for_bls12_381::<
290            NuggetBLSnCPPoP<TinyBLS381>,
291        >();
292    }
293}