chik_bls/
signature.rs

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
18// we use the augmented scheme
19pub(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        // placeholder
33        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        // Infinity was considered a valid G2Element in older Relic versions
95        // For historical compatibililty this behavior is maintained.
96        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
251// validate a series of public keys (G1 points) and G2 points. These points are
252// paired and the resulting GT points are multiplied. If the resulting GT point
253// is the identity, the function returns true, otherwise false. To validate an
254// aggregate signature, include the G1 generator and the signature as one of the
255// pairs.
256pub 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, // hash
271            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
329// aggregate the signatures into a single one. It can then be validated using
330// aggregate_verify()
331pub 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
343// verify a signature given a single public key and message using the augmented
344// scheme, i.e. the public key is pre-pended to the message before hashed to G2.
345pub 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, // hash
360            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
372// verify an aggregate signature given all public keys and messages.
373// Messages will been augmented with the public key.
374// returns true if the signature is valid.
375pub 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, // hash
405            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
450// verify an aggregate signature by pre-paired public keys and messages.
451// Messages having been augmented and hashed to G2 and then paired with the G1
452// public key.
453// returns true if the signature is valid.
454pub 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
475// Signs msg using sk without augmenting the message with the public key. This
476// function is used when the caller augments the message with some other public
477// key
478pub 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
496// Signs msg using sk using the augmented scheme, meaning the public key is
497// pre-pended to msg befire signing.
498pub 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            // just any random bytes are not a valid signature and should fail
593            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        // test case from:
676        // from blspy import PrivateKey
677        // from blspy import AugSchemeMPL
678        // sk = PrivateKey.from_bytes(bytes.fromhex("52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb"))
679        // data = b"foobar"
680        // print(AugSchemeMPL.sign(sk, data))
681        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        // from blspy import PrivateKey
705        // from blspy import AugSchemeMPL
706        // sk = PrivateKey.from_bytes(bytes.fromhex("52d75c4707e39595b27314547f9723e5530c01198af3fc5849d9a7af65631efb"))
707        // data = b"foobar"
708        // sk0 = AugSchemeMPL.derive_child_sk(sk, 0)
709        // sk1 = AugSchemeMPL.derive_child_sk(sk, 1)
710        // sk2 = AugSchemeMPL.derive_child_sk(sk, 2)
711        // sk3 = AugSchemeMPL.derive_child_sk(sk, 3)
712
713        // sig0 = AugSchemeMPL.sign(sk0, data)
714        // sig1 = AugSchemeMPL.sign(sk1, data)
715        // sig2 = AugSchemeMPL.sign(sk2, data)
716        // sig3 = AugSchemeMPL.sign(sk3, data)
717
718        // agg = AugSchemeMPL.aggregate([sig0, sig1, sig2, sig3])
719
720        // 87bce2c588f4257e2792d929834548c7d3af679272cb4f8e1d24cf4bf584dd287aa1d9f5e53a86f288190db45e1d100d0a5e936079a66a709b5f35394cf7d52f49dd963284cb5241055d54f8cf48f61bc1037d21cae6c025a7ea5e9f4d289a18
721
722        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        // ensure the aggregate signature verifies OK
749        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        // order does not matter
757        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, &gts));
778        assert!(aggregate_verify(&agg, pks.iter().map(|pk| (pk, &msg[..]))));
779
780        // the order of the GTElements does not matter
781        for _ in 0..num_keys {
782            gts.rotate_right(1);
783            pks.rotate_right(1);
784            assert!(aggregate_verify_gt(&agg, &gts));
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, &gts[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        // order does not matter
821        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        // order does not matter
844        assert!(aggregate_verify(&agg, pk.iter().zip(msg).rev()));
845    }
846
847    #[test]
848    fn test_aggregate_signature_identity() {
849        // when verifying 0 messages, an identity signature is considered valid
850        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        // public keys mixed with the wrong message
872        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        // public keys mixed with the wrong message
891        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        // test case from: bls-signatures/src/test.cpp
906        // "Chik test vector 2 (Augmented, aggregate of aggregates)"
907        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        // test case from: bls-signatures/src/test.cpp
955        // "Should sign with the zero key"
956        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        // test case from: bls-signatures/src/test.cpp
963        // "Should Aug aggregate many G2Elements, diff message"
964
965        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        // test case from: bls-signatures/src/test.cpp
986        // "Aggregate Verification of zero items with infinity should pass"
987        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        // test case from: bls-signatures/src/test.cpp
999        // "Should aggregate with multiple levels, degenerate"
1000
1001        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        // test case from: bls-signatures/src/test.cpp
1022        // "Should aggregate with multiple levels, different messages"
1023
1024        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        // test case from: bls-signatures/src/test.cpp
1058        // "Aug Scheme"
1059
1060        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        // Wrong G2Element
1090        assert!(!verify(&sig2, &pk1, msg1));
1091        assert!(!verify(
1092            &Signature::from_bytes(&sig2v).unwrap(),
1093            &PublicKey::from_bytes(&pk1v).unwrap(),
1094            msg1
1095        ));
1096        // Wrong msg
1097        assert!(!verify(&sig1, &pk1, msg2));
1098        assert!(!verify(
1099            &Signature::from_bytes(&sig1v).unwrap(),
1100            &PublicKey::from_bytes(&pk1v).unwrap(),
1101            msg2
1102        ));
1103        // Wrong pk
1104        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    // test cases from zksnark test in chik_rs
1161    #[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        // negate on infinity is a no-op
1197        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            // adding the negative undoes adding the positive
1216            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            // scalar multiply by 2 is the same as adding oneself
1237            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    // test cases from klvm_rs
1258    #[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    // test cases from klvm_rs
1266    #[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}