1use 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#[derive(Debug, CanonicalSerialize, CanonicalDeserialize)]
32pub struct PublicKeyInSignatureGroup<E: EngineBLS>(pub E::SignatureGroup);
33broken_derives!(PublicKeyInSignatureGroup); #[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
45impl<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 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 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 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 fn sign(&mut self, message: &Message) -> DoubleSignature<E> {
107 DoublePublicKeyScheme::sign(&mut self.into_vartime(), message)
108 }
109}
110
111#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize)]
113pub struct DoubleSignature<E: EngineBLS>(pub E::SignatureGroup, SchnorrProof<E>);
114
115impl<E: EngineBLS> DoubleSignature<E> {
116 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#[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))) }
158
159 fn signature(&self) -> Signature<E> {
160 Signature(self.signature.0)
161 }
162
163 fn verify(self) -> bool {
164 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
173impl<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}