1#![allow(non_snake_case)]
45
46use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
47use core::convert::TryFrom;
48use super::field::{GF255e, ModInt256};
49use super::blake2s::Blake2s256;
50use super::{CryptoRng, RngCore};
51use super::{Zu128, Zu256, Zu384};
52
53#[derive(Clone, Copy, Debug)]
55pub struct Point {
56 E: GF255e,
77 U: GF255e,
78 Z: GF255e,
79 T: GF255e,
80}
81
82pub type Scalar = ModInt256<0x1F52C8AE74D84525, 0x9D0C930F54078C53,
86 0xFFFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF>;
87
88impl Scalar {
89 pub fn encode(self) -> [u8; 32] {
91 self.encode32()
92 }
93}
94
95impl Point {
96
97 pub const NEUTRAL: Self = Self {
99 E: GF255e::MINUS_ONE,
100 Z: GF255e::ONE,
101 U: GF255e::ZERO,
102 T: GF255e::ZERO,
103 };
104
105 pub const BASE: Self = Self {
110 E: GF255e::w64be(0, 0, 0, 3),
111 Z: GF255e::ONE,
112 U: GF255e::ONE,
113 T: GF255e::ONE,
114 };
115
116 const ETA: GF255e = GF255e::w64be(
127 0x10ED2DB33C69B85F, 0xE414983FE53688E3,
128 0xA60D864FB30E6336, 0xD99E0F1BAA938AEE);
129
130 pub fn set_decode(&mut self, buf: &[u8]) -> u32 {
142 if buf.len() != 32 {
144 *self = Self::NEUTRAL;
145 return 0;
146 }
147
148 let (u, mut r) = GF255e::decode32(buf);
150
151 let uu = u.square();
153 let ee = uu.square().mul8() + GF255e::ONE;
154 let (e, r2) = ee.sqrt();
155 r &= r2;
156 self.E = GF255e::select(&GF255e::MINUS_ONE, &e, r);
162 self.Z = GF255e::ONE;
163 self.U = GF255e::select(&GF255e::ZERO, &u, r);
164 self.T = GF255e::select(&GF255e::ZERO, &uu, r);
165 r
166 }
167
168 pub fn decode(buf: &[u8]) -> Option<Point> {
177 let mut P = Point::NEUTRAL;
178 if P.set_decode(buf) != 0 {
179 Some(P)
180 } else {
181 None
182 }
183 }
184
185 pub fn encode(self) -> [u8; 32] {
189 let iZ = GF255e::ONE / self.Z;
193 let mut u = self.U * iZ;
194 let sgn = (((self.E * iZ).encode()[0] & 1) as u32).wrapping_neg();
195 u.set_cond(&-u, sgn);
196 u.encode()
197 }
198
199 fn from_affine_extended(P: &PointAffineExtended) -> Self {
202 Self {
203 E: P.e,
204 Z: GF255e::ONE,
205 U: P.u,
206 T: P.t,
207 }
208 }
209
210 fn set_add(&mut self, rhs: &Self) {
212 let (E1, Z1, U1, T1) = (&self.E, &self.Z, &self.U, &self.T);
213 let (E2, Z2, U2, T2) = (&rhs.E, &rhs.Z, &rhs.U, &rhs.T);
214
215 let e1e2 = E1 * E2;
231 let u1u2 = U1 * U2;
232 let z1z2 = Z1 * Z2;
233 let t1t2 = T1 * T2;
234 let eu = (E1 + U1) * (E2 + U2) - e1e2 - u1u2;
235 let zt = (Z1 + T1) * (Z2 + T2) - z1z2 - t1t2;
236 let bpt1t2 = t1t2.mul8(); let hd = z1z2 - bpt1t2;
238 let T3 = eu.square();
239 let Z3 = hd.square();
240 let E3 = (z1z2 + bpt1t2) * e1e2 + u1u2.mul16() * zt;
241 let U3 = hd * eu; self.E = E3;
243 self.Z = Z3;
244 self.U = U3;
245 self.T = T3;
246 }
247
248 fn set_add_affine_extended(&mut self, rhs: &PointAffineExtended) {
252 let (E1, Z1, U1, T1) = (&self.E, &self.Z, &self.U, &self.T);
253 let (e2, u2, t2) = (&rhs.e, &rhs.u, &rhs.t);
254
255 let e1e2 = E1 * e2;
270 let u1u2 = U1 * u2;
271 let t1t2 = T1 * t2;
272 let eu = (E1 + U1) * (e2 + u2) - e1e2 - u1u2;
273 let zt = Z1 * t2 + T1;
274 let bpt1t2 = t1t2.mul8(); let hd = Z1 - bpt1t2;
276 let T3 = eu.square();
277 let Z3 = hd.square();
278 let E3 = (Z1 + bpt1t2) * e1e2 + u1u2.mul16() * zt;
279 let U3 = hd * eu; self.E = E3;
281 self.Z = Z3;
282 self.U = U3;
283 self.T = T3;
284 }
285
286 fn set_sub_affine_extended(&mut self, rhs: &PointAffineExtended) {
290 let mrhs = PointAffineExtended {
291 e: rhs.e,
292 u: -rhs.u,
293 t: rhs.t,
294 };
295 self.set_add_affine_extended(&mrhs);
296 }
297
298 pub fn set_double(&mut self) {
300 let (E, Z, U) = (&self.E, &self.Z, &self.U);
301
302 let ee = E.square();
308 let J = E * U.mul2();
309 let X = ee.square();
310 let W = Z.square().mul2() - ee;
311
312 let ww = W.square();
320 let jj = J.square();
321 self.E = X.mul2() - ww;
322 self.Z = ww;
323 self.U = W * J; self.T = jj;
325 }
326
327 #[inline(always)]
329 pub fn double(self) -> Self {
330 let mut r = self;
331 r.set_double();
332 r
333 }
334
335 pub fn set_xdouble(&mut self, n: u32) {
337 if n == 0 {
338 return;
339 }
340
341 let (E, Z, U) = (&self.E, &self.Z, &self.U);
345
346 let ee = E.square();
348 let mut J = E * U.mul2();
349 let mut X = ee.square();
350 let mut W = Z.square().mul2() - ee;
351
352 for _ in 1..n {
354 let ww = W.square();
361 let t1 = ww - X.mul2();
362 let t2 = t1.square();
363 J *= t1 * W.mul2(); W = t2 - ww.square().mul2();
365 X = t2.square();
366 }
367
368 let ww = W.square();
370 let jj = J.square();
371 self.E = X.mul2() - ww;
372 self.Z = ww;
373 self.U = W * J; self.T = jj;
375 }
376
377 #[inline(always)]
379 pub fn xdouble(self, n: u32) -> Self {
380 let mut r = self;
381 r.set_xdouble(n);
382 r
383 }
384
385 #[inline(always)]
387 pub fn set_neg(&mut self) {
388 self.U.set_neg();
389 }
390
391 fn set_sub(&mut self, rhs: &Self) {
393 self.set_add(&-rhs);
394 }
395
396 pub fn set_mul_small(&mut self, n: u64) {
402 if n == 0 {
403 *self = Self::NEUTRAL;
404 return;
405 }
406 if n == 1 {
407 return;
408 }
409
410 let nlen = 64 - n.leading_zeros();
411 let T = *self;
412 let mut ndbl = 0u32;
413 for i in (0..(nlen - 1)).rev() {
414 ndbl += 1;
415 if ((n >> i) & 1) == 0 {
416 continue;
417 }
418 self.set_xdouble(ndbl);
419 ndbl = 0;
420 self.set_add(&T);
421 }
422 self.set_xdouble(ndbl);
423 }
424
425 #[inline]
430 pub fn equals(self, rhs: Self) -> u32 {
431 (self.U * rhs.E).equals(rhs.U * self.E)
440 }
441
442 #[inline(always)]
448 pub fn isneutral(self) -> u32 {
449 self.U.iszero()
450 }
451
452 #[inline]
460 pub fn set_cond(&mut self, P: &Self, ctl: u32) {
461 self.E.set_cond(&P.E, ctl);
462 self.Z.set_cond(&P.Z, ctl);
463 self.U.set_cond(&P.U, ctl);
464 self.T.set_cond(&P.T, ctl);
465 }
466
467 #[inline(always)]
472 pub fn select(P0: &Self, P1: &Self, ctl: u32) -> Self {
473 let mut P = *P0;
474 P.set_cond(P1, ctl);
475 P
476 }
477
478 #[inline]
484 pub fn set_condneg(&mut self, ctl: u32) {
485 self.U.set_cond(&-self.U, ctl);
486 }
487
488 fn map_to_curve(f: &GF255e) -> Self {
494 let f2_4 = f.mul2().square();
502 let x1num = f2_4 - GF255e::w64be(0, 0, 0, 7);
503 let x2num = Self::ETA * (f2_4 + GF255e::w64be(0, 0, 0, 7));
504 let x12den = f.mul4();
505
506 let f3_4 = f2_4 * f;
510 let f5_16 = f3_4 * f2_4;
511 let f7_64 = f5_16 * f2_4;
512 let yt1 = f7_64 - f3_4.mul_small(77);
513 let yt2 = f5_16.mul_small(11) - f.mul_small(343);
514 let yy1num = yt1 + yt2;
515 let yy2num = Self::ETA * (yt2 - yt1);
516 let y12den = f2_4.mul2();
517
518 let ctl1 = !((yy1num.legendre() >> 1) as u32);
522 let ctl2 = !ctl1 & !((yy2num.legendre() >> 1) as u32);
523 let ctl3 = !ctl1 & !ctl2;
524 let mut xnum = x1num;
525 let mut xden = x12den;
526 let mut yynum = yy1num;
527 let mut yden = y12den;
528 xnum.set_cond(&x2num, ctl2);
529 yynum.set_cond(&yy2num, ctl2);
530 xnum.set_cond(&(x1num * x2num), ctl3);
531 xden.set_cond(&x12den.square(), ctl3);
532 yynum.set_cond(&(yy1num * yy2num), ctl3);
533 yden.set_cond(&y12den.square(), ctl3);
534 let (ynum, _) = yynum.sqrt(); let unum = xnum * yden;
538 let uden = xden * ynum;
539
540 let Xnum = -unum.square().mul8();
544 let mut Xden = uden.square();
545 let Unum = (xnum * xden * uden).mul2();
546 let mut Uden = unum * (xnum.square() - xden.square().mul8());
547
548 let fz = f.iszero();
551 Xden.set_cond(&GF255e::ONE, fz);
552 Uden.set_cond(&GF255e::ONE, fz);
553
554 let xx = Xnum.square();
556 let mbzz = Xden.square().mul2();
557 let Enum = xx + mbzz;
558 let Eden = xx - mbzz;
559
560 let ud2 = Uden.square();
562 let uned = Unum * Eden;
563 let E = Enum * ud2;
564 let Z = Eden * ud2;
565 let U = Uden * uned;
566 let T = Unum * uned;
567
568 Self { E, Z, U, T }
569 }
570
571 pub fn hash_to_curve(hash_name: &str, data: &[u8]) -> Self {
588 let mut sh = Blake2s256::new();
589 let (blob1, blob2);
590 if hash_name.len() == 0 {
591 sh.update(&[0x01u8, 0x52u8]);
592 sh.update(data);
593 blob1 = sh.finalize_reset();
594 sh.update(&[0x02u8, 0x52u8]);
595 sh.update(data);
596 blob2 = sh.finalize_reset();
597 } else {
598 sh.update(&[0x01u8, 0x48u8]);
599 sh.update(hash_name.as_bytes());
600 sh.update(&[0x00u8]);
601 sh.update(data);
602 blob1 = sh.finalize_reset();
603 sh.update(&[0x02u8, 0x48u8]);
604 sh.update(hash_name.as_bytes());
605 sh.update(&[0x00u8]);
606 sh.update(data);
607 blob2 = sh.finalize_reset();
608 }
609 let f1 = GF255e::decode_reduce(&blob1);
610 let f2 = GF255e::decode_reduce(&blob2);
611 Self::map_to_curve(&f1) + Self::map_to_curve(&f2)
612 }
613
614 pub const HASHNAME_SHA224: &'static str = "sha224";
615 pub const HASHNAME_SHA256: &'static str = "sha256";
616 pub const HASHNAME_SHA384: &'static str = "sha384";
617 pub const HASHNAME_SHA512: &'static str = "sha512";
618 pub const HASHNAME_SHA512_224: &'static str = "sha512224";
619 pub const HASHNAME_SHA512_256: &'static str = "sha512256";
620 pub const HASHNAME_SHA3_224: &'static str = "sha3224";
621 pub const HASHNAME_SHA3_256: &'static str = "sha3256";
622 pub const HASHNAME_SHA3_384: &'static str = "sha3384";
623 pub const HASHNAME_SHA3_512: &'static str = "sha3512";
624 pub const HASHNAME_BLAKE2B: &'static str = "blake2b";
625 pub const HASHNAME_BLAKE2S: &'static str = "blake2s";
626 pub const HASHNAME_BLAKE3: &'static str = "blake3";
627
628 fn recode_u128(n: u128) -> [i8; 26] {
660 let mut sd = [0i8; 26];
661 let mut x = n;
662 let mut cc: u32 = 0; for j in 0..26 {
664 let d = ((x as u32) & 0x1F) + cc;
665 x >>= 5;
666 let m = 16u32.wrapping_sub(d) >> 8;
667 sd[j] = (d.wrapping_sub(m & 32)) as i8;
668 cc = m & 1;
669 }
670 sd
671 }
672
673 fn lookup(win: &[GF255e; 64], k: i8) -> Self {
675 let s = ((k as i32) >> 8) as u32;
678 let f = ((k as u32) ^ s).wrapping_sub(s).wrapping_sub(1);
679 let vv = GF255e::lookup16_x4(win, f);
680 let mut P = Self {
681 E: vv[0],
682 U: vv[1],
683 Z: vv[2],
684 T: vv[3],
685 };
686
687 let fz = ((f as i32) >> 31) as u32;
690 P.E.set_cond(&Self::NEUTRAL.E, fz);
691 P.Z.set_cond(&Self::NEUTRAL.Z, fz);
692
693 P.set_condneg(s);
695
696 P
697 }
698
699 fn lookup_affine_extended(win: &[GF255e; 48], k: i8)
702 -> PointAffineExtended
703 {
704 let s = ((k as i32) >> 8) as u32;
707 let f = ((k as u32) ^ s).wrapping_sub(s).wrapping_sub(1);
708 let vv = GF255e::lookup16_x3(win, f);
709 let mut P = PointAffineExtended {
710 e: vv[0],
711 u: vv[1],
712 t: vv[2],
713 };
714
715 let fz = ((f as i32) >> 31) as u32;
718 P.e.set_cond(&PointAffineExtended::NEUTRAL.e, fz);
719
720 P.set_condneg(s);
722
723 P
724 }
725
726 fn mul_divr_rounded(k: &Zu256, e: &Zu128) -> Zu128 {
732 let mut z = k.mul256x128(e);
734
735 const HR: Zu384 = Zu384::w64le(
737 0x8FA964573A6C2292, 0xCE864987AA03C629,
738 0xFFFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF,
739 0x0000000000000000, 0x0000000000000000);
740
741 const R0: Zu128 = Zu128::w64le(0xE0AD37518B27BADB, 0x62F36CF0ABF873AC);
743
744 z.set_add(&HR);
746
747 let (z0, mut y) = z.trunc_and_rsh_cc(1, 254);
750
751 let t = y.mul128x128(&R0);
753
754 let w = t.add_rsh224(&z0);
756
757 y.set_sub_u32(1 - (w >> 30));
761
762 y
763 }
764
765 fn split_mu(k: &Scalar) -> (u128, u32, u128, u32) {
771 let ki = Zu256::decode(&k.encode()).unwrap();
773
774 const EU: Zu128 = Zu128::w64le(0x2ACCF9DEC93F6111, 0x1A509F7A53C2C6E6);
776 const EV: Zu128 = Zu128::w64le(0x0B7A31305466F77E, 0x7D440C6AFFBB3A93);
777
778 let c = Self::mul_divr_rounded(&ki, &EV);
781 let d = Self::mul_divr_rounded(&ki, &EU);
782
783 let mut k0 = ki.trunc128();
786 k0.set_sub(&d.mul128x128trunc(&EU));
787 k0.set_sub(&c.mul128x128trunc(&EV));
788 let mut k1 = d.mul128x128trunc(&EV);
789 k1.set_sub(&c.mul128x128trunc(&EU));
790
791 let (n0, s0) = k0.abs();
792 let (n1, s1) = k1.abs();
793 (n0, s0, n1, s1)
794 }
795
796 fn zeta(self) -> Self {
798 Self {
799 E: self.E,
800 Z: self.Z,
801 U: self.U * Self::ETA,
802 T: -self.T
803 }
804 }
805
806 pub fn set_mul(&mut self, n: &Scalar) {
811 let (n0, s0, n1, s1) = Self::split_mu(n);
813
814 let mut win0 = [GF255e::ZERO; 64];
820 self.set_condneg(s0);
821 (win0[0], win0[1], win0[2], win0[3]) = (self.E, self.U, self.Z, self.T);
822 for i in 1..8 {
823 let mut Q = Self {
824 E: win0[4 * i - 4],
825 U: win0[4 * i - 3],
826 Z: win0[4 * i - 2],
827 T: win0[4 * i - 1],
828 };
829 Q.set_double();
830 win0[8 * i - 4] = Q.E;
831 win0[8 * i - 3] = Q.U;
832 win0[8 * i - 2] = Q.Z;
833 win0[8 * i - 1] = Q.T;
834 Q += *self;
835 win0[8 * i + 0] = Q.E;
836 win0[8 * i + 1] = Q.U;
837 win0[8 * i + 2] = Q.Z;
838 win0[8 * i + 3] = Q.T;
839 }
840 let mut Q = Self {
841 E: win0[28],
842 U: win0[29],
843 Z: win0[30],
844 T: win0[31],
845 };
846 Q.set_double();
847 win0[60] = Q.E;
848 win0[61] = Q.U;
849 win0[62] = Q.Z;
850 win0[63] = Q.T;
851
852 let mut win1 = [GF255e::ZERO; 64];
853 for i in 0..16 {
854 let mut Q = Self {
855 E: win0[4 * i + 0],
856 U: win0[4 * i + 1],
857 Z: win0[4 * i + 2],
858 T: win0[4 * i + 3],
859 }.zeta();
860 Q.set_condneg(s0 ^ s1);
861 win1[4 * i + 0] = Q.E;
862 win1[4 * i + 1] = Q.U;
863 win1[4 * i + 2] = Q.Z;
864 win1[4 * i + 3] = Q.T;
865 }
866
867 let sd0 = Self::recode_u128(n0);
869 let sd1 = Self::recode_u128(n1);
870
871 *self = Self::lookup(&win0, sd0[25]);
873 self.set_add(&Self::lookup(&win1, sd1[25]));
874 for i in (0..25).rev() {
875 self.set_xdouble(5);
876 self.set_add(&Self::lookup(&win0, sd0[i]));
877 self.set_add(&Self::lookup(&win1, sd1[i]));
878 }
879 }
880
881 pub fn set_mulgen(&mut self, n: &Scalar) {
887 let (n0, s0, n1, s1) = Self::split_mu(n);
889
890 let sd0 = Self::recode_u128(n0);
892 let mut sd1 = Self::recode_u128(n1);
893
894 let zn = (s0 ^ s1) as i8;
898 for i in 0..26 {
899 sd1[i] -= zn & (sd1[i] << 1);
900 }
901
902 *self = Self::from_affine_extended(
908 &Self::lookup_affine_extended(&PRECOMP_B30, sd0[12]));
909 self.set_add_affine_extended(
910 &Self::lookup_affine_extended(&PRECOMP_B95, sd0[25]));
911 self.set_add_affine_extended(
912 &Self::lookup_affine_extended(&PRECOMP_B30, sd1[12]).zeta());
913 self.set_add_affine_extended(
914 &Self::lookup_affine_extended(&PRECOMP_B95, sd1[25]).zeta());
915
916 for i in (0..6).rev() {
918 self.set_xdouble(5);
919 self.set_add_affine_extended(
920 &Self::lookup_affine_extended(&PRECOMP_B, sd0[i]));
921 self.set_add_affine_extended(
922 &Self::lookup_affine_extended(&PRECOMP_B30, sd0[i + 6]));
923 self.set_add_affine_extended(
924 &Self::lookup_affine_extended(&PRECOMP_B65, sd0[i + 13]));
925 self.set_add_affine_extended(
926 &Self::lookup_affine_extended(&PRECOMP_B95, sd0[i + 19]));
927 self.set_add_affine_extended(
928 &Self::lookup_affine_extended(&PRECOMP_B, sd1[i]).zeta());
929 self.set_add_affine_extended(
930 &Self::lookup_affine_extended(&PRECOMP_B30, sd1[i + 6]).zeta());
931 self.set_add_affine_extended(
932 &Self::lookup_affine_extended(&PRECOMP_B65, sd1[i + 13]).zeta());
933 self.set_add_affine_extended(
934 &Self::lookup_affine_extended(&PRECOMP_B95, sd1[i + 19]).zeta());
935 }
936
937 self.set_condneg(s0);
939 }
940
941 #[inline]
946 pub fn mulgen(n: &Scalar) -> Self {
947 let mut P = Self::NEUTRAL;
948 P.set_mulgen(n);
949 P
950 }
951
952 fn recode_scalar_NAF(n: &Scalar) -> [i8; 255] {
959 let mut sd = [0i8; 255];
974 let bb = n.encode();
975 let mut x = bb[0] as u32;
976 for i in 0..255 {
977 if (i & 7) == 4 && i < 252 {
978 x += (bb[(i + 4) >> 3] as u32) << 4;
979 }
980 let m = (x & 1).wrapping_neg(); let v = x & m & 31; let c = (v & 16) << 1; let d = v.wrapping_sub(c); sd[i] = d as i8;
985 x = x.wrapping_sub(d) >> 1;
986 }
987 sd
988 }
989
990 fn recode_u128_NAF(n: u128) -> [i8; 130] {
997 let mut sd = [0i8; 130];
999 let mut y = n;
1000 for i in 0..129 {
1001 let x = y as u32;
1002 let m = (x & 1).wrapping_neg(); let v = x & m & 31; let c = (v & 16) << 1; sd[i] = v.wrapping_sub(c) as i8;
1006 y = y.wrapping_sub(v as u128).wrapping_add(c as u128) >> 1;
1007 }
1008 sd
1009 }
1010
1011 pub fn set_mul_add_mulgen_vartime(&mut self, u: &Scalar, v: &Scalar) {
1020 let (u0, s0, u1, s1) = Self::split_mu(u);
1022
1023 let mut win = [Self::NEUTRAL; 8];
1026 let Q = self.double();
1027 win[0] = *self;
1028 for i in 1..8 {
1029 win[i] = win[i - 1] + Q;
1030 }
1031
1032 let mut win0 = [Self::NEUTRAL; 8];
1038 win0[0] = *self;
1039 win0[0].set_condneg(s0);
1040 let Q = win0[0].double();
1041 for i in 1..8 {
1042 win0[i] = win0[i - 1] + Q;
1043 }
1044 let mut win1 = [Self::NEUTRAL; 8];
1045 for i in 0..8 {
1046 win1[i] = win0[i].zeta();
1047 win1[i].set_condneg(s0 ^ s1);
1048 }
1049
1050 let sd0 = Self::recode_u128_NAF(u0);
1053 let sd1 = Self::recode_u128_NAF(u1);
1054 let sd2 = Self::recode_scalar_NAF(v);
1055
1056 let mut zz = true;
1057 let mut ndbl = 0u32;
1058 for i in (0..130).rev() {
1059 ndbl += 1;
1061
1062 let e0 = sd0[i];
1065 let e1 = sd1[i];
1066 let e2 = sd2[i];
1067 let e3 = if i < 125 { sd2[i + 130] } else { 0 };
1068 if ((e0 as u32) | (e1 as u32) | (e2 as u32) | (e3 as u32)) == 0 {
1069 continue;
1070 }
1071
1072 if zz {
1074 *self = Self::NEUTRAL;
1075 zz = false;
1076 } else {
1077 self.set_xdouble(ndbl);
1078 }
1079 ndbl = 0u32;
1080
1081 if e0 != 0 {
1083 if e0 > 0 {
1084 self.set_add(&win0[e0 as usize >> 1]);
1085 } else {
1086 self.set_sub(&win0[(-e0) as usize >> 1]);
1087 }
1088 }
1089 if e1 != 0 {
1090 if e1 > 0 {
1091 self.set_add(&win1[e1 as usize >> 1]);
1092 } else {
1093 self.set_sub(&win1[(-e1) as usize >> 1]);
1094 }
1095 }
1096 if e2 != 0 {
1097 if e2 > 0 {
1098 let j = 3 * ((e2 as usize) - 1);
1099 let Q = PointAffineExtended {
1100 e: PRECOMP_B[j + 0],
1101 u: PRECOMP_B[j + 1],
1102 t: PRECOMP_B[j + 2],
1103 };
1104 self.set_add_affine_extended(&Q);
1105 } else {
1106 let j = 3 * (((-e2) as usize) - 1);
1107 let Q = PointAffineExtended {
1108 e: PRECOMP_B[j + 0],
1109 u: PRECOMP_B[j + 1],
1110 t: PRECOMP_B[j + 2],
1111 };
1112 self.set_sub_affine_extended(&Q);
1113 }
1114 }
1115 if e3 != 0 {
1116 if e3 > 0 {
1117 self.set_add_affine_extended(
1118 &PRECOMP_B130_ODD[(e3 as usize) >> 1]);
1119 } else {
1120 self.set_sub_affine_extended(
1121 &PRECOMP_B130_ODD[((-e3) as usize) >> 1]);
1122 }
1123 }
1124 }
1125
1126 if zz {
1127 *self = Self::NEUTRAL;
1128 } else {
1129 if ndbl > 0 {
1130 self.set_xdouble(ndbl);
1131 }
1132 }
1133 }
1134
1135 #[inline(always)]
1143 pub fn mul_add_mulgen_vartime(self, u: &Scalar, v: &Scalar) -> Self {
1144 let mut R = self;
1145 R.set_mul_add_mulgen_vartime(u, v);
1146 R
1147 }
1148
1149 pub fn set_mul128_add_mulgen_vartime(&mut self, u: u128, v: &Scalar) {
1158 let sdu = Self::recode_u128_NAF(u);
1160 let sdv = Self::recode_scalar_NAF(&v);
1161
1162 let mut win = [Self::NEUTRAL; 8];
1165 let Q = self.double();
1166 win[0] = *self;
1167 for i in 1..8 {
1168 win[i] = win[i - 1] + Q;
1169 }
1170
1171 let mut zz = true;
1172 let mut ndbl = 0u32;
1173 for i in (0..130).rev() {
1174 ndbl += 1;
1176
1177 let e1 = sdu[i];
1180 let e2 = sdv[i];
1181 let e3 = if i < 125 { sdv[i + 130] } else { 0 };
1182 if ((e1 as u32) | (e2 as u32) | (e3 as u32)) == 0 {
1183 continue;
1184 }
1185
1186 if zz {
1188 *self = Self::NEUTRAL;
1189 zz = false;
1190 } else {
1191 self.set_xdouble(ndbl);
1192 }
1193 ndbl = 0u32;
1194
1195 if e1 != 0 {
1197 if e1 > 0 {
1198 self.set_add(&win[e1 as usize >> 1]);
1199 } else {
1200 self.set_sub(&win[(-e1) as usize >> 1]);
1201 }
1202 }
1203 if e2 != 0 {
1204 if e2 > 0 {
1205 let j = 3 * ((e2 as usize) - 1);
1206 let Q = PointAffineExtended {
1207 e: PRECOMP_B[j + 0],
1208 u: PRECOMP_B[j + 1],
1209 t: PRECOMP_B[j + 2],
1210 };
1211 self.set_add_affine_extended(&Q);
1212 } else {
1213 let j = 3 * (((-e2) as usize) - 1);
1214 let Q = PointAffineExtended {
1215 e: PRECOMP_B[j + 0],
1216 u: PRECOMP_B[j + 1],
1217 t: PRECOMP_B[j + 2],
1218 };
1219 self.set_sub_affine_extended(&Q);
1220 }
1221 }
1222 if e3 != 0 {
1223 if e3 > 0 {
1224 self.set_add_affine_extended(
1225 &PRECOMP_B130_ODD[(e3 as usize) >> 1]);
1226 } else {
1227 self.set_sub_affine_extended(
1228 &PRECOMP_B130_ODD[((-e3) as usize) >> 1]);
1229 }
1230 }
1231 }
1232
1233 if zz {
1234 *self = Self::NEUTRAL;
1235 } else {
1236 if ndbl > 0 {
1237 self.set_xdouble(ndbl);
1238 }
1239 }
1240 }
1241
1242 #[inline(always)]
1250 pub fn mul128_add_mulgen_vartime(self, u: u128, v: &Scalar) -> Self {
1251 let mut R = self;
1252 R.set_mul128_add_mulgen_vartime(u, v);
1253 R
1254 }
1255}
1256
1257impl Add<Point> for Point {
1258 type Output = Point;
1259
1260 #[inline(always)]
1261 fn add(self, other: Point) -> Point {
1262 let mut r = self;
1263 r.set_add(&other);
1264 r
1265 }
1266}
1267
1268impl Add<&Point> for Point {
1269 type Output = Point;
1270
1271 #[inline(always)]
1272 fn add(self, other: &Point) -> Point {
1273 let mut r = self;
1274 r.set_add(other);
1275 r
1276 }
1277}
1278
1279impl Add<Point> for &Point {
1280 type Output = Point;
1281
1282 #[inline(always)]
1283 fn add(self, other: Point) -> Point {
1284 let mut r = *self;
1285 r.set_add(&other);
1286 r
1287 }
1288}
1289
1290impl Add<&Point> for &Point {
1291 type Output = Point;
1292
1293 #[inline(always)]
1294 fn add(self, other: &Point) -> Point {
1295 let mut r = *self;
1296 r.set_add(other);
1297 r
1298 }
1299}
1300
1301impl AddAssign<Point> for Point {
1302 #[inline(always)]
1303 fn add_assign(&mut self, other: Point) {
1304 self.set_add(&other);
1305 }
1306}
1307
1308impl AddAssign<&Point> for Point {
1309 #[inline(always)]
1310 fn add_assign(&mut self, other: &Point) {
1311 self.set_add(other);
1312 }
1313}
1314
1315impl Mul<Scalar> for Point {
1316 type Output = Point;
1317
1318 #[inline(always)]
1319 fn mul(self, other: Scalar) -> Point {
1320 let mut r = self;
1321 r.set_mul(&other);
1322 r
1323 }
1324}
1325
1326impl Mul<&Scalar> for Point {
1327 type Output = Point;
1328
1329 #[inline(always)]
1330 fn mul(self, other: &Scalar) -> Point {
1331 let mut r = self;
1332 r.set_mul(other);
1333 r
1334 }
1335}
1336
1337impl Mul<Scalar> for &Point {
1338 type Output = Point;
1339
1340 #[inline(always)]
1341 fn mul(self, other: Scalar) -> Point {
1342 let mut r = *self;
1343 r.set_mul(&other);
1344 r
1345 }
1346}
1347
1348impl Mul<&Scalar> for &Point {
1349 type Output = Point;
1350
1351 #[inline(always)]
1352 fn mul(self, other: &Scalar) -> Point {
1353 let mut r = *self;
1354 r.set_mul(other);
1355 r
1356 }
1357}
1358
1359impl MulAssign<Scalar> for Point {
1360 #[inline(always)]
1361 fn mul_assign(&mut self, other: Scalar) {
1362 self.set_mul(&other);
1363 }
1364}
1365
1366impl MulAssign<&Scalar> for Point {
1367 #[inline(always)]
1368 fn mul_assign(&mut self, other: &Scalar) {
1369 self.set_mul(other);
1370 }
1371}
1372
1373impl Mul<Point> for Scalar {
1374 type Output = Point;
1375
1376 #[inline(always)]
1377 fn mul(self, other: Point) -> Point {
1378 let mut r = other;
1379 r.set_mul(&self);
1380 r
1381 }
1382}
1383
1384impl Mul<&Point> for Scalar {
1385 type Output = Point;
1386
1387 #[inline(always)]
1388 fn mul(self, other: &Point) -> Point {
1389 let mut r = *other;
1390 r.set_mul(&self);
1391 r
1392 }
1393}
1394
1395impl Mul<Point> for &Scalar {
1396 type Output = Point;
1397
1398 #[inline(always)]
1399 fn mul(self, other: Point) -> Point {
1400 let mut r = other;
1401 r.set_mul(self);
1402 r
1403 }
1404}
1405
1406impl Mul<&Point> for &Scalar {
1407 type Output = Point;
1408
1409 #[inline(always)]
1410 fn mul(self, other: &Point) -> Point {
1411 let mut r = *other;
1412 r.set_mul(self);
1413 r
1414 }
1415}
1416
1417impl Mul<u64> for Point {
1418 type Output = Point;
1419
1420 #[inline(always)]
1421 fn mul(self, other: u64) -> Point {
1422 let mut r = self;
1423 r.set_mul_small(other);
1424 r
1425 }
1426}
1427
1428impl Mul<u64> for &Point {
1429 type Output = Point;
1430
1431 #[inline(always)]
1432 fn mul(self, other: u64) -> Point {
1433 let mut r = *self;
1434 r.set_mul_small(other);
1435 r
1436 }
1437}
1438
1439impl MulAssign<u64> for Point {
1440 #[inline(always)]
1441 fn mul_assign(&mut self, other: u64) {
1442 self.set_mul_small(other);
1443 }
1444}
1445
1446impl Mul<Point> for u64 {
1447 type Output = Point;
1448
1449 #[inline(always)]
1450 fn mul(self, other: Point) -> Point {
1451 let mut r = other;
1452 r.set_mul_small(self);
1453 r
1454 }
1455}
1456
1457impl Mul<&Point> for u64 {
1458 type Output = Point;
1459
1460 #[inline(always)]
1461 fn mul(self, other: &Point) -> Point {
1462 let mut r = *other;
1463 r.set_mul_small(self);
1464 r
1465 }
1466}
1467
1468impl Neg for Point {
1469 type Output = Point;
1470
1471 #[inline(always)]
1472 fn neg(self) -> Point {
1473 let mut r = self;
1474 r.set_neg();
1475 r
1476 }
1477}
1478
1479impl Neg for &Point {
1480 type Output = Point;
1481
1482 #[inline(always)]
1483 fn neg(self) -> Point {
1484 let mut r = *self;
1485 r.set_neg();
1486 r
1487 }
1488}
1489
1490impl Sub<Point> for Point {
1491 type Output = Point;
1492
1493 #[inline(always)]
1494 fn sub(self, other: Point) -> Point {
1495 let mut r = self;
1496 r.set_sub(&other);
1497 r
1498 }
1499}
1500
1501impl Sub<&Point> for Point {
1502 type Output = Point;
1503
1504 #[inline(always)]
1505 fn sub(self, other: &Point) -> Point {
1506 let mut r = self;
1507 r.set_sub(other);
1508 r
1509 }
1510}
1511
1512impl Sub<Point> for &Point {
1513 type Output = Point;
1514
1515 #[inline(always)]
1516 fn sub(self, other: Point) -> Point {
1517 let mut r = *self;
1518 r.set_sub(&other);
1519 r
1520 }
1521}
1522
1523impl Sub<&Point> for &Point {
1524 type Output = Point;
1525
1526 #[inline(always)]
1527 fn sub(self, other: &Point) -> Point {
1528 let mut r = *self;
1529 r.set_sub(other);
1530 r
1531 }
1532}
1533
1534impl SubAssign<Point> for Point {
1535 #[inline(always)]
1536 fn sub_assign(&mut self, other: Point) {
1537 self.set_sub(&other);
1538 }
1539}
1540
1541impl SubAssign<&Point> for Point {
1542 #[inline(always)]
1543 fn sub_assign(&mut self, other: &Point) {
1544 self.set_sub(other);
1545 }
1546}
1547
1548#[derive(Clone, Copy, Debug)]
1555pub struct PrivateKey {
1556 sec: Scalar, pub public_key: PublicKey, }
1559
1560#[derive(Clone, Copy, Debug)]
1566pub struct PublicKey {
1567 pub point: Point,
1568 pub encoded: [u8; 32],
1569}
1570
1571impl PrivateKey {
1572
1573 pub fn generate<T: CryptoRng + RngCore>(rng: &mut T) -> Self {
1575 loop {
1576 let mut tmp = [0u8; 32];
1577 rng.fill_bytes(&mut tmp);
1578 let sec = Scalar::decode_reduce(&tmp);
1579 if sec.iszero() == 0 {
1580 return Self::from_scalar(&sec);
1581 }
1582 }
1583 }
1584
1585 pub fn from_scalar(sec: &Scalar) -> Self {
1589 assert!(sec.iszero() == 0);
1590 let point = Point::mulgen(&sec);
1591 let encoded = point.encode();
1592 Self { sec: *sec, public_key: PublicKey { point, encoded } }
1593 }
1594
1595 pub fn decode(buf: &[u8]) -> Option<Self> {
1600 let (sec, mut ok) = Scalar::decode32(buf);
1601 ok &= !sec.iszero();
1602 if ok != 0 {
1603 Some(Self::from_scalar(&sec))
1604 } else {
1605 None
1606 }
1607 }
1608
1609 pub fn encode(self) -> [u8; 32] {
1613 self.sec.encode()
1614 }
1615
1616 pub fn sign(self, hash_name: &str, data: &[u8]) -> [u8; 48] {
1628 self.sign_seeded(&[0u8; 0], hash_name, data)
1629 }
1630
1631 pub fn sign_randomized<T: CryptoRng + RngCore>(self, rng: &mut T,
1645 hash_name: &str, data: &[u8]) -> [u8; 48]
1646 {
1647 let mut seed = [0u8; 32];
1648 rng.fill_bytes(&mut seed);
1649 self.sign_seeded(&seed, hash_name, data)
1650 }
1651
1652 pub fn sign_seeded(self, seed: &[u8], hash_name: &str, data: &[u8])
1668 -> [u8; 48]
1669 {
1670 let mut sh = Blake2s256::new();
1691 sh.update(&self.sec.encode());
1692 sh.update(&self.public_key.encoded);
1693 sh.update(&(seed.len() as u64).to_le_bytes());
1694 sh.update(seed);
1695 if hash_name.len() == 0 {
1696 sh.update(&[0x52u8]);
1697 } else {
1698 sh.update(&[0x48u8]);
1699 sh.update(hash_name.as_bytes());
1700 sh.update(&[0x00u8]);
1701 }
1702 sh.update(data);
1703 let k = Scalar::decode_reduce(&sh.finalize());
1704
1705 let R = Point::mulgen(&k);
1707 let cb = make_challenge(&R, &self.public_key.encoded, hash_name, data);
1708 let s = k + self.sec * Scalar::from_u128(u128::from_le_bytes(cb));
1709 let mut sig = [0u8; 48];
1710 sig[ 0..16].copy_from_slice(&cb);
1711 sig[16..48].copy_from_slice(&s.encode());
1712 sig
1713 }
1714
1715 pub fn ECDH(self, peer_pk: &[u8]) -> ([u8; 32], u32) {
1729 let mut Q = Point::NEUTRAL;
1731 let mut ok = Q.set_decode(peer_pk);
1732 ok &= !Q.isneutral();
1733
1734 let mut shared = (self.sec * Q).encode();
1739 let alt = self.sec.encode();
1740 let z = (!ok) as u8;
1741 for i in 0..32 {
1742 shared[i] ^= z & (shared[i] ^ alt[i]);
1743 }
1744
1745 let mut sh = Blake2s256::new();
1747
1748 if peer_pk.len() == 32 {
1754 let mut cc = 0u32;
1757 for i in (0..32).rev() {
1758 let v1 = self.public_key.encoded[i] as u32;
1759 let v2 = peer_pk[i] as u32;
1760 cc = v1.wrapping_sub(v2 + cc) >> 31;
1761 }
1762 let z1 = cc.wrapping_neg() as u8;
1763 let z2 = !z1;
1764 let mut pk1 = [0u8; 32];
1765 let mut pk2 = [0u8; 32];
1766 for i in 0..32 {
1767 let b1 = self.public_key.encoded[i];
1768 let b2 = peer_pk[i];
1769 pk1[i] = (b1 & z1) | (b2 & z2);
1770 pk2[i] = (b1 & z2) | (b2 & z1);
1771 }
1772 sh.update(&pk1);
1773 sh.update(&pk2);
1774 } else {
1775 sh.update(&self.public_key.encoded);
1776 sh.update(peer_pk);
1777 }
1778
1779 sh.update(&[(0x46 + (ok & 0x0D)) as u8]);
1781 sh.update(&shared);
1782
1783 let mut key = [0u8; 32];
1785 key[..].copy_from_slice(&sh.finalize());
1786 (key, ok)
1787 }
1788}
1789
1790impl PublicKey {
1791
1792 pub fn from_point(point: &Point) -> Self {
1796 assert!(point.isneutral() == 0);
1797 Self { point: *point, encoded: point.encode() }
1798 }
1799
1800 pub fn decode(buf: &[u8]) -> Option<PublicKey> {
1808 let point = Point::decode(buf)?;
1809 if point.isneutral() != 0 {
1810 None
1811 } else {
1812 let mut encoded = [0u8; 32];
1813 encoded[..].copy_from_slice(&buf[0..32]);
1814 Some(Self { point, encoded })
1815 }
1816 }
1817
1818 pub fn encode(self) -> [u8; 32] {
1822 self.encoded
1823 }
1824
1825 pub fn verify(self, sig: &[u8], hash_name: &str, data: &[u8]) -> bool {
1837 if sig.len() != 48 {
1838 return false;
1839 }
1840 let c = u128::from_le_bytes(*<&[u8; 16]>::try_from(&sig[0..16]).unwrap());
1841 let (s, ok) = Scalar::decode32(&sig[16..48]);
1842 if ok == 0 {
1843 return false;
1844 }
1845 let R = (-self.point).mul128_add_mulgen_vartime(c, &s);
1846 let cb = make_challenge(&R, &self.encoded, hash_name, data);
1847 return cb[..] == sig[0..16];
1848 }
1849}
1850
1851fn make_challenge(R: &Point, enc_pk: &[u8; 32], hash_name: &str, data: &[u8])
1858 -> [u8; 16]
1859{
1860 let mut sh = Blake2s256::new();
1861 sh.update(&R.encode());
1862 sh.update(enc_pk);
1863 if hash_name.len() == 0 {
1864 sh.update(&[0x52u8]);
1865 } else {
1866 sh.update(&[0x48u8]);
1867 sh.update(hash_name.as_bytes());
1868 sh.update(&[0x00u8]);
1869 }
1870 sh.update(data);
1871 let mut c = [0u8; 16];
1872 c[..].copy_from_slice(&sh.finalize()[0..16]);
1873 c
1874}
1875
1876#[derive(Clone, Copy, Debug)]
1885struct PointAffineExtended {
1886 e: GF255e,
1887 u: GF255e,
1888 t: GF255e,
1889}
1890
1891impl PointAffineExtended {
1892
1893 const NEUTRAL: Self = Self {
1894 e: GF255e::MINUS_ONE,
1895 u: GF255e::ZERO,
1896 t: GF255e::ZERO,
1897 };
1898
1899 #[inline(always)]
1900 fn zeta(self) -> Self {
1901 Self {
1902 e: self.e,
1903 u: self.u * Point::ETA,
1904 t: -self.t,
1905 }
1906 }
1907
1908 #[inline(always)]
1909 fn set_condneg(&mut self, ctl: u32) {
1910 self.u.set_cond(&-self.u, ctl);
1911 }
1912}
1913
1914static PRECOMP_B: [GF255e; 48] = [
1916 GF255e::w64be(0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
1918 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFB722),
1919 GF255e::w64be(0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
1920 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFB724),
1921 GF255e::w64be(0x0000000000000000, 0x0000000000000000,
1922 0x0000000000000000, 0x0000000000000001),
1923 GF255e::w64be(0x65E0A72F05397829, 0xCBC14E5E0A72F053,
1925 0x97829CBC14E5E0A7, 0x2F05397829CB8754),
1926 GF255e::w64be(0x4924924924924924, 0x9249249249249249,
1927 0x2492492492492492, 0x4924924924921F82),
1928 GF255e::w64be(0x414E5E0A72F05397, 0x829CBC14E5E0A72F,
1929 0x05397829CBC14E5E, 0x0A72F05397827791),
1930 GF255e::w64be(0x6E6BA44DDB3919FD, 0x4D5065C0BA270925,
1932 0xAD8273027F0E7D48, 0x26AFA803D61A9E2F),
1933 GF255e::w64be(0x12358E75D30336A0, 0xAB617909A3E20224,
1934 0x6B1CEBA6066D4156, 0xC2F21347C4043E79),
1935 GF255e::w64be(0x7287BBB2DC59141C, 0x0509961D71E284EF,
1936 0xC58EF652F0485A50, 0xC4FAF5442BDDB3C7),
1937 GF255e::w64be(0x70EC8E896A9E26BB, 0x691B44636A4256DB,
1939 0x3400B87117DA45FB, 0x4318414607C6AB0F),
1940 GF255e::w64be(0x05B837449A5D608E, 0xECF205B837449A5D,
1941 0x608EECF205B83744, 0x9A5D608EECF20278),
1942 GF255e::w64be(0x2375E8119918E929, 0x03ADCBE22101F311,
1943 0x853223D7F44E59F2, 0x4D0A213B4402088D),
1944 GF255e::w64be(0x45C1EDAE67F29B6C, 0x8BCFBBBB4324F63F,
1946 0xE427EAA88C3BEE68, 0x2DC2D3741789EEBB),
1947 GF255e::w64be(0x67AFCB2DAF089728, 0xA7990E074CA048F3,
1948 0x1BF074743BB5F39C, 0xE0D494F725A47337),
1949 GF255e::w64be(0x3E3560E7BB5DF4DA, 0x8982206A724B43CC,
1950 0xE00C1E20C1C66FF4, 0xC91927493D361051),
1951 GF255e::w64be(0x6DB05620A7BB37FB, 0xE98C3A469592D1D5,
1953 0x38EDF8B7F8B8E188, 0x9BC52C6FDD64E133),
1954 GF255e::w64be(0x30592749502236D4, 0x5E54F462670CA0FF,
1955 0x44B5BEF2D9C9EF58, 0xF42F3A0E06E24C0D),
1956 GF255e::w64be(0x34F3562FDA88753E, 0xD7991971E94A460E,
1957 0x76ED99CCAEE9D26F, 0x355D1614AEB11ACD),
1958 GF255e::w64be(0x4C5C3FA382AAF7AC, 0xC36F69694BFC77E7,
1960 0xD86308C5232C88D0, 0xE8D6CBC7678229FB),
1961 GF255e::w64be(0x6DD8CDFA520AED5A, 0x350914B3EE64BF7F,
1962 0xB885C9D1EB4CC9E1, 0x7EB52414159EF4EA),
1963 GF255e::w64be(0x56861F4D0A217C1C, 0x0957AB7A60AC1520,
1964 0x818C73930C2A0899, 0x59DAD0E634C75544),
1965 GF255e::w64be(0x536DD4D34D59EB93, 0x7952681BD02A45B6,
1967 0x5277E004AEA16EEC, 0xB1EE3EECACE73BFD),
1968 GF255e::w64be(0x3899CEA405D19C1A, 0x3AB270B8E0887316,
1969 0xF8F94746A2120378, 0x6625736C14AE7C9A),
1970 GF255e::w64be(0x532698BCB811270A, 0xF3C520B8FCA311FD,
1971 0x89B68A9C8B0077A8, 0x4D9B8F5639729F9A),
1972 GF255e::w64be(0x5D760C5405D6CFAF, 0xAA492C177AD3E4F4,
1974 0x98A1A433C755E87B, 0x904992094ACFFA61),
1975 GF255e::w64be(0x16A802006BF1BEA6, 0xB6738274FE0973BF,
1976 0xD816F7B2ECD3353E, 0x57B5D8562F5F28C4),
1977 GF255e::w64be(0x431DA1A672CB2D3C, 0x56244B8A32B42796,
1978 0x76CA668F88C812F9, 0x8D2F2DE6815F2EFF),
1979 GF255e::w64be(0x30290CF961B06E3A, 0xAF5539730762C505,
1981 0x803FC1C6AAD5CD46, 0x8EB44683ACC048BE),
1982 GF255e::w64be(0x7B37113C916F803C, 0x4AA37581A9B6AD5E,
1983 0x55838146CC140A37, 0x3AA366BBB889903E),
1984 GF255e::w64be(0x252DC97C189ECFD9, 0x9EDDA370E828C438,
1985 0xC70EAC518AE5C163, 0xD912EBC4E1C6283E),
1986 GF255e::w64be(0x467C84CA2424A548, 0x6F385F29F643AF23,
1988 0x09DF0EB0A3919A65, 0x38A7E99599D93A3B),
1989 GF255e::w64be(0x158521078CD1F209, 0x8C133221E772B327,
1990 0x65CF6B9CAB741725, 0xA9A8911D864E7F82),
1991 GF255e::w64be(0x5D4A07E9BC1F036B, 0xC3FC1F026C5406EA,
1992 0xFAE4DC5553E938EB, 0x41583C9A8F92D685),
1993 GF255e::w64be(0x19007B50A56088E6, 0xB4C47837DC725B4E,
1995 0xF9192F3072387F81, 0x5B65EC077C403B92),
1996 GF255e::w64be(0x1819A3081E878CBC, 0xAC10CA6CD1ED6814,
1997 0x046FD295C10A2A1F, 0x1B3E38DAF789767B),
1998 GF255e::w64be(0x2213A3D93959DA85, 0x4742F3CB3DEB52CB,
1999 0xAE5BB5318E506208, 0x4203ACE2FF9309B4),
2000 GF255e::w64be(0x118FC94162B377A4, 0xC1844EC2004952D2,
2002 0xDDA789FB4A2D58E9, 0x5669DD87D12F7002),
2003 GF255e::w64be(0x68069289CF95CA7F, 0x6ECDFF0332EC6927,
2004 0x982FC6B00D403467, 0x6F077C677EF99DC0),
2005 GF255e::w64be(0x0E2364672DB22F61, 0x028EBB02AB0AE384,
2006 0xE02396E9E43361F5, 0xF1F0EC984099DC93),
2007 GF255e::w64be(0x0B3C9854075F7676, 0xF968F7338F922CF2,
2009 0x5A668C22A3492EE9, 0x3939F44CF0DA9535),
2010 GF255e::w64be(0x3D37FCBAB8595FB5, 0x83925568F9CA1E3F,
2011 0x5FE95976F2881B19, 0xFA4B698C2D5375B3),
2012 GF255e::w64be(0x0C4AC28DE6AF9B7D, 0xE13C4A7639E5E234,
2013 0x41B211E505C5A659, 0x0266FAA875DEF4DC),
2014 GF255e::w64be(0x6EEF26D87D3B6832, 0xDA84A01A1181FE26,
2016 0x9D9DD93F615DEFAA, 0xABC55F7A179D927E),
2017 GF255e::w64be(0x50B35D49D9A28BA9, 0xB52E059B6051E0F8,
2018 0x8FA2EDA8E408B67B, 0x8005B508E6EDAFFE),
2019 GF255e::w64be(0x0CCF7FF00D563132, 0xCC7CCE327009957D,
2020 0x54BD0CFFC1B29AC7, 0xB111F1B5F7C6525E),
2021 GF255e::w64be(0x676824C9A296F053, 0x03D9F770D7F5F415,
2023 0xF8FAE043DB5120DD, 0x97DA44A024F31B2E),
2024 GF255e::w64be(0x251A19311A6DB76E, 0x706D8A1F41E90ED8,
2025 0x15064C9132683177, 0x2D808316E1227049),
2026 GF255e::w64be(0x2C8D5EC4B15D04AE, 0x7C16D8FF7BF95128,
2027 0x0DB49CC10C6EE0A8, 0x95191DCA9E05F91A),
2028];
2029
2030static PRECOMP_B30: [GF255e; 48] = [
2032 GF255e::w64be(0x13CA1147905FCBF5, 0x52326246403CA5BF,
2034 0x3C35D84AA762ECE3, 0x907DB8CBF42BC887),
2035 GF255e::w64be(0x21807A9E869F9959, 0x1A5450AEA131BEFF,
2036 0xD8A529F6B8C7B090, 0x7CC2003EE88F4078),
2037 GF255e::w64be(0x3AEE62CB93CED7F1, 0x7067AB25891EE3B5,
2038 0xF718381811963DB2, 0x73FBF78B8823C053),
2039 GF255e::w64be(0x1F0B55F7538062C6, 0xF5F7EC08D23CBB26,
2041 0x9FDF60EC98F382F9, 0x085234005B2AB43E),
2042 GF255e::w64be(0x2A01A7A66A64F8DE, 0x165DCC5F4ADC9ACF,
2043 0xC8364B4B5B081003, 0x93B71E8B59F69390),
2044 GF255e::w64be(0x3B685E42E10E7D85, 0xA4740FCA9242B2B1,
2045 0xCB8F01643355CDCC, 0x4C40F18C5B63A979),
2046 GF255e::w64be(0x20580EA099D82FC7, 0x392A3EFC5FB42AF4,
2048 0xE6DBF5BFBFA90AD6, 0x0A700BA2732E6D3B),
2049 GF255e::w64be(0x344DC3902A2BB913, 0x3CD6D4F887D5ADBB,
2050 0x0D1F0F40860C8B79, 0xE696F91B6027E51B),
2051 GF255e::w64be(0x5B06BAC6615CFE93, 0x121D9D81E43446B7,
2052 0x01B0E0FE346B8431, 0x4C0B7DC3E9389D91),
2053 GF255e::w64be(0x035262D6FA42CCD9, 0x931C814DF00837A5,
2055 0xC4C14E9CCDB62641, 0xE72798BFE43FF79F),
2056 GF255e::w64be(0x7F5A47C4B8A71462, 0xEA5542F0423A6B08,
2057 0x7D627151D46A1F28, 0x0ECCB2E2278F9787),
2058 GF255e::w64be(0x40F104BED34B471B, 0xD6443D61DA82B80B,
2059 0xE3DDBBE02A015838, 0xCBA8747656E79C58),
2060 GF255e::w64be(0x71C205F522D89932, 0x82D85463B52A35E6,
2062 0xA9100D1A84D2984B, 0xFA3DE32CCB7A9574),
2063 GF255e::w64be(0x4CA23E185D27384C, 0x1118B84EFBABE26A,
2064 0x32A77CB45507DF64, 0x32EDBA4A0D03AA4B),
2065 GF255e::w64be(0x7E407DF2A38A26C7, 0xB84215DB55AC3228,
2066 0xCA1887B16E532444, 0xBFCFC5A884A0529A),
2067 GF255e::w64be(0x7B331EF6B0BB0807, 0xF996B645F02F7435,
2069 0x2A1FD6F2C3D03ED9, 0xFE3ADDEB0040571C),
2070 GF255e::w64be(0x7BFDA5402A7099E1, 0x554EE5C206C34691,
2071 0x835EF867125662CE, 0xA09544EF1016424A),
2072 GF255e::w64be(0x5619E82C5020A665, 0x208F3395E8B0B098,
2073 0x2CDCF267BD76607D, 0xF10534DCFB398915),
2074 GF255e::w64be(0x3AAD0F388C740A4C, 0x5C2275E090803FF7,
2076 0xD5905F5975C11A6A, 0x7C8644BA3F31E86B),
2077 GF255e::w64be(0x6489741694C2DB65, 0xAF6326F66B245EBA,
2078 0xBDAB7C7103D81CC4, 0xAC15C4E14810B01D),
2079 GF255e::w64be(0x724D3E13C3B6EAB8, 0x055E3DDC866AEBA3,
2080 0x6324B89BD96935CE, 0xCAE36C5E76A80C0A),
2081 GF255e::w64be(0x6ECA645765B3F184, 0xAC888AF902D3F2F6,
2083 0x23B990A9715300BD, 0xEAE77CD5A217B5D7),
2084 GF255e::w64be(0x687C7F6805609029, 0x7DFB6BBCF4D4B95C,
2085 0x03FD10706E8EC9E3, 0x37DA5CC5DF7466C6),
2086 GF255e::w64be(0x0A557BAA6263696D, 0x4ED35671F7B6DB07,
2087 0x6DDDF7B4D68A7534, 0xA44FD3085FE84D18),
2088 GF255e::w64be(0x4D5A31F81E16CAFF, 0x4E475474481F6751,
2090 0x7707A1054E57DBAB, 0x228358287E4B16B5),
2091 GF255e::w64be(0x1CF5388644F4CE58, 0x7E38C6B544AA249B,
2092 0xFAD21ABA6C967EB2, 0x5B1BA39F15E5BA43),
2093 GF255e::w64be(0x183B4E113203FB02, 0x33591AA143EE1F0E,
2094 0xF41F3F8FF5B2D5E6, 0x3F1703B436F4194D),
2095 GF255e::w64be(0x52897BFEAB1D3143, 0x28E16088AC8DD35A,
2097 0xEA6AC104B4377B37, 0x0A811568C23ED90B),
2098 GF255e::w64be(0x002DE451776F7575, 0x3E060714E384BC65,
2099 0xE84AD604731B838E, 0x9AE461EC05877BB3),
2100 GF255e::w64be(0x5FDCB9FB3F4C5797, 0x4046647612284F1C,
2101 0x542A5F62FD3D5C15, 0xDBEE341D80A8F52B),
2102 GF255e::w64be(0x7B1E1E0BB13A0D6E, 0x2E6F086CE5352381,
2104 0xF3F02ECDB61A483C, 0xCFC498866CBD23AE),
2105 GF255e::w64be(0x0385B60F3A5A829E, 0x4663742D210BCFBC,
2106 0xA7FC1E3D6835CE52, 0xC7DB9CBFAD8ED920),
2107 GF255e::w64be(0x3CFEE0A952259507, 0xD0C22765111F323D,
2108 0x29C93C6A6818E347, 0xDDC8215D410F748E),
2109 GF255e::w64be(0x440B9571A929A001, 0x616ADFF6E1A940B6,
2111 0x9D09F8A5348BF0A4, 0xF5C70615A2446EDD),
2112 GF255e::w64be(0x1C34B1769CD9E8C0, 0x460D033431555AFF,
2113 0x8F3A5C73FE927246, 0xF1EFD63E64A23B70),
2114 GF255e::w64be(0x2E6C853FDF78D4ED, 0xFBAE6180855FFB65,
2115 0x708D63C96ECE5F95, 0x76BE8AA8492971C8),
2116 GF255e::w64be(0x3060A8FFD41ACB33, 0xBD87FEECB7B9BB70,
2118 0x687781C1CD697D56, 0x43D0702FEEDA9F23),
2119 GF255e::w64be(0x098A2753C0DBF107, 0xE0407DAF679B0D54,
2120 0x9AEB5F577D172973, 0xEEEBCA9CDAC6A674),
2121 GF255e::w64be(0x4CAC1DF8F2DD5B83, 0x833BAD3C72274AFD,
2122 0x3C87C94A681CC18A, 0xB54EC85B102F1B29),
2123 GF255e::w64be(0x1F74F35992B895FB, 0x27E87DC21466BE9F,
2125 0x5B91677373AE781D, 0x07B29BD4692B324D),
2126 GF255e::w64be(0x5621598564421391, 0x680C35679657B7D9,
2127 0x35C8698010EE5359, 0xB1367E5D176D57AE),
2128 GF255e::w64be(0x132D657EED4666C6, 0xAF951851C14759B1,
2129 0x6F7B4359EFDC6B41, 0x226AE41DE0FE7D8B),
2130 GF255e::w64be(0x42B8E1E2340C4287, 0x6802040565529D9F,
2132 0x49890999F86805A3, 0x8CA7E11E18A667E0),
2133 GF255e::w64be(0x2FA5817BF1E95411, 0x07444FF660C223DB,
2134 0xA3CD06160A4F17D9, 0x0B25611A486A0DD3),
2135 GF255e::w64be(0x5133112D58780265, 0x01553E2CF86C3AB4,
2136 0x49DF33855A03D435, 0xA05CF4F734DB0C34),
2137 GF255e::w64be(0x2C431C1D74A7D3EE, 0x7984C9CC1F4B73CF,
2139 0x40EED2E1E791753A, 0xDE28AB433C184B7B),
2140 GF255e::w64be(0x7C3481BB7E32FFDA, 0xC3BF689ACC092270,
2141 0xDF729EFA0C7134ED, 0x06F0E664D5BC69B5),
2142 GF255e::w64be(0x1A0A913F0152C5C0, 0xD723AE975F7B4D00,
2143 0x3D51AA24984B9AFC, 0xBD18C0E8BD385F52),
2144];
2145
2146static PRECOMP_B65: [GF255e; 48] = [
2148 GF255e::w64be(0x131F48849CB5AC4A, 0x54C453E54BE22F73,
2150 0xB9D67A9106B8CB54, 0x779009D871F79606),
2151 GF255e::w64be(0x64CEC2C957589D91, 0xC6A2DE7E1AF5BC7B,
2152 0xBEA76CAB621DDC00, 0x52A070403A68BCB4),
2153 GF255e::w64be(0x6E78594A21A5AAD2, 0x48E8393CFF13EC0E,
2154 0x222B7C0CD599D9CB, 0x17E71DD1EB9D832B),
2155 GF255e::w64be(0x0ADECEF07226CD6D, 0x7559D60B3193DA7D,
2157 0x1BA7B3E1CBE84C19, 0xEEE6DD38D8E9151C),
2158 GF255e::w64be(0x741A90CA667A29FD, 0xA32D826F66894018,
2159 0xB35B3FB65A19A30B, 0xD483D08E776177F2),
2160 GF255e::w64be(0x40534B306985620E, 0x6C805A5DABAECD17,
2161 0xC9233D8219ECC70E, 0xC699D8CD1BE2027B),
2162 GF255e::w64be(0x390940AD8D0885BF, 0x7B11CD4B6C9CC38D,
2164 0x5A40972FCDA92791, 0x33F6746ED6A45A0E),
2165 GF255e::w64be(0x098D3AB90B09C2B4, 0x0519A68AAB4295EB,
2166 0xAF41508342D7801D, 0x4A504A5DED61CB7F),
2167 GF255e::w64be(0x41A590927B5F6FD7, 0x0696A39545C181DE,
2168 0x92D534263FFE78C9, 0xA06F9DAD59A456C6),
2169 GF255e::w64be(0x6F29FAC9056CB53E, 0x4265FDF93F20B5C4,
2171 0x1522644129185A8F, 0x93B1A7E3CD5855D2),
2172 GF255e::w64be(0x4ABF14CD5591D3DC, 0xC47BA10C5052CE6E,
2173 0xA5F032C51EF980F7, 0x26744CD17E4ADE86),
2174 GF255e::w64be(0x6470D11011381CFF, 0x893FFC0CA3CB3C98,
2175 0x4563C7AD47CE6A39, 0x1D5909B1A76336E1),
2176 GF255e::w64be(0x742236A2B9985165, 0x9AE9B0736E87C51E,
2178 0x74427A8818227B9E, 0x648443E48591C275),
2179 GF255e::w64be(0x4B36B3BE374E74CB, 0x9DD36D925FB45810,
2180 0x695C5863633AC0BB, 0xDB2EB15DD80EB7AB),
2181 GF255e::w64be(0x7563AAD0685E3293, 0x52217A6F3280BAD3,
2182 0xBCF6E190CBC99BC3, 0x3B02030497F19A1B),
2183 GF255e::w64be(0x637BA56A42C4587D, 0x9318569D6BC1A5D5,
2185 0x748A8C77D6669E2A, 0xD8AD585D0C14DC83),
2186 GF255e::w64be(0x143CF8A090ACB085, 0x0C0776C9F6ED32DE,
2187 0x763067186E58108F, 0x2473D6DB1425C001),
2188 GF255e::w64be(0x2C301B6BCC1F09C1, 0x3A3345F98418DD26,
2189 0xDE3B04BA9040AF87, 0x73CDF9E505579C38),
2190 GF255e::w64be(0x5C780EAA96A1BB91, 0x1094A46B6F56FA43,
2192 0x0E16666D8273B21D, 0xE14526AA9D051B56),
2193 GF255e::w64be(0x7EE7B8C1D61C83DD, 0xBAC06821F2BF788C,
2194 0x33088969E8FB612B, 0xE95E218127D26209),
2195 GF255e::w64be(0x72AB912B16C33383, 0x617E1C89A1A25303,
2196 0x624FFDB35FA59240, 0x0474E6971F3502A9),
2197 GF255e::w64be(0x6B3865BE473732FF, 0xE95C514D17DD5343,
2199 0xD6C684EDF26076D9, 0xE800A094D67CC3ED),
2200 GF255e::w64be(0x235872299B5B142E, 0x34DFEFB2A6C39FFC,
2201 0x3260DA08A5D337CB, 0x4C033B2301944CB8),
2202 GF255e::w64be(0x2961CB37E34C35A1, 0x7B1EF0DEBBFAA0EE,
2203 0x08AA04266FC23C15, 0x439324FCD04090FB),
2204 GF255e::w64be(0x32138C48916B15C7, 0xF8815AEC9C0105B4,
2206 0xDD56EA4894B8F6C1, 0xE7847250A19EF549),
2207 GF255e::w64be(0x07DF0CC5D7C9E88D, 0xADD356D1CA14E352,
2208 0x53193A718D75331F, 0x6742B67C6086DF92),
2209 GF255e::w64be(0x713B783B3766078D, 0x0D31937E03003B68,
2210 0x643500CDE6FADF0D, 0x5C9C41C3B8594D9B),
2211 GF255e::w64be(0x5C9329786A90B198, 0x83A3CE92BEFEC84E,
2213 0x4FD5981D24E25FBE, 0x25F90BCEB299A5D0),
2214 GF255e::w64be(0x79E82E420C17C457, 0x3F6064CC7E287D25,
2215 0x476A1D01EBBFE2BB, 0x7982C54051C4DF08),
2216 GF255e::w64be(0x1813C6ED70DAFA38, 0x27984BF87B6F0AD1,
2217 0x73165189E2EF99F8, 0x8CE01EA2E8B54114),
2218 GF255e::w64be(0x4515BBA1AEAFD937, 0x8D0D667D16879C64,
2220 0x383BFB84CDDA791E, 0x7CAD33020884167D),
2221 GF255e::w64be(0x3CC8BC3168B5A376, 0xB97069DD65593890,
2222 0x854CBABF2D02F041, 0x00FF128613403E58),
2223 GF255e::w64be(0x058DA5FED462C39D, 0x206DA25D9FE2783E,
2224 0xF8F2F98E5BEF4381, 0xC303EBB8F65D98BA),
2225 GF255e::w64be(0x419A7DEC26A3D7FA, 0x97A6D06EB281AE98,
2227 0xB0DF0BF1929E91A1, 0x8EE71CA88021D1F8),
2228 GF255e::w64be(0x2E344D49A48AE286, 0xDCBB82BD08CEE05A,
2229 0x5AF4A67AE9C4AE24, 0xC97787D39A76E4A1),
2230 GF255e::w64be(0x60570F440CB85A8A, 0x15EB451E43025B6A,
2231 0xDC1EF290D77A0305, 0x877FB541EB5BEC17),
2232 GF255e::w64be(0x40255DC81F644B88, 0x3CA545A989E728B3,
2234 0x0DAC5E2EBE8D1017, 0xBF9758CD45295FBE),
2235 GF255e::w64be(0x052051EDAFC87131, 0xAA36C89F8D5B502A,
2236 0xFDEE555C9009703F, 0x6AF277E67A9FAA68),
2237 GF255e::w64be(0x50C64067319D2237, 0x0F6D233DC4F2C4BA,
2238 0x9B85D45C9AA3A8E1, 0xDED77C4486AAB04C),
2239 GF255e::w64be(0x1CE1017108071F0B, 0x71830A04FECF5B00,
2241 0xADED92BC897B71B1, 0xEC2944EFB6EED8F5),
2242 GF255e::w64be(0x0E7D16D056A9DF14, 0xDEBD7D4FDDF67479,
2243 0x096B209129DDE65F, 0x795B6B03F7146048),
2244 GF255e::w64be(0x136A3753275A04FE, 0x2F8383D036FFDEC3,
2245 0x6E06A2EFFBF79614, 0x8A96C7C2F4D51B6A),
2246 GF255e::w64be(0x09C0518DA671868A, 0xBF13A51C8C3DB802,
2248 0x533027C62A4254F0, 0x714774712F78D8DC),
2249 GF255e::w64be(0x406E88577206C6C4, 0xEDF6131ABB08D620,
2250 0xAE53B9A6D617E037, 0xD25E4076E71417FD),
2251 GF255e::w64be(0x7A35DA9A106BD4A6, 0x69CB583FD3DDA8C2,
2252 0x5FD6950193780470, 0xA7B19AB7E5261DBE),
2253 GF255e::w64be(0x7257A8479DFC6C73, 0x572C2A14570CFF08,
2255 0xE948852FC3436317, 0x4819F142C1EA898F),
2256 GF255e::w64be(0x046E957DC3F6F2CA, 0x9346F2E220459FE3,
2257 0xE520B3017D250954, 0x82C844492F879AB2),
2258 GF255e::w64be(0x78BE6830E382EC23, 0xAA62937A623721E5,
2259 0x75D85076E298321B, 0xFE1CAB3D1875E47C),
2260];
2261
2262static PRECOMP_B95: [GF255e; 48] = [
2264 GF255e::w64be(0x064AA342C59C0DA0, 0xFAA44349B6734FEB,
2266 0xD30B1C84CDE9765C, 0xB766DECCD7834FF7),
2267 GF255e::w64be(0x119D5D1A55EC18E7, 0x28C31FF060305E40,
2268 0xFD06B4B9CEDAC228, 0x7ACD061D37C3D1D6),
2269 GF255e::w64be(0x0DD8CA46CB20E0DD, 0xE43FA70510BFE509,
2270 0xECE63FBCDBED83DA, 0x926FC4E7B0289F0D),
2271 GF255e::w64be(0x78FC954AD8D52006, 0x44C3AEC51F2964F2,
2273 0xC312AE3005158590, 0x18F98B63350A8752),
2274 GF255e::w64be(0x7AD8E671EE17C670, 0x3313ED7AAB04D140,
2275 0x91B847ED26B6CF94, 0x0BD0148E77CE6A5E),
2276 GF255e::w64be(0x3297466638BBC445, 0xC8B94BDE93D3D902,
2277 0xCE649E0260C40EFC, 0x698A7797F808A2C7),
2278 GF255e::w64be(0x547CD638F8AF40BB, 0x694F8ED466CC3C37,
2280 0x16E8ABF34D5A844C, 0x09409889B0E98F27),
2281 GF255e::w64be(0x7D8AD1764CED7A3F, 0x809AF4FF01016ACA,
2282 0x6148669B1336FCEC, 0xDD11E9CDAF91678A),
2283 GF255e::w64be(0x4B6AD6950FFA9CBA, 0x9B1CB599B9C46D93,
2284 0xE5BCC800B27EACD0, 0x9B72E257C7E326A2),
2285 GF255e::w64be(0x613C8ECBF0A848FC, 0xA564AA42C0C97700,
2287 0x38702E4B6A61439F, 0x924CF8F624C8F8B9),
2288 GF255e::w64be(0x63A19A4AC2160C37, 0x11ABC58D9EF7F4CE,
2289 0xBEB8664E3B46464B, 0xCFA2A379144F4EE3),
2290 GF255e::w64be(0x62DC6DBA747D1E89, 0xA127C8EDEF4200D0,
2291 0x48056960613E4959, 0x6692BE27FA7A1351),
2292 GF255e::w64be(0x25A6EC411F77CB78, 0xCF69A4B2A11A4469,
2294 0x6B4EB9B6E6D5AB02, 0x0B43FA3ECF550A24),
2295 GF255e::w64be(0x03C98282001ADFA6, 0x4E9D1C740827ACB5,
2296 0x5D18C2E1F33671B6, 0xBE3D87A48426EBF8),
2297 GF255e::w64be(0x7115EE66A4C38C36, 0xC01DBE749F798A3C,
2298 0x6B6A0A0C660809E0, 0x1953D2EF4892BC98),
2299 GF255e::w64be(0x56AE980BD465F711, 0x396287DA54A2D27E,
2301 0x24B76B26F2E1DC5F, 0x084F3670B14FCFE3),
2302 GF255e::w64be(0x68FE969D595DA557, 0xA5B443E88C8A995B,
2303 0xCA00F145963AEB78, 0xAD0F1CF8D4A2A9ED),
2304 GF255e::w64be(0x5E30E5A5B1B6CF94, 0x0E53A7329BDB49DB,
2305 0x20E070005600A972, 0xA34F29143251910F),
2306 GF255e::w64be(0x39DD38009BECF484, 0xCA293874749E2E36,
2308 0xEC50E5B1342F274F, 0x69D091B933C51A9D),
2309 GF255e::w64be(0x61EA99C35B5C8714, 0x73EB7E911AFAB636,
2310 0x9592E0C84567F3E0, 0xD0490A8282D23DAC),
2311 GF255e::w64be(0x653961AD8EA3C366, 0x657DED2350C83F99,
2312 0x13E2CD23184CD0F6, 0xEE17FED2BAD25EAE),
2313 GF255e::w64be(0x2DDAB2D5C942F940, 0xB115E746EE5CE792,
2315 0xCB08BD516DAF829A, 0xAC1B5F5EC677FCD5),
2316 GF255e::w64be(0x50E1C5CB1035BA92, 0xE61AA40355321930,
2317 0x769600329037F973, 0x2B462BE2026F26BF),
2318 GF255e::w64be(0x0A74F122D11A9C92, 0x3DD40D9211FE4955,
2319 0x94C64564B78FC4EE, 0x0D609806ABA20D95),
2320 GF255e::w64be(0x40DE5F775041CCAB, 0x73DD00B07B577D81,
2322 0x480C472D1D6FD5F9, 0x1B1FBEAECBC67597),
2323 GF255e::w64be(0x7F172F027F7D714B, 0x7ADC900272DBFC13,
2324 0xF6FA872F9B5F7D84, 0xDFACD7B8DF4BD3FD),
2325 GF255e::w64be(0x64A0666FB8EFAEFD, 0xE43A2E53396F5703,
2326 0x7B4423C03DA78BB2, 0x1A2ECB81239BA603),
2327 GF255e::w64be(0x483FC465507787CD, 0x6EB1438B4C5E389C,
2329 0x8A501C2572F5F3FA, 0xA51D77D1040D73BE),
2330 GF255e::w64be(0x67CA12B3AA2B3592, 0x9A613CA0B8D3CC03,
2331 0x65C3630287E6F750, 0xF143D0A2D8197B12),
2332 GF255e::w64be(0x3CF43FC1A0AACBB2, 0x82DAE17DC8A1D998,
2333 0x77117A96356E0823, 0x66EA45588D44B244),
2334 GF255e::w64be(0x7FFDB40231B7728D, 0xE467A2F1BBD605FC,
2336 0x9381100ED4068C36, 0xE9CA1BD79F88055A),
2337 GF255e::w64be(0x4E531B74E4EDBC3B, 0xE53148AEAF77C797,
2338 0x636E3907AEE17932, 0xE828BF5DAFD9FBA0),
2339 GF255e::w64be(0x3BFF8E3C1DCB6A65, 0x7E88F8DB430F4FCE,
2340 0xCF59614C8ED50CF4, 0x33176787CD1F7BC6),
2341 GF255e::w64be(0x7DC8FDD36CEC85F6, 0x5EBABED548F85E28,
2343 0x7EDC5478A24A247C, 0x4FE60DBAC12937B5),
2344 GF255e::w64be(0x14AAD6B599A78A1E, 0x59164ECA80DBC2BC,
2345 0xA8C14E4C401A8725, 0x66D1C4E7F84DBCB7),
2346 GF255e::w64be(0x6AB96CBAD2CE2586, 0x5EAF9F16DAFF788D,
2347 0xB1D294C4F04CF4AD, 0x80FD38F7897A80E2),
2348 GF255e::w64be(0x3BC04AFD4061401B, 0x306E5F900F95B543,
2350 0xA53CBD8CD928AFCF, 0x87DC988002BBDBAF),
2351 GF255e::w64be(0x08D948612F474B91, 0xDF2876502B201BC0,
2352 0x448EC22797892CBB, 0x7C38EDBD8C233710),
2353 GF255e::w64be(0x1CA7F5781A92A0F3, 0x979AD724BC3DA9A7,
2354 0x89FC8B82D263BE84, 0x17B5FC58F1356C46),
2355 GF255e::w64be(0x20016465EBA3350C, 0x3FBE5678BAC454E5,
2357 0x5E2423EAACCF1E4D, 0xF264480132A6E2C3),
2358 GF255e::w64be(0x0E4BBBA7186F99D8, 0x6F473508FECBBD48,
2359 0xF18F65CE65A3396F, 0x4945F8F959B9DE26),
2360 GF255e::w64be(0x084DC6999483CA11, 0x92A119A8ABB18530,
2361 0x05FAF50A98B3E130, 0x19015F2BFA19C676),
2362 GF255e::w64be(0x1CEBB3668FBDD74E, 0xDB22A366E6177378,
2364 0x13BC29C94FAF4AEF, 0x6E86AA974593CF40),
2365 GF255e::w64be(0x772B639D97FD5F72, 0xC1EA09F19EA3A887,
2366 0xA8938E24467348C8, 0xA71611FBE0733F1D),
2367 GF255e::w64be(0x3155981ADF087198, 0x67B9E52CE3D3192F,
2368 0x8590411621A233CB, 0x4271B7E0FC853D04),
2369 GF255e::w64be(0x6F0F32C830EFFC50, 0x7362CB98477DB14B,
2371 0xD1A82D6F06C29AF5, 0xEAC2235CB6359790),
2372 GF255e::w64be(0x0A5A0B095EEF3AE2, 0x708B748FFC2CF704,
2373 0x333F90D71213C5D6, 0xEB6C22C3F0A9107A),
2374 GF255e::w64be(0x0E8698BBF8AD3D92, 0x70AF08850E90B07C,
2375 0xB4197DF3F7DA5D80, 0x2FC30C729DC8534D),
2376];
2377
2378static PRECOMP_B130_ODD: [PointAffineExtended; 8] = [
2380 PointAffineExtended {
2382 e: GF255e::w64be(0x06CB9DE70E47A525, 0x9FBB8D6BBC2E0657,
2383 0x04DA93AE9BE27159, 0x869B548FDE63606E),
2384 u: GF255e::w64be(0x1E3A7692F3E02AB1, 0x2B998E19EE40437C,
2385 0xEF9A2E5ACD520CD9, 0x6A6F8767CAF58BCB),
2386 t: GF255e::w64be(0x6383719F46FAC0AE, 0x2FCDD9E72158E8D4,
2387 0xC1FEC4C782CB44C6, 0x12DCF83EC50BD952),
2388 },
2389 PointAffineExtended {
2391 e: GF255e::w64be(0x7F9D9B87A431B60A, 0x7A63055985C3FC53,
2392 0x9225D9C973152188, 0xA69544938C9DC498),
2393 u: GF255e::w64be(0x62BAF3EF3C842009, 0x4FA122A357313D72,
2394 0xC29D0227105E6338, 0x4A8F6858185A63C2),
2395 t: GF255e::w64be(0x54C34BDF628B654A, 0xC5FE42DEAF33DE83,
2396 0x799295C376EF453F, 0x183908457B30E0BC),
2397 },
2398 PointAffineExtended {
2400 e: GF255e::w64be(0x552022F75A7FF671, 0xA458CD165446291A,
2401 0x75DE8E82AE7AD735, 0xB5DA3AAFCEA3BDDC),
2402 u: GF255e::w64be(0x282E209409ADD692, 0x6DDAC4AB9F7AE17C,
2403 0xEB86F24ADFCADBF5, 0x055D6CCDE9EC95DF),
2404 t: GF255e::w64be(0x775F596632FB79E4, 0x541CE0C53EC38691,
2405 0x5AF736BE387EA15D, 0x60BA3A7F6B02F394),
2406 },
2407 PointAffineExtended {
2409 e: GF255e::w64be(0x4830813F189FDCFE, 0x5E05B4C4DB704F5D,
2410 0xE9BDF6AD5FC76584, 0x70FD1203988BD912),
2411 u: GF255e::w64be(0x372239482AEC172D, 0x6FB5672D05CA0B5B,
2412 0xC1293137B7F95D67, 0x9E343B6FEBEF1413),
2413 t: GF255e::w64be(0x35266C9ACED8D90B, 0x21A50BBDCF12747E,
2414 0xF796A60E89BAA4F4, 0xEDC0FD9628A8DD36),
2415 },
2416 PointAffineExtended {
2418 e: GF255e::w64be(0x3D9DAAB30A815D03, 0xD7CF00B1D04465E4,
2419 0x6DA60DAF31722070, 0x05C1A1E0BAB51F9C),
2420 u: GF255e::w64be(0x1098E4FDD37C43A8, 0xDBEDF58A6CB19695,
2421 0xF9ECBC7F186E562F, 0x0005FACD5D6FBDE5),
2422 t: GF255e::w64be(0x03BBDFC635166005, 0x4CA31E3B83E29BB6,
2423 0xBB03E3FDF6E447C2, 0x0BE5ED639180368F),
2424 },
2425 PointAffineExtended {
2427 e: GF255e::w64be(0x49DD1840D5C76617, 0xD3CC1E91A2BA4AF5,
2428 0xCE23B177E0B06A27, 0xEF2391D9C14BA968),
2429 u: GF255e::w64be(0x7D63505AA664C8D5, 0x2AE38CC2BA9B270B,
2430 0xF436DDDA8ED45B2B, 0x933CB8852B544684),
2431 t: GF255e::w64be(0x30F0D235E547B2AD, 0x396102BA67CD8FA6,
2432 0x84FD6E87816D4B31, 0x3D63011A6518ADF3),
2433 },
2434 PointAffineExtended {
2436 e: GF255e::w64be(0x4489AC6538239FA8, 0x87620DD6665947AC,
2437 0xC52014D6E24C4D0F, 0x3A2AA626DE84F742),
2438 u: GF255e::w64be(0x653EE371D2801E6A, 0x59F3D4C5BB3DFDCC,
2439 0xF94983893D4AABD6, 0x1A722773E489DDB8),
2440 t: GF255e::w64be(0x6E8DE13723DFA5BC, 0x3AF72BF16ED6198C,
2441 0x336E96DD99975786, 0xA14B344A108032A6),
2442 },
2443 PointAffineExtended {
2445 e: GF255e::w64be(0x18371273F6385B25, 0x38A9D7CCABB539CA,
2446 0x8D9649ABD8EE3F78, 0xB21E962DCC9C968E),
2447 u: GF255e::w64be(0x2316B87D49C2D67C, 0xDCDC45FA8BB04D8E,
2448 0xAB79B9C555C2BE32, 0xBBD36EB39B38C8C4),
2449 t: GF255e::w64be(0x79B75334C85A090C, 0x4B8F046B40C3632A,
2450 0xFE575987C8449D15, 0x5E85E0F841CFEA05),
2451 },
2452];
2453
2454#[cfg(test)]
2457mod tests {
2458
2459 use super::{Point, Scalar, PrivateKey, PublicKey};
2460 use sha2::{Sha256, Digest};
2461 use crate::blake2s::Blake2s256;
2462 use crate::field::GF255e;
2463
2464 static KAT_DECODE_OK: [&str; 21] = [
2485"0000000000000000000000000000000000000000000000000000000000000000",
2486"8d94d29406f613c642019d7dbda7121510be572d323181af1a0914e8d1080903",
2487"23a121249d7a31475a8603bfab1ec71d94fd0dd033c4a6111937ce8649474b51",
2488"a040d74b0374447b31b3c70c815c380c5ab9f9efaca7ee75a51a2a7fbfabc615",
2489"892180c7ba29f4980fbd56219704b6eeb161053867294aed2cdb520301721a61",
2490"8eabe2a42cca04c02a009faab48eb9255c9594b6c9467b03479c00c22bcc423f",
2491"ac3bd3c64e2e441b19b7f35e450c6c68346e76bcb2a8b137a7de9e0185bd9603",
2492"e53a91660b5e8e8cbdf8603af5b6e4dca4b70d400739c292cc85ff3f4ba2e875",
2493"8d33a31606aec0eae122d81896982c8866a1a9f1ebd750d944e83cac3f2f6041",
2494"39415ca52c40d1233087280b99a80bf946156cefc5a0fcfc4cd6f640dfbcfc45",
2495"4a7bb7961c063e7e1aad732efc6f2a4ac990318b0a9b406ae3c20c8b64bef239",
2496"36530914a8e71d6092ef0414e7adfc2485870dd3b2c967b245a0de3f11f84941",
2497"36170b60f0fbfda49917de84b99c3f3d901c7fad3e4210fff5f8be7aaf3b1a6c",
2498"2a9d3fa655934f2909de0a158ae66e35b268b2682c795e77c5e9d3cdecf76142",
2499"e6eb5e9ed983e1f270a72bd0c4a868798ea042efc8bda3adb78d5bc2438b5411",
2500"f153b63a831d9a5309dc6936453883c31a929af9943bf7bfb35c10fa9f4ff968",
2501"89aeb7a251b63d70ece76dd1b16e14bb97a6c181c880d369e373c4d2854f9315",
2502"bd66a62f55d033b7c9d8dc68714787b1baed252c66220e0a5d6960ddc8f0d362",
2503"ef782de017160be60b3bfff454b0fe589c34a3e6f1f9275b520a91c4ebc85945",
2504"faaf35e1911512270789f220d2d31e21cf4b2ba6b98da2dffb5fb0dbb06ae402",
2505"8f4b5186669f788374e3759badbc10384e9b1661090c2183ee19b4990056b15f",
2506 ];
2507
2508 static KAT_DECODE_BAD: [&str; 40] = [
2509 "26b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
2511"e77f719c0bb70774d38b65f54e686da67c5cb40327dc54a35e4eede259c40ef5",
2512"1da164d9f10443a44adaa689b304fc620b0084b83a3a980745f0a7bc909736a5",
2513"6685163e6eb1ef12173b1292a5ce168f0902df2d0cc5f8d84221e218455e66cc",
2514"9be913019bee05796667cdfa16f24cd352d966dd6f7d0c34760e6ab6a72aa4bc",
2515"c7d0dc80aaa13be5c83eab4a2690c8689a86b192848e0b23037e6432afccc0bd",
2516"ddb2ada3211019b1f9360c1c773a935b3e0dbb554db3e3296b3edbe31468cdbd",
2517"f190aba112cc538499ccb40d0a03981a357fcad60bc6a0b76e2b01a3189c09f8",
2518"d689e881ac051dd2d853d91a2abebdea4c587696a207e05e77c1b4228bdfabea",
2519"4f62d302458e99fa0d7d3f09dd853fd341414db3c0c84bac9c61b18edfc5b8ac",
2520"fcd17606aacd5f2d45360a26c8709680766b6a3167815ac591168b16bd299ce2",
2521"ec4ecc7c8683f7ff435012a8458650e4edc3faef26dd02c455b05d659db194d2",
2522"b85eb4cf83a14cff1c6360d619a61062fa2a12e52be9d03ac39a4baae25b87f2",
2523"692ab83e0120189cab03921949edc4181310f984f2d611f53a1f944c62dfbba4",
2524"d22892e900c7fb06a8b481348e56cb6c6ac7dee630ea8d7750cd5d7c809108f4",
2525"8f275e14c648647cffe8968b8f463a9e6625510c13b90121e8679a4f18af3dea",
2526"38cb8c5808478faabc4aa9bdc27469867d968b3db335ad5711971bc7e23107b2",
2527"af39fab77d9de6dfe58ab9f5973588211fb12b6213ffa66038b07fb571c85bb5",
2528"f16d6faed0a0acf357900acb15d8b27d10dadf5db0b5fd545eeb8b4784e2aeed",
2529"f3af66c2a8f69db459cffb0f18136c08751596c03c2380bd8bec413e758ea79c",
2530
2531 "464b242d1c4c8860f05c36c21568a428433c32efe8634382bdb38ef392527840",
2533"3a7f1237413bafd046210bc6974b04f8e51c944eaf6b0346c9ebde1dd3dfca4d",
2534"840b63fa443bf4f8a491bd26abbfe415fe0898c176b3cc74f54494b15d01fd14",
2535"38c4ef0dd9b16de9f38f2915fba12ea7579687b3d045680aab2781abbb54e476",
2536"b0215102edc6a067471dfaecd71f7339a08ba005461ee652f2eee219806a330a",
2537"7ede36ac262d13c1445e84c7cb0643e3dfc81d0d2b45a8efc0c5eb0fef9adc65",
2538"225ee2a9f8cbf55ba44529e5e06db708b0bb9f0724654120a7f642d9f90f722a",
2539"1648b3502c9406fb650ffd5fd185f7f04c7a37183e024345e4c060c11da4334a",
2540"877c919914c70af38631f5a28ee98b2c85c0188facc3158a44a529f840552849",
2541"7112294bcc34bfed1f4050df27e669721d4943387893c806c9b436f5e7666711",
2542"e219124c9afa4f7c69b2a010c6a9cf82a8aaae67d28d01c274432f9018d2dc78",
2543"98a7fa5f994c06c15b8e919c4281459e1d3f9f6477ba2589346b11fa97088e73",
2544"73a881c422e9594ac9d8fd3eff56b8a920f50819916c96aab5b0da0912d75f3b",
2545"1fcbb61c5c447348aca7d005f605787950a6e58d91ab4481ce88bc93e7771921",
2546"886e412db5af6173f59696d486d6fd80c302febeb740bf64ced4dfdc0b7cff7a",
2547"8d7d3d424e413e7e0d984b518dca099f0a6d95d7335ecf72b369c0f4fa12524a",
2548"d9321c34e92d4faff2e22e6b45883bd1cc02f30c21f9c36924e4ca9e481d994b",
2549"7c33da291f0df8180c031975041b05d684ae46ace81023ff1ef36d137e174328",
2550"0577366515537e4d4129c358306105508d405cb310888a02b0361815aa91b769",
2551"b17a73c541514d26a361f23ffb635e3ec4d671deb26364a8b608c9b4e200b506",
2552 ];
2553
2554 static KAT_ADD: [[&str; 6]; 20] = [
2555 [
2558"dfb1ca41e8528d308ccd8bcba774df736d45c046be7ddbd16cf4d09e4bd6713d",
2559"5ca1f4dcdc62691e34a39ef351d89b23279bc0c9df39ce041ea1c1797c2dc954",
2560"1965427d058cb8177e90a5347a71c4d8e8c984efb059b391b834fa020276336f",
2561"7f95cd111ebcc875c2901d8cbe1a998e515da8dfda172afe7ef831ab7cd9fa34",
2562"9dd5baa72fb2a502a92ebce19770953b61edbbe918468c8de917dd0fe5d45333",
2563"979158d8691c7905469f7767a093250277fe35814d0d7660a91c701c8ea67c4c",
2564 ], [
2565"c314c44cfdedb72330565f3484f0b9ca5af5f8bd07c435e295ef236f25d41a5e",
2566"21107c12f9ffd2fd3add888ec2db9b1c90dd2af8e3c85d4de5188e711c4a277b",
2567"469506f2b9102b9749cfc3b5ee3bd40fe5431671095d816fe4c532a8644c9b52",
2568"d9465de29203ad90622c4effd6ff37c99298e7a973742a7ce41c926df2ee5c61",
2569"be51fb71259eaa489a24af77e2eeb319dc57b9e5c5fd02fc573eae58e3c93001",
2570"9fcd219e21e802f9ca690fed8c88136bad85243b3e58524f7ee0ff0d5a87fb66",
2571 ], [
2572"1608e067352acfe93e4d9925860e7fe0036cee802a41187f138c7407148b6249",
2573"8f7a3119ed80d0f37fee244ce0ad6ee64d9ff33ef96c870a87dbc0e5405a9d46",
2574"b0c6ebe2dfb85ac3d7c707d3999728cc8dd835ef8cb96fd139fe6e1828841357",
2575"85fa17f27db6337446b9285f037cb4ef13da278189864d5c080b375915ead92e",
2576"c86e83cb4da7e786ea6b60d783c8ee438cbeb6d3b48712fe7a05f4ab5799724e",
2577"277703b788d7c22c3ef83cb1dadb8f12c2cde24273aa347e93cb53039e0dfc36",
2578 ], [
2579"9ed7b348a6c89cf4ae7686ca60d7e8e4d84aa8914902de9b0c3c0e773a5d2338",
2580"3ae19805b28e8fd11aa08e2b3504a5f929c7d195108e9f1feb6151b50c16b002",
2581"b2b6a406654c7605a1ffade8ede158e306e44ebc6c9df121be93d386803d713d",
2582"fc9f740da4eb3f789ff9f2de63566c1cfe82b7e9469312f92e5f06add5b42c01",
2583"9a19d29014ee1166eb8075802e473fce54ed18ed64dd5d177b3609579314735d",
2584"5a16f010530c9e34358a20f5da9a341553fef73b8d0469f025586316c46bf519",
2585 ], [
2586"e13b4bbc01698f5ad066af91836e421fd222c6ff9155ecbc8343eb596c96625e",
2587"304dd928342859ecc0b8f8f8a04653dab139e3b5c19dc6d94285c5426e0ff81b",
2588"43b646939e1818e4233641697b95a0a498d14b94c75f2fa40f87ec5f1068822a",
2589"b8864ffb961f3902316463cc1c10242eb21783807dab44155e5ac0cf1c79671e",
2590"799f6b2a9765582995e8af3c409d662edcee092ef8b90b6fc616753d610be611",
2591"e5aeb24c1e7c70a09405918bff754d00514e21e78b30bfb16f4afe0afba04026",
2592 ], [
2593"456e102ab8cd3de4da2f87aef97de56322cfd090cd1bdfce2f7d1a12f3044c03",
2594"dab7d1e828f3a0fa442813138b9500d5a6e8593cc2b258c38f4bc2f6677c2b4f",
2595"4ee98f9b18ab3e943dc44ef8a1d34cad80010d56da720ad481d106ead5f8237a",
2596"69c3d94898c16ef6a8e8b704bd75f795d5f61a2d0e5ad88ede10f0463511fb4e",
2597"adef55541436f51828188f2262d14d0338e29e225619e8b4367373b56e717505",
2598"779053e1aa82aab9b4db23a6c62b20c1302ed57e0050f9ccc6c962abba9a2919",
2599 ], [
2600"47c3a0316cbe7eefd75e9ac28d048ce4a66c4d1f4b6e1ac2f01b92202b0de45e",
2601"868e38053880afaedea957f8a15f5fc1a7d259a9e9c81d17c7c6e459a242e343",
2602"1ea1e821d1c0455a3bce1b02cba1954222eaec267609f0e020df07a30f4d651e",
2603"fd15ff8f1ffb8ab93202477a50bffcb51919f9601f00dc4e8d5f7f67bd2e5961",
2604"5dd3d5b70105d7b9489f371a118982ace633004d0d6bd0826b6ce531f1ee973a",
2605"6d03d8bf6b7151c4bbcde92060f50cd2079893a4008285ee398fb52ae9ff3f79",
2606 ], [
2607"ee848f7817d3e971b2b54c8eb7e10b1fbab5ad289923734eb44823a02527f072",
2608"a01f4dc1ad54ea5fc196970626b5cf4ef85f70c653b094611d38a5066f2bfb45",
2609"11e843d9e9ef7f61e7832326db3ba20c0d32e8536a2d626eb8972288a8415053",
2610"cf17d00741fa91e8e3a8e5a9567fc470a37124ad7bb1e3261d42e06c61d94f40",
2611"2787fc966f26beb21166505bd8086538d7bab1c478d40afd4aaa6566d1f20c43",
2612"6a6a2ed9fbcc30fca854f44c5bbb461f08d8496e51e4448860fbba36131c214f",
2613 ], [
2614"7a0a00759d1cd4d5e8b105de55df8e24c4c0f77126d93012d821f7329ee8bf4a",
2615"896782828d9778495af5e81c1d2728eb65701b5702f5c76339c6327f747f2d79",
2616"5fdcd0e79e3710af16a8429971d604a37219df13a81db02f17a075959636aa78",
2617"38377262c89d13499fec4289370b84d2f8909b5ff7f78f852fa58de75b501212",
2618"33101a47819a4cb010a2fafa2200b9eea178eb295d827aa70ac1eab90f209847",
2619"07e8fdc7e3c6f94c7ea00db775c57a78e276a9bdadd9bf48edc8fa2e7d84be7f",
2620 ], [
2621"20a3145554aa24612918a65010f5721dc35f1b521643bb7a9bd128283eccf801",
2622"7936bc60842ba0473107baab33f72323434774cdfd1fdee13d4ec630173bbf07",
2623"d093d883ce426874c3eb10d07d742945e54dbadfd3d0987ff2257b2d6e36de41",
2624"5d7790edde5459bac7944afee96d11ecf7a09fa908d017a1dc0bfa21f48c6c5b",
2625"6aca1b02bfa6d8a3ad6cd8885bae5b67f25988e0482b2d89066ae73240fc340c",
2626"3d6f0b6f496aa935d91165d70460f2f98077fb07c8aa440220fcd185a9bbe804",
2627 ], [
2628"161c59317e19a3563366812fece786e996484b8fd5d1c148ebd7dcdc8e88be5c",
2629"7f3715d5ce4db0494b4a3385a04611b18a4d7bd22765a212beba300a33dadb6a",
2630"aa27b14f18dcd37ea3cc8d240b643c87c26f6aa76ed7e4fe96557c84e10f820b",
2631"a016d56b4104213befa959dc13b34adf4721e848c7e06908c8dc549d873d9d64",
2632"a15e3b933bd4ec8f3a81a17249cdc110478cf1f936755f854ae1512df2f3ed45",
2633"8e0c587d9ebedf7ae2be0a40670068b7a063ed82d0bd2cf8488c83a9a2578e58",
2634 ], [
2635"716a5981c982111525789284a3b28513647e27d94a8bb8d070f0a4b7d994844e",
2636"ef84ea063af30e199e5d1b68c7d0e2ba3474cafe2b1e68b65a9882b660ced801",
2637"a30e0c2d8d09e41927fc91751d9c7b93cd857805fe3ba094cbc0f2d81dd47f20",
2638"36954215cc4c68afda107cf709bc02b293951cefeb3cdf255c7057bcd0594f2a",
2639"ff26b0308c876b707eb05fdde588efcee433302123afe241a7779622ebb00475",
2640"f241b4863d570b3400e052c190a58262d7350d4ea23b8a3a51d46c7fb616d373",
2641 ], [
2642"eaa1f6043a6fc4aacf323f037b7f2d3fb4e76b4294b9ef70bb917c9cd9254d76",
2643"592f8c5cee2995928ecb7a4a5bc4c900c90fc3ce160829c99e7d9bd94944de39",
2644"a875ac408e17b91a87f02699cada2e861157f431e3a534ec2596ad7f9b5ec606",
2645"1eefe83ba8687ec47cdd7f3f452429dcf7f409471a90591a0448cc1ecf0e5e3e",
2646"29a810343e6df60509302e68b2a5d0afd8e0052ce66c96c12f1731aaac9c8a26",
2647"c9191c9a53b59af68a329c0ecd9bce33b859f37fa5bf810dd13cdad11b2fd941",
2648 ], [
2649"030605efbc3bb274c4a57facc65d60def032e2c5fc8fcbffa0132ccfd05fc342",
2650"b35a69133de37947d0d4a53c978ec6411be97da282e36596ebd3d7c6ae53af7d",
2651"c3438989ccd4966ca03afbf5ae4d9b4fffb63233ff5cf62ff2f89518ab859845",
2652"03267f801c066774e3ce7ca37c70e2b011389b46ed48cc2bc506deaf349a4167",
2653"06169d3dc96c474d31dedfbe5c7b5ebece757f55da11cd39dffa1d1f5876f71a",
2654"f30fed8c79c1c5accff0bf1027b3a22dc4766cb123f86a6e2429fff470d1da7a",
2655 ], [
2656"ee24e224fdf4cb9e03719ab4e621eef4bce1257ae337c9b55306d78d8801df15",
2657"bd80f4653d286e6150247bcc0fc3028857fe1af36d034e410928c0a3e6ec0522",
2658"16fa8cdf21208d7cfe1a32b1b8a76fad08e3bd4388559d60e551505b0ff1bc2a",
2659"124859494ea846482a104ffedac43faaa90255fa16c4e2ad6d56f2e9d928b40c",
2660"6fb267fc018e758ae323c287639c3bd070128f060417cd9120d0f050f8015d57",
2661"7ddf2a10f4a37299caeec5ccc9a0d601e3276ee0ec3a280e63cc8e777dead80f",
2662 ], [
2663"89ce0216734a92f4c20f35baede5961645da4429a90ed58380e662d1efc41213",
2664"419a372d235448fbae16df3a8e2cb663372e8d90cab86a4cd6644f864957a22a",
2665"fe7b16216610acad06fb1b94f0d9ffc61f8bcb54f7dcb3cf51c3b6ac194e6156",
2666"4d49806b7bccc8be2aac9cdd76ebf704bb441ff57e714844ea7eaf0a7e19e77a",
2667"fb199c8b717288f1d3d4050ffabd0c074a5a3958064ec96b8909f5d55bb1eb70",
2668"d01b9c987ba6049327c96f9b2b5dc6b83cd26044522b676c1949197288827a6d",
2669 ], [
2670"67dbfa93752bb778433352037a2a9074442cd4d245ae48cf1144606cbb0a6752",
2671"79611d1fa2eaee38bcb69e015a1ad7b76486171f1730124c8b1bb2df8bcc5218",
2672"4f66724b154d19e0ba806e7877f668c9fd36a5e82e5ea42f2f7d887dc8ea5d7f",
2673"eac67bac9ab914eda3279f7e6c1b7d65497899b6254fade7eb06d5e7f9fc9615",
2674"411b470ae6914ce475c102cc3a4137b164cc261f7651ee66c1eca8d3aa1eaf56",
2675"5300a7cd35274040890994d59131dd845c935db8b9dddb073f6fde47f4633430",
2676 ], [
2677"fce47a5b4d1663b9eeb8d93012096f12a6509f45a7d2de5269b6b12686492320",
2678"b607242257bd8805c6798b11b8ff30b3bfa5a186d0bca466a938d2f01bcbbf42",
2679"9339b879a6afbfabc0d3cb8477b639d0d2d5483782b4ab92199677cd15e76647",
2680"995456185abe9a56a94027a6708f7931795fa8509454a2d0b5f4c87d2182bb5c",
2681"2bfc84e851330e272ec66f518cfe84d7d444072b835c4f4b8b9c55dda8b9dd62",
2682"8950242ea5180f4a6c6aaa57539ce4d861be902d81a3e2668a0b62a6352e6b58",
2683 ], [
2684"9af6d2b370ef3d90d1fedc3dd4b77ecb895416a51ac291f42e281ede5c80aa2c",
2685"ea82dc22ee1cab5b512aed06024124c270088f54fa257d3a4ef74e311c7bbb0d",
2686"44729e9aafc33a1f1d981b86909395f3d5b2aa4da2d2289e0df06232419dc35c",
2687"98837dc918083bb59db02f472aaf329ff678a92d96a4b26106ed353fa4a80248",
2688"4a0d207b569516ef57f8d11ab777b1cc75ff0e37aec2439bb43b151215bb8852",
2689"a4732968e39260f27f1e2f9e91bb29438ab11e8ae03916c914f64bb83864b128",
2690 ], [
2691"5f65a4910e32732bce8611479b2c64276b426e935981cac8071222fbbec93f52",
2692"d382bd0d89a9d52dbc4aac37ca3cd8dc7b656235561baf43c4d9894ffd498f0d",
2693"d88df2e1d8d02ba7957fee18949be935e9b28b4e6ff842a020255a5a8e1d517a",
2694"4df39c13b5a53ee6cc628f0f6aa833c4263cb19e94790fc9f9d9cb7e701d781d",
2695"6c48a7564f72c814bb855604f64387a88a5cc0489f26399b1e646dc4d93ab642",
2696"75d6d4dd5bbcccc2c881ee126812a34712e7be5f7bcb4111751aeaabdfd7b23d",
2697 ]
2698 ];
2699
2700 #[test]
2701 fn encode_decode() {
2702 for i in 0..KAT_DECODE_OK.len() {
2703 let buf = hex::decode(KAT_DECODE_OK[i]).unwrap();
2704 let Q = Point::decode(&buf).unwrap();
2705 assert!(Q.encode()[..] == buf);
2706 }
2707 for i in 0..KAT_DECODE_BAD.len() {
2708 let buf = hex::decode(KAT_DECODE_BAD[i]).unwrap();
2709 assert!(Point::decode(&buf).is_none());
2710 }
2711 }
2712
2713 #[test]
2714 fn base_arith() {
2715 for i in 0..KAT_ADD.len() {
2716 let buf1 = hex::decode(KAT_ADD[i][0]).unwrap();
2717 let buf2 = hex::decode(KAT_ADD[i][1]).unwrap();
2718 let buf3 = hex::decode(KAT_ADD[i][2]).unwrap();
2719 let buf4 = hex::decode(KAT_ADD[i][3]).unwrap();
2720 let buf5 = hex::decode(KAT_ADD[i][4]).unwrap();
2721 let buf6 = hex::decode(KAT_ADD[i][5]).unwrap();
2722 let P1 = Point::decode(&buf1).unwrap();
2723 let P2 = Point::decode(&buf2).unwrap();
2724 let P3 = Point::decode(&buf3).unwrap();
2725 let P4 = Point::decode(&buf4).unwrap();
2726 let P5 = Point::decode(&buf5).unwrap();
2727 let P6 = Point::decode(&buf6).unwrap();
2728 assert!(P1.equals(P1) == 0xFFFFFFFF);
2729 assert!(P2.equals(P2) == 0xFFFFFFFF);
2730 assert!(P3.equals(P3) == 0xFFFFFFFF);
2731 assert!(P4.equals(P4) == 0xFFFFFFFF);
2732 assert!(P5.equals(P5) == 0xFFFFFFFF);
2733 assert!(P6.equals(P6) == 0xFFFFFFFF);
2734 assert!(P1.equals(P2) == 0x00000000);
2735 assert!(P1.equals(P3) == 0x00000000);
2736 assert!(P1.equals(P4) == 0x00000000);
2737 assert!(P1.equals(P5) == 0x00000000);
2738 assert!(P1.equals(P6) == 0x00000000);
2739 let Q3 = P1 + P2;
2740 assert!(Q3.equals(P3) != 0);
2741 assert!(Q3.encode()[..] == buf3);
2742 let Q4 = P1.double();
2743 assert!(Q4.equals(P4) != 0);
2744 assert!(Q4.encode()[..] == buf4);
2745 let R4 = P1 + P1;
2746 assert!(R4.equals(P4) != 0);
2747 assert!(R4.equals(Q4) != 0);
2748 assert!(R4.encode()[..] == buf4);
2749 let Q5 = P4 + P2;
2750 assert!(Q5.equals(P5) != 0);
2751 assert!(Q5.encode()[..] == buf5);
2752 let R5 = Q4 + P2;
2753 assert!(R5.equals(P5) != 0);
2754 assert!(R5.equals(Q5) != 0);
2755 assert!(R5.encode()[..] == buf5);
2756 let S5 = P1 + Q3;
2757 assert!(S5.equals(P5) != 0);
2758 assert!(S5.equals(Q5) != 0);
2759 assert!(S5.equals(R5) != 0);
2760 assert!(S5.encode()[..] == buf5);
2761 let Q6 = Q3.double();
2762 assert!(Q6.equals(P6) != 0);
2763 assert!(Q6.encode()[..] == buf6);
2764 let R6 = Q4 + P2.double();
2765 assert!(R6.equals(P6) != 0);
2766 assert!(R6.equals(Q6) != 0);
2767 assert!(R6.encode()[..] == buf6);
2768 let S6 = R5 + P2;
2769 assert!(S6.equals(P6) != 0);
2770 assert!(S6.equals(Q6) != 0);
2771 assert!(S6.equals(R6) != 0);
2772 assert!(S6.encode()[..] == buf6);
2773
2774 let mut T = Q6;
2775 for j in 0..10 {
2776 let S = R6.xdouble(j as u32);
2777 assert!(T.equals(S) != 0);
2778 assert!(T.encode() == S.encode());
2779 T = T.double();
2780 }
2781
2782 assert!((R6 + Point::NEUTRAL).encode()[..] == buf6);
2783 }
2784 }
2785
2786 #[test]
2787 fn mulgen() {
2788 let sbuf = hex::decode("938b4583a72eb5382f3a2fa2ce57c3a4e5de0bbf30042ef0a86e36f4b8600d14").unwrap();
2789 let (s, ok) = Scalar::decode32(&sbuf);
2790 assert!(ok == 0xFFFFFFFF);
2791 let rbuf = hex::decode("02907f5f9930501d9fb42fd62653a149e2155d7ef8ff3dc82deb8783b5ead353").unwrap();
2792 let R = Point::decode(&rbuf).unwrap();
2793 let P = Point::BASE * s;
2794 assert!(P.equals(R) == 0xFFFFFFFF);
2795 assert!(P.encode()[..] == rbuf);
2796 let Q = Point::mulgen(&s);
2797 assert!(Q.equals(R) == 0xFFFFFFFF);
2798 assert!(Q.encode()[..] == rbuf);
2799 }
2800
2801 #[test]
2802 fn split_mu() {
2803
2804 const MU: Scalar = Scalar::w64be(
2805 0x3304A73398CAEADB, 0x37382C8933C3F6D9,
2806 0xB153382D88E2CF39, 0x9C46EF0C23DF370D);
2807
2808 let mut sh = Sha256::new();
2809 for i in 0..100 {
2810 sh.update((i as u64).to_le_bytes());
2811 let v = sh.finalize_reset();
2812 let k = Scalar::decode_reduce(&v);
2813 let (n0, s0, n1, s1) = Point::split_mu(&k);
2814 let mut k0 = Scalar::from_u128(n0);
2815 k0.set_cond(&-k0, s0);
2816 let mut k1 = Scalar::from_u128(n1);
2817 k1.set_cond(&-k1, s1);
2818 assert!(k.equals(k0 + MU * k1) == 0xFFFFFFFF);
2819 }
2820 }
2821
2822 #[test]
2823 fn mul() {
2824 let mut sh = Sha256::new();
2825 for i in 0..20 {
2826 sh.update(((2 * i + 0) as u64).to_le_bytes());
2828 let v1 = sh.finalize_reset();
2829 sh.update(((2 * i + 1) as u64).to_le_bytes());
2830 let v2 = sh.finalize_reset();
2831
2832 let s1 = Scalar::decode_reduce(&v1);
2833 let s2 = Scalar::decode_reduce(&v2);
2834 let s3 = s1 * s2;
2835 let P1 = Point::mulgen(&s1);
2836 let Q1 = s1 * Point::BASE;
2837 assert!(P1.equals(Q1) == 0xFFFFFFFF);
2838 let P2 = Point::mulgen(&s3);
2839 let Q2 = s2 * Q1;
2840 assert!(P2.equals(Q2) == 0xFFFFFFFF);
2841 }
2842
2843 let mut T = Point::BASE.xdouble(120);
2844 assert!(T.encode()[..] == hex::decode("40bb85fb77b5bc0729686725ff9a89c749d64471d4e994931e834d6972fb652e").unwrap());
2845 for _ in 0..1000 {
2846 let n = Scalar::decode_reduce(&T.encode());
2847 T *= n;
2848 }
2849 assert!(T.encode()[..] == hex::decode("d3c47ce3a042da4f3da80852a8c5bbbda0dcdf4b1ad51c5da9f746e0dc5e5760").unwrap());
2850 }
2851
2852 #[test]
2853 fn mul_add_mulgen() {
2854 let mut sh = Sha256::new();
2855 for i in 0..20 {
2856 sh.update(((3 * i + 0) as u64).to_le_bytes());
2858 let v1 = sh.finalize_reset();
2859 sh.update(((3 * i + 1) as u64).to_le_bytes());
2860 let v2 = sh.finalize_reset();
2861 sh.update(((3 * i + 2) as u64).to_le_bytes());
2862 let v3 = sh.finalize_reset();
2863 let A = Point::mulgen(&Scalar::decode_reduce(&v1));
2864 let u = Scalar::decode_reduce(&v2);
2865 let v = Scalar::decode_reduce(&v3);
2866
2867 let R1 = u * A + Point::mulgen(&v);
2870 let R2 = A.mul_add_mulgen_vartime(&u, &v);
2871 assert!(R1.equals(R2) == 0xFFFFFFFF);
2872 }
2873 }
2874
2875 static KAT_MAP_TO_CURVE: [[&str; 2]; 40] = [
2876 [
2878"0000000000000000000000000000000000000000000000000000000000000000",
2879"0000000000000000000000000000000000000000000000000000000000000000",
2880 ], [
2881"723a35545d0a7a28943ca04c4b617ed4dcbbb7849eea0a44559756bf8d45d680",
2882"f3cba9554c4c06272bfe3f51261c7cb3678c527495137618530c74da2a43414d",
2883 ], [
2884"0e285c3b0dd3bc06de5f84508a82548f95abea361cd851473572343d5f1b2c41",
2885"9c87035855c71ba2691011b35e0dca62a2bc707a532ee80dc64c40e80e828e1b",
2886 ], [
2887"b09e6ff542a126b128d0c959a7dddb74defddba36804d37a8ff618df0090d443",
2888"54d75a829df2b19a2a4d91e700ad918bc02bb6f22107b4983bc1e05ff3190d41",
2889 ], [
2890"6752e27a0ad5286a189940663c8703891d794d225c70a43733fc7121a9888026",
2891"1530d881b5d802744c6994b4244b9cf21da2701d6a0a7a8ef0e29b9f4ff63f74",
2892 ], [
2893"1f32b5d73288138bb2bf2366bd22e454ddfd8c48feecfbc33ef840c04e45af27",
2894"a6dfea8c3442c5ba1fc653f196215590b025f081a538ca51d72869e7ad1ef343",
2895 ], [
2896"7bb73f7b85dbf165fb2c185bea9bab794730ada7ac12787785555e3b628325f2",
2897"ac41b778c468b8c939c251a03dec03c2a49cb82d672a800dec8eee5a237b9958",
2898 ], [
2899"73689d8361ffa3d866db43f4f07cdd3cc40dcfeb4c87a7bcd0707caeb8b87d7c",
2900"4e7960431a67ea2498e8b5bcb515c56de6304a1f486144961ac30b242a16cd33",
2901 ], [
2902"e69f4b22d05dc7d00763063fd29c4dec1d3250f10d245087549260f257752f9a",
2903"73f89a33902e496c5d61ca609fcbe0b385b5ef0357420f23809fd60d703af603",
2904 ], [
2905"fc911bbdadd2ae6010b5fdff3a236eea7270f63977c6f2d7cb7e404131941e17",
2906"b40efdd01d6b1678345352d17a93596873cba4f861f7febbc75dc729b0b3a967",
2907 ], [
2908"5cf1c3c547c6b6c35a6f1e0e18836ba9495a1340eb650795a3c0353441988e49",
2909"8319ff7a59791640b8d811ad0903907e4ad092505dc4f8ffa6431cd6928df844",
2910 ], [
2911"aa147bc7eb3659dfa327f0af067ef8ebf233e8b95633a26f97da175372a81501",
2912"9d3e1587230c097098229a28487ffbbb2ac7007ebefe3d2be631b9925c9f2901",
2913 ], [
2914"512729297f0cd62a02a7ca546ab8666785aa63a51d0e2edb1d1cc5e760793907",
2915"e787a112ac61bc5ce399565ae6c37225a424834c87d2a91dfe345a01f688034e",
2916 ], [
2917"25195837a7a1fe5585a9fd125809fd6caad0217d01cc0707bc2591f0dd406932",
2918"756e0e09b3b485ab4c6b876b4be36e3ae2d57ecb9afdf317ade3f2bd21ee3507",
2919 ], [
2920"5e78ba1b1d0f5c006b5c0e740d8f37b3f3332c51aaa876debd169d629d313d8f",
2921"52595e618a146ee56e11d3a2aa12a7746c57dd8bab13f56f122fb5b425cbfe68",
2922 ], [
2923"abd9fbee5625b2b9527e6fc007fa8e5166fc4c3b107486fedf27ee9a54b6fd60",
2924"26a742ac2bc65720790960915af5652952356d5ee84cf61da72f67a064ce967e",
2925 ], [
2926"c25163787f737f1e016a67d4dbad8cbe4331787cc65f23d7383f93888b2b9d52",
2927"3a214343560cee77d9065f6a1f3aecf523e3caec815c39ce83c70441dc03cb3e",
2928 ], [
2929"39f5603a06d2958dd485c9862aedf0bca0e71dee6fb1509c1fc51bd457fd19ff",
2930"7ea9f6b375a5e4877aec88c0a151d6e7f0e17bf890d63a3ee798d346f7df305e",
2931 ], [
2932"274822b4713f0d03cde0410fc70545ee608aabd2adbd671495e1737b5f4a0ba1",
2933"6d2c6af450083f10abb853449e3a02ed946b4eaeab83b24d031c4a66d66c975b",
2934 ], [
2935"320ada54aff47138c3a85852524536b4f8817226dec94d9b48ad3b0bdf9677ce",
2936"352a4595e6144cc3ebdc5e7ba9d2d5a70f52f4f07d0580cca42304436b815642",
2937 ], [
2938"2b626f86360f5e1b9f8236e3990d5594b477bc52e0465777be80cb8b021bf8b1",
2939"e1b3b53403a843269201e043a73916bd0be4577bfd6b78fb941437f42ea4dd7a",
2940 ], [
2941"e0549613fd58b01c1e32404c83d390c6acbc1cd69fdde89bb0f4074723f734ad",
2942"b4a49c5529ae2f3ad3a7796f95a00ead0969243558f3b6ff6a359fc21191490f",
2943 ], [
2944"6b1d7b15aaf41ac151923d58a4c8c027566cec8220d98cd4501309daa259d605",
2945"1451d6ea3f3c93dedc3b3159c33c3c84c2c3766ee1d3ef96955914bbdf15f069",
2946 ], [
2947"c49b1777775059bbfa05fd83ec6d14d46cbef91fa3e9fe9a2e07885d926947d5",
2948"f9d09fae607c55af5a4dbe073f1cc19f034f8ac1106ed9279c0bb766896a5f5f",
2949 ], [
2950"134c2597128a8867f90dcfd1c33f3ffc57638534d0e3491cc43749afe7be5fed",
2951"ab2473703c6f3b602539b9a6616e8e5dfabaaccf39a4a2c021423e1f2b292104",
2952 ], [
2953"1bf00cc0ca59dedccac2da93b5a3fec9ff65acd0ce92dbe13fb53d6fb688833b",
2954"cd452b2bd9cb2128e29b37627865a0becd5cc85f7fd7e5dc61287d33698a7158",
2955 ], [
2956"0ba02b6a7ce2e2556739299745ea20ffd4df8556b983bb71ddf4d2cbd8aac77e",
2957"b934730eaeb0851d5d4db5d2428d485e029103b88c68e6fc9c24af636f86ba23",
2958 ], [
2959"ef50a39fdb8f88b94f98877cdf97800dbdd3e95f93415b924d985c846e4a5754",
2960"e1906955c28b5034e2dbffc4b9429b9540a7441a094fa453bc97cc4fae500a4a",
2961 ], [
2962"ea5eea9023cd657d1bab53b4a709e961f03672d975154cb7f0b04191c666fd3a",
2963"ed99fd5f5344c641326ab44a1670e1ef7af9cbf10ae4d948556fee4ab0e9260a",
2964 ], [
2965"f1d6ca77d1ad6b53db5f55f97628879e6dbe819f355d97fa3077d899e98cb6ae",
2966"1d348e1c2c68c9ecf1494db397547018c4417268e3218a9cdf8bb30e6444fb58",
2967 ], [
2968"5793d8a97e650da4e9ca4540eb52fa565dab309eb0e9bafb8659f7d47098b007",
2969"3b9c9c2623e23be1b99c3169d7b08fb73ca892962233a01cfe1b86e2d0fd9903",
2970 ], [
2971"0712f766c5f6db6ccd926d92bec2d6a35391ccbced21661acc6ec57d6757d5a0",
2972"c49595a2bce3a434d8701ce7bfd8d5241912bb032ac250afe152122e24fc2865",
2973 ], [
2974"ad80519e5b13da5e05e0652435d944656a28af7734bbd05428cdd8b99609e9d1",
2975"fa104d70219c53df9df3dc2370d6a0ace0806068e16ee803e3e2695110396614",
2976 ], [
2977"c909546acd3ff1d750ae50b886dc83d2e9034a3972d5de3891825ae41b60afef",
2978"ccb7ce67b471335891b82a1301d7e98fe8c30d4972f5d7b1b22b418f2eb1253e",
2979 ], [
2980"abafb6538877ab38cb909307eb11ead4e11ac2054110f174abec506276c30559",
2981"b5e61c01ce7f0294e7289cedb19c973ef0ee600285bc3626ec02e40c1293f565",
2982 ], [
2983"c266be61b0724dad07a2417c78710767baebf168e71984ab084f808528a3fd36",
2984"d1a0eb95a8681eb0bf72cc7426e708cbe0acc4d1fac64a0f0b0e70841894df08",
2985 ], [
2986"ec7ac0c0e996296d3e5c19dc7b14fb3b140cecdfeb7909c8afbc7441b1a25851",
2987"36cdb3ed03e9f17378f36ce5b851c86f31b594204e42873329def6991548484c",
2988 ], [
2989"4b6e7b392d706eeb04c76e552d0ebca92b9155770c169dc40b93fa9b6568c0bc",
2990"451bafd5654f097900ad0bc3f860937284187fbfdaeb0ec5a2da083c3d585030",
2991 ], [
2992"9c31cf29b6fb775ff36abfba52a800ca75ca5ae9ec70e6e334e72af0cd4f6d44",
2993"13b10053406de3298cbb83ff7aec300dc66f3b381edf51220a4fe59879daca0a",
2994 ], [
2995"f1969458ac27c6dd5bbafb01fe0b572b7a2f099737f67289f6124134f2e35c40",
2996"08c2bd77a2793ae156c89043a0d41a5dff7c3cc33fee347e7f4a987b0ad0c44e",
2997 ]
2998 ];
2999
3000 #[test]
3001 fn map_to_curve() {
3002 for i in 0..KAT_MAP_TO_CURVE.len() {
3003 let buf1 = hex::decode(KAT_MAP_TO_CURVE[i][0]).unwrap();
3004 let buf2 = hex::decode(KAT_MAP_TO_CURVE[i][1]).unwrap();
3005 let f = GF255e::decode_reduce(&buf1);
3006 let Q = Point::map_to_curve(&f);
3007 assert!(Q.encode()[..] == buf2);
3008 }
3009 }
3010
3011 static KAT_HASH1: [&str; 100] = [
3012 "ea5af1b80af04ff3efee57f0a97cdee34686ab6038c28c09fec9c95b57f7b454",
3015"061cad337330c4f365092f07dab0c05e715e50897d288843ecacd349d4bf9b14",
3016"1f77e336d1810d3747830fe1c6533f69f65ff4045049308941f6acb05111560e",
3017"04b9fd9d18bdc3a601194037c435e48a23304f2da8885aadfd9343f812ac8633",
3018"372562db7b536a2fd960ba3521b93e8cf8303ff73a37b261cfdd5f5121689e16",
3019"1c1fbed5c4f710076cc550d3486c838f510670876b41097b96e64f3a5c29d33a",
3020"de3731edfea76b0c10f0bd5a2901beb95b8b509e0fd59d5311fa6e5681d76817",
3021"078dfea0b1e8cad647af96e30a031458b18e24130553ea7424c6ffec3dd2cb78",
3022"1f4b6bc8a64c88de144f4bc009aaad628d908df81995356ee2a4d85a91328e10",
3023"66e58ad880b5ce8b17d6b5fd4470845d48bbe3973e0ba3b244a0054cda188c23",
3024"69931df9a6e6d5872742aee633518373d5f38529cdcf182494921b5ad0d0d05c",
3025"241ffca335f346f30cdf6ccabe87dde0545c30dbfb270894837ad330315ee503",
3026"ec57e395ee1287aac0bed4fee327081a8c0b63c69bdb6fd300c721bc0302a90f",
3027"86156fb75fc6c53dbbcd40c6b310fbd1f436d660c3badb2ca54123ecd3f46c31",
3028"a2a88863d1067100d46aa77f6bac68af5c9977a303ad4a4851be274b4e704277",
3029"64c1d9f08912dedb5c10ed972b078f9bd0eb335d232b98c7adfaee8ac02cba27",
3030"75f37a183101ed3d09178fe8d4dfa88ac446a8bd38e251db25657cfa49161659",
3031"8a5111b149a22a26e8771cbc08bbfaccd37136750400eeebb1cb2f5f4236f93a",
3032"e2d67210a9d4ade9209b8bab4aae5d23d6003f1f4d2c86902ea2ff78f338e35b",
3033"1d1494b9eff0669514d9a5b95d1d93e2974c936fe6a5f0891d8c0a8fb3703426",
3034"03407d01f2261f7ea11f060c11fa334caacf070091f316c60dee1ee9c9e32054",
3035"3325b4cd99b2b15a16dec5147c36c949c68bf0a11aed4af888381978ef7b231e",
3036"3d5c44bb387298de396b5ff2c21e7ea7df4388137e7d94b82614a7aff1fa110a",
3037"bbc9df0d359f305629182a462f59760cab2716194b0ede35cef1b55581985a6f",
3038"cccbc6c821b2666dc674306c777d10e0ea45c0f8bcd1c80ca3b97e7e0635f744",
3039"50893c06248ce299fcb07a8e9a69bec1e37a3365858ba5820c8812879ec6f647",
3040"2371e553cc971af5b27c51dbf3d97bd2c40f7440f9de8f0834c86e09f643973b",
3041"380cff51d54f153e50bc6bb3c102b7aa293166ed8ed90cf4cf28446311bb7f39",
3042"6e04d42b1dc364c0fed689ebcae48a36d6cd3a227b50d30c489d63bbdaa28826",
3043"199ef6706a42d10eeda4add04cb6ea2a7ccd818fd00ac34985e98522c7d0fb66",
3044"83fcb078a23b92d0a9918f36d81ab87b7efc4a0e3c4007d195da59c3af1be228",
3045"31c4a7af764846813587fb7d02482d797c85f8d8e549ab414b60b30a18126475",
3046"fe99a252275a49b60e79583f9b442eff20fa5dee990e1942cf130db58c918b55",
3047"87d2ef19a8ab402aa2f8afb5f5614062522568aff3fdc0554d2ae17ecb1b7f28",
3048"7b80858594e29abc534d1deebecd27fb5f190b8099de8f85fa571cf538c5a533",
3049"50ac79e72d05ab2eb101740ecb3d514b09a23e30dce2737371d791ad5d331470",
3050"8bcec431440081c08ccc81889a79607af663a3f052987b319ae75e44ffbdbd4d",
3051"a4fbb6a452282e68a7c2abbae31950bc5a5a6b5831cf15290b8381689b023c01",
3052"39d26112e82b84a4263bf6c6d35f8c1ad3bbbc522149edb6de29caa6b6cc5c3b",
3053"8ac6c95be88a132dba4b235b0cdd78b2838e47365dbca0fd6c597db80607cb00",
3054"a3be23f26ac3e37a86242a3df61b655e1a5e5f67888336aaf105ef4ea153a669",
3055"9c3d9821bbd84521082387a9593605109434b8548497096147f17750eabdc778",
3056"fe375d92eafdea8f3a8885dc014022ddc5806a52081b4a6cffd477a6d45c8f2c",
3057"1ffada1e8589c3a22c4667f00cc494d3638a1021bd37476ba18e73fcfad2297a",
3058"b627268344164762b879c97c2af7b8f1e39ae1b090c96c4c2c76ee4da6ad7111",
3059"1f983d4c111ffea3dbde3c272456d37cdd5e26f579d10c49ce51d570ccdfc30d",
3060"187ae3f089466e208b5a92cd238f684c393ca7c0401de03a8436f20e36451048",
3061"2c56ad19e29ca45bb1493eb292aa50e3dcc1afac9e9b4a227a411d86123db73b",
3062"29709e5b4d73f76f98ce756f3546be0b405a28741027cdf01af67b3c2f58622e",
3063"134654b17d79fee88c695b868e806f6e6c8f8a61d3b3e3de7d3fc2e031a1482a",
3064"4c607b8036775f91d839d1886149986f9b4cd0fb2662731bef3fca0ae93fda2f",
3065"f2712f11d3728449fa13604a998d2a42e126f997dfe0241ef76ddb0f613aa722",
3066"9c1295bd24147d4f65a0904c37f0df6011513b98eb2242d9f96d7dcb2909c861",
3067"499e4b77146070f43d756d2972ac4fe0bb9ecb4ea31e2661851c4fa753261603",
3068"f8a7d6f2e46ceb766b082cd71ee042a2b7c9e0dc34b72a28eddb19449e9ea748",
3069"46c8b88b6b297826dbc60173861174e1335945a06346132a387e72fbfcbf0429",
3070"12a91c2cd8c98850f2cf152e6c7675072d40d82079b740afc73470d5083b714f",
3071"9a3ff5663fc4984d4b2d574e005463b4ea6946293dfaf0b9e7fa20b333dee13c",
3072"99ecacdc83164feefe463d9a0f2c664a1d3df5708bef679b3ab18c1766adf43a",
3073"4d79d4f75b6420b4d8c655f9edf9cd6e3e35f31caba239bcc77ba54260632114",
3074"27e076ee9a2764557144d3fd582392b9ac3d62555465ffd62c0f5b50e2ca4e2b",
3075"a95cbdd42ed59b40056a7d8a0dca6bfb182c89b7470d8ef37e0ee05818812756",
3076"fb73526b9a92d0ac9e99fc5dfe1c0d8b7d9cc76dc5f83ddee9b1ffa77d4a4675",
3077"64816f3e0d8a2927fa436610a56cbc98efa03a94cb76035f4500c4ee72d2b511",
3078"a9814706e9e9b7466b940707fbd01efbf17cb0a3ce6883f477eccdfc6cc5bf0e",
3079"1f249011e0547fd832d01d544ecce48bf2d6aae19a554828a55463043d254b5f",
3080"12d756781f3678803f8172ec76eee3ea31bbf9d4a0007689af696dfc93080250",
3081"a76136861eec114a12ec54e2c456ba7b7c15ca7f2789d0999e84d23eda03ea15",
3082"7c340a48954bd74952c4e7ce02f41136d49c62a173311f15d800523acbfcf914",
3083"4ccdfc53c12c6fd1f411ab0d4dcb199e3b233233f41e363ae95b70ef6977d049",
3084"a0c81c623907fb5d0b622aa130eb67135dea275dcf0dbbeb6cbff08215eb4908",
3085"d5d1e3b30c3a371da222ec51d65bd5336c5065c9c16e9d9133b00737c6305c48",
3086"525091d72c384b01c91c26a5da768fd68b6b36cc229ee8891385d4403915eb6c",
3087"01a7d44c8f874f71e7a70e1b55f2fc8d71a99f459ef8ae70d34d66a8d71ea30e",
3088"d6dda270e11589af3b1c705b9251900dd3b81f9e554956b8eb3a7a4ae916e36d",
3089"1aeddb680087fb91167eb61957750d57451ed71f84e07c016f4ca3cb8e583152",
3090"6d56a726a1cc5c7ca4ad3ea3bc5d41706226ffacce94ab0a85f31954dc41e753",
3091"af3ad2a1cedb9dffa4f69409010282f0300ba04ca88ea5ef87317d83d3010828",
3092"bfb4780461d488cc2cfc3b8f1ebec04d7fdeee95cf59e07fadd2bb9184f5f556",
3093"a96ab0695d4c2cff8f41a8ab7868c15b0b5e70577c8c56627021e9982dbea84f",
3094"6711a9f24b4ff403bd1ce746537e58a3c0c45977a9eedd555407ce2751d0ce27",
3095"3cc85d0baf0b26a256a720ce3cbb91b311e426bf716473f3859ece8a36f8fb6c",
3096"1e5cf78356dcff1f8fe58ebcfc1e90292f6142e054421a774a887cbc336bdd35",
3097"a00f56894911407c4512024fd759f0718f3a3d0655d9c9852a843012a344087d",
3098"59797550857639dd58fa3f66c31bd72a952afde111003978dd2569635cf6540f",
3099"feef6d815d0cbb61c91a12d73e24d4351882792468af06862daf10b79ce42907",
3100"bc98b35e139c8f719988cbf6e5136354f456574b254ebc493a71230431508248",
3101"72e5540c1a098b440965b225a236ab602294de18ba2e4c352a2b10e04f852c12",
3102"927538bc57870541c7de1e79c84c83b7ee05dc7ebd644492412596be3c5c1726",
3103"f17a2db81a86b89d5bfa43e621e22beac92b3d926aaf384be9dd1ee708534c30",
3104"187f0bf6ab3371698442799b5e735c9e641b0315a4ed030d7c40726991929b00",
3105"547462c858e44eb8017175d3e0be3750393d055385ea78b0466dcd8b258bf11f",
3106"f39ad973a6c75065ca09c035b6348c1cd5aab7d33a44d5981e1dc18a162b8d16",
3107"6bfa4dd66e1f9095f2c6556f4b5063e84a3aba74abf31f85c95ac38e38169045",
3108"ae180573571bd83f2ca4a9b950083da0e0600caedf3026cd84ecc5c5d4a83c1f",
3109"0b57aa0c4911f3126927481df5c8d9bba655873ae155db0278b56dc59904b44a",
3110"250201733273378d852141e5daef96491d6e4a37566515a629052ae09256cf3b",
3111"60a388ccc29d8b053ba1ab8f69145f9fdfc482f10d15ce74426ccf6cf1ebb93d",
3112"455b14a130fbb2541c05aedd8769fde56775e6cad121bbc04ca303835e8c703d",
3113"b6f338df7475aeff91a409db0b55ef806752e2cc17c8c4147514f3d3d70f2827",
3114 ];
3115
3116 static KAT_HASH2: [&str; 10] = [
3117 "bf7e5b0c9466d872b546438e856fc2ef3d2cf2eb11403cbae8dd7422674d0517",
3120"57008d73669f292b351ee7ccf0981e63fc678535822b2d9c90df67d855b31262",
3121"f59238b5b070edb198cb709605a162b9056391304d9fcea64605543a58357d66",
3122"2f763b1ace8ce6f0a032dc593ff95810314691433eadd6ff663f0378a4589d68",
3123"78700053b6e785a077dfe6f386d525ff51579e321062c1e08164ba0fa3ea4e65",
3124"7bdfb71b647d61b47eb46b996f26930f80f36a4959729b42cf2b62c7e51e2e57",
3125"2a63f2b4b05943bd18cac172f2915c4ae801320d257b354c72fff1de469f2a2f",
3126"73f5c0b5229d9c6e0dbc4578d20db00efe718b3e6a975a1627fec75206f18736",
3127"7d671c6dd8d448d11c31216477adc91ad5ac189946cb61534e7f615b57c16716",
3128"ea2e3c8084d87bff62973a4e02896f42787b247416477d1a84323627e30e3447",
3129 ];
3130
3131 #[test]
3132 fn hash_to_curve() {
3133 let mut data = [0u8; 100];
3134 for i in 0..data.len() {
3135 data[i] = i as u8;
3136 }
3137 for i in 0..KAT_HASH1.len() {
3138 let Q = Point::hash_to_curve("", &data[0..i]);
3139 let out = hex::decode(KAT_HASH1[i]).unwrap();
3140 assert!(Q.encode()[..] == out);
3141 }
3142
3143 for i in 0..KAT_HASH2.len() {
3144 let mut sh = Blake2s256::new();
3145 sh.update(&[i as u8]);
3146 let data = sh.finalize();
3147 let Q = Point::hash_to_curve(Point::HASHNAME_BLAKE2S, &data);
3148 let out = hex::decode(KAT_HASH2[i]).unwrap();
3149 assert!(Q.encode()[..] == out);
3150 }
3151 }
3152
3153 static KAT_SIGN: [[&str; 5]; 20] = [
3154 [
3161"b0c4721e9e9b534aacf9700b127be576bcf8506ad19819f809626296bf218038",
3162"1b9327a8d6c8e9445b41ba3fc4125521611bfabfb404668a78a13972c2ce7232",
3163"",
3164"ec14004660d4b02da3b86b1bc5afa7b2e4827f0ee1c9a25472a2bcac521bc231",
3165"fcb4f45ad552974fe6273a5c2e44caf83ea4712046dde4b60fa64dbaa26477a19f91acd5a648d0348c2b7f2d19034e07",
3166 ], [
3167"46e0d7d2cf8801383489a33d7d0bfc7f0ee8169f219040dd44b01e733aa6a625",
3168"54200642cb45da3d6deaea3243459c510f204f14f7952ff9f29ffcf3ac0ea020",
3169"97",
3170"bd1a4655b90f873c53fe908f4109bb8dfcd9096312b447a6434af3c35304b7d1",
3171"03ea3b335fdf8436a3ddd0417b89a83ab939620efb5f0208698a0062556e1c25247f699388d8b66f58ae99efec6d812a",
3172 ], [
3173"6b7edc4accfa2e5ead52447fa1bba0878d5a799f7744644eac43a38094fef919",
3174"eba8a65eebbca7960de2ee4c60ef7745eb1284f324c5bc2c762d74ed2f95683a",
3175"aef7",
3176"6230441be7f030f180e81dc44502b24ed94260490d140ae738bb80746051651e",
3177"80fcf39eeb55cc737eb711644725cbe8f5e69f538e59d9acc6ea7ef1f5d497989d27815efb49774f5c0b34f3f60b8507",
3178 ], [
3179"899f693d23f9bb913fd46df6b5959f0536efc1d4516e89decb4f1227d07e0b36",
3180"38ba0f050fa355290f7fa46620b95e648271eedbde3f17f393c7a914de313c4b",
3181"ea57fb",
3182"e877b70f8c12aff466a4dbd6284bd0c6ad7cf66376bdad599f22145f8277bc52",
3183"5b62b6e459bed4133e78002aa9f01cd425cd3bf8f6c3c8618cef38b61ee9954108f7e4df635b6c8f7b7b51eb4be5d805",
3184 ], [
3185"88b8143ff1bd263488da0de8756235e64a993a02d3821cdc920bae07d765683d",
3186"d92d7d971129858b84f25c785e857e5210f8d4d67c5eeb015d89ac20fd72191e",
3187"842d1ac7",
3188"b4c94e55cc622b96b49fcfe6b913ce3a06050b7e9b26fe840389145088d59502",
3189"7188f8faacea2d6e306a466868e439cf8b2cb0d629aefe429bb403d8ef6b01b4e5c3edd651f7e75ef3ecff9025163e22",
3190 ], [
3191"3055cc4730d43086f1de2de3218fe523e5023b90aa350647ac66cc6fc8c0b909",
3192"f45d1721efa8f19ad4951b307215fd0d1f2d2c88b367f1e8de4594884c913c2f",
3193"159c3e27b1",
3194"a7ad895209663ae35bfb3fb0e44cc83616bb876d14608e5b09c20d19f57839d4",
3195"cdbe66382372b0bde4cf0aeb161222adcd3e9f73831a9c2992b7ab056b265f3618bc04963d40f8639a95f7bf2b3d3a11",
3196 ], [
3197"86d83fd4eacfc4183b434d4b53774e7b96d3b90e60be4825d4f11356d6406802",
3198"79f5b593358afe4eeab86b8ce03ddb0948f557a19c4f1518c9f41786304a5716",
3199"b07511b1ea1f",
3200"0bd1a3ff8506a918b8bd733c31cec084927241dda2ede63f719a6758872c94ab",
3201"7a4b305ec8aa070908383db3bab19fca96634a10a144bb1b0a411073e2ec67b09ca34561f0809662bb49823391f43836",
3202 ], [
3203"1a2bb01bd52783d80234995836e324576f379a1eafc641082b789551e5e61e3b",
3204"c605d076744aa10cd8b210d8eb72a10d30d4e7bf90e1dc66a9a95bd4f7e35a24",
3205"ffc13f192d2bcd",
3206"f328909fd158f3541c2da54b758ccf750bfe4afa717b00094fd30e7fd69661e3",
3207"07b120787a23c7949d5af517e022fd9edd98c2c66cb49ec980c58a36c88b09581455b6314d59eefc030281c67d40dc1d",
3208 ], [
3209"6da52d7184e46888cf28f426a55d4959b4e0b8742989955511221f5fd11ba11f",
3210"357b8ce82ab53b84c00f57bad4c7cac2a9031cda35b739b93b9e9816e0196e46",
3211"9bdc3225b951dcb7",
3212"7de5f8c2c35149558c0a6bef84596669100f6350f07aefed58120d6dc3531231",
3213"8c2f8691e8e3d571ddf4c9ab4031ae35b6ed58efcdc0c7094392d33ed98a6b22fdb5a63ef2975c5ee47a8459b7f51706",
3214 ], [
3215"5d8c7af067d55e821a02d897defc1e1ec7b958a35ef88ff5d6e6ccbb46ea1425",
3216"b81b33ce13b84b7e16ddbdfea36e60d41f2b8d5296dcdf37e6f94855fc44d614",
3217"d7cdf50fa8f045a646",
3218"9fbcee44419bc19b97bb673d0055faa0aae1861f44c682345fb3494e610e26da",
3219"404225638891273ea82119a46d6ee821b62e63a736e1110678e908f16906a199730ff39f1c390277a2605ff3cb0b3303",
3220 ], [
3221"2d6d24dc143d8ee3edee22588e6dce7b182a99d16c71626cfaee3545fbf69119",
3222"beec5d4ac050aee9d8cf762e9344492117713c4ec66a5f4bbe89fc119d3cea47",
3223"3106a8fd984b8b531081",
3224"4ca14993a888660c624f816db0c893bfac69d5ddf04cced60333d94ac1b0e2f5",
3225"6454711333f86f606a97eb1260a2d14eed0d6d378c47fb64dedb0712a618387ea785668988f0e806e779417342aab704",
3226 ], [
3227"52138cbf38a8489588bf9df27424d1ae6aa558f4d14cb48d6db2e2acb8e6fc34",
3228"4be1272e9ce768cd66da0ae13db31e0d43df1141ac548d75550db5bb34c8b308",
3229"7018379cfee44be20b27c0",
3230"ed427029b6afbfe2a73c7a73605bfb47b4db8eadc940bddc103098a06d7b7daf",
3231"daa96d208afe11b333bf0c640ebe5356ecbe43ccc62d98a5d9862b35d6542054bda991ea83f562754bd2ed3e3dca640c",
3232 ], [
3233"41d050597273cef83ff9d472b755c97503ce591fd0bea4a95e342572be560317",
3234"b249e18d4cc019b65ebac2725c8f9d2215916ea4abad71c6f8ed7cf2c734ad4a",
3235"2cc3a1dacfe47cbfbe6bf9a1",
3236"2b083962ac0f0d9421bffdf9377f06e7152c3677e911029b08f9d40688c8aaa8",
3237"5e3caec500d71a35db64e477dd3c802de1bfbabb57b0e4b06604f86b71e43458e8ba26e517c79ac04d7fe9cac21d1010",
3238 ], [
3239"65ca33e7427779d99685cc79290352e7a50e2e00c8e56cbfa8113c84d5ad5013",
3240"280e5ac034faf3e5e77c4096a81cd2f5158a153fb6990c52170ddd9cada3e954",
3241"d25216525cc3e3e5b1d2a8f0ed",
3242"cf44d2ca3441b9089e99a00eb90fe161bc994990469a46b488e08711a7ba8d9e",
3243"dd3550665d38232217e82fdf9f6616e499e132cfba0b411ac899347023bbfaa846f22583b7cfb6ee1f68ae83a7c57023",
3244 ], [
3245"42997b627130ad187138ba99ea491919876c2ac11a7072f63134dc66198b4430",
3246"446ff1e2e8b1c3d88777619edaf906cd1a0e9d19183c352b025b897cbdb2fe0e",
3247"cc01f34688fe08b6390452072519",
3248"79d41d37434fa78c4cd3fb421c7caa26704df53c215adcc4f7807adde10c7438",
3249"2506dcf20f46b27e488855e8bcbcfb8ff9c21cbdd42dac379bf594d128b4a3aa2b987aa3f97594b66c58a3b95898b50c",
3250 ], [
3251"0b8a8838ab2eba7c1e6844bf99fd2c8643292fc6e4af5929607d06a4ef86271f",
3252"d84e000c6b08e19ac2c5be79ae814c9ab371d6947a2a943bc65861eb067f255e",
3253"6168bb30469723d4ad04f80e42103e",
3254"0756a67df9f84be0d319c4e8d324f3b77077f9322f9603f015df27f2804b17a2",
3255"d56d36d4f15f2b565c505e14001b97408d75e67c5ed5bedff00ddda06efaab6323fb22ff96c81bf737a07e114486c812",
3256 ], [
3257"f115a80e22a3c99fadf4c270f1c3ea44d8525469b1f6e79bd94e46857a74263a",
3258"910aeb2fb18804c5e6275302a2f873167f1ea749df6e3fd88feec6633cc9394e",
3259"c26c33d95cc9ecac0d6f2081e887e23b",
3260"86b36dde6d628b67332456b5d41d09737a057215f72f89094d071422e705b82e",
3261"5a060f9dbbde6d2c3ce85fffe8c9d28011517d7970efcbba6f89133508b92e9b94672ae9f7e252609aca1f6a0ca1bb05",
3262 ], [
3263"bbaa3f6a2949e50460ef2a74b448641639e08374396371479e234a9d21152504",
3264"f2295930923865a14602e81f75a5caec9d59952c8102a0003d143b9c53bd0e12",
3265"3b5838b50fe7674016ca8f07e62c785be8",
3266"86497726e18b409075f7036b1c65deacab22cf85d2ae64ef1857e17a9713e4fb",
3267"2be07b51ed87a4f0e2008aa113b3002f567fd6a200fb8fcdadcfb6a702472cefd40c7a0d72f6bc2ca6d82e9db54d4304",
3268 ], [
3269"115dbea4c2fa4052f9493a5ec191fec5166ab7698e596b3f6e63d4270622b934",
3270"f4e080af64068465bec753da1b152d1fabea5a283420d8737019bb3fa01cff55",
3271"8701db242b917c34be6f66b979756f8eab58",
3272"a2edb2c979a443ff733c32453d350f09af33068a5640af90940315e7d3c87957",
3273"f6de011b6f6900f63083b727c1115e29cec046b25a9e2483f00789602653addcb3000ad316d0bede5ca0fbd6c0e44e29",
3274 ], [
3275"d6aacd7885ee0183ca96cdf71c49e3596073d0894e9100880d7b38f9f3521400",
3276"66fde0f01d063ce623b604811beae9ddc5661f0d85e097d320df77aeecbb3e2e",
3277"5d8b25fffbc925783eaf34dab0c582e6432815",
3278"ba789f5876b8db6ae44d0e4507de9993c83e504804c1f3f8619adbd717847b77",
3279"48ca28bd49f281f2620a4cc87adf301ae980c5154a35a9483f4aaab9ae791b44afa6be2053ef2100718f44006645651f",
3280 ]
3281 ];
3282
3283 #[test]
3284 fn signature() {
3285 for i in 0..KAT_SIGN.len() {
3286 let sk = PrivateKey::decode(&hex::decode(KAT_SIGN[i][0]).unwrap()).unwrap();
3287 let pk = PublicKey::decode(&hex::decode(KAT_SIGN[i][1]).unwrap()).unwrap();
3288 assert!(sk.public_key.encoded == pk.encoded);
3289 let seed = hex::decode(KAT_SIGN[i][2]).unwrap();
3290 let mut hv = hex::decode(KAT_SIGN[i][3]).unwrap();
3291 let expected = hex::decode(KAT_SIGN[i][4]).unwrap();
3292 let sig = sk.sign_seeded(&seed, Point::HASHNAME_BLAKE2S, &hv);
3293 assert!(sig[..] == expected);
3294 assert!(pk.verify(&sig, Point::HASHNAME_BLAKE2S, &hv) == true);
3295 hv[31] ^= 0x80;
3296 assert!(pk.verify(&sig, Point::HASHNAME_BLAKE2S, &hv) == false);
3297 }
3298 }
3299
3300 static KAT_ECDH: [[&str; 5]; 20] = [
3301 [
3308"9dcb9151ce0a7cb41dd14737338dc87d75f3ef7552bd17d53a442d0ed1b21931",
3309"ec85965eba95780181cb469f6db8ad117c5cfa941286ded7b839d34525768e4d",
3310"82e849c462d9efe63e7575552a4ff9ffaa065064fe33145efa013d8f50365db3",
3311"d5dabc3ef4d9e0b4162c2ba16a4938f0e4129172d54fd61880a7ee7e25fcc524",
3312"e805b0e59b201f0eab9844f0f3281ecf97046b2cbc017f27b6ac607af6337f95",
3313 ], [
3314"034c40f610153bf9997909131996d5f80e889594398d90af4a355c9fce97f83c",
3315"eb224cadb595d0b02c5b96b86faad18f149bfd1cb8c0760239c568b62def3d59",
3316"7f5830c8eb95d3aa46687a5699987dd905453a23d59a9e83d94dbfcd1489b6be",
3317"9f9c9aa9a69c750305ed05cb1cc180b566464486cee544c6c9ce901b2e155002",
3318"607ef72e0956680a4fb1681a9738e0b3a4f805741dcfc239d6645f775f357f22",
3319 ], [
3320"3f25bd6eda431ff6c03751121be1e25efda115bdaf67cdb84a0b6b2ee75c461d",
3321"e13dc3c334027453db737f6c9454451d2c567da110876a8c1f2d7cb94079e022",
3322"d7095e7aa9c8f96ca0c94f322e53980ea7f1d11daedb05e90c907c30838e28e2",
3323"8f77a4f12394390b5cb1df34ca9e3baf9751cb789d3fdd215a7216c30c6f687a",
3324"140970b23bf8b7949ab64d2fd1683d1c402f88ff3874af1bcdddfa4b273d24fb",
3325 ], [
3326"d072edc3292fc9ab93e7757122c814509043f3cff33b4d1be8478c50a2afbf0d",
3327"195a4427064cf84d045a978f0ae6b0d2a9665b69c46fcd997d1cf902db8af932",
3328"4e8ac122f0ca6f480ba93b6763b359b0fa07975b36d712932b938e3c4e421879",
3329"b408e4965f8e483231668d53ca896ea6f44f8bb3c073a051084454654c99c337",
3330"ab171ef85183b7773a41015b7e036920421257697f442f196e9e15d4c04747c9",
3331 ], [
3332"debf0abb614a6664e92d73a93073edb5229d282045ea556a4177177bb424ec08",
3333"695b1b056a4e1af72d0d402202dff3ce673a9503a8cfba9f1d604d8ef8ff6463",
3334"a95bc6e922cf178f93ad2ac9254e8cd9786eccea9e0d698954ef8950ece7e372",
3335"d3c8e5260b4e9460c07c33fc8bf2b025718fe7d94f0d57f3a00696e90cb6f942",
3336"4a7cd7502678863fe49a57d931c4a68c717681e574de5373146ad381ef3e8f5c",
3337 ], [
3338"f241d84958ecfa4da98dbc655e4ecdb39f82aec2d93bbddf56e7edbbc1ada03e",
3339"2d0a234ccc310f215317660ca94f65a1f62e45b117fb72bc4b66cd737f2b146b",
3340"72308c39d148a74c0913bc88c8f3673661983427f21e41a4bb576daa7c6fac31",
3341"095155875b4f029d25962fe5021091b7d1a8c3e345b00c318099d15c2ac9ed71",
3342"538fd628a643e63924cce9d26380b5cbffcd388e80cf4ef8d1257af0e5475275",
3343 ], [
3344"7adea62155559a0b3ad074a4ef04b0ddf6ccadcb7bc4717eb5d803371aae7c2a",
3345"29493a7661a957cbbd100b76fa76da1725d1ea688f21c0656e53fe9175510b0b",
3346"fe5cfc84ef368e43b530fe352475784d24bcda02fe133b85b0e63bcb865cb337",
3347"e365ab6bda9f5876281b87b64a51885dcc38bc55d2a39cb4a1870a137e71363a",
3348"5cb0777c26dde80eccd62d2ad682f68dc750fd7bac0ec32b8fd5bcf5d0f95d45",
3349 ], [
3350"455c966ba7bd0674a899a6506ae0950ace532047a3b9ccb1aaff473e6c15b21e",
3351"f2a562c8c170af956619a9832d7ff5a8cb437fff9b4da54e32ccb553c22eaa78",
3352"b389326411e8fdcdc28c8ff2c8d1bb96bd9ee47d1e842d6855da5e46aa82ff42",
3353"66b4ef586c05db3748c9703bd0b2ea07b627e847d653b7aea9e7c6067ee94942",
3354"3cccf46cecf4f29d8729ba4619fd246b98af32efc9eccd82955f4b3a9117084b",
3355 ], [
3356"265affbed17b2e7bf8f1f1674ee2b5e4df8f94b63da296e6b1399f8612d67224",
3357"0ce6d5fef2aa6dcbee3836da27927be205e5ef293d8110e3a6bb683c5ab03307",
3358"f905e2cfa22342282ba96c517d4a312b47222fec94c2438492f0653d361b4798",
3359"2df3ee157bea2a10db450426efdf8c8e09b825fea293a93988e48b4e7c392f00",
3360"ef4ddaa976ceeaf48dac9e769b2e11e9adf281b4c8107b6c11114c617776b406",
3361 ], [
3362"068c07d784663308e53c4cbb8d030c09155640f2b29c80e55d6f9c9250f96938",
3363"7cd059a1236216d01c0b6eb1bfc498fdba92ad9b35f1952290528aceb01f2e7b",
3364"8241202843de3638dc4eabfa9ba4bb1fcd583ed41613716f22b284f71f23866e",
3365"1d9ffe1bf02362267a7347540daf49c17cfe759fce0d6dad80805ad8ff359678",
3366"a1a6ed4088a2ce83a78caf90ce2dc79eb6402d8bfee8eefdef1a44e832f68365",
3367 ], [
3368"97a281e2545a9de414f544cb9830d8cf7975a0c02c756d1631d6d5ca364de637",
3369"f12c27746e758baf98829e787a3351654f2680128be5a393325e2e4f71a4c94a",
3370"4fcb2e817eda1c8874bcd34cf38537f26fe5dbd4856d1d75b7f2fabb72503bc6",
3371"ee1137915736672af7368617b0c018597e70dc688c6514ee17c1bc9c78469108",
3372"47db4fcb16e258d02ce0e8bd5a0f737f14e1caf9d78c05008703f8980190f0c0",
3373 ], [
3374"857aede049b75cc9e877a24722626c91a85cc62851cfe7494660095cebd6b516",
3375"ef76d2d5ed8dd0a7ccecc48b3623f589df0b31e461276b79183b25d43fc8d52c",
3376"4ffb1be9de0c203e472d8061445b5bbdbbedfd4746a9de810404c079f0e7954a",
3377"fb84621dc915729c2b5f439f4e2d82a4acc5d4399d1122b21b2da5292036e017",
3378"8a9bf15b8f33a3f1a83b94e36e9c0c24b2bf6bb1178485b7d9e679e40c56640d",
3379 ], [
3380"acd4f4526043d14c626e752bd9e46e3acc67468c077b9c09bb85c2ca2849be16",
3381"0fd69b2fe624b85d4d313c3679ec1dacafd005c7002e925f56940d872f339c7b",
3382"c87f53b379da8ee65258c6b398d6d72637280ed3760c5ebf61c92419ef963ec0",
3383"8cfa6f50f3fd35c653e45dd8d6babf483c0d8e7f219953b8cb148dc5e5e91016",
3384"0205fe0fa6796de6e212e8c9994f8cb71e5b48cca64340d77742ea57b753f338",
3385 ], [
3386"7df1a00a4271e729f336af36ff8e20f14af5259f0aa1ce1f77ec4ee9ae004130",
3387"20798df98a93c43e5f95b1bda47bac292be89384de6039c614f026dc520dff68",
3388"404b819a79f76b5be9178fe5a14f300b135cf83313d1e3bec440d706ccd04080",
3389"fe78461564f462328e61640690f1481ac29ca83239891e5967f10d38aac0e658",
3390"d4259f680aaecf8957f04a9e55bf5c37ff11f3c8a3abed884eb25cec775f7e6b",
3391 ], [
3392"6a72fec38380c931b3d8cab9543ba041af9e20c73b8b086c8d08a711455dfe3e",
3393"9a242966308adc876b1a00db83f3f8144e8b942a3afa498cebc676cd2f5ea16e",
3394"a176318ca194e5ffdf3bfc639ff7e8c194ddb8250ae43823780e110d510bbb17",
3395"8a1cda96b144a0d39e070c5a6d741847f1e877348b95b3dbcf8a29ebb613d44c",
3396"23d10eb01d1d574f04a429c11b1a0478ac7302b83b4d161ff544270251affda8",
3397 ], [
3398"02c1b0268c67747a76ca378e2d7e93a6de1083de5e24f57074c960627292b431",
3399"d08cddf88afef688c60f2c8a9718a458cac8ccd39269099753366518fee08575",
3400"8c1b9d64b8ea71970453fd38f771772e1628168181be107a2891f782d408938d",
3401"c1973b4cf687a2b59399e7c3b6f7edbfc159a23a2ff2595f8a44c2ba6e072d1a",
3402"607f822fe40334f1ce90c467e33db59268969764efdc9cc861873d0f9be5e1e3",
3403 ], [
3404"85b8bc942b9a68e4417452af0d59ca0f611744e6a5248c238166d37a2c0bfa0c",
3405"3903e118bfdc70203e7dce44a05438855ade072b7280fb47784404e5bb52115b",
3406"8a1c7a17baf71b7219f4021cad96e39dcc3842a04c42a4be4e53cc04db0ceef5",
3407"7e6e7c8911a6a8d3ff80324a7f051ca7aa83fdbe7d6580ccee14fe2be1171439",
3408"8d865c6dba70aeb9aa0de9a4d21a9a7171b10831a1e849c9039fb2b65993e76e",
3409 ], [
3410"072a97460c465e2b6896fedb93fac4f6c2955a57c0488b3e086eac2a9e714e3c",
3411"bfd29c67c5d2e30903c1734ef38364f7530af59b08ecc52e9d204e05c7ad270e",
3412"2bc2b8f386cebb93e3924018cb63c0e803548e499539110033ec00cf4f16e0e7",
3413"4b8a9308e575fb549c300c0dabd1f835432e581d0c58ece1e039104ee5e37c10",
3414"8167c8df36cd17c9abfbbcafdc9ec0579cd36ee2e6a4b53e0d1f7df1a8492d34",
3415 ], [
3416"6548f8d6120770714a7c3e266c3f7d06f64eb78cee2b878f1f1b268dfa558e29",
3417"5c7c7d5ecef71cafaa97ca1257986522c21e116daf8dc74cf716a67c50b07d50",
3418"89cbb2d7a029af9c60481a0593e46cd6d2ed8639fb99fdd0cdd54500b136583a",
3419"9491d56f59b71b06dab44959074447cf673ca7f6eafba946e0a212b8aa8d2732",
3420"f1e8cfbdf3e7aff1740cfdb5aae772a3afefb1706237bd9109127157a6a4b3c0",
3421 ], [
3422"61cebf8acf562c79813e85102fa9f310fdd1525490a0a1f324e427649d4b3524",
3423"a84fad2c58abe53609e745b2ddda507d4d1c58a4a77973ef55d7e81884d18211",
3424"725a9db4fb2cd41ae8e15b7f5662e57197f2c9f3ea3fd799ee99466d2a149eaa",
3425"1207ae7f8c51a690c60f4a31dd3141169f57a9c3eb37a872de27c9c5eadae00e",
3426"90b406707f7f32ea205e524462f83cd9846420c48cb29bb659db97426241c8fa",
3427 ]
3428 ];
3429
3430 #[test]
3431 fn ECDH() {
3432 for i in 0..KAT_ECDH.len() {
3433 let sk = PrivateKey::decode(&hex::decode(KAT_ECDH[i][0]).unwrap()).unwrap();
3434 let peer1 = hex::decode(KAT_ECDH[i][1]).unwrap();
3435 let refkey1 = hex::decode(KAT_ECDH[i][2]).unwrap();
3436 let peer2 = hex::decode(KAT_ECDH[i][3]).unwrap();
3437 let refkey2 = hex::decode(KAT_ECDH[i][4]).unwrap();
3438 let (key1, ok1) = sk.ECDH(&peer1);
3439 assert!(ok1 == 0xFFFFFFFF);
3440 assert!(key1[..] == refkey1);
3441 let (key2, ok2) = sk.ECDH(&peer2);
3442 assert!(ok2 == 0x00000000);
3443 assert!(key2[..] == refkey2);
3444 }
3445 }
3446}