1use crate::{Error, GTElement, PublicKey, Result, SecretKey};
2use blst::*;
3use chik_sha2::Sha256;
4use chik_traits::{read_bytes, Streamable};
5#[cfg(feature = "py-bindings")]
6use pyo3::exceptions::PyNotImplementedError;
7#[cfg(feature = "py-bindings")]
8use pyo3::prelude::*;
9#[cfg(feature = "py-bindings")]
10use pyo3::types::PyType;
11use std::borrow::Borrow;
12use std::fmt;
13use std::hash::{Hash, Hasher};
14use std::io::Cursor;
15use std::mem::MaybeUninit;
16use std::ops::{Add, AddAssign, Neg, SubAssign};
17
18pub(crate) const DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_";
20
21#[cfg_attr(
22 feature = "py-bindings",
23 pyo3::pyclass(name = "G2Element"),
24 derive(chik_py_streamable_macro::PyStreamable)
25)]
26#[derive(Clone, Default)]
27pub struct Signature(pub(crate) blst_p2);
28
29#[cfg(feature = "arbitrary")]
30impl<'a> arbitrary::Arbitrary<'a> for Signature {
31 fn arbitrary(_u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
32 Ok(Self::default())
34 }
35}
36
37impl Signature {
38 pub fn from_bytes_unchecked(buf: &[u8; 96]) -> Result<Self> {
39 let p2 = unsafe {
40 let mut p2_affine = MaybeUninit::<blst_p2_affine>::uninit();
41 let ret = blst_p2_uncompress(p2_affine.as_mut_ptr(), buf.as_ptr());
42 if ret != BLST_ERROR::BLST_SUCCESS {
43 return Err(Error::InvalidSignature(ret));
44 }
45 let mut p2 = MaybeUninit::<blst_p2>::uninit();
46 blst_p2_from_affine(p2.as_mut_ptr(), &p2_affine.assume_init());
47 p2.assume_init()
48 };
49 Ok(Self(p2))
50 }
51
52 pub fn from_bytes(buf: &[u8; 96]) -> Result<Self> {
53 let ret = Self::from_bytes_unchecked(buf)?;
54 if ret.is_valid() {
55 Ok(ret)
56 } else {
57 Err(Error::InvalidSignature(BLST_ERROR::BLST_POINT_NOT_ON_CURVE))
58 }
59 }
60
61 pub fn from_uncompressed(buf: &[u8; 192]) -> Result<Self> {
62 let p2 = unsafe {
63 let mut p2_affine = MaybeUninit::<blst_p2_affine>::uninit();
64 let ret = blst_p2_deserialize(p2_affine.as_mut_ptr(), buf.as_ptr());
65 if ret != BLST_ERROR::BLST_SUCCESS {
66 return Err(Error::InvalidSignature(ret));
67 }
68 let mut p2 = MaybeUninit::<blst_p2>::uninit();
69 blst_p2_from_affine(p2.as_mut_ptr(), &p2_affine.assume_init());
70 p2.assume_init()
71 };
72 Ok(Self(p2))
73 }
74
75 pub fn to_bytes(&self) -> [u8; 96] {
76 unsafe {
77 let mut bytes = MaybeUninit::<[u8; 96]>::uninit();
78 blst_p2_compress(bytes.as_mut_ptr().cast::<u8>(), &self.0);
79 bytes.assume_init()
80 }
81 }
82
83 pub fn generator() -> Self {
84 unsafe { Self(*blst_p2_generator()) }
85 }
86
87 pub fn aggregate(&mut self, sig: &Signature) {
88 unsafe {
89 blst_p2_add_or_double(&mut self.0, &self.0, &sig.0);
90 }
91 }
92
93 pub fn is_valid(&self) -> bool {
94 unsafe { blst_p2_is_inf(&self.0) || blst_p2_in_g2(&self.0) }
97 }
98
99 pub fn negate(&mut self) {
100 unsafe {
101 blst_p2_cneg(&mut self.0, true);
102 }
103 }
104
105 pub fn scalar_multiply(&mut self, int_bytes: &[u8]) {
106 unsafe {
107 let mut scalar = MaybeUninit::<blst_scalar>::uninit();
108 blst_scalar_from_be_bytes(scalar.as_mut_ptr(), int_bytes.as_ptr(), int_bytes.len());
109 blst_p2_mult(&mut self.0, &self.0, scalar.as_ptr().cast::<u8>(), 256);
110 }
111 }
112
113 pub fn pair(&self, other: &PublicKey) -> GTElement {
114 let ans = unsafe {
115 let mut ans = MaybeUninit::<blst_fp12>::uninit();
116 let mut aff1 = MaybeUninit::<blst_p1_affine>::uninit();
117 let mut aff2 = MaybeUninit::<blst_p2_affine>::uninit();
118
119 blst_p1_to_affine(aff1.as_mut_ptr(), &other.0);
120 blst_p2_to_affine(aff2.as_mut_ptr(), &self.0);
121
122 blst_miller_loop(ans.as_mut_ptr(), &aff2.assume_init(), &aff1.assume_init());
123 blst_final_exp(ans.as_mut_ptr(), ans.as_ptr());
124 ans.assume_init()
125 };
126 GTElement(ans)
127 }
128}
129
130impl Streamable for Signature {
131 fn update_digest(&self, digest: &mut Sha256) {
132 digest.update(self.to_bytes());
133 }
134
135 fn stream(&self, out: &mut Vec<u8>) -> chik_traits::chik_error::Result<()> {
136 out.extend_from_slice(&self.to_bytes());
137 Ok(())
138 }
139
140 fn parse<const TRUSTED: bool>(
141 input: &mut Cursor<&[u8]>,
142 ) -> chik_traits::chik_error::Result<Self> {
143 let input = read_bytes(input, 96)?.try_into().unwrap();
144 if TRUSTED {
145 Ok(Self::from_bytes_unchecked(input)?)
146 } else {
147 Ok(Self::from_bytes(input)?)
148 }
149 }
150}
151
152impl PartialEq for Signature {
153 fn eq(&self, other: &Self) -> bool {
154 unsafe { blst_p2_is_equal(&self.0, &other.0) }
155 }
156}
157impl Eq for Signature {}
158
159impl Hash for Signature {
160 fn hash<H: Hasher>(&self, state: &mut H) {
161 state.write(&self.to_bytes());
162 }
163}
164
165impl fmt::Debug for Signature {
166 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
167 formatter.write_fmt(format_args!(
168 "<G2Element {}>",
169 &hex::encode(self.to_bytes())
170 ))
171 }
172}
173
174impl AddAssign<&Signature> for Signature {
175 fn add_assign(&mut self, rhs: &Signature) {
176 unsafe {
177 blst_p2_add_or_double(&mut self.0, &self.0, &rhs.0);
178 }
179 }
180}
181
182impl Neg for Signature {
183 type Output = Signature;
184 fn neg(mut self) -> Self::Output {
185 self.negate();
186 self
187 }
188}
189
190impl Neg for &Signature {
191 type Output = Signature;
192 fn neg(self) -> Self::Output {
193 let mut ret = self.clone();
194 ret.negate();
195 ret
196 }
197}
198
199impl SubAssign<&Signature> for Signature {
200 fn sub_assign(&mut self, rhs: &Signature) {
201 unsafe {
202 let mut neg = rhs.clone();
203 blst_p2_cneg(&mut neg.0, true);
204 blst_p2_add_or_double(&mut self.0, &self.0, &neg.0);
205 }
206 }
207}
208
209impl Add<&Signature> for Signature {
210 type Output = Signature;
211 fn add(mut self, rhs: &Signature) -> Signature {
212 unsafe {
213 blst_p2_add_or_double(&mut self.0, &self.0, &rhs.0);
214 self
215 }
216 }
217}
218
219impl Add<&Signature> for &Signature {
220 type Output = Signature;
221 fn add(self, rhs: &Signature) -> Signature {
222 let p1 = unsafe {
223 let mut ret = MaybeUninit::<blst_p2>::uninit();
224 blst_p2_add_or_double(ret.as_mut_ptr(), &self.0, &rhs.0);
225 ret.assume_init()
226 };
227 Signature(p1)
228 }
229}
230
231#[cfg(feature = "serde")]
232impl serde::Serialize for Signature {
233 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
234 where
235 S: serde::Serializer,
236 {
237 chik_serde::ser_bytes(&self.to_bytes(), serializer, true)
238 }
239}
240
241#[cfg(feature = "serde")]
242impl<'de> serde::Deserialize<'de> for Signature {
243 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
244 where
245 D: serde::Deserializer<'de>,
246 {
247 Self::from_bytes(&chik_serde::de_bytes(deserializer)?).map_err(serde::de::Error::custom)
248 }
249}
250
251pub fn aggregate_pairing<G1: Borrow<PublicKey>, G2: Borrow<Signature>, I>(data: I) -> bool
257where
258 I: IntoIterator<Item = (G1, G2)>,
259{
260 let mut data = data.into_iter().peekable();
261 if data.peek().is_none() {
262 return true;
263 }
264
265 let mut v: Vec<u64> = vec![0; unsafe { blst_pairing_sizeof() } / 8];
266 let ctx = unsafe {
267 let ctx = v.as_mut_slice().as_mut_ptr().cast::<blst_pairing>();
268 blst_pairing_init(
269 ctx,
270 true, DST.as_ptr(),
272 DST.len(),
273 );
274 ctx
275 };
276
277 for (g1, g2) in data {
278 if !g1.borrow().is_valid() {
279 return false;
280 }
281 if !g2.borrow().is_valid() {
282 return false;
283 }
284
285 let g1_affine = unsafe {
286 let mut g1_affine = MaybeUninit::<blst_p1_affine>::uninit();
287 blst_p1_to_affine(g1_affine.as_mut_ptr(), &g1.borrow().0);
288 g1_affine.assume_init()
289 };
290
291 let g2_affine = unsafe {
292 let mut g2_affine = MaybeUninit::<blst_p2_affine>::uninit();
293 blst_p2_to_affine(g2_affine.as_mut_ptr(), &g2.borrow().0);
294 g2_affine.assume_init()
295 };
296
297 unsafe {
298 blst_pairing_raw_aggregate(ctx, &g2_affine, &g1_affine);
299 }
300 }
301
302 unsafe {
303 blst_pairing_commit(ctx);
304 blst_pairing_finalverify(ctx, std::ptr::null())
305 }
306}
307
308pub fn hash_to_g2(msg: &[u8]) -> Signature {
309 hash_to_g2_with_dst(msg, DST)
310}
311
312pub fn hash_to_g2_with_dst(msg: &[u8], dst: &[u8]) -> Signature {
313 let p2 = unsafe {
314 let mut p2 = MaybeUninit::<blst_p2>::uninit();
315 blst_hash_to_g2(
316 p2.as_mut_ptr(),
317 msg.as_ptr(),
318 msg.len(),
319 dst.as_ptr(),
320 dst.len(),
321 std::ptr::null(),
322 0,
323 );
324 p2.assume_init()
325 };
326 Signature(p2)
327}
328
329pub fn aggregate<Sig: Borrow<Signature>, I>(sigs: I) -> Signature
332where
333 I: IntoIterator<Item = Sig>,
334{
335 let mut ret = Signature::default();
336
337 for s in sigs {
338 ret.aggregate(s.borrow());
339 }
340 ret
341}
342
343pub fn verify<Msg: AsRef<[u8]>>(sig: &Signature, key: &PublicKey, msg: Msg) -> bool {
346 unsafe {
347 let mut pubkey_affine = MaybeUninit::<blst_p1_affine>::uninit();
348 let mut sig_affine = MaybeUninit::<blst_p2_affine>::uninit();
349
350 blst_p1_to_affine(pubkey_affine.as_mut_ptr(), &key.0);
351 blst_p2_to_affine(sig_affine.as_mut_ptr(), &sig.0);
352
353 let mut augmented_msg = key.to_bytes().to_vec();
354 augmented_msg.extend_from_slice(msg.as_ref());
355
356 let err = blst_core_verify_pk_in_g1(
357 &pubkey_affine.assume_init(),
358 &sig_affine.assume_init(),
359 true, augmented_msg.as_ptr(),
361 augmented_msg.len(),
362 DST.as_ptr(),
363 DST.len(),
364 std::ptr::null(),
365 0,
366 );
367
368 err == BLST_ERROR::BLST_SUCCESS
369 }
370}
371
372pub fn aggregate_verify<Pk: Borrow<PublicKey>, Msg: Borrow<[u8]>, I>(
376 sig: &Signature,
377 data: I,
378) -> bool
379where
380 I: IntoIterator<Item = (Pk, Msg)>,
381{
382 if !sig.is_valid() {
383 return false;
384 }
385
386 let mut data = data.into_iter().peekable();
387 if data.peek().is_none() {
388 return *sig == Signature::default();
389 }
390
391 let sig_gt = unsafe {
392 let mut sig_affine = MaybeUninit::<blst_p2_affine>::uninit();
393 let mut sig_gt = MaybeUninit::<blst_fp12>::uninit();
394 blst_p2_to_affine(sig_affine.as_mut_ptr(), &sig.0);
395 blst_aggregated_in_g2(sig_gt.as_mut_ptr(), sig_affine.as_ptr());
396 sig_gt.assume_init()
397 };
398
399 let mut v: Vec<u64> = vec![0; unsafe { blst_pairing_sizeof() } / 8];
400 let ctx = unsafe {
401 let ctx = v.as_mut_ptr().cast::<blst_pairing>();
402 blst_pairing_init(
403 ctx,
404 true, DST.as_ptr(),
406 DST.len(),
407 );
408 ctx
409 };
410
411 let mut aug_msg = Vec::<u8>::new();
412 for (pk, msg) in data {
413 if !pk.borrow().is_valid() {
414 return false;
415 }
416
417 let pk_affine = unsafe {
418 let mut pk_affine = MaybeUninit::<blst_p1_affine>::uninit();
419 blst_p1_to_affine(pk_affine.as_mut_ptr(), &pk.borrow().0);
420 pk_affine.assume_init()
421 };
422
423 aug_msg.clear();
424 aug_msg.extend_from_slice(&pk.borrow().to_bytes());
425 aug_msg.extend_from_slice(msg.borrow());
426
427 let err = unsafe {
428 blst_pairing_aggregate_pk_in_g1(
429 ctx,
430 &pk_affine,
431 std::ptr::null(),
432 aug_msg.as_ptr(),
433 aug_msg.len(),
434 std::ptr::null(),
435 0,
436 )
437 };
438
439 if err != BLST_ERROR::BLST_SUCCESS {
440 return false;
441 }
442 }
443
444 unsafe {
445 blst_pairing_commit(ctx);
446 blst_pairing_finalverify(ctx, &sig_gt)
447 }
448}
449
450pub fn aggregate_verify_gt<Gt: Borrow<GTElement>, I>(sig: &Signature, data: I) -> bool
455where
456 I: IntoIterator<Item = Gt>,
457{
458 if !sig.is_valid() {
459 return false;
460 }
461
462 let mut data = data.into_iter();
463 let Some(agg) = data.next() else {
464 return *sig == Signature::default();
465 };
466
467 let mut agg = agg.borrow().clone();
468 for gt in data {
469 agg *= gt.borrow();
470 }
471
472 agg == sig.pair(&PublicKey::generator())
473}
474
475pub fn sign_raw<Msg: AsRef<[u8]>>(sk: &SecretKey, msg: Msg) -> Signature {
479 let p2 = unsafe {
480 let mut p2 = MaybeUninit::<blst_p2>::uninit();
481 blst_hash_to_g2(
482 p2.as_mut_ptr(),
483 msg.as_ref().as_ptr(),
484 msg.as_ref().len(),
485 DST.as_ptr(),
486 DST.len(),
487 std::ptr::null(),
488 0,
489 );
490 blst_sign_pk_in_g1(p2.as_mut_ptr(), p2.as_ptr(), &sk.0);
491 p2.assume_init()
492 };
493 Signature(p2)
494}
495
496pub fn sign<Msg: AsRef<[u8]>>(sk: &SecretKey, msg: Msg) -> Signature {
499 let mut aug_msg = sk.public_key().to_bytes().to_vec();
500 aug_msg.extend_from_slice(msg.as_ref());
501 sign_raw(sk, aug_msg)
502}
503
504#[cfg(feature = "py-bindings")]
505#[pyo3::pymethods]
506impl Signature {
507 #[classattr]
508 pub const SIZE: usize = 96;
509
510 #[new]
511 pub fn init() -> Self {
512 Self::default()
513 }
514
515 #[classmethod]
516 #[pyo3(name = "from_parent")]
517 pub fn from_parent(_cls: &Bound<'_, PyType>, _instance: &Self) -> PyResult<PyObject> {
518 Err(PyNotImplementedError::new_err(
519 "Signature does not support from_parent().",
520 ))
521 }
522
523 #[pyo3(name = "pair")]
524 pub fn py_pair(&self, other: &PublicKey) -> GTElement {
525 self.pair(other)
526 }
527
528 #[staticmethod]
529 #[pyo3(name = "generator")]
530 pub fn py_generator() -> Self {
531 Self::generator()
532 }
533
534 pub fn __str__(&self) -> String {
535 hex::encode(self.to_bytes())
536 }
537
538 #[must_use]
539 pub fn __add__(&self, rhs: &Self) -> Self {
540 self + rhs
541 }
542
543 pub fn __iadd__(&mut self, rhs: &Self) {
544 *self += rhs;
545 }
546}
547
548#[cfg(feature = "py-bindings")]
549mod pybindings {
550 use super::*;
551
552 use crate::parse_hex::parse_hex_string;
553
554 use chik_traits::{FromJsonDict, ToJsonDict};
555
556 impl ToJsonDict for Signature {
557 fn to_json_dict(&self, py: Python<'_>) -> PyResult<PyObject> {
558 let bytes = self.to_bytes();
559 Ok(("0x".to_string() + &hex::encode(bytes))
560 .into_pyobject(py)?
561 .into_any()
562 .unbind())
563 }
564 }
565
566 impl FromJsonDict for Signature {
567 fn from_json_dict(o: &Bound<'_, PyAny>) -> PyResult<Self> {
568 Ok(Self::from_bytes(
569 parse_hex_string(o, 96, "Signature")?
570 .as_slice()
571 .try_into()
572 .unwrap(),
573 )?)
574 }
575 }
576}
577
578#[cfg(test)]
579mod tests {
580 use super::*;
581 use hex::FromHex;
582 use rand::rngs::StdRng;
583 use rand::{Rng, SeedableRng};
584 use rstest::rstest;
585
586 #[test]
587 fn test_from_bytes() {
588 let mut rng = StdRng::seed_from_u64(1337);
589 let mut data = [0u8; 96];
590 for _i in 0..50 {
591 rng.fill(data.as_mut_slice());
592 match Signature::from_bytes(&data) {
594 Err(Error::InvalidSignature(err)) => {
595 assert!([
596 BLST_ERROR::BLST_BAD_ENCODING,
597 BLST_ERROR::BLST_POINT_NOT_ON_CURVE
598 ]
599 .contains(&err));
600 }
601 Err(e) => {
602 panic!("unexpected error from_bytes(): {e}");
603 }
604 Ok(v) => {
605 panic!("unexpected value from_bytes(): {v:?}");
606 }
607 }
608 }
609 }
610
611 #[test]
612 fn test_default_is_valid() {
613 let sig = Signature::default();
614 assert!(sig.is_valid());
615 }
616
617 #[test]
618 fn test_infinity_is_valid() {
619 let mut data = [0u8; 96];
620 data[0] = 0xc0;
621 let sig = Signature::from_bytes(&data).unwrap();
622 assert!(sig.is_valid());
623 }
624
625 #[test]
626 fn test_is_valid() {
627 let mut rng = StdRng::seed_from_u64(1337);
628 let mut data = [0u8; 32];
629 let msg = [0u8; 32];
630 for _i in 0..50 {
631 rng.fill(data.as_mut_slice());
632 let sk = SecretKey::from_seed(&data);
633 let sig = sign(&sk, msg);
634 assert!(sig.is_valid());
635 }
636 }
637
638 #[test]
639 fn test_roundtrip() {
640 let mut rng = StdRng::seed_from_u64(1337);
641 let mut data = [0u8; 32];
642 let mut msg = [0u8; 32];
643 rng.fill(msg.as_mut_slice());
644 for _i in 0..50 {
645 rng.fill(data.as_mut_slice());
646 let sk = SecretKey::from_seed(&data);
647 let sig = sign(&sk, msg);
648 let bytes = sig.to_bytes();
649 let sig2 = Signature::from_bytes(&bytes).unwrap();
650 assert_eq!(sig, sig2);
651 }
652 }
653
654 #[test]
655 fn test_random_verify() {
656 let mut rng = StdRng::seed_from_u64(1337);
657 let mut data = [0u8; 32];
658 let mut msg = [0u8; 32];
659 rng.fill(msg.as_mut_slice());
660 for _i in 0..20 {
661 rng.fill(data.as_mut_slice());
662 let sk = SecretKey::from_seed(&data);
663 let pk = sk.public_key();
664 let sig = sign(&sk, msg);
665 assert!(verify(&sig, &pk, msg));
666
667 let bytes = sig.to_bytes();
668 let sig2 = Signature::from_bytes(&bytes).unwrap();
669 assert!(verify(&sig2, &pk, msg));
670 }
671 }
672
673 #[test]
674 fn test_verify() {
675 let msg = b"foobar";
682 let sk = SecretKey::from_bytes(
683 &<[u8; 32]>::from_hex(
684 "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb",
685 )
686 .unwrap(),
687 )
688 .unwrap();
689
690 let sig = sign(&sk, msg);
691 assert!(verify(&sig, &sk.public_key(), msg));
692
693 assert_eq!(sig.to_bytes(), <[u8; 96]>::from_hex("b45825c0ee7759945c0189b4c38b7e54231ebadc83a851bec3bb7cf954a124ae0cc8e8e5146558332ea152f63bf8846e04826185ef60e817f271f8d500126561319203f9acb95809ed20c193757233454be1562a5870570941a84605bd2c9c9a").unwrap());
694 }
695
696 fn aug_msg_to_g2(pk: &PublicKey, msg: &[u8]) -> Signature {
697 let mut augmented = pk.to_bytes().to_vec();
698 augmented.extend_from_slice(msg);
699 hash_to_g2(augmented.as_slice())
700 }
701
702 #[test]
703 fn test_aggregate_signature() {
704 let sk_hex = "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb";
723 let sk = SecretKey::from_bytes(&<[u8; 32]>::from_hex(sk_hex).unwrap()).unwrap();
724 let msg = b"foobar";
725 let mut agg1 = Signature::default();
726 let mut agg2 = Signature::default();
727 let mut sigs = Vec::<Signature>::new();
728 let mut data = Vec::<(PublicKey, &[u8])>::new();
729 let mut pairs = Vec::<(PublicKey, Signature)>::new();
730 for idx in 0..4 {
731 let derived = sk.derive_hardened(idx as u32);
732 let pk = derived.public_key();
733 data.push((pk, msg));
734 let sig = sign(&derived, msg);
735 agg1.aggregate(&sig);
736 agg2 += &sig;
737 sigs.push(sig);
738 pairs.push((pk, aug_msg_to_g2(&pk, msg)));
739 }
740 let agg3 = aggregate(&sigs);
741 let agg4 = &sigs[0] + &sigs[1] + &sigs[2] + &sigs[3];
742
743 assert_eq!(agg1.to_bytes(), <[u8; 96]>::from_hex("87bce2c588f4257e2792d929834548c7d3af679272cb4f8e1d24cf4bf584dd287aa1d9f5e53a86f288190db45e1d100d0a5e936079a66a709b5f35394cf7d52f49dd963284cb5241055d54f8cf48f61bc1037d21cae6c025a7ea5e9f4d289a18").unwrap());
744 assert_eq!(agg1, agg2);
745 assert_eq!(agg1, agg3);
746 assert_eq!(agg1, agg4);
747
748 assert!(aggregate_verify(&agg1, data.clone()));
750 assert!(aggregate_verify(&agg2, data.clone()));
751 assert!(aggregate_verify(&agg3, data.clone()));
752 assert!(aggregate_verify(&agg4, data.clone()));
753
754 pairs.push((-PublicKey::generator(), agg1));
755 assert!(aggregate_pairing(pairs.clone()));
756 assert!(aggregate_pairing(pairs.into_iter().rev()));
758 }
759
760 #[rstest]
761 fn test_aggregate_gt_signature(#[values(0, 1, 2, 3, 4, 5, 100)] num_keys: usize) {
762 let sk_hex = "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb";
763 let sk = SecretKey::from_bytes(&<[u8; 32]>::from_hex(sk_hex).unwrap()).unwrap();
764 let msg = b"foobar";
765 let mut agg = Signature::default();
766 let mut gts = Vec::<GTElement>::new();
767 let mut pks = Vec::<PublicKey>::new();
768 for idx in 0..num_keys {
769 let derived = sk.derive_hardened(idx as u32);
770 let pk = derived.public_key();
771 let sig = sign(&derived, msg);
772 agg.aggregate(&sig);
773 gts.push(aug_msg_to_g2(&pk, msg).pair(&pk));
774 pks.push(pk);
775 }
776
777 assert!(aggregate_verify_gt(&agg, >s));
778 assert!(aggregate_verify(&agg, pks.iter().map(|pk| (pk, &msg[..]))));
779
780 for _ in 0..num_keys {
782 gts.rotate_right(1);
783 pks.rotate_right(1);
784 assert!(aggregate_verify_gt(&agg, >s));
785 assert!(aggregate_verify(&agg, pks.iter().map(|pk| (pk, &msg[..]))));
786 }
787 for _ in 0..num_keys {
788 gts.rotate_right(1);
789 pks.rotate_right(1);
790 assert!(!aggregate_verify_gt(&agg, >s[1..]));
791 assert!(!aggregate_verify(
792 &agg,
793 pks[1..].iter().map(|pk| (pk, &msg[..]))
794 ));
795 }
796 }
797
798 #[test]
799 fn test_aggregate_duplicate_signature() {
800 let sk_hex = "52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb";
801 let sk = SecretKey::from_bytes(&<[u8; 32]>::from_hex(sk_hex).unwrap()).unwrap();
802 let msg = b"foobar";
803 let mut agg = Signature::default();
804 let mut data = Vec::<(PublicKey, &[u8])>::new();
805 let mut pairs = Vec::<(PublicKey, Signature)>::new();
806 for _idx in 0..2 {
807 let pk = sk.public_key();
808 data.push((pk, msg));
809 agg.aggregate(&sign(&sk, *msg));
810
811 pairs.push((pk, aug_msg_to_g2(&pk, msg)));
812 }
813
814 assert_eq!(agg.to_bytes(), <[u8; 96]>::from_hex("a1cca6540a4a06d096cb5b5fc76af5fd099476e70b623b8c6e4cf02ffde94fc0f75f4e17c67a9e350940893306798a3519368b02dc3464b7270ea4ca233cfa85a38da9e25c9314e81270b54d1e773a2ec5c3e14c62dac7abdebe52f4688310d3").unwrap());
815
816 assert!(aggregate_verify(&agg, data));
817
818 pairs.push((-PublicKey::generator(), agg));
819 assert!(aggregate_pairing(pairs.clone()));
820 assert!(aggregate_pairing(pairs.into_iter().rev()));
822 }
823
824 #[cfg(test)]
825 fn random_sk<R: Rng>(rng: &mut R) -> SecretKey {
826 let mut data = [0u8; 64];
827 rng.fill(data.as_mut_slice());
828 SecretKey::from_seed(&data)
829 }
830
831 #[test]
832 fn test_aggregate_signature_separate_msg() {
833 let mut rng = StdRng::seed_from_u64(1337);
834 let sk = [random_sk(&mut rng), random_sk(&mut rng)];
835 let pk = [sk[0].public_key(), sk[1].public_key()];
836 let msg: [&'static [u8]; 2] = [b"foo", b"foobar"];
837 let sig = [sign(&sk[0], msg[0]), sign(&sk[1], msg[1])];
838 let mut agg = Signature::default();
839 agg.aggregate(&sig[0]);
840 agg.aggregate(&sig[1]);
841
842 assert!(aggregate_verify(&agg, pk.iter().zip(msg)));
843 assert!(aggregate_verify(&agg, pk.iter().zip(msg).rev()));
845 }
846
847 #[test]
848 fn test_aggregate_signature_identity() {
849 let empty = Vec::<(PublicKey, &[u8])>::new();
851 assert!(aggregate_verify(&Signature::default(), empty));
852
853 let pairs = vec![(-PublicKey::generator(), Signature::default())];
854 assert!(aggregate_pairing(pairs));
855 }
856
857 #[test]
858 fn test_invalid_aggregate_signature() {
859 let mut rng = StdRng::seed_from_u64(1337);
860 let sk = [random_sk(&mut rng), random_sk(&mut rng)];
861 let pk = [sk[0].public_key(), sk[1].public_key()];
862 let msg: [&'static [u8]; 2] = [b"foo", b"foobar"];
863 let sig = [sign(&sk[0], msg[0]), sign(&sk[1], msg[1])];
864 let g2s = [aug_msg_to_g2(&pk[0], msg[0]), aug_msg_to_g2(&pk[1], msg[1])];
865 let mut agg = Signature::default();
866 agg.aggregate(&sig[0]);
867 agg.aggregate(&sig[1]);
868
869 assert!(!aggregate_verify(&agg, [(&pk[0], msg[0])]));
870 assert!(!aggregate_verify(&agg, [(&pk[1], msg[1])]));
871 assert!(!aggregate_verify(
873 &agg,
874 [(&pk[0], msg[1]), (&pk[1], msg[0])]
875 ));
876 assert!(!aggregate_verify(
877 &agg,
878 [(&pk[1], msg[0]), (&pk[0], msg[1])]
879 ));
880
881 let gen_sig = (&-PublicKey::generator(), agg);
882 assert!(!aggregate_pairing([
883 (&pk[0], g2s[0].clone()),
884 gen_sig.clone()
885 ]));
886 assert!(!aggregate_pairing([
887 (&pk[1], g2s[1].clone()),
888 gen_sig.clone()
889 ]));
890 assert!(!aggregate_pairing([
892 (&pk[0], g2s[1].clone()),
893 (&pk[1], g2s[0].clone()),
894 gen_sig.clone()
895 ]));
896 assert!(!aggregate_pairing([
897 (&pk[1], g2s[0].clone()),
898 (&pk[0], g2s[1].clone()),
899 gen_sig.clone()
900 ]));
901 }
902
903 #[test]
904 fn test_vector_2_aggregate_of_aggregates() {
905 let message1 = [1_u8, 2, 3, 40];
908 let message2 = [5_u8, 6, 70, 201];
909 let message3 = [9_u8, 10, 11, 12, 13];
910 let message4 = [15_u8, 63, 244, 92, 0, 1];
911
912 let sk1 = SecretKey::from_seed(&[2_u8; 32]);
913 let sk2 = SecretKey::from_seed(&[3_u8; 32]);
914
915 let pk1 = sk1.public_key();
916 let pk2 = sk2.public_key();
917
918 let sig1 = sign(&sk1, message1);
919 let sig2 = sign(&sk2, message2);
920 let sig3 = sign(&sk2, message1);
921 let sig4 = sign(&sk1, message3);
922 let sig5 = sign(&sk1, message1);
923 let sig6 = sign(&sk1, message4);
924
925 let agg_sig_l = aggregate([sig1, sig2]);
926 let agg_sig_r = aggregate([sig3, sig4, sig5]);
927 let aggsig = aggregate([agg_sig_l, agg_sig_r, sig6]);
928
929 assert!(aggregate_verify(
930 &aggsig,
931 [
932 (&pk1, message1.as_ref()),
933 (&pk2, message2.as_ref()),
934 (&pk2, message1.as_ref()),
935 (&pk1, message3.as_ref()),
936 (&pk1, message1.as_ref()),
937 (&pk1, message4.as_ref())
938 ]
939 ));
940
941 assert_eq!(
942 aggsig.to_bytes(),
943 <[u8; 96]>::from_hex(
944 "a1d5360dcb418d33b29b90b912b4accde535cf0e52caf467a005dc632d9f7af44b6c4e9acd4\
945 6eac218b28cdb07a3e3bc087df1cd1e3213aa4e11322a3ff3847bbba0b2fd19ddc25ca964871\
946 997b9bceeab37a4c2565876da19382ea32a962200"
947 )
948 .unwrap()
949 );
950 }
951
952 #[test]
953 fn test_signature_zero_key() {
954 let sk = SecretKey::from_bytes(&[0; 32]).unwrap();
957 assert_eq!(sign(&sk, [1_u8, 2, 3]), Signature::default());
958 }
959
960 #[test]
961 fn test_aggregate_many_g2_elements_diff_message() {
962 let mut rng = StdRng::seed_from_u64(1337);
966
967 let mut pairs = Vec::<(PublicKey, Vec<u8>)>::new();
968 let mut sigs = Vec::<Signature>::new();
969
970 for i in 0..80 {
971 let message = vec![0_u8, 100, 2, 45, 64, 12, 12, 63, i];
972 let sk = random_sk(&mut rng);
973 let sig = sign(&sk, &message);
974 pairs.push((sk.public_key(), message));
975 sigs.push(sig);
976 }
977
978 let aggsig = aggregate(sigs);
979
980 assert!(aggregate_verify(&aggsig, pairs));
981 }
982
983 #[test]
984 fn test_aggregate_identity() {
985 let sig = Signature::default();
988 let aggsig = aggregate([&sig]);
989 assert_eq!(aggsig, sig);
990 assert_eq!(aggsig, Signature::default());
991
992 let pairs: [(&PublicKey, &[u8]); 0] = [];
993 assert!(aggregate_verify(&aggsig, pairs));
994 }
995
996 #[test]
997 fn test_aggregate_multiple_levels_degenerate() {
998 let mut rng = StdRng::seed_from_u64(1337);
1002
1003 let message1 = [100_u8, 2, 254, 88, 90, 45, 23];
1004 let sk1 = random_sk(&mut rng);
1005 let pk1 = sk1.public_key();
1006 let mut agg_sig = sign(&sk1, message1);
1007 let mut pairs: Vec<(PublicKey, &[u8])> = vec![(pk1, &message1)];
1008
1009 for _i in 0..10 {
1010 let sk = random_sk(&mut rng);
1011 let pk = sk.public_key();
1012 pairs.push((pk, &message1));
1013 let sig = sign(&sk, message1);
1014 agg_sig.aggregate(&sig);
1015 }
1016 assert!(aggregate_verify(&agg_sig, pairs));
1017 }
1018
1019 #[test]
1020 fn test_aggregate_multiple_levels_different_messages() {
1021 let mut rng = StdRng::seed_from_u64(1337);
1025
1026 let message1 = [100_u8, 2, 254, 88, 90, 45, 23];
1027 let message2 = [192_u8, 29, 2, 0, 0, 45, 23];
1028 let message3 = [52_u8, 29, 2, 0, 0, 45, 102];
1029 let message4 = [99_u8, 29, 2, 0, 0, 45, 222];
1030
1031 let sk1 = random_sk(&mut rng);
1032 let sk2 = random_sk(&mut rng);
1033
1034 let pk1 = sk1.public_key();
1035 let pk2 = sk2.public_key();
1036
1037 let sig1 = sign(&sk1, message1);
1038 let sig2 = sign(&sk2, message2);
1039 let sig3 = sign(&sk2, message3);
1040 let sig4 = sign(&sk1, message4);
1041
1042 let agg_sig_l = aggregate([sig1, sig2]);
1043 let agg_sig_r = aggregate([sig3, sig4]);
1044 let agg_sig = aggregate([agg_sig_l, agg_sig_r]);
1045
1046 let all_pairs: [(&PublicKey, &[u8]); 4] = [
1047 (&pk1, &message1),
1048 (&pk2, &message2),
1049 (&pk2, &message3),
1050 (&pk1, &message4),
1051 ];
1052 assert!(aggregate_verify(&agg_sig, all_pairs));
1053 }
1054
1055 #[test]
1056 fn test_aug_scheme() {
1057 let msg1 = [7_u8, 8, 9];
1061 let msg2 = [10_u8, 11, 12];
1062
1063 let sk1 = SecretKey::from_seed(&[4_u8; 32]);
1064 let pk1 = sk1.public_key();
1065 let pk1v = pk1.to_bytes();
1066 let sig1 = sign(&sk1, msg1);
1067 let sig1v = sig1.to_bytes();
1068
1069 assert!(verify(&sig1, &pk1, msg1));
1070 assert!(verify(
1071 &Signature::from_bytes(&sig1v).unwrap(),
1072 &PublicKey::from_bytes(&pk1v).unwrap(),
1073 msg1
1074 ));
1075
1076 let sk2 = SecretKey::from_seed(&[5_u8; 32]);
1077 let pk2 = sk2.public_key();
1078 let pk2v = pk2.to_bytes();
1079 let sig2 = sign(&sk2, msg2);
1080 let sig2v = sig2.to_bytes();
1081
1082 assert!(verify(&sig2, &pk2, msg2));
1083 assert!(verify(
1084 &Signature::from_bytes(&sig2v).unwrap(),
1085 &PublicKey::from_bytes(&pk2v).unwrap(),
1086 msg2
1087 ));
1088
1089 assert!(!verify(&sig2, &pk1, msg1));
1091 assert!(!verify(
1092 &Signature::from_bytes(&sig2v).unwrap(),
1093 &PublicKey::from_bytes(&pk1v).unwrap(),
1094 msg1
1095 ));
1096 assert!(!verify(&sig1, &pk1, msg2));
1098 assert!(!verify(
1099 &Signature::from_bytes(&sig1v).unwrap(),
1100 &PublicKey::from_bytes(&pk1v).unwrap(),
1101 msg2
1102 ));
1103 assert!(!verify(&sig1, &pk2, msg1));
1105 assert!(!verify(
1106 &Signature::from_bytes(&sig1v).unwrap(),
1107 &PublicKey::from_bytes(&pk2v).unwrap(),
1108 msg1
1109 ));
1110
1111 let aggsig = aggregate([sig1, sig2]);
1112 let aggsigv = aggsig.to_bytes();
1113 let pairs: [(&PublicKey, &[u8]); 2] = [(&pk1, &msg1), (&pk2, &msg2)];
1114 assert!(aggregate_verify(&aggsig, pairs));
1115 assert!(aggregate_verify(
1116 &Signature::from_bytes(&aggsigv).unwrap(),
1117 pairs
1118 ));
1119 }
1120
1121 #[test]
1122 fn test_hash() {
1123 fn hash<T: Hash>(v: T) -> u64 {
1124 use std::collections::hash_map::DefaultHasher;
1125 let mut h = DefaultHasher::new();
1126 v.hash(&mut h);
1127 h.finish()
1128 }
1129
1130 let mut rng = StdRng::seed_from_u64(1337);
1131 let mut data = [0u8; 32];
1132 rng.fill(data.as_mut_slice());
1133 let sk = SecretKey::from_seed(&data);
1134 let sig1 = sign(&sk, [0, 1, 2]);
1135 let sig2 = sign(&sk, [0, 1, 2, 3]);
1136
1137 assert!(hash(sig1) != hash(sig2));
1138 assert_eq!(hash(sign(&sk, [0, 1, 2])), hash(sign(&sk, [0, 1, 2])));
1139 }
1140
1141 #[test]
1142 fn test_debug() {
1143 let mut data = [0u8; 96];
1144 data[0] = 0xc0;
1145 let sig = Signature::from_bytes(&data).unwrap();
1146 assert_eq!(
1147 format!("{sig:?}"),
1148 format!("<G2Element {}>", hex::encode(data))
1149 );
1150 }
1151
1152 #[test]
1153 fn test_generator() {
1154 assert_eq!(
1155 hex::encode(Signature::generator().to_bytes()),
1156 "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8"
1157 );
1158 }
1159
1160 #[rstest]
1162 #[case("0a7ecb9c6d6f0af8d922c9b348d686f7f827c5f5d7a53036e5dd6c4cfe088806375d730251df57c03b0eaa41ca2a9cc51817cfd6118c065e9b337e42a6b66621e2ffa79f576ae57dcb4916459b0131d42383b790a4f60c5aeb339b61a78d85a808b73e0701084dc16b5d7aa8c2f5385f83a217bc29934d0d02c51365410232e3c0288438e3110aa6e8cdef7bd32c46d60d0104952aaa0f0545cbe1548b70eed8b543ce19ede34cc51a387d092221417db0253f4651666b17303e225eac706107", "8a7ecb9c6d6f0af8d922c9b348d686f7f827c5f5d7a53036e5dd6c4cfe088806375d730251df57c03b0eaa41ca2a9cc51817cfd6118c065e9b337e42a6b66621e2ffa79f576ae57dcb4916459b0131d42383b790a4f60c5aeb339b61a78d85a8")]
1163 #[case("13e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801", "93e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb8")]
1164 #[case("140acf170629d78244fb753f05fb79578add9217add53996d5de7c3005880c0dea903f851d6be749ebfb81c9721871370ef60428444d76f4ff81515628a4eb63e72c3cd7651a23c4eca109d1d88fec5a53626b36c76407926f308366b5ded1b219a481d87c6f87a4021fa8aa32851874f01b3eb011f6ed69c7884717fb0f5239bdc7310c2bc287659cd4a93976deaac20f4a21f0b004c767be4a21f36861616a5399b3e27431dc8133f325603230eaf1debdce8077105ab46baafa4836842305", "b40acf170629d78244fb753f05fb79578add9217add53996d5de7c3005880c0dea903f851d6be749ebfb81c9721871370ef60428444d76f4ff81515628a4eb63e72c3cd7651a23c4eca109d1d88fec5a53626b36c76407926f308366b5ded1b2")]
1165 fn test_from_uncompressed(#[case] input: &str, #[case] expect: &str) {
1166 let input = hex::decode(input).unwrap();
1167 let g2 = Signature::from_uncompressed(input.as_slice().try_into().unwrap()).unwrap();
1168 let compressed = g2.to_bytes();
1169 assert_eq!(hex::encode(compressed), expect);
1170 }
1171
1172 #[test]
1173 fn test_negate_roundtrip() {
1174 let mut rng = StdRng::seed_from_u64(1337);
1175 let mut data = [0u8; 32];
1176 let mut msg = [0u8; 32];
1177 rng.fill(msg.as_mut_slice());
1178 for _i in 0..50 {
1179 rng.fill(data.as_mut_slice());
1180 let sk = SecretKey::from_seed(&data);
1181 let g2 = sign(&sk, msg);
1182
1183 let mut g2_neg = g2.clone();
1184 g2_neg.negate();
1185 assert!(g2_neg != g2);
1186
1187 g2_neg.negate();
1188 assert!(g2_neg == g2);
1189 }
1190 }
1191
1192 #[test]
1193 fn test_negate_infinity() {
1194 let g2 = Signature::default();
1195 let mut g2_neg = g2.clone();
1196 g2_neg.negate();
1198 assert!(g2_neg == g2);
1199 }
1200
1201 #[test]
1202 fn test_negate() {
1203 let mut rng = StdRng::seed_from_u64(1337);
1204 let mut data = [0u8; 32];
1205 let mut msg = [0u8; 32];
1206 rng.fill(msg.as_mut_slice());
1207 for _i in 0..50 {
1208 rng.fill(data.as_mut_slice());
1209 let sk = SecretKey::from_seed(&data);
1210 let g2 = sign(&sk, msg);
1211 let mut g2_neg = g2.clone();
1212 g2_neg.negate();
1213
1214 let mut g2_double = g2.clone();
1215 g2_double += &g2;
1217 assert!(g2_double != g2);
1218 g2_double += &g2_neg;
1219 assert!(g2_double == g2);
1220 }
1221 }
1222
1223 #[test]
1224 fn test_scalar_multiply() {
1225 let mut rng = StdRng::seed_from_u64(1337);
1226 let mut data = [0u8; 32];
1227 let mut msg = [0u8; 32];
1228 rng.fill(msg.as_mut_slice());
1229 for _i in 0..50 {
1230 rng.fill(data.as_mut_slice());
1231 let sk = SecretKey::from_seed(&data);
1232 let mut g2 = sign(&sk, msg);
1233 let mut g2_double = g2.clone();
1234 g2_double += &g2;
1235 assert!(g2_double != g2);
1236 g2.scalar_multiply(&[2]);
1238 assert!(g2_double == g2);
1239 }
1240 }
1241
1242 #[test]
1243 fn test_hash_to_g2_different_dst() {
1244 const DEFAULT_DST: &[u8] = b"BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_";
1245 const CUSTOM_DST: &[u8] = b"foobar";
1246
1247 let mut rng = StdRng::seed_from_u64(1337);
1248 let mut msg = [0u8; 32];
1249 for _i in 0..50 {
1250 rng.fill(&mut msg);
1251 let default_hash = hash_to_g2(&msg);
1252 assert_eq!(default_hash, hash_to_g2_with_dst(&msg, DEFAULT_DST));
1253 assert!(default_hash != hash_to_g2_with_dst(&msg, CUSTOM_DST));
1254 }
1255 }
1256
1257 #[rstest]
1259 #[case("abcdef0123456789", "92596412844e12c4733b5a6bfc5727cde4c20b345665d2de99de163266f3ba6a944c6c0fdd9d9fe57b9a4acb769bf3780456f8aab4cd41a70836dba57a5278a85fbd18eb96a2b56cfbda853186c9d190c43e63bc3e6a181aed692e97bbdb1944")]
1260 fn test_hash_to_g2(#[case] input: &str, #[case] expect: &str) {
1261 let g2 = hash_to_g2(input.as_bytes());
1262 assert_eq!(hex::encode(g2.to_bytes()), expect);
1263 }
1264
1265 #[rstest]
1267 #[case("abcdef0123456789", "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_", "8ee1ff66094b8975401c86ad424076d97fed9c2025db5f9dfde6ed455c7bff34b55e96379c1f9ee3c173633587f425e50aed3e807c6c7cd7bed35d40542eee99891955b2ea5321ebde37172e2c01155138494c2d725b03c02765828679bf011e")]
1268 #[case("abcdef0123456789", "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_", "92596412844e12c4733b5a6bfc5727cde4c20b345665d2de99de163266f3ba6a944c6c0fdd9d9fe57b9a4acb769bf3780456f8aab4cd41a70836dba57a5278a85fbd18eb96a2b56cfbda853186c9d190c43e63bc3e6a181aed692e97bbdb1944")]
1269 fn test_hash_to_g2_with_dst(#[case] input: &str, #[case] dst: &str, #[case] expect: &str) {
1270 let g2 = hash_to_g2_with_dst(input.as_bytes(), dst.as_bytes());
1271 assert_eq!(hex::encode(g2.to_bytes()), expect);
1272 }
1273}
1274
1275#[cfg(test)]
1276#[cfg(feature = "py-bindings")]
1277mod pytests {
1278 use super::*;
1279
1280 use pyo3::Python;
1281 use rand::rngs::StdRng;
1282 use rand::{Rng, SeedableRng};
1283 use rstest::rstest;
1284
1285 #[test]
1286 fn test_json_dict_roundtrip() {
1287 pyo3::prepare_freethreaded_python();
1288 let mut rng = StdRng::seed_from_u64(1337);
1289 let mut data = [0u8; 32];
1290 let mut msg = [0u8; 10];
1291 for _i in 0..50 {
1292 rng.fill(data.as_mut_slice());
1293 rng.fill(msg.as_mut_slice());
1294 let sk = SecretKey::from_seed(&data);
1295 let sig = sign(&sk, msg);
1296 Python::with_gil(|py| {
1297 let string = sig.to_json_dict(py).expect("to_json_dict");
1298 let py_class = py.get_type::<Signature>();
1299 let sig2 = Signature::from_json_dict(&py_class, py, string.bind(py))
1300 .unwrap()
1301 .extract(py)
1302 .unwrap();
1303 assert_eq!(sig, sig2);
1304 });
1305 }
1306 }
1307
1308 #[rstest]
1309 #[case("0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e", "Signature, invalid length 95 expected 96")]
1310 #[case("0x000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00", "Signature, invalid length 97 expected 96")]
1311 #[case("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e", "Signature, invalid length 95 expected 96")]
1312 #[case("000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00", "Signature, invalid length 97 expected 96")]
1313 #[case("00r102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0ff000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f", "invalid hex")]
1314 fn test_json_dict(#[case] input: &str, #[case] msg: &str) {
1315 pyo3::prepare_freethreaded_python();
1316 Python::with_gil(|py| {
1317 let py_class = py.get_type::<Signature>();
1318 let err = Signature::from_json_dict(
1319 &py_class,
1320 py,
1321 &input.to_string().into_pyobject(py).unwrap().into_any(),
1322 )
1323 .unwrap_err();
1324 assert_eq!(err.value(py).to_string(), msg.to_string());
1325 });
1326 }
1327}