w3f_bls/
double.rs

1//! ## BLS key pair with public key in both G1 and G2
2//! ## Unaggreagated BLS signature along side with their DLEQ proof
3//!
4//! Implements schemes suggested the
5//! [paper](https://eprint.iacr.org/2022/1611)
6//!
7//! The scheme proposes for the public key be represented by doube points,
8//! both in G1 and G2 and aggregate keys in G1.
9//!
10//! It also proposes that each individual BLS signature accompany a DLEQ proof
11//! for faster verification
12
13use alloc::vec::Vec;
14use core::iter::once;
15
16use ark_ec::{AffineRepr, CurveGroup};
17
18use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
19
20use sha2::Sha256;
21
22use crate::broken_derives;
23use crate::chaum_pedersen_signature::{ChaumPedersenSigner, ChaumPedersenVerifier};
24use crate::schnorr_pop::SchnorrProof;
25use crate::serialize::SerializableToBytes;
26use crate::single::{Keypair, KeypairVT, PublicKey, SecretKeyVT, Signature};
27use crate::{EngineBLS, Message, Signed};
28
29/// Wrapper for a point in the signature group which is supposed to
30/// the same logarithm as the public key in the public key group
31#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
32pub struct PublicKeyInSignatureGroup<E: EngineBLS>(pub E::SignatureGroup);
33broken_derives!(PublicKeyInSignatureGroup); // Actually the derive works for this one, not sure why.
34
35/// BLS Public Key with sub keys in both groups.
36#[derive(Debug, Clone, CanonicalSerialize, CanonicalDeserialize)]
37pub struct DoublePublicKey<E: EngineBLS>(pub E::SignatureGroup, pub E::PublicKeyGroup);
38
39impl<E: EngineBLS> DoublePublicKey<E> {
40    pub fn verify(&self, message: &Message, signature: &DoubleSignature<E>) -> bool {
41        signature.verify(message, self)
42    }
43}
44
45/// Serialization for DoublePublickey
46impl<E: EngineBLS> SerializableToBytes for DoublePublicKey<E> {
47    const SERIALIZED_BYTES_SIZE: usize =
48        E::SIGNATURE_SERIALIZED_SIZE + E::PUBLICKEY_SERIALIZED_SIZE;
49}
50
51pub trait DoublePublicKeyScheme<E: EngineBLS> {
52    fn into_public_key_in_signature_group(&self) -> PublicKeyInSignatureGroup<E>;
53
54    /// Return a double public object containing public keys both in G1 and G2
55    fn into_double_public_key(&self) -> DoublePublicKey<E>;
56    fn sign(&mut self, message: &Message) -> DoubleSignature<E>;
57}
58
59impl<E: EngineBLS> DoublePublicKeyScheme<E> for SecretKeyVT<E> {
60    fn into_public_key_in_signature_group(&self) -> PublicKeyInSignatureGroup<E> {
61        PublicKeyInSignatureGroup(
62            <E::SignatureGroup as CurveGroup>::Affine::generator().into_group() * self.0,
63        )
64    }
65
66    fn into_double_public_key(&self) -> DoublePublicKey<E> {
67        DoublePublicKey(
68            self.into_public_key_in_signature_group().0,
69            self.into_public().0,
70        )
71    }
72
73    /// Sign a message using a Seedabale RNG created from a seed derived from the message and key
74    fn sign(&mut self, message: &Message) -> DoubleSignature<E> {
75        let chaum_pedersen_signature =
76            ChaumPedersenSigner::<E, Sha256>::generate_cp_signature(self, &message);
77        DoubleSignature(chaum_pedersen_signature.0 .0, chaum_pedersen_signature.1)
78    }
79}
80
81impl<E: EngineBLS> DoublePublicKeyScheme<E> for KeypairVT<E> {
82    fn into_public_key_in_signature_group(&self) -> PublicKeyInSignatureGroup<E> {
83        self.secret.into_public_key_in_signature_group()
84    }
85
86    fn into_double_public_key(&self) -> DoublePublicKey<E> {
87        self.secret.into_double_public_key()
88    }
89
90    /// Sign a message using a Seedabale RNG created from a seed derived from the message and key
91    fn sign(&mut self, message: &Message) -> DoubleSignature<E> {
92        DoublePublicKeyScheme::sign(&mut self.secret, message)
93    }
94}
95
96impl<E: EngineBLS> DoublePublicKeyScheme<E> for Keypair<E> {
97    fn into_public_key_in_signature_group(&self) -> PublicKeyInSignatureGroup<E> {
98        self.into_vartime().into_public_key_in_signature_group()
99    }
100
101    fn into_double_public_key(&self) -> DoublePublicKey<E> {
102        self.into_vartime().into_double_public_key()
103    }
104
105    /// Sign a message using a Seedabale RNG created from a seed derived from the message and key
106    fn sign(&mut self, message: &Message) -> DoubleSignature<E> {
107        DoublePublicKeyScheme::sign(&mut self.into_vartime(), message)
108    }
109}
110
111/// Detached BLS Signature containing DLEQ
112#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)]
113pub struct DoubleSignature<E: EngineBLS>(pub E::SignatureGroup, SchnorrProof<E>);
114
115impl<E: EngineBLS> DoubleSignature<E> {
116    //const DESCRIPTION : &'static str = "A BLS signature";
117
118    /// Verify a single BLS signature using DLEQ proof
119    pub fn verify(&self, message: &Message, publickey: &DoublePublicKey<E>) -> bool {
120        <PublicKeyInSignatureGroup<E> as ChaumPedersenVerifier<E, Sha256>>::verify_cp_signature(
121            &PublicKeyInSignatureGroup(publickey.0),
122            &message,
123            (Signature(self.0), self.1),
124        )
125    }
126}
127
128/// Message with attached BLS signature
129///
130///
131#[derive(Debug, Clone)]
132pub struct DoubleSignedMessage<E: EngineBLS> {
133    pub message: Message,
134    pub publickey: DoublePublicKey<E>,
135    pub signature: DoubleSignature<E>,
136}
137
138impl<E: EngineBLS> PartialEq<Self> for DoubleSignedMessage<E> {
139    fn eq(&self, other: &Self) -> bool {
140        self.message.eq(&other.message)
141            && self.publickey.0.eq(&other.publickey.0)
142            && self.publickey.1.eq(&other.publickey.1)
143            && self.signature.0.eq(&other.signature.0)
144    }
145}
146
147impl<'a, E: EngineBLS> Signed for &'a DoubleSignedMessage<E> {
148    type E = E;
149
150    type M = Message;
151    type PKG = PublicKey<E>;
152
153    type PKnM = ::core::iter::Once<(Message, PublicKey<E>)>;
154
155    fn messages_and_publickeys(self) -> Self::PKnM {
156        once((self.message.clone(), PublicKey(self.publickey.1))) // TODO:  Avoid clone
157    }
158
159    fn signature(&self) -> Signature<E> {
160        Signature(self.signature.0)
161    }
162
163    fn verify(self) -> bool {
164        //we chaum pederesen verification which is faster
165        ChaumPedersenVerifier::<E, Sha256>::verify_cp_signature(
166            &PublicKeyInSignatureGroup::<E>(self.publickey.0),
167            &self.message,
168            (Signature(self.signature.0), self.signature.1),
169        )
170    }
171}
172
173/// Serialization for DoubleSignature
174impl<E: EngineBLS> SerializableToBytes for DoubleSignature<E> {
175    const SERIALIZED_BYTES_SIZE: usize = E::SIGNATURE_SERIALIZED_SIZE + 2 * E::SECRET_KEY_SIZE;
176}
177
178#[cfg(all(test, feature = "std"))]
179mod tests {
180    use rand::thread_rng;
181
182    use super::*;
183
184    use ark_bls12_377::Bls12_377;
185    use ark_bls12_381::Bls12_381;
186    use ark_ec::bls12::Bls12Config;
187    use ark_ec::hashing::curve_maps::wb::{WBConfig, WBMap};
188    use ark_ec::hashing::map_to_curve_hasher::MapToCurve;
189    use ark_ec::pairing::Pairing as PairingEngine;
190
191    use crate::{EngineBLS, Message, TinyBLS};
192
193    fn double_public_serialization_test<
194        EB: EngineBLS<Engine = E>,
195        E: PairingEngine,
196        P: Bls12Config,
197    >(
198        x: DoubleSignedMessage<EB>,
199    ) -> DoubleSignedMessage<EB>
200    where
201        <P as Bls12Config>::G2Config: WBConfig,
202        WBMap<<P as Bls12Config>::G2Config>: MapToCurve<<E as PairingEngine>::G2>,
203    {
204        let DoubleSignedMessage {
205            message,
206            publickey,
207            signature,
208        } = x;
209
210        let publickey = DoublePublicKey::<EB>::from_bytes(&publickey.to_bytes()).unwrap();
211        let signature = DoubleSignature::<EB>::from_bytes(&signature.to_bytes()).unwrap();
212
213        DoubleSignedMessage {
214            message,
215            publickey,
216            signature,
217        }
218    }
219
220    fn test_single_bls_message_double_signature_scheme<
221        EB: EngineBLS<Engine = E>,
222        E: PairingEngine,
223        P: Bls12Config,
224    >()
225    where
226        <P as Bls12Config>::G2Config: WBConfig,
227        WBMap<<P as Bls12Config>::G2Config>: MapToCurve<<E as PairingEngine>::G2>,
228    {
229        let good = Message::new(b"ctx", b"test message");
230
231        let mut keypair = Keypair::<EB>::generate(thread_rng());
232        let public_key = DoublePublicKeyScheme::into_double_public_key(&mut keypair);
233        let good_sig = DoublePublicKeyScheme::sign(&mut keypair, &good);
234
235        assert!(
236            public_key.verify(&good, &good_sig),
237            "Verification of a valid signature failed!"
238        );
239
240        let bad = Message::new(b"ctx", b"wrong message");
241        let bad_sig = DoublePublicKeyScheme::sign(&mut keypair, &bad);
242
243        assert!(bad_sig.verify(
244            &bad,
245            &DoublePublicKeyScheme::into_double_public_key(&keypair)
246        ));
247
248        assert!(good != bad, "good == bad");
249        assert!(good_sig.0 != bad_sig.0, "good sig == bad sig");
250
251        assert!(
252            !bad_sig.verify(
253                &good,
254                &DoublePublicKeyScheme::into_double_public_key(&keypair)
255            ),
256            "Verification of a signature on a different message passed!"
257        );
258        assert!(
259            !good_sig.verify(
260                &bad,
261                &DoublePublicKeyScheme::into_double_public_key(&keypair)
262            ),
263            "Verification of a signature on a different message passed!"
264        );
265    }
266
267    #[test]
268    fn test_double_public_key_double_signature_serialization_for_bls12_377() {
269        let mut keypair =
270            Keypair::<TinyBLS<Bls12_377, ark_bls12_377::Config>>::generate(thread_rng());
271        let message = Message::new(b"ctx", b"test message");
272        let good_sig0 = DoublePublicKeyScheme::sign(&mut keypair, &message);
273
274        let signed_message = DoubleSignedMessage {
275            message: message,
276            publickey: DoublePublicKey(
277                keypair.into_public_key_in_signature_group().0,
278                keypair.public.0,
279            ),
280            signature: good_sig0,
281        };
282
283        assert!(
284            signed_message.verify(),
285            "valid double signed message should verify"
286        );
287
288        let deserialized_signed_message = double_public_serialization_test::<
289            TinyBLS<Bls12_377, ark_bls12_377::Config>,
290            Bls12_377,
291            ark_bls12_377::Config,
292        >(signed_message);
293
294        assert!(
295            deserialized_signed_message.verify(),
296            "deserialized valid double signed message should verify"
297        );
298    }
299
300    #[test]
301    fn test_double_public_key_double_signature_serialization_for_bls12_381() {
302        let mut keypair =
303            Keypair::<TinyBLS<Bls12_381, ark_bls12_381::Config>>::generate(thread_rng());
304        let message = Message::new(b"ctx", b"test message");
305        let good_sig0 = DoublePublicKeyScheme::sign(&mut keypair, &message);
306
307        let signed_message = DoubleSignedMessage {
308            message: message,
309            publickey: DoublePublicKey(
310                keypair.into_public_key_in_signature_group().0,
311                keypair.public.0,
312            ),
313            signature: good_sig0,
314        };
315
316        assert!(
317            signed_message.verify(),
318            "valid double signed message should verify"
319        );
320
321        let deserialized_signed_message = double_public_serialization_test::<
322            TinyBLS<Bls12_381, ark_bls12_381::Config>,
323            Bls12_381,
324            ark_bls12_381::Config,
325        >(signed_message);
326
327        assert!(
328            deserialized_signed_message.verify(),
329            "deserialized valid double signed message should verify"
330        );
331    }
332
333    #[test]
334    fn test_single_bls_message_double_signature_scheme_for_bls12_377() {
335        test_single_bls_message_double_signature_scheme::<
336            TinyBLS<Bls12_377, ark_bls12_377::Config>,
337            Bls12_377,
338            ark_bls12_377::Config,
339        >();
340    }
341
342    #[test]
343    fn test_single_bls_message_double_signature_scheme_for_bls12_381() {
344        test_single_bls_message_double_signature_scheme::<
345            TinyBLS<Bls12_381, ark_bls12_381::Config>,
346            Bls12_381,
347            ark_bls12_381::Config,
348        >();
349    }
350}