arnaucube
arnaucube/babyjubjub-rsPublic Self-hosted repository
babyjubjub-rs/src/lib.rs
src/lib.rsRaw
  1// WARNING still updating the code, it works, but is still in process the refactor.
  2
  3extern crate rand;
  4#[macro_use]
  5extern crate ff;
  6use ff::*;
  7
  8use poseidon_rs::Poseidon;
  9pub type Fr = poseidon_rs::Fr; // alias
 10
 11#[macro_use]
 12extern crate arrayref;
 13extern crate generic_array;
 14extern crate num;
 15extern crate num_bigint;
 16extern crate num_traits;
 17
 18extern crate rand6;
 19use rand6::Rng;
 20
 21use blake2::{Blake2b, Digest};
 22use std::cmp::min;
 23
 24use num_bigint::{BigInt, RandBigInt, RandomBits, Sign, ToBigInt};
 25use num_traits::{One, Zero};
 26
 27use generic_array::GenericArray;
 28
 29pub mod utils;
 30
 31#[macro_use]
 32extern crate lazy_static;
 33
 34lazy_static! {
 35    static ref D: Fr = Fr::from_str("168696").unwrap();
 36    static ref D_big: BigInt = BigInt::parse_bytes(b"168696", 10).unwrap();
 37    static ref A: Fr = Fr::from_str("168700").unwrap();
 38    static ref A_big: BigInt = BigInt::parse_bytes(b"168700", 10).unwrap();
 39    pub static ref Q: BigInt = BigInt::parse_bytes(
 40        b"21888242871839275222246405745257275088548364400416034343698204186575808495617",10
 41    )
 42    .unwrap();
 43    // pub static ref Q: Fr = Fr::from_str(
 44    //     "21888242871839275222246405745257275088548364400416034343698204186575808495617"
 45    // )
 46    // .unwrap();
 47    static ref B8: Point = Point {
 48        x: Fr::from_str(
 49            "5299619240641551281634865583518297030282874472190772894086521144482721001553",
 50        )
 51        .unwrap(),
 52        y: Fr::from_str(
 53            "16950150798460657717958625567821834550301663161624707787222815936182638968203",
 54        )
 55        .unwrap(),
 56            // z: Fr::one(),
 57    };
 58    static ref ORDER: Fr = Fr::from_str(
 59        "21888242871839275222246405745257275088614511777268538073601725287587578984328",
 60    )
 61    .unwrap();
 62
 63    // SUBORDER = ORDER >> 3
 64    // static ref SUBORDER: Fr = Fr::from_str(
 65    //     "i2736030358979909402780800718157159386076813972158567259200215660948447373041",
 66    // )
 67    // .unwrap();
 68    static ref SUBORDER: BigInt = &BigInt::parse_bytes(
 69                b"21888242871839275222246405745257275088614511777268538073601725287587578984328",
 70                        10,
 71                            )
 72            .unwrap()
 73                    >> 3;
 74    static ref poseidon: poseidon_rs::Poseidon = Poseidon::new();
 75}
 76
 77#[derive(Clone, Debug)]
 78pub struct PointProjective {
 79    pub x: Fr,
 80    pub y: Fr,
 81    pub z: Fr,
 82}
 83
 84impl PointProjective {
 85    pub fn affine(&self) -> Point {
 86        if self.z.is_zero() {
 87            return Point {
 88                x: Fr::zero(),
 89                y: Fr::zero(),
 90            };
 91        }
 92
 93        let mut zinv = self.z.inverse().unwrap();
 94        let mut x = self.x;
 95        x.mul_assign(&zinv);
 96        let mut y = self.y;
 97        y.mul_assign(&zinv);
 98
 99        Point {
100            x: x.clone(),
101            y: y.clone(),
102        }
103    }
104    pub fn add(&self, q: &PointProjective) -> Result<PointProjective, String> {
105        // add-2008-bbjlp https://hyperelliptic.org/EFD/g1p/auto-twisted-projective.html#doubling-dbl-2008-bbjlp
106        let mut a = self.z;
107        a.mul_assign(&q.z);
108        let mut b = a;
109        b.square();
110        let mut c = self.x;
111        c.mul_assign(&q.x);
112        let mut d = self.y;
113        d.mul_assign(&q.y);
114        let mut e = D.clone();
115        e.mul_assign(&c);
116        e.mul_assign(&d);
117        let mut f = b;
118        f.sub_assign(&e);
119        let mut g = b;
120        g.add_assign(&e);
121        let mut x1y1 = self.x;
122        x1y1.add_assign(&self.y);
123        let mut x2y2 = q.x;
124        x2y2.add_assign(&q.y);
125        let mut aux = x1y1;
126        aux.mul_assign(&x2y2);
127        aux.sub_assign(&c);
128        aux.sub_assign(&d);
129        let mut x3 = a;
130        x3.mul_assign(&f);
131        x3.mul_assign(&aux);
132        let mut ac = A.clone();
133        ac.mul_assign(&c);
134        let mut dac = d;
135        dac.sub_assign(&ac);
136        let mut y3 = a;
137        y3.mul_assign(&g);
138        y3.mul_assign(&dac);
139        let mut z3 = f;
140        z3.mul_assign(&g);
141
142        Ok(PointProjective {
143            x: x3.clone(),
144            y: y3.clone(),
145            z: z3.clone(),
146        })
147    }
148}
149
150#[derive(Clone, Debug)]
151pub struct Point {
152    pub x: Fr,
153    pub y: Fr,
154}
155
156impl Point {
157    pub fn projective(&self) -> PointProjective {
158        PointProjective {
159            x: self.x.clone(),
160            y: self.y.clone(),
161            z: Fr::one(),
162        }
163    }
164
165    pub fn mul_scalar(&self, n: &BigInt) -> Result<Point, String> {
166        let mut r: PointProjective = PointProjective {
167            x: Fr::zero(),
168            y: Fr::one(),
169            z: Fr::one(),
170        };
171        let mut exp: PointProjective = self.projective();
172        let (_, b) = n.to_bytes_le();
173        for i in 0..n.bits() {
174            if test_bit(&b, i) {
175                r = r.add(&exp)?;
176            }
177            exp = exp.add(&exp)?;
178        }
179        Ok(r.affine())
180    }
181
182    pub fn compress(&self) -> [u8; 32] {
183        let p = &self;
184        let mut r: [u8; 32] = [0; 32];
185        let x_big = BigInt::parse_bytes(to_hex(&p.x).as_bytes(), 16).unwrap();
186        let y_big = BigInt::parse_bytes(to_hex(&p.y).as_bytes(), 16).unwrap();
187        let (_, y_bytes) = y_big.to_bytes_le();
188        let len = min(y_bytes.len(), r.len());
189        r[..len].copy_from_slice(&y_bytes[..len]);
190        if &x_big > &(&Q.clone() >> 1) {
191            r[31] = r[31] | 0x80;
192        }
193        r
194    }
195
196    pub fn equals(&self, p: Point) -> bool {
197        if self.x == p.x && self.y == p.y {
198            return true;
199        }
200        false
201    }
202}
203
204pub fn test_bit(b: &Vec<u8>, i: usize) -> bool {
205    return b[i / 8] & (1 << (i % 8)) != 0;
206}
207
208pub fn decompress_point(bb: [u8; 32]) -> Result<Point, String> {
209    // https://tools.ietf.org/html/rfc8032#section-5.2.3
210    let mut sign: bool = false;
211    let mut b = bb.clone();
212    if b[31] & 0x80 != 0x00 {
213        sign = true;
214        b[31] = b[31] & 0x7F;
215    }
216    let y: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[..]);
217    if y >= Q.clone() {
218        return Err("y outside the Finite Field over R".to_string());
219    }
220    let one: BigInt = One::one();
221
222    // x^2 = (1 - y^2) / (a - d * y^2) (mod p)
223    let den = utils::modinv(
224        &utils::modulus(
225            &(&A_big.clone() - utils::modulus(&(&D_big.clone() * (&y * &y)), &Q)),
226            &Q,
227        ),
228        &Q,
229    )?;
230    let mut x: BigInt = utils::modulus(&((one - utils::modulus(&(&y * &y), &Q)) * den), &Q);
231    x = utils::modsqrt(&x, &Q)?;
232
233    if sign && !(&x > &(&Q.clone() >> 1)) || (!sign && (&x > &(&Q.clone() >> 1))) {
234        x = x * -1.to_bigint().unwrap();
235    }
236    x = utils::modulus(&x, &Q);
237    let x_fr: Fr = Fr::from_str(&x.to_string()).unwrap();
238    let y_fr: Fr = Fr::from_str(&y.to_string()).unwrap();
239    Ok(Point { x: x_fr, y: y_fr })
240}
241
242#[derive(Debug, Clone)]
243pub struct Signature {
244    r_b8: Point,
245    s: BigInt,
246}
247
248impl Signature {
249    pub fn compress(&self) -> [u8; 64] {
250        let mut b: Vec<u8> = Vec::new();
251        b.append(&mut self.r_b8.compress().to_vec());
252        let (_, s_bytes) = self.s.to_bytes_le();
253        let mut s_32bytes: [u8; 32] = [0; 32];
254        let len = min(s_bytes.len(), s_32bytes.len());
255        s_32bytes[..len].copy_from_slice(&s_bytes[..len]);
256        b.append(&mut s_32bytes.to_vec());
257        let mut r: [u8; 64] = [0; 64];
258        r[..].copy_from_slice(&b[..]);
259        r
260    }
261}
262
263pub fn decompress_signature(b: &[u8; 64]) -> Result<Signature, String> {
264    let r_b8_bytes: [u8; 32] = *array_ref!(b[..32], 0, 32);
265    let s: BigInt = BigInt::from_bytes_le(Sign::Plus, &b[32..]);
266    let r_b8 = decompress_point(r_b8_bytes);
267    match r_b8 {
268        Result::Err(err) => return Err(err.to_string()),
269        Result::Ok(res) => Ok(Signature {
270            r_b8: res.clone(),
271            s: s,
272        }),
273    }
274}
275
276pub struct PrivateKey {
277    key: BigInt,
278}
279
280impl PrivateKey {
281    pub fn public(&self) -> Result<Point, String> {
282        // https://tools.ietf.org/html/rfc8032#section-5.1.5
283        let pk = B8.mul_scalar(&self.key)?;
284        Ok(pk.clone())
285    }
286
287    pub fn sign(&self, msg: BigInt) -> Result<Signature, String> {
288        if msg > Q.clone() {
289            return Err("msg outside the Finite Field".to_string());
290        }
291        // https://tools.ietf.org/html/rfc8032#section-5.1.6
292        let mut hasher = Blake2b::new();
293        let (_, sk_bytes) = self.key.to_bytes_be();
294        hasher.input(sk_bytes);
295        let mut h = hasher.result(); // h: hash(sk)
296                                     // s: h[32:64]
297        let (_, msg_bytes) = msg.to_bytes_be();
298        let msgFr: Fr = Fr::from_str(&msg.to_string()).unwrap();
299
300        let s = GenericArray::<u8, generic_array::typenum::U32>::from_mut_slice(&mut h[32..64]);
301        let r_bytes = utils::concatenate_arrays(s, &msg_bytes);
302        let mut r = BigInt::from_bytes_be(Sign::Plus, &r_bytes[..]);
303        r = utils::modulus(&r, &SUBORDER);
304        let r8: Point = B8.mul_scalar(&r)?;
305        let a = &self.public()?;
306
307        let hm_input = vec![r8.x.clone(), r8.y.clone(), a.x.clone(), a.y.clone(), msgFr];
308        let hm = poseidon.hash(hm_input)?;
309
310        let mut s = &self.key << 3;
311        let hmB = BigInt::parse_bytes(to_hex(&hm).as_bytes(), 16).unwrap();
312        s = hmB * s;
313        s = r + s;
314        s = s % &SUBORDER.clone();
315
316        Ok(Signature {
317            r_b8: r8.clone(),
318            s: s,
319        })
320    }
321
322    pub fn sign_schnorr(&self, m: BigInt) -> Result<(Point, BigInt), String> {
323        // random r
324        let mut rng = rand6::thread_rng();
325        let k = rng.gen_biguint(1024).to_bigint().unwrap();
326
327        // r = k·G
328        let r = B8.mul_scalar(&k)?;
329
330        // h = H(x, r, m)
331        let pk = &self.public()?;
332        let h = schnorr_hash(&pk, m, &r)?;
333
334        // s= k+x·h
335        let s = k + &self.key * &h;
336        Ok((r, s))
337    }
338}
339
340pub fn schnorr_hash(pk: &Point, msg: BigInt, c: &Point) -> Result<BigInt, String> {
341    if msg > Q.clone() {
342        return Err("msg outside the Finite Field".to_string());
343    }
344    let msgFr: Fr = Fr::from_str(&msg.to_string()).unwrap();
345    let hm_input = vec![pk.x.clone(), pk.y.clone(), c.x.clone(), c.y.clone(), msgFr];
346    let h = poseidon.hash(hm_input)?;
347    println!("h {:?}", h.to_string());
348    let hB = BigInt::parse_bytes(to_hex(&h).as_bytes(), 16).unwrap();
349    Ok(hB)
350}
351
352pub fn verify_schnorr(pk: Point, m: BigInt, r: Point, s: BigInt) -> Result<bool, String> {
353    // sG = s·G
354    let sg = B8.mul_scalar(&s)?;
355
356    // r + h · x
357    let h = schnorr_hash(&pk, m, &r)?;
358    let pk_h = pk.mul_scalar(&h)?;
359    let right = r.projective().add(&pk_h.projective())?;
360
361    Ok(sg.equals(right.affine()))
362}
363
364pub fn new_key() -> PrivateKey {
365    // https://tools.ietf.org/html/rfc8032#section-5.1.5
366    let mut rng = rand6::thread_rng();
367    let sk_raw = rng.gen_biguint(1024).to_bigint().unwrap();
368
369    let mut hasher = Blake2b::new();
370    let (_, sk_raw_bytes) = sk_raw.to_bytes_be();
371    hasher.input(sk_raw_bytes);
372    let mut h = hasher.result();
373
374    h[0] = h[0] & 0xF8;
375    h[31] = h[31] & 0x7F;
376    h[31] = h[31] | 0x40;
377
378    let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]);
379
380    PrivateKey { key: sk }
381}
382
383pub fn verify(pk: Point, sig: Signature, msg: BigInt) -> bool {
384    if msg > Q.clone() {
385        return false;
386    }
387    let msgFr: Fr = Fr::from_str(&msg.to_string()).unwrap();
388    let hm_input = vec![
389        sig.r_b8.x.clone(),
390        sig.r_b8.y.clone(),
391        pk.x.clone(),
392        pk.y.clone(),
393        msgFr,
394    ];
395    let hm = match poseidon.hash(hm_input) {
396        Result::Err(_) => return false,
397        Result::Ok(hm) => hm,
398    };
399    let l = match B8.mul_scalar(&sig.s) {
400        Result::Err(_) => return false,
401        Result::Ok(l) => l,
402    };
403    let hmB = BigInt::parse_bytes(to_hex(&hm).as_bytes(), 16).unwrap();
404    let r = match sig.r_b8.projective().add(
405        &pk.mul_scalar(&(8.to_bigint().unwrap() * hmB))
406            .unwrap()
407            .projective(),
408    ) {
409        Result::Err(_) => return false,
410        Result::Ok(r) => r,
411    };
412    l.equals(r.affine())
413}
414
415#[cfg(test)]
416mod tests {
417    use super::*;
418    extern crate rustc_hex;
419    use rustc_hex::{FromHex, ToHex};
420
421    #[test]
422    fn test_add_same_point() {
423        let p: PointProjective = PointProjective {
424            x: Fr::from_str(
425                "17777552123799933955779906779655732241715742912184938656739573121738514868268",
426            )
427            .unwrap(),
428            y: Fr::from_str(
429                "2626589144620713026669568689430873010625803728049924121243784502389097019475",
430            )
431            .unwrap(),
432            z: Fr::one(),
433        };
434        let q: PointProjective = PointProjective {
435            x: Fr::from_str(
436                "17777552123799933955779906779655732241715742912184938656739573121738514868268",
437            )
438            .unwrap(),
439            y: Fr::from_str(
440                "2626589144620713026669568689430873010625803728049924121243784502389097019475",
441            )
442            .unwrap(),
443            z: Fr::one(),
444        };
445        let res = p.add(&q).unwrap().affine();
446        assert_eq!(
447            res.x,
448            Fr::from_str(
449                "6890855772600357754907169075114257697580319025794532037257385534741338397365"
450            )
451            .unwrap()
452        );
453        assert_eq!(
454            res.y,
455            Fr::from_str(
456                "4338620300185947561074059802482547481416142213883829469920100239455078257889"
457            )
458            .unwrap()
459        );
460    }
461    #[test]
462    fn test_add_different_points() {
463        let p: PointProjective = PointProjective {
464            x: Fr::from_str(
465                "17777552123799933955779906779655732241715742912184938656739573121738514868268",
466            )
467            .unwrap(),
468            y: Fr::from_str(
469                "2626589144620713026669568689430873010625803728049924121243784502389097019475",
470            )
471            .unwrap(),
472            z: Fr::one(),
473        };
474        let q: PointProjective = PointProjective {
475            x: Fr::from_str(
476                "16540640123574156134436876038791482806971768689494387082833631921987005038935",
477            )
478            .unwrap(),
479            y: Fr::from_str(
480                "20819045374670962167435360035096875258406992893633759881276124905556507972311",
481            )
482            .unwrap(),
483            z: Fr::one(),
484        };
485        let res = p.add(&q).unwrap().affine();
486        assert_eq!(
487            res.x,
488            Fr::from_str(
489                "7916061937171219682591368294088513039687205273691143098332585753343424131937"
490            )
491            .unwrap()
492        );
493        assert_eq!(
494            res.y,
495            Fr::from_str(
496                "14035240266687799601661095864649209771790948434046947201833777492504781204499"
497            )
498            .unwrap()
499        );
500    }
501
502    #[test]
503    fn test_mul_scalar() {
504        let p: Point = Point {
505            x: Fr::from_str(
506                "17777552123799933955779906779655732241715742912184938656739573121738514868268",
507            )
508            .unwrap(),
509            y: Fr::from_str(
510                "2626589144620713026669568689430873010625803728049924121243784502389097019475",
511            )
512            .unwrap(),
513        };
514        let res_m = p.mul_scalar(&3.to_bigint().unwrap()).unwrap();
515        let res_a = p.projective().add(&p.projective()).unwrap();
516        let res_a = res_a.add(&p.projective()).unwrap().affine();
517        assert_eq!(res_m.x, res_a.x);
518        assert_eq!(
519            res_m.x,
520            Fr::from_str(
521                "19372461775513343691590086534037741906533799473648040012278229434133483800898"
522            )
523            .unwrap()
524        );
525        assert_eq!(
526            res_m.y,
527            Fr::from_str(
528                "9458658722007214007257525444427903161243386465067105737478306991484593958249"
529            )
530            .unwrap()
531        );
532
533        let n = BigInt::parse_bytes(
534            b"14035240266687799601661095864649209771790948434046947201833777492504781204499",
535            10,
536        )
537        .unwrap();
538        let res2 = p.mul_scalar(&n).unwrap();
539        assert_eq!(
540            res2.x,
541            Fr::from_str(
542                "17070357974431721403481313912716834497662307308519659060910483826664480189605"
543            )
544            .unwrap()
545        );
546        assert_eq!(
547            res2.y,
548            Fr::from_str(
549                "4014745322800118607127020275658861516666525056516280575712425373174125159339"
550            )
551            .unwrap()
552        );
553    }
554
555    #[test]
556    fn test_new_key_sign_verify_0() {
557        let sk = new_key();
558        let pk = sk.public().unwrap();
559        let msg = 5.to_bigint().unwrap();
560        let sig = sk.sign(msg.clone()).unwrap();
561        let v = verify(pk, sig, msg);
562        assert_eq!(v, true);
563    }
564
565    #[test]
566    fn test_new_key_sign_verify_1() {
567        let sk = new_key();
568        let pk = sk.public().unwrap();
569        let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
570        let sig = sk.sign(msg.clone()).unwrap();
571        let v = verify(pk, sig, msg);
572        assert_eq!(v, true);
573    }
574
575    #[test]
576    fn test_point_compress_decompress() {
577        let p: Point = Point {
578            x: Fr::from_str(
579                "17777552123799933955779906779655732241715742912184938656739573121738514868268",
580            )
581            .unwrap(),
582            y: Fr::from_str(
583                "2626589144620713026669568689430873010625803728049924121243784502389097019475",
584            )
585            .unwrap(),
586        };
587        let p_comp = p.compress();
588        assert_eq!(
589            p_comp[..].to_hex(),
590            "53b81ed5bffe9545b54016234682e7b2f699bd42a5e9eae27ff4051bc698ce85"
591        );
592        let p2 = decompress_point(p_comp).unwrap();
593        assert_eq!(p.x, p2.x);
594        assert_eq!(p.y, p2.y);
595    }
596
597    #[test]
598    fn test_point_decompress0() {
599        let y_bytes_raw = "b5328f8791d48f20bec6e481d91c7ada235f1facf22547901c18656b6c3e042f"
600            .from_hex()
601            .unwrap();
602        let mut y_bytes: [u8; 32] = [0; 32];
603        y_bytes.copy_from_slice(&y_bytes_raw);
604        let p = decompress_point(y_bytes).unwrap();
605
606        let expected_px_raw = "b86cc8d9c97daef0afe1a4753c54fb2d8a530dc74c7eee4e72b3fdf2496d2113"
607            .from_hex()
608            .unwrap();
609        let mut e_px_bytes: [u8; 32] = [0; 32];
610        e_px_bytes.copy_from_slice(&expected_px_raw);
611        let expected_px: Fr =
612            Fr::from_str(&BigInt::from_bytes_le(Sign::Plus, &e_px_bytes).to_string()).unwrap();
613        assert_eq!(&p.x, &expected_px);
614    }
615
616    #[test]
617    fn test_point_decompress1() {
618        let y_bytes_raw = "70552d3ff548e09266ded29b33ce75139672b062b02aa66bb0d9247ffecf1d0b"
619            .from_hex()
620            .unwrap();
621        let mut y_bytes: [u8; 32] = [0; 32];
622        y_bytes.copy_from_slice(&y_bytes_raw);
623        let p = decompress_point(y_bytes).unwrap();
624
625        let expected_px_raw = "30f1635ba7d56f9cb32c3ffbe6dca508a68c7f43936af11a23c785ce98cb3404"
626            .from_hex()
627            .unwrap();
628        let mut e_px_bytes: [u8; 32] = [0; 32];
629        e_px_bytes.copy_from_slice(&expected_px_raw);
630        let expected_px: Fr =
631            Fr::from_str(&BigInt::from_bytes_le(Sign::Plus, &e_px_bytes).to_string()).unwrap();
632        assert_eq!(&p.x, &expected_px);
633    }
634
635    #[test]
636    fn test_point_decompress_loop() {
637        for _ in 0..5 {
638            let random_bytes = rand6::thread_rng().gen::<[u8; 32]>();
639            let sk_raw: BigInt = BigInt::from_bytes_le(Sign::Plus, &random_bytes[..]);
640            let mut hasher = Blake2b::new();
641            let (_, sk_raw_bytes) = sk_raw.to_bytes_be();
642            hasher.input(sk_raw_bytes);
643            let mut h = hasher.result();
644
645            h[0] = h[0] & 0xF8;
646            h[31] = h[31] & 0x7F;
647            h[31] = h[31] | 0x40;
648
649            let sk = BigInt::from_bytes_le(Sign::Plus, &h[..]);
650            let point = B8.mul_scalar(&sk).unwrap();
651            let cmp_point = point.compress();
652            let dcmp_point = decompress_point(cmp_point).unwrap();
653
654            assert_eq!(&point.x, &dcmp_point.x);
655            assert_eq!(&point.y, &dcmp_point.y);
656        }
657    }
658
659    #[test]
660    fn test_signature_compress_decompress() {
661        let sk = new_key();
662        let pk = sk.public().unwrap();
663
664        for i in 0..5 {
665            let msg_raw = "123456".to_owned() + &i.to_string();
666            let msg = BigInt::parse_bytes(msg_raw.as_bytes(), 10).unwrap();
667            let sig = sk.sign(msg.clone()).unwrap();
668
669            let compressed_sig = sig.compress();
670            let decompressed_sig = decompress_signature(&compressed_sig).unwrap();
671            assert_eq!(&sig.r_b8.x, &decompressed_sig.r_b8.x);
672            assert_eq!(&sig.r_b8.y, &decompressed_sig.r_b8.y);
673            assert_eq!(&sig.s, &decompressed_sig.s);
674
675            let v = verify(pk.clone(), decompressed_sig, msg);
676            assert_eq!(v, true);
677        }
678    }
679
680    #[test]
681    fn test_schnorr_signature() {
682        let sk = new_key();
683        let pk = sk.public().unwrap();
684
685        let msg = BigInt::parse_bytes(b"123456789012345678901234567890", 10).unwrap();
686        let (s, e) = sk.sign_schnorr(msg.clone()).unwrap();
687        println!("s {:?}", s.x.to_string());
688        println!("s {:?}", s.y.to_string());
689        println!("e {:?}", e.to_string());
690        let verification = verify_schnorr(pk, msg, s, e).unwrap();
691        assert_eq!(true, verification);
692    }
693}