crrl/
jq255e.rs

1//! Jq255e implementation.
2//!
3//! This module implements generic group operations on the jq255e
4//! group, which is itself isomorphic to a subgroup of the
5//! double-odd elliptic curve of equation `y^2 = x*(x^2 - 2)` over
6//! the finite field GF(2^255 - 18651). This group is described
7//! on the [double-odd site]. The group has a prime order order `r`
8//! (an integer slightly below 2^254). A conventional base point is
9//! defined; like all non-neutral elements in a prime order group, it
10//! generates the whole group.
11//!
12//! A group element is represented by the `Point` structure. Group
13//! elements are called "points" because they are internally represented
14//! by points on an elliptic curve; however, the `Point` structure, by
15//! construction, contains only proper representatives of the group
16//! element, not just any point. `Point` instances can be used in
17//! additions and subtractions with the usual `+` and `-` operators; all
18//! combinations of raw values and references are accepted, as well as
19//! compound assignment operators `+=` and `-=`. Specialized functions
20//! are available, in particular for point doubling (`Point::double()`)
21//! and for sequences of successive doublings (`Point::xdouble()`), the
22//! latter using some extra optimizations. Multiplication by an integer
23//! (`u64` type) or a scalar (`Scalar` structure) is also accepted, using
24//! the `*` and `*=` operators. Scalars are integers modulo `r`. The
25//! `Scalar` structure represents such a value; it implements all usual
26//! arithmetic operators (`+`, `-`, `*` and `/`, as well as `+=`, `-=`,
27//! `*=` and `/=`).
28//!
29//! Scalars can be encoded over 32 bytes (using unsigned little-endian
30//! convention) and decoded back. Encoding is always canonical, and
31//! decoding always verifies that the value is indeed in the canonical
32//! range.
33//!
34//! Points can be encoded over 32 bytes, and decoded back. As with
35//! scalars, encoding is always canonical, and verified upon decoding.
36//! Point encoding uses only 255 bits; the top bit (most significant bit
37//! of the last byte) is always zero. The decoding process verifies that
38//! the top bit is indeed zero.
39//!
40//! [double-odd site]: https://doubleodd.group/
41
42// Projective/fractional coordinates traditionally use uppercase letters,
43// using lowercase only for affine coordinates.
44#![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/// An element in the jq255e group.
54#[derive(Clone, Copy, Debug)]
55pub struct Point {
56    // We use extended coordinates on the Jacobi quartic curve with
57    // equation: e^2 = (a^2 - 4*b)*u^4 + u^2 + 1
58    // The map from the base curve is defined as:
59    //   u = x/y
60    //   e = u^2*(x - b/x)
61    // For the point (0,0) (the neutral in the jq255e group, which is the
62    // unique point of order 2 on the curve), we set u = 0 and e = -1.
63    // From the curve equation, e = (x^2 - b)/(x^2 + a*x + b), so that
64    // it is always defined and non-zero, and e = -1 for x = 0; as for u,
65    // it is the inverse of the slope of the line from (0,0) to the point,
66    // so the extreme case for (0,0) itself is a vertical tangent, which
67    // is why we use u = 0. Since addition of (0,0) on the curve becomes
68    // on the quartic the transform (e,u) -> (-e,-u), we can also map
69    // the point-at-infinity of the initial curve into (1,0) on the quartic.
70    //
71    // In extended coordinates, we have:
72    //   Z != 0 and E != 0 for all points
73    //   e = E/Z
74    //   u = U/Z
75    //   u^2 = T/Z   (hence U^2 = T*Z)
76    E: GF255e,
77    U: GF255e,
78    Z: GF255e,
79    T: GF255e,
80}
81
82/// Integers modulo r = 2^254 - 131528281291764213006042413802501683931.
83///
84/// `r` is the prime order of the jq255e group.
85pub type Scalar = ModInt256<0x1F52C8AE74D84525, 0x9D0C930F54078C53,
86                            0xFFFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF>;
87
88impl Scalar {
89    /// Encodes a scalar element into bytes (little-endian).
90    pub fn encode(self) -> [u8; 32] {
91        self.encode32()
92    }
93}
94
95impl Point {
96
97    /// The group neutral element.
98    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    /// The conventional base point (group generator).
106    ///
107    /// This point generates the whole group, which has prime order r
108    /// (integers modulo r are represented by the `Scalar` type).
109    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    /* unused
117    /// The curve `a` constant (0).
118    const A: GF255e = GF255e::ZERO;
119    /// The curve `b` constant (-2).
120    const B: GF255e = GF255e::w64be(
121        0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
122        0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFB723);
123    */
124
125    /// A square root of -1 in GF255e (we use the non-negative root).
126    const ETA: GF255e = GF255e::w64be(
127        0x10ED2DB33C69B85F, 0xE414983FE53688E3,
128        0xA60D864FB30E6336, 0xD99E0F1BAA938AEE);
129
130    /// Tries to decode a point from bytes.
131    ///
132    /// If the source slice has not length exactly 32 bytes, then
133    /// decoding fails. If the source bytes are not a valid, canonical
134    /// encoding of a group element, then decoding fails. On success,
135    /// 0xFFFFFFFF is returned; on failure, 0x00000000 is returned. On
136    /// failure, this point is set to the neutral.
137    ///
138    /// If the source length is exactly 32 bytes, then the decoding
139    /// outcome (success or failure) should remain hidden from
140    /// timing-based side channels.
141    pub fn set_decode(&mut self, buf: &[u8]) -> u32 {
142        // Check that the input length is correct.
143        if buf.len() != 32 {
144            *self = Self::NEUTRAL;
145            return 0;
146        }
147
148        // Decode the u coordinate.
149        let (u, mut r) = GF255e::decode32(buf);
150
151        // e^2 = (a^2-4*b)*u^4 - 2*a*u^2 + 1
152        let uu = u.square();
153        let ee = uu.square().mul8() + GF255e::ONE;
154        let (e, r2) = ee.sqrt();
155        r &= r2;
156        // GF255e::sqrt() already returns the non-negative root, we do
157        // not have to test the sign of e and adjust.
158
159        // We have the point in affine coordinates, except on failure,
160        // in which case we have to adjust the values.
161        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    /// Tries to decode a point from some bytes.
169    ///
170    /// Decoding succeeds only if the source slice has length exactly 32
171    /// bytes, and contains the canonical encoding of a valid curve
172    /// point. Sicne this method returns an `Option<Point>`, it
173    /// inherently leaks (through timing-based side channels) whether
174    /// decoding succeeded or not; to avoid that, consider using
175    /// `set_decode()`. The decoded point itself, however, does not leak.
176    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    /// Encodes this point into exactly 32 bytes.
186    ///
187    /// Encoding is always canonical.
188    pub fn encode(self) -> [u8; 32] {
189        // - Choose the element representant whose e coordinate is
190        //   non-negative.
191        // - Encode the u coordinate of that point.
192        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    /// Creates a point by converting a point in extended affine
200    /// coordinates (e, u, u^2).
201    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    /// Adds another point (`rhs`) to this point.
211    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        // Generic case (8M+3S):
216        //   constants on the dual curve:
217        //      a' = -2*a          (jq255e: a' = 0)
218        //      b' = a^2 - 4*b     (jq255e: b' = 8)
219        //   e1e2 = E1*E2
220        //   z1z2 = Z1*Z2
221        //   u1u2 = U1*U2
222        //   t1t2 = T1*T2
223        //     zt = (Z1 + T1)*(Z2 + T2) - z1z2 - t1t2
224        //     eu = (E1 + U1)*(E2 + U2) - e1e2 - u1u2
225        //     hd = z1z2 - b'*t1t2
226        //     E3 = (z1z2 + b'*t1t2)*(e1e2 + a'*u1u2) + 2*b'*u1u2*zt
227        //     Z3 = hd^2
228        //     T3 = eu^2
229        //     U3 = ((hd + eu)^2 - Z3 - T3)/2  # Or: U3 = hd*eu
230        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();  // (a^2 - 4*b)*T1*T2
237        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;  // faster than: ((hd + eu)^2 - Z3 - T3)/2
242        self.E = E3;
243        self.Z = Z3;
244        self.U = U3;
245        self.T = T3;
246    }
247
248    /// Specialized point addition routine when the other operand is in
249    /// affine extended coordinates (used in the pregenerated tables for
250    /// multiples of the base point).
251    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        // Generic case (7M+3S):
256        //   constants on the dual curve:
257        //      a' = -2*a          (jq255e: a' = 0)
258        //      b' = a^2 - 4*b     (jq255e: b' = 8)
259        //   e1e2 = E1*E2
260        //   u1u2 = U1*U2
261        //   t1t2 = T1*T2
262        //     zt = Z1*t2 + T1
263        //     eu = (E1 + U1)*(E2 + U2) - e1e2 - u1u2
264        //     hd = Z1 - b'*t1t2
265        //     E3 = (Z1 + b'*t1t2)*(e1e2 + a'*u1u2) + 2*b'*u1u2*zt
266        //     Z3 = hd^2
267        //     T3 = eu^2
268        //     U3 = ((hd + eu)^2 - Z3 - T3)/2  # Or: U3 = hd*eu
269        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();  // (a^2 - 4*b)*T1*T2
275        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;  // faster than: ((hd + eu)^2 - Z3 - T3)/2
280        self.E = E3;
281        self.Z = Z3;
282        self.U = U3;
283        self.T = T3;
284    }
285
286    /// Specialized point subtraction routine when the other operand is in
287    /// affine extended coordinates (used in the pregenerated tables for
288    /// multiples of the base point).
289    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    /// Doubles this point (in place).
299    pub fn set_double(&mut self) {
300        let (E, Z, U) = (&self.E, &self.Z, &self.U);
301
302        // P ezut -> 2*P xwj  (1M+3S)
303        //    ee = E^2
304        //    X  = ee^2
305        //    W  = 2*Z^2 - ee
306        //    J  = 2*E*U
307        let ee = E.square();
308        let J = E * U.mul2();
309        let X = ee.square();
310        let W = Z.square().mul2() - ee;
311
312        // P xwj -> P ezut  (3S)
313        //    ww = W^2
314        //    jj = J^2
315        //    E  = 2*X - ww
316        //    Z  = ww
317        //    U  = ((W + J)^2 - ww - jj)/2  # Or: U = W*J
318        //    T  = jj
319        let ww = W.square();
320        let jj = J.square();
321        self.E = X.mul2() - ww;
322        self.Z = ww;
323        self.U = W * J;  // faster than: ((W + J).square() - ww - jj).half()
324        self.T = jj;
325    }
326
327    /// Doubles this point.
328    #[inline(always)]
329    pub fn double(self) -> Self {
330        let mut r = self;
331        r.set_double();
332        r
333    }
334
335    /// Doubles this point n times (in place).
336    pub fn set_xdouble(&mut self, n: u32) {
337        if n == 0 {
338            return;
339        }
340
341        // First doubling switches to xwj, with cost 1M+3S; subsequent
342        // doublings work on the xwj representation (1M+5S each). At the
343        // end, we convert back to ezut in cost 3S.
344        let (E, Z, U) = (&self.E, &self.Z, &self.U);
345
346        // P ezut -> 2*P xwj  (1M+3S)
347        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        // Subsequent doublings in xwj  (n-1)*(1M+5S)
353        for _ in 1..n {
354            // ww = W^2
355            // t1 = ww - 2*X
356            // t2 = t1^2
357            // J' = ((W + t1)^2 - ww - t2)*J  # Or: J' = 2*W*t1*J
358            // W' = t2 - 2*ww^2
359            // X' = t2^2
360            let ww = W.square();
361            let t1 = ww - X.mul2();
362            let t2 = t1.square();
363            J *= t1 * W.mul2();  // faster than (W + t1)^2 - ww - t2
364            W = t2 - ww.square().mul2();
365            X = t2.square();
366        }
367
368        // Conversion xwj -> ezut  (3S)
369        let ww = W.square();
370        let jj = J.square();
371        self.E = X.mul2() - ww;
372        self.Z = ww;
373        self.U = W * J;  // faster than: ((W + J).square() - ww - jj).half()
374        self.T = jj;
375    }
376
377    /// Doubles this point n times.
378    #[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    /// Negates this point (in place).
386    #[inline(always)]
387    pub fn set_neg(&mut self) {
388        self.U.set_neg();
389    }
390
391    /// Subtract another point (`rhs`) from this point.
392    fn set_sub(&mut self, rhs: &Self) {
393        self.set_add(&-rhs);
394    }
395
396    /// Multiplies this point by a small integer.
397    ///
398    /// This operation is constant-time with regard to the source point,
399    /// but NOT with regard to the multiplier; the multiplier `n` MUST
400    /// NOT be secret.
401    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    /// Compares two points for equality.
426    ///
427    /// Returned value is 0xFFFFFFFF if the two points are equal,
428    /// 0x00000000 otherwise.
429    #[inline]
430    pub fn equals(self, rhs: Self) -> u32 {
431        // Points are equal if and only if they have the same image through
432        // isogeny theta1:
433        //    theta1(e, u) = (f, v)
434        //    with f = (a^2 - 4*b)*u^2, and v = u/e
435        // In the theta1 output, coordinate v of a point uniquely identifies
436        // the point. Thus, we only need to compare u1/e1 and u2/e2, which
437        // is equivalent to comparing u1*e2 and u2*e1 (since e1 and e2 are
438        // never zero).
439        (self.U * rhs.E).equals(rhs.U * self.E)
440    }
441
442    /// Tests whether this point is the neutral (identity point on the
443    /// curve).
444    ///
445    /// Returned value is 0xFFFFFFFF for the neutral, 0x00000000
446    /// otherwise.
447    #[inline(always)]
448    pub fn isneutral(self) -> u32 {
449        self.U.iszero()
450    }
451
452    /// Conditionally copies the provided point (`P`) into `self`.
453    ///
454    ///  - If `ctl` = 0xFFFFFFFF, then the value of `P` is copied into `self`.
455    ///
456    ///  - If `ctl` = 0x00000000, then the value of `self` is unchanged.
457    ///
458    /// `ctl` MUST be equal to 0x00000000 or 0xFFFFFFFF.
459    #[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    /// Returns a point equal to `P0` (if `ctl` = 0x00000000) or `P1` (if
468    /// `ctl` = 0xFFFFFFFF).
469    ///
470    /// Value `ctl` MUST be either 0x00000000 or 0xFFFFFFFF.
471    #[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    /// Conditionally negates this point.
479    ///
480    /// This point is negated if `ctl` = 0xFFFFFFFF, but kept unchanged
481    /// if `ctl` = 0x00000000. `ctl` MUST be equal to 0x00000000 or
482    /// 0xFFFFFFFF.
483    #[inline]
484    pub fn set_condneg(&mut self, ctl: u32) {
485        self.U.set_cond(&-self.U, ctl);
486    }
487
488    /// Maps a field element into a point.
489    ///
490    /// This map output is not uniformly distributed; in general, it should
491    /// be used only through `hash_to_curve()`, which invokes this map
492    /// twice.
493    fn map_to_curve(f: &GF255e) -> Self {
494        // We map to the dual curve E(a',b') with:
495        //   a' = -2*a = 0
496        //   b' = a^2 - 4*b = 8
497
498        // x1num = 4*f^2 + (1 - b')
499        // x2num = eta*(4*f^2 - (1 - b'))
500        // x12den = 4*f
501        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        // yy1num = 64*f^7 + 16*(3+b')*f^5 + 4*(3-2*b'-b'^2)*f^3 + (1-b')^3*f
507        // yy2num = -eta*(64*f^7 - 16*(3+b')*f^5 + 4*(3-2*b'-b'^2)*f^3 - (1-b')^3*f)
508        // y12den = 8*f^2
509        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        // Use x1 and y1 if yy1num is square.
519        // Otherwise, use x2 and y2 if yy2num is square.
520        // Otherwise, use x3 and y3.
521        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();  // sqrt() returns the non-negative root
535
536        // u = x/y
537        let unum = xnum * yden;
538        let uden = xden * ynum;
539
540        // Apply the theta_{1/2} isogeny to get back to curve E[a,b].
541        //   x' = 4*b*u^2
542        //   u' = 2*x/(u*(x^2 - b'))
543        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        // If the source scalar was zero, then computations above were not
549        // good and we got zero in all values; we must fix the denominators.
550        let fz = f.iszero();
551        Xden.set_cond(&GF255e::ONE, fz);
552        Uden.set_cond(&GF255e::ONE, fz);
553
554        // Compute the 'e' coordinate with e = (x^2 - b)/(x^2 + a*x + b).
555        let xx = Xnum.square();
556        let mbzz = Xden.square().mul2();
557        let Enum = xx + mbzz;
558        let Eden = xx - mbzz;
559
560        // Convert to extended coordinates.
561        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    /// Hashes some data into a point.
572    ///
573    /// Given some input bytes, a group element is deterministically
574    /// generated; the output distribution should be indistinguishable
575    /// from uniform random generation, and the discrete logarithm of the
576    /// output relatively to any given point is unknown.
577    ///
578    /// The input bytes are provided as `data`. If these bytes are a
579    /// hash value, then the hash function name should be provided as
580    /// `hash_name`, corresponding to one of the defined constants
581    /// (`HASHNAME_SHA256`, `HASHNAME_BLAKE2S`, etc). In general, the
582    /// name to use is the "formal" name of the hash function, converted
583    /// to lowercase and without punctuation signs (e.g. SHA-256 uses
584    /// the name `sha256`). If the input bytes are not an already
585    /// computed hash value, but some other raw data, then `hash_name`
586    /// shall be set to an empty string.
587    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    /* unused
629    /// Recodes a scalar into 51 signed digits.
630    ///
631    /// Each digit is in -15..+16, top digit is in 0..+16.
632    fn recode_scalar(n: &Scalar) -> [i8; 51] {
633        let mut sd = [0i8; 51];
634        let bb = n.encode();
635        let mut cc: u32 = 0;       // carry from lower digits
636        let mut i: usize = 0;      // index of next source byte
637        let mut acc: u32 = 0;      // buffered bits
638        let mut acc_len: i32 = 0;  // number of buffered bits
639        for j in 0..51 {
640            if acc_len < 5 {
641                acc |= (bb[i] as u32) << acc_len;
642                acc_len += 8;
643                i += 1;
644            }
645            let d = (acc & 0x1F) + cc;
646            acc >>= 5;
647            acc_len -= 5;
648            let m = 16u32.wrapping_sub(d) >> 8;
649            sd[j] = (d.wrapping_sub(m & 32)) as i8;
650            cc = m & 1;
651        }
652        sd
653    }
654    */
655
656    /// Recodes a half-width scalar into 26 signed digits.
657    ///
658    /// Each digit is in -15..+16, top digit is in 0..+8.
659    fn recode_u128(n: u128) -> [i8; 26] {
660        let mut sd = [0i8; 26];
661        let mut x = n;
662        let mut cc: u32 = 0;       // carry from lower digits
663        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    /// Lookups a point from a window, with sign handling (constant-time).
674    fn lookup(win: &[GF255e; 64], k: i8) -> Self {
675        // Split k into its sign s (0xFFFFFFFF for negative) and
676        // absolute value (f), then subtract 1 from f.
677        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        // If f == -1 then the four coordinates are left at zero, and we
688        // must adjust that.
689        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        // Negate the point if the original index k was negative.
694        P.set_condneg(s);
695
696        P
697    }
698
699    /// Lookups a point from a window of points in affine extended
700    /// coordinates, with sign handling (constant-time).
701    fn lookup_affine_extended(win: &[GF255e; 48], k: i8)
702        -> PointAffineExtended
703    {
704        // Split k into its sign s (0xFFFFFFFF for negative) and
705        // absolute value (f), then subtract 1 from f.
706        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        // If f == -1 then the four coordinates are left at zero, and we
716        // must adjust that.
717        let fz = ((f as i32) >> 31) as u32;
718        P.e.set_cond(&PointAffineExtended::NEUTRAL.e, fz);
719
720        // Negate the point if the original index k was negative.
721        P.set_condneg(s);
722
723        P
724    }
725
726    /// Supports scalar splitting.
727    ///
728    /// Given a 256-bit integer k (unsigned, provided as 8 32-bit limbs in
729    /// little-endian order, less than the group order r) and a multiplier
730    /// integer e (lower than 2^127 - 2), compute y = round(k*e / r).
731    fn mul_divr_rounded(k: &Zu256, e: &Zu128) -> Zu128 {
732        // z <- k*e
733        let mut z = k.mul256x128(e);
734
735        // (r-1)/2 (padded to 384 bits)
736        const HR: Zu384 = Zu384::w64le(
737            0x8FA964573A6C2292, 0xCE864987AA03C629,
738            0xFFFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF,
739            0x0000000000000000, 0x0000000000000000);
740
741        // r0 = 2^254 - r
742        const R0: Zu128 = Zu128::w64le(0xE0AD37518B27BADB, 0x62F36CF0ABF873AC);
743
744        // z <- z + (r-1)/2
745        z.set_add(&HR);
746
747        // z0 <- z mod 2^254
748        // y <- floor(z / 2^254) + 1
749        let (z0, mut y) = z.trunc_and_rsh_cc(1, 254);
750
751        // t <- y*r0
752        let t = y.mul128x128(&R0);
753
754        // Get the high 32-bit limb of t + z0.
755        let w = t.add_rsh224(&z0);
756
757        // The high limb is in w and is lower than 2^31. If it is
758        // lower than 2^30, then y is too large and we must decrement
759        // it; otherwise, we keep it unchanged.
760        y.set_sub_u32(1 - (w >> 30));
761
762        y
763    }
764
765    /// Splits a scalar k into k0 and k1 (signed) such that
766    /// k = k0 + k1*mu (with mu being a given square root of -1 modulo r).
767    ///
768    /// This function returns |k0|, sgn(k0), |k1| and sgn(k1), with
769    /// sgn(x) = 0xFFFFFFFF for x < 0, 0x00000000 for x >= 0.
770    fn split_mu(k: &Scalar) -> (u128, u32, u128, u32) {
771        // Obtain k as an integer t in the 0..r-1 range.
772        let ki = Zu256::decode(&k.encode()).unwrap();
773
774        // Constants u and v such that mu = u/v mod r.
775        const EU: Zu128 = Zu128::w64le(0x2ACCF9DEC93F6111, 0x1A509F7A53C2C6E6);
776        const EV: Zu128 = Zu128::w64le(0x0B7A31305466F77E, 0x7D440C6AFFBB3A93);
777
778        // c <- round(ki*v / r)
779        // d <- round(ki*u / r)
780        let c = Self::mul_divr_rounded(&ki, &EV);
781        let d = Self::mul_divr_rounded(&ki, &EU);
782
783        // k0 = k - d*u - c*v
784        // k1 = d*v - c*u
785        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    /// Endomorphism on the group.
797    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    /// Multiplies this point by a scalar (in place).
807    ///
808    /// This operation is constant-time with regard to both the points
809    /// and the scalar value.
810    pub fn set_mul(&mut self, n: &Scalar) {
811        // Split the scalar with the endomorphism.
812        let (n0, s0, n1, s1) = Self::split_mu(n);
813
814        // Compute the 5-bit windows:
815        //   win0[i] = (i+1)*sgn(k0)*P
816        //   win1[i] = (i+1)*sgn(k1)*zeta(P)
817        // with zeta(e, u) = (e, u*eta) for eta = sqrt(-1) (this is an
818        // endomorphism on the group).
819        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        // Recode the two half-width scalars into 26 digits each.
868        let sd0 = Self::recode_u128(n0);
869        let sd1 = Self::recode_u128(n1);
870
871        // Process the two digit sequences in high-to-low order.
872        *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    /// Sets this point by multiplying the conventional generator by the
882    /// provided scalar.
883    ///
884    /// This operation is constant-time. It is faster than using the
885    /// generic multiplication on `Self::BASE`.
886    pub fn set_mulgen(&mut self, n: &Scalar) {
887        // Split the scalar with the endomorphism.
888        let (n0, s0, n1, s1) = Self::split_mu(n);
889
890        // Recode the two half-width scalars into 26 digits each.
891        let sd0 = Self::recode_u128(n0);
892        let mut sd1 = Self::recode_u128(n1);
893
894        // If n0 and n1 have distinct signs, then we need to apply
895        // the -zeta endomorphism instead of zeta. We do this by
896        // negating the digits in sd1 if necessary.
897        let zn = (s0 ^ s1) as i8;
898        for i in 0..26 {
899            sd1[i] -= zn & (sd1[i] << 1);
900        }
901
902        // We process eight chunks in parallel, with alternating sizes
903        // (in digits): 6, 7, 6, 7, 6, 7, 6, 7. First four chunks are
904        // for n0, and work over the precomputed tables for B, B30, B65
905        // and B95; the four other chunks work over the same tables but
906        // with the zeta endomorphism applied.
907        *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        // Process the digits in high-to-low order.
917        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        // If n0 was negative then we need to negate the result.
938        self.set_condneg(s0);
939    }
940
941    /// Creates a point by multiplying the conventional generator by the
942    /// provided scalar.
943    ///
944    /// This operation is constant-time.
945    #[inline]
946    pub fn mulgen(n: &Scalar) -> Self {
947        let mut P = Self::NEUTRAL;
948        P.set_mulgen(n);
949        P
950    }
951
952    /// 5-bit wNAF recoding of a scalar; output is a sequence of 255
953    /// digits.
954    ///
955    /// Non-zero digits have an odd value, between -15 and +15
956    /// (inclusive). (The recoding is constant-time, but use of wNAF is
957    /// inherently non-constant-time.)
958    fn recode_scalar_NAF(n: &Scalar) -> [i8; 255] {
959        // We use a branchless algorithm to avoid misprediction
960        // penalties.
961        //
962        // Let x be the current (complete) integer:
963        //  - If x is even, then the next digit is 0.
964        //  - Otherwise, we produce a digit from the low five bits of
965        //    x. If these low bits have value v (odd, 1..31 range):
966        //     - If v <= 15, then the next digit is v.
967        //     - Otherwise, the next digit is v - 32, and we add 32 to x.
968        //    When then subtract v from x (i.e. we clear the low five bits).
969        // Once the digit has been produced, we divide x by 2 and loop.
970        //
971        // Since r < 2^254, only 255 digits are necessary at most.
972
973        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();  // -1 if x is odd, 0 otherwise
981            let v = x & m & 31;              // low 5 bits if x odd, or 0
982            let c = (v & 16) << 1;           // carry (0 or 32)
983            let d = v.wrapping_sub(c);       // next digit
984            sd[i] = d as i8;
985            x = x.wrapping_sub(d) >> 1;
986        }
987        sd
988    }
989
990    /// 5-bit wNAF recoding of a nonnegative integer.
991    ///
992    /// 129 digits are produced (array has size 130, extra value is 0).
993    /// Non-zero digits have an odd value, between -15 and +15
994    /// (inclusive). (The recoding is constant-time, but use of wNAF is
995    /// inherently non-constant-time.)
996    fn recode_u128_NAF(n: u128) -> [i8; 130] {
997        // See recode_scalar_NAF() for details.
998        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();  // -1 if x is odd, 0 otherwise
1003            let v = x & m & 31;              // low 5 bits if x odd, or 0
1004            let c = (v & 16) << 1;           // carry (0 or 32)
1005            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    /// Given scalars `u` and `v`, sets this point to `u*self + v*B`
1012    /// (with `B` being the conventional generator of the prime order
1013    /// subgroup).
1014    ///
1015    /// This can be used to support Schnorr signature verification.
1016    ///
1017    /// THIS FUNCTION IS NOT CONSTANT-TIME; it shall be used only with
1018    /// public data.
1019    pub fn set_mul_add_mulgen_vartime(&mut self, u: &Scalar, v: &Scalar) {
1020        // Split the first scalar with the endomorphism.
1021        let (u0, s0, u1, s1) = Self::split_mu(u);
1022
1023        // Compute the window for the current point:
1024        //   win[i] = (2*i+1)*self    (i = 0 to 7)
1025        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        // Compute the 5-bit windows for the first scalar:
1033        //   win0[i] = (2*i+1)*sgn(k0)*self         (i = 0 to 7)
1034        //   win1[i] = (2*i+1)*sgn(k1)*zeta(self)   (i = 0 to 7)
1035        // with zeta(e, u) = (e, u*eta) for eta = sqrt(-1) (this is an
1036        // endomorphism on the group).
1037        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        // Recode the two half-width scalars u0 and u1, and the
1051        // full-width scalar v, into 5-bit wNAF.
1052        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            // We have one more doubling to perform.
1060            ndbl += 1;
1061
1062            // Get next digits. If they are all zeros, then we can loop
1063            // immediately.
1064            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            // Apply accumulated doubles.
1073            if zz {
1074                *self = Self::NEUTRAL;
1075                zz = false;
1076            } else {
1077                self.set_xdouble(ndbl);
1078            }
1079            ndbl = 0u32;
1080
1081            // Process digits.
1082            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    /// Given scalars `u` and `v`, returns `u*self + v*B` (with `B` being
1136    /// the conventional generator of the prime order subgroup).
1137    ///
1138    /// This can be used to support Schnorr signature verification.
1139    ///
1140    /// THIS FUNCTION IS NOT CONSTANT-TIME; it shall be used only with
1141    /// public data.
1142    #[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    /// Given integer `u` and scalar `v`, sets this point to `u*self + v*B`
1150    /// (with `B` being the conventional generator of the prime order
1151    /// subgroup).
1152    ///
1153    /// This can be used to support Schnorr signature verification.
1154    ///
1155    /// THIS FUNCTION IS NOT CONSTANT-TIME; it shall be used only with
1156    /// public data.
1157    pub fn set_mul128_add_mulgen_vartime(&mut self, u: u128, v: &Scalar) {
1158        // Recode the integer and scalar in 5-bit wNAF.
1159        let sdu = Self::recode_u128_NAF(u);
1160        let sdv = Self::recode_scalar_NAF(&v);
1161
1162        // Compute the window for the current point:
1163        //   win[i] = (2*i+1)*self    (i = 0 to 7)
1164        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            // We have one more doubling to perform.
1175            ndbl += 1;
1176
1177            // Get next digits. If they are all zeros, then we can loop
1178            // immediately.
1179            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            // Apply accumulated doubles.
1187            if zz {
1188                *self = Self::NEUTRAL;
1189                zz = false;
1190            } else {
1191                self.set_xdouble(ndbl);
1192            }
1193            ndbl = 0u32;
1194
1195            // Process digits.
1196            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    /// Given integer `u` and scalar `v`, returns `u*self + v*B` (with
1243    /// `B` being the conventional generator of the prime order subgroup).
1244    ///
1245    /// This can be used to support Schnorr signature verification.
1246    ///
1247    /// THIS FUNCTION IS NOT CONSTANT-TIME; it shall be used only with
1248    /// public data.
1249    #[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// ========================================================================
1549
1550/// A jq255e private key.
1551///
1552/// Such a key wraps around a secret non-zero scalar. It also contains
1553/// a copy of the public key.
1554#[derive(Clone, Copy, Debug)]
1555pub struct PrivateKey {
1556    sec: Scalar,                // secret scalar
1557    pub public_key: PublicKey,  // public key
1558}
1559
1560/// A jq255e public key.
1561///
1562/// It wraps around a jq255e element, but also includes a copy of the
1563/// encoded point. The point and its encoded version can be accessed
1564/// directly; if modified, then the two values MUST match.
1565#[derive(Clone, Copy, Debug)]
1566pub struct PublicKey {
1567    pub point: Point,
1568    pub encoded: [u8; 32],
1569}
1570
1571impl PrivateKey {
1572
1573    /// Generates a new private key from a cryptographically secure RNG.
1574    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    /// Instantiates a private key from a secret scalar.
1586    ///
1587    /// If the provided scalar is zero, then a panic is triggered.
1588    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    /// Instantiates a private key by decoding it from bytes.
1596    ///
1597    /// If the source bytes do not encode a correct private key,
1598    /// then None is returned.
1599    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    /// Encode a private key into bytes.
1610    ///
1611    /// This encodes the private scalar into exactly 32 bytes.
1612    pub fn encode(self) -> [u8; 32] {
1613        self.sec.encode()
1614    }
1615
1616    /// Signs a message with this private key.
1617    ///
1618    /// The data to sign is provided as `data`. When using raw data,
1619    /// the `hash_name` string should be an empty string; otherwise,
1620    /// `data` is supposed to be a hash value computed over the message
1621    /// data, and `hash_name` identifies the hash function. Rules for
1622    /// the hash name are identical to `Point::hash_to_curve()`.
1623    ///
1624    /// This function uses a deterministic process to compute the
1625    /// per-signature secret scalar. Signing the same message twice
1626    /// with the same key yields the same signature.
1627    pub fn sign(self, hash_name: &str, data: &[u8]) -> [u8; 48] {
1628        self.sign_seeded(&[0u8; 0], hash_name, data)
1629    }
1630
1631    /// Signs a message with this private key.
1632    ///
1633    /// The data to sign is provided as `data`. When using raw data,
1634    /// the `hash_name` string should be an empty string; otherwise,
1635    /// `data` is supposed to be a hash value computed over the message
1636    /// data, and `hash_name` identifies the hash function. Rules for
1637    /// the hash name are identical to `Point::hash_to_curve()`.
1638    ///
1639    /// This function uses a randomized process to compute the
1640    /// per-signature secret scalar. The provided `rng` is supposed to
1641    /// be cryptographically secure (it implements the `CryptoRng`
1642    /// trait) but signatures are still safe even if the `rng` turns out
1643    /// to be flawed and entirely predictable.
1644    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    /// Signs a message with this private key.
1653    ///
1654    /// The data to sign is provided as `data`. When using raw data,
1655    /// the `hash_name` string should be an empty string; otherwise,
1656    /// `data` is supposed to be a hash value computed over the message
1657    /// data, and `hash_name` identifies the hash function. Rules for
1658    /// the hash name are identical to `Point::hash_to_curve()`.
1659    ///
1660    /// This function uses a deterministic process to compute the
1661    /// per-signature secret scalar. The provided `seed` is included
1662    /// in that process. Having a varying seed (not necessarily secret
1663    /// or random) improves resistance to fault attack (where an
1664    /// attacker forces glitches in the hardware through physically
1665    /// intrusive actions, and tries to infer information on the private
1666    /// key from the result).
1667    pub fn sign_seeded(self, seed: &[u8], hash_name: &str, data: &[u8])
1668        -> [u8; 48]
1669    {
1670        // Make the per-signature k value. We use a derandomized process
1671        // which is deterministic: a BLAKE2s hash is computed over the
1672        // concatenation of:
1673        //    the private key (encoded)
1674        //    the public key (encoded)
1675        //    the length of the seed, in bytes (over 8 bytes, little-endian)
1676        //    the seed
1677        //    if data is raw:
1678        //        one byte of value 0x52
1679        //        the data
1680        //    else:
1681        //        one byte of value 0x48
1682        //        the hash function name
1683        //        one byte of value 0x00
1684        //        the data (supposedly, a hash value)
1685        // The BLAKE2s output (32 bytes) is then interpreted as an
1686        // integer (unsigned little-endian convention) and reduced modulo
1687        // the group order (i.e. turned into a scalar). This induces
1688        // negligible bias because the jq255e order is close enough to
1689        // a power of 2.
1690        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        // Use k to generate the signature.
1706        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    /// ECDH key exchange.
1716    ///
1717    /// Given this private key, and the provided peer public key (encoded),
1718    /// return the 32-byte shared key. The process fails if the `peer_pk`
1719    /// slice does not have length exactly 32 bytes, or does not encode
1720    /// a valid jq255e element, or encodes the neutral element. On success,
1721    /// the 32-byte key is returned along with 0xFFFFFFFFu32. On failure,
1722    /// a different key (unguessable by outsiders) is returned, along with
1723    /// 0x00000000u32.
1724    ///
1725    /// Processing is constant-time. If the `peer_pk` slice has length
1726    /// exactly 32 bytes, then outsiders cannot know through timing-based
1727    /// side-channels whether the process succeeded or failed.
1728    pub fn ECDH(self, peer_pk: &[u8]) -> ([u8; 32], u32) {
1729        // Decode peer public key.
1730        let mut Q = Point::NEUTRAL;
1731        let mut ok = Q.set_decode(peer_pk);
1732        ok &= !Q.isneutral();
1733
1734        // Compute shared output. If the process failed, our private key
1735        // is used instead, so that the derived key is unknown by outsiders
1736        // but still appears to be deterministic relatively to the
1737        // received peer bytes.
1738        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        // We use BLAKE2s for the key derivation.
1746        let mut sh = Blake2s256::new();
1747
1748        // If the source slice did not have length 32 bytes, then the
1749        // exchange necessarily fails and the memory access pattern is
1750        // distinguished from a success, so that we can use a separate
1751        // path in that case. We also do not both with ordering public
1752        // keys.
1753        if peer_pk.len() == 32 {
1754            // Compare the two public keys lexicographically, so that
1755            // we inject the "lowest" first.
1756            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        // Leading byte denotes the success (0x53) or failure (0x46).
1780        sh.update(&[(0x46 + (ok & 0x0D)) as u8]);
1781        sh.update(&shared);
1782
1783        // Output key is the hash output.
1784        let mut key = [0u8; 32];
1785        key[..].copy_from_slice(&sh.finalize());
1786        (key, ok)
1787    }
1788}
1789
1790impl PublicKey {
1791
1792    /// Creates and instance from a curve point.
1793    ///
1794    /// A panic is triggered if the point is the neutral.
1795    pub fn from_point(point: &Point) -> Self {
1796        assert!(point.isneutral() == 0);
1797        Self { point: *point, encoded: point.encode() }
1798    }
1799
1800    /// Decodes the provided bytes as a public key.
1801    ///
1802    /// If the source slice does not have length exactly 32 bytes,
1803    /// or the bytes do not encode a valid jq255e element, or the bytes
1804    /// encode the neutral element, then the process fails and this
1805    /// function returns `None`. Otherwise, the decoded public key
1806    /// is returned.
1807    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    /// Encode this public key into exactly 32 bytes.
1819    ///
1820    /// This simply returns the contents of the `encoded` field.
1821    pub fn encode(self) -> [u8; 32] {
1822        self.encoded
1823    }
1824
1825    /// Verifies a signature on a message against this public key.
1826    ///
1827    /// The message is provided as `data`, which is a hash value that
1828    /// was computed over the actual message data with the hash function
1829    /// identified by `hash_name` (see `Point::hash_to_curve()` for
1830    /// naming rules). If `data` contains the raw message data, to be
1831    /// used directly without an intermediate hashing, then `hash_name`
1832    /// shall be an empty string.
1833    ///
1834    /// Note: this function is not constant-time; it assumes that the
1835    /// public key and signature value are public data.
1836    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
1851/// Computes the 16-byte "challenge" of a signature.
1852///
1853/// The per-signature point R, encoded public key, and (hashed) data
1854/// are provided. Use an empty string for `hash_name` if the `data`
1855/// is raw (unhashed). This function is used for both signature generation
1856/// and signature verification.
1857fn 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// ========================================================================
1877
1878// We hardcode known multiples of the points B, (2^65)*B, (2^130)*B
1879// and (2^195)*B, with B being the conventional base point. These are
1880// used to speed mulgen() operations up. The points are moreover stored
1881// in a three-coordinate format (e, u, u^2).
1882
1883/// A point in affine extended coordinates (e, u, u^2)
1884#[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
1914// Points i*B for i = 1 to 16, affine extended format (e, u, t)
1915static PRECOMP_B: [GF255e; 48] = [
1916    // B * 1
1917    GF255e::w64be(0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
1918                  0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFB722),
1919    GF255e::w64be(0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
1920                  0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFB724),
1921    GF255e::w64be(0x0000000000000000, 0x0000000000000000,
1922                  0x0000000000000000, 0x0000000000000001),
1923    // B * 2
1924    GF255e::w64be(0x65E0A72F05397829, 0xCBC14E5E0A72F053,
1925                  0x97829CBC14E5E0A7, 0x2F05397829CB8754),
1926    GF255e::w64be(0x4924924924924924, 0x9249249249249249,
1927                  0x2492492492492492, 0x4924924924921F82),
1928    GF255e::w64be(0x414E5E0A72F05397, 0x829CBC14E5E0A72F,
1929                  0x05397829CBC14E5E, 0x0A72F05397827791),
1930    // B * 3
1931    GF255e::w64be(0x6E6BA44DDB3919FD, 0x4D5065C0BA270925,
1932                  0xAD8273027F0E7D48, 0x26AFA803D61A9E2F),
1933    GF255e::w64be(0x12358E75D30336A0, 0xAB617909A3E20224,
1934                  0x6B1CEBA6066D4156, 0xC2F21347C4043E79),
1935    GF255e::w64be(0x7287BBB2DC59141C, 0x0509961D71E284EF,
1936                  0xC58EF652F0485A50, 0xC4FAF5442BDDB3C7),
1937    // B * 4
1938    GF255e::w64be(0x70EC8E896A9E26BB, 0x691B44636A4256DB,
1939                  0x3400B87117DA45FB, 0x4318414607C6AB0F),
1940    GF255e::w64be(0x05B837449A5D608E, 0xECF205B837449A5D,
1941                  0x608EECF205B83744, 0x9A5D608EECF20278),
1942    GF255e::w64be(0x2375E8119918E929, 0x03ADCBE22101F311,
1943                  0x853223D7F44E59F2, 0x4D0A213B4402088D),
1944    // B * 5
1945    GF255e::w64be(0x45C1EDAE67F29B6C, 0x8BCFBBBB4324F63F,
1946                  0xE427EAA88C3BEE68, 0x2DC2D3741789EEBB),
1947    GF255e::w64be(0x67AFCB2DAF089728, 0xA7990E074CA048F3,
1948                  0x1BF074743BB5F39C, 0xE0D494F725A47337),
1949    GF255e::w64be(0x3E3560E7BB5DF4DA, 0x8982206A724B43CC,
1950                  0xE00C1E20C1C66FF4, 0xC91927493D361051),
1951    // B * 6
1952    GF255e::w64be(0x6DB05620A7BB37FB, 0xE98C3A469592D1D5,
1953                  0x38EDF8B7F8B8E188, 0x9BC52C6FDD64E133),
1954    GF255e::w64be(0x30592749502236D4, 0x5E54F462670CA0FF,
1955                  0x44B5BEF2D9C9EF58, 0xF42F3A0E06E24C0D),
1956    GF255e::w64be(0x34F3562FDA88753E, 0xD7991971E94A460E,
1957                  0x76ED99CCAEE9D26F, 0x355D1614AEB11ACD),
1958    // B * 7
1959    GF255e::w64be(0x4C5C3FA382AAF7AC, 0xC36F69694BFC77E7,
1960                  0xD86308C5232C88D0, 0xE8D6CBC7678229FB),
1961    GF255e::w64be(0x6DD8CDFA520AED5A, 0x350914B3EE64BF7F,
1962                  0xB885C9D1EB4CC9E1, 0x7EB52414159EF4EA),
1963    GF255e::w64be(0x56861F4D0A217C1C, 0x0957AB7A60AC1520,
1964                  0x818C73930C2A0899, 0x59DAD0E634C75544),
1965    // B * 8
1966    GF255e::w64be(0x536DD4D34D59EB93, 0x7952681BD02A45B6,
1967                  0x5277E004AEA16EEC, 0xB1EE3EECACE73BFD),
1968    GF255e::w64be(0x3899CEA405D19C1A, 0x3AB270B8E0887316,
1969                  0xF8F94746A2120378, 0x6625736C14AE7C9A),
1970    GF255e::w64be(0x532698BCB811270A, 0xF3C520B8FCA311FD,
1971                  0x89B68A9C8B0077A8, 0x4D9B8F5639729F9A),
1972    // B * 9
1973    GF255e::w64be(0x5D760C5405D6CFAF, 0xAA492C177AD3E4F4,
1974                  0x98A1A433C755E87B, 0x904992094ACFFA61),
1975    GF255e::w64be(0x16A802006BF1BEA6, 0xB6738274FE0973BF,
1976                  0xD816F7B2ECD3353E, 0x57B5D8562F5F28C4),
1977    GF255e::w64be(0x431DA1A672CB2D3C, 0x56244B8A32B42796,
1978                  0x76CA668F88C812F9, 0x8D2F2DE6815F2EFF),
1979    // B * 10
1980    GF255e::w64be(0x30290CF961B06E3A, 0xAF5539730762C505,
1981                  0x803FC1C6AAD5CD46, 0x8EB44683ACC048BE),
1982    GF255e::w64be(0x7B37113C916F803C, 0x4AA37581A9B6AD5E,
1983                  0x55838146CC140A37, 0x3AA366BBB889903E),
1984    GF255e::w64be(0x252DC97C189ECFD9, 0x9EDDA370E828C438,
1985                  0xC70EAC518AE5C163, 0xD912EBC4E1C6283E),
1986    // B * 11
1987    GF255e::w64be(0x467C84CA2424A548, 0x6F385F29F643AF23,
1988                  0x09DF0EB0A3919A65, 0x38A7E99599D93A3B),
1989    GF255e::w64be(0x158521078CD1F209, 0x8C133221E772B327,
1990                  0x65CF6B9CAB741725, 0xA9A8911D864E7F82),
1991    GF255e::w64be(0x5D4A07E9BC1F036B, 0xC3FC1F026C5406EA,
1992                  0xFAE4DC5553E938EB, 0x41583C9A8F92D685),
1993    // B * 12
1994    GF255e::w64be(0x19007B50A56088E6, 0xB4C47837DC725B4E,
1995                  0xF9192F3072387F81, 0x5B65EC077C403B92),
1996    GF255e::w64be(0x1819A3081E878CBC, 0xAC10CA6CD1ED6814,
1997                  0x046FD295C10A2A1F, 0x1B3E38DAF789767B),
1998    GF255e::w64be(0x2213A3D93959DA85, 0x4742F3CB3DEB52CB,
1999                  0xAE5BB5318E506208, 0x4203ACE2FF9309B4),
2000    // B * 13
2001    GF255e::w64be(0x118FC94162B377A4, 0xC1844EC2004952D2,
2002                  0xDDA789FB4A2D58E9, 0x5669DD87D12F7002),
2003    GF255e::w64be(0x68069289CF95CA7F, 0x6ECDFF0332EC6927,
2004                  0x982FC6B00D403467, 0x6F077C677EF99DC0),
2005    GF255e::w64be(0x0E2364672DB22F61, 0x028EBB02AB0AE384,
2006                  0xE02396E9E43361F5, 0xF1F0EC984099DC93),
2007    // B * 14
2008    GF255e::w64be(0x0B3C9854075F7676, 0xF968F7338F922CF2,
2009                  0x5A668C22A3492EE9, 0x3939F44CF0DA9535),
2010    GF255e::w64be(0x3D37FCBAB8595FB5, 0x83925568F9CA1E3F,
2011                  0x5FE95976F2881B19, 0xFA4B698C2D5375B3),
2012    GF255e::w64be(0x0C4AC28DE6AF9B7D, 0xE13C4A7639E5E234,
2013                  0x41B211E505C5A659, 0x0266FAA875DEF4DC),
2014    // B * 15
2015    GF255e::w64be(0x6EEF26D87D3B6832, 0xDA84A01A1181FE26,
2016                  0x9D9DD93F615DEFAA, 0xABC55F7A179D927E),
2017    GF255e::w64be(0x50B35D49D9A28BA9, 0xB52E059B6051E0F8,
2018                  0x8FA2EDA8E408B67B, 0x8005B508E6EDAFFE),
2019    GF255e::w64be(0x0CCF7FF00D563132, 0xCC7CCE327009957D,
2020                  0x54BD0CFFC1B29AC7, 0xB111F1B5F7C6525E),
2021    // B * 16
2022    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
2030// Points i*(2^30)*B for i = 1 to 16, affine extended format (e, u, t)
2031static PRECOMP_B30: [GF255e; 48] = [
2032    // (2^30)*B * 1
2033    GF255e::w64be(0x13CA1147905FCBF5, 0x52326246403CA5BF,
2034                  0x3C35D84AA762ECE3, 0x907DB8CBF42BC887),
2035    GF255e::w64be(0x21807A9E869F9959, 0x1A5450AEA131BEFF,
2036                  0xD8A529F6B8C7B090, 0x7CC2003EE88F4078),
2037    GF255e::w64be(0x3AEE62CB93CED7F1, 0x7067AB25891EE3B5,
2038                  0xF718381811963DB2, 0x73FBF78B8823C053),
2039    // (2^30)*B * 2
2040    GF255e::w64be(0x1F0B55F7538062C6, 0xF5F7EC08D23CBB26,
2041                  0x9FDF60EC98F382F9, 0x085234005B2AB43E),
2042    GF255e::w64be(0x2A01A7A66A64F8DE, 0x165DCC5F4ADC9ACF,
2043                  0xC8364B4B5B081003, 0x93B71E8B59F69390),
2044    GF255e::w64be(0x3B685E42E10E7D85, 0xA4740FCA9242B2B1,
2045                  0xCB8F01643355CDCC, 0x4C40F18C5B63A979),
2046    // (2^30)*B * 3
2047    GF255e::w64be(0x20580EA099D82FC7, 0x392A3EFC5FB42AF4,
2048                  0xE6DBF5BFBFA90AD6, 0x0A700BA2732E6D3B),
2049    GF255e::w64be(0x344DC3902A2BB913, 0x3CD6D4F887D5ADBB,
2050                  0x0D1F0F40860C8B79, 0xE696F91B6027E51B),
2051    GF255e::w64be(0x5B06BAC6615CFE93, 0x121D9D81E43446B7,
2052                  0x01B0E0FE346B8431, 0x4C0B7DC3E9389D91),
2053    // (2^30)*B * 4
2054    GF255e::w64be(0x035262D6FA42CCD9, 0x931C814DF00837A5,
2055                  0xC4C14E9CCDB62641, 0xE72798BFE43FF79F),
2056    GF255e::w64be(0x7F5A47C4B8A71462, 0xEA5542F0423A6B08,
2057                  0x7D627151D46A1F28, 0x0ECCB2E2278F9787),
2058    GF255e::w64be(0x40F104BED34B471B, 0xD6443D61DA82B80B,
2059                  0xE3DDBBE02A015838, 0xCBA8747656E79C58),
2060    // (2^30)*B * 5
2061    GF255e::w64be(0x71C205F522D89932, 0x82D85463B52A35E6,
2062                  0xA9100D1A84D2984B, 0xFA3DE32CCB7A9574),
2063    GF255e::w64be(0x4CA23E185D27384C, 0x1118B84EFBABE26A,
2064                  0x32A77CB45507DF64, 0x32EDBA4A0D03AA4B),
2065    GF255e::w64be(0x7E407DF2A38A26C7, 0xB84215DB55AC3228,
2066                  0xCA1887B16E532444, 0xBFCFC5A884A0529A),
2067    // (2^30)*B * 6
2068    GF255e::w64be(0x7B331EF6B0BB0807, 0xF996B645F02F7435,
2069                  0x2A1FD6F2C3D03ED9, 0xFE3ADDEB0040571C),
2070    GF255e::w64be(0x7BFDA5402A7099E1, 0x554EE5C206C34691,
2071                  0x835EF867125662CE, 0xA09544EF1016424A),
2072    GF255e::w64be(0x5619E82C5020A665, 0x208F3395E8B0B098,
2073                  0x2CDCF267BD76607D, 0xF10534DCFB398915),
2074    // (2^30)*B * 7
2075    GF255e::w64be(0x3AAD0F388C740A4C, 0x5C2275E090803FF7,
2076                  0xD5905F5975C11A6A, 0x7C8644BA3F31E86B),
2077    GF255e::w64be(0x6489741694C2DB65, 0xAF6326F66B245EBA,
2078                  0xBDAB7C7103D81CC4, 0xAC15C4E14810B01D),
2079    GF255e::w64be(0x724D3E13C3B6EAB8, 0x055E3DDC866AEBA3,
2080                  0x6324B89BD96935CE, 0xCAE36C5E76A80C0A),
2081    // (2^30)*B * 8
2082    GF255e::w64be(0x6ECA645765B3F184, 0xAC888AF902D3F2F6,
2083                  0x23B990A9715300BD, 0xEAE77CD5A217B5D7),
2084    GF255e::w64be(0x687C7F6805609029, 0x7DFB6BBCF4D4B95C,
2085                  0x03FD10706E8EC9E3, 0x37DA5CC5DF7466C6),
2086    GF255e::w64be(0x0A557BAA6263696D, 0x4ED35671F7B6DB07,
2087                  0x6DDDF7B4D68A7534, 0xA44FD3085FE84D18),
2088    // (2^30)*B * 9
2089    GF255e::w64be(0x4D5A31F81E16CAFF, 0x4E475474481F6751,
2090                  0x7707A1054E57DBAB, 0x228358287E4B16B5),
2091    GF255e::w64be(0x1CF5388644F4CE58, 0x7E38C6B544AA249B,
2092                  0xFAD21ABA6C967EB2, 0x5B1BA39F15E5BA43),
2093    GF255e::w64be(0x183B4E113203FB02, 0x33591AA143EE1F0E,
2094                  0xF41F3F8FF5B2D5E6, 0x3F1703B436F4194D),
2095    // (2^30)*B * 10
2096    GF255e::w64be(0x52897BFEAB1D3143, 0x28E16088AC8DD35A,
2097                  0xEA6AC104B4377B37, 0x0A811568C23ED90B),
2098    GF255e::w64be(0x002DE451776F7575, 0x3E060714E384BC65,
2099                  0xE84AD604731B838E, 0x9AE461EC05877BB3),
2100    GF255e::w64be(0x5FDCB9FB3F4C5797, 0x4046647612284F1C,
2101                  0x542A5F62FD3D5C15, 0xDBEE341D80A8F52B),
2102    // (2^30)*B * 11
2103    GF255e::w64be(0x7B1E1E0BB13A0D6E, 0x2E6F086CE5352381,
2104                  0xF3F02ECDB61A483C, 0xCFC498866CBD23AE),
2105    GF255e::w64be(0x0385B60F3A5A829E, 0x4663742D210BCFBC,
2106                  0xA7FC1E3D6835CE52, 0xC7DB9CBFAD8ED920),
2107    GF255e::w64be(0x3CFEE0A952259507, 0xD0C22765111F323D,
2108                  0x29C93C6A6818E347, 0xDDC8215D410F748E),
2109    // (2^30)*B * 12
2110    GF255e::w64be(0x440B9571A929A001, 0x616ADFF6E1A940B6,
2111                  0x9D09F8A5348BF0A4, 0xF5C70615A2446EDD),
2112    GF255e::w64be(0x1C34B1769CD9E8C0, 0x460D033431555AFF,
2113                  0x8F3A5C73FE927246, 0xF1EFD63E64A23B70),
2114    GF255e::w64be(0x2E6C853FDF78D4ED, 0xFBAE6180855FFB65,
2115                  0x708D63C96ECE5F95, 0x76BE8AA8492971C8),
2116    // (2^30)*B * 13
2117    GF255e::w64be(0x3060A8FFD41ACB33, 0xBD87FEECB7B9BB70,
2118                  0x687781C1CD697D56, 0x43D0702FEEDA9F23),
2119    GF255e::w64be(0x098A2753C0DBF107, 0xE0407DAF679B0D54,
2120                  0x9AEB5F577D172973, 0xEEEBCA9CDAC6A674),
2121    GF255e::w64be(0x4CAC1DF8F2DD5B83, 0x833BAD3C72274AFD,
2122                  0x3C87C94A681CC18A, 0xB54EC85B102F1B29),
2123    // (2^30)*B * 14
2124    GF255e::w64be(0x1F74F35992B895FB, 0x27E87DC21466BE9F,
2125                  0x5B91677373AE781D, 0x07B29BD4692B324D),
2126    GF255e::w64be(0x5621598564421391, 0x680C35679657B7D9,
2127                  0x35C8698010EE5359, 0xB1367E5D176D57AE),
2128    GF255e::w64be(0x132D657EED4666C6, 0xAF951851C14759B1,
2129                  0x6F7B4359EFDC6B41, 0x226AE41DE0FE7D8B),
2130    // (2^30)*B * 15
2131    GF255e::w64be(0x42B8E1E2340C4287, 0x6802040565529D9F,
2132                  0x49890999F86805A3, 0x8CA7E11E18A667E0),
2133    GF255e::w64be(0x2FA5817BF1E95411, 0x07444FF660C223DB,
2134                  0xA3CD06160A4F17D9, 0x0B25611A486A0DD3),
2135    GF255e::w64be(0x5133112D58780265, 0x01553E2CF86C3AB4,
2136                  0x49DF33855A03D435, 0xA05CF4F734DB0C34),
2137    // (2^30)*B * 16
2138    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
2146// Points i*(2^65)*B for i = 1 to 16, affine extended format (e, u, t)
2147static PRECOMP_B65: [GF255e; 48] = [
2148    // (2^65)*B * 1
2149    GF255e::w64be(0x131F48849CB5AC4A, 0x54C453E54BE22F73,
2150                  0xB9D67A9106B8CB54, 0x779009D871F79606),
2151    GF255e::w64be(0x64CEC2C957589D91, 0xC6A2DE7E1AF5BC7B,
2152                  0xBEA76CAB621DDC00, 0x52A070403A68BCB4),
2153    GF255e::w64be(0x6E78594A21A5AAD2, 0x48E8393CFF13EC0E,
2154                  0x222B7C0CD599D9CB, 0x17E71DD1EB9D832B),
2155    // (2^65)*B * 2
2156    GF255e::w64be(0x0ADECEF07226CD6D, 0x7559D60B3193DA7D,
2157                  0x1BA7B3E1CBE84C19, 0xEEE6DD38D8E9151C),
2158    GF255e::w64be(0x741A90CA667A29FD, 0xA32D826F66894018,
2159                  0xB35B3FB65A19A30B, 0xD483D08E776177F2),
2160    GF255e::w64be(0x40534B306985620E, 0x6C805A5DABAECD17,
2161                  0xC9233D8219ECC70E, 0xC699D8CD1BE2027B),
2162    // (2^65)*B * 3
2163    GF255e::w64be(0x390940AD8D0885BF, 0x7B11CD4B6C9CC38D,
2164                  0x5A40972FCDA92791, 0x33F6746ED6A45A0E),
2165    GF255e::w64be(0x098D3AB90B09C2B4, 0x0519A68AAB4295EB,
2166                  0xAF41508342D7801D, 0x4A504A5DED61CB7F),
2167    GF255e::w64be(0x41A590927B5F6FD7, 0x0696A39545C181DE,
2168                  0x92D534263FFE78C9, 0xA06F9DAD59A456C6),
2169    // (2^65)*B * 4
2170    GF255e::w64be(0x6F29FAC9056CB53E, 0x4265FDF93F20B5C4,
2171                  0x1522644129185A8F, 0x93B1A7E3CD5855D2),
2172    GF255e::w64be(0x4ABF14CD5591D3DC, 0xC47BA10C5052CE6E,
2173                  0xA5F032C51EF980F7, 0x26744CD17E4ADE86),
2174    GF255e::w64be(0x6470D11011381CFF, 0x893FFC0CA3CB3C98,
2175                  0x4563C7AD47CE6A39, 0x1D5909B1A76336E1),
2176    // (2^65)*B * 5
2177    GF255e::w64be(0x742236A2B9985165, 0x9AE9B0736E87C51E,
2178                  0x74427A8818227B9E, 0x648443E48591C275),
2179    GF255e::w64be(0x4B36B3BE374E74CB, 0x9DD36D925FB45810,
2180                  0x695C5863633AC0BB, 0xDB2EB15DD80EB7AB),
2181    GF255e::w64be(0x7563AAD0685E3293, 0x52217A6F3280BAD3,
2182                  0xBCF6E190CBC99BC3, 0x3B02030497F19A1B),
2183    // (2^65)*B * 6
2184    GF255e::w64be(0x637BA56A42C4587D, 0x9318569D6BC1A5D5,
2185                  0x748A8C77D6669E2A, 0xD8AD585D0C14DC83),
2186    GF255e::w64be(0x143CF8A090ACB085, 0x0C0776C9F6ED32DE,
2187                  0x763067186E58108F, 0x2473D6DB1425C001),
2188    GF255e::w64be(0x2C301B6BCC1F09C1, 0x3A3345F98418DD26,
2189                  0xDE3B04BA9040AF87, 0x73CDF9E505579C38),
2190    // (2^65)*B * 7
2191    GF255e::w64be(0x5C780EAA96A1BB91, 0x1094A46B6F56FA43,
2192                  0x0E16666D8273B21D, 0xE14526AA9D051B56),
2193    GF255e::w64be(0x7EE7B8C1D61C83DD, 0xBAC06821F2BF788C,
2194                  0x33088969E8FB612B, 0xE95E218127D26209),
2195    GF255e::w64be(0x72AB912B16C33383, 0x617E1C89A1A25303,
2196                  0x624FFDB35FA59240, 0x0474E6971F3502A9),
2197    // (2^65)*B * 8
2198    GF255e::w64be(0x6B3865BE473732FF, 0xE95C514D17DD5343,
2199                  0xD6C684EDF26076D9, 0xE800A094D67CC3ED),
2200    GF255e::w64be(0x235872299B5B142E, 0x34DFEFB2A6C39FFC,
2201                  0x3260DA08A5D337CB, 0x4C033B2301944CB8),
2202    GF255e::w64be(0x2961CB37E34C35A1, 0x7B1EF0DEBBFAA0EE,
2203                  0x08AA04266FC23C15, 0x439324FCD04090FB),
2204    // (2^65)*B * 9
2205    GF255e::w64be(0x32138C48916B15C7, 0xF8815AEC9C0105B4,
2206                  0xDD56EA4894B8F6C1, 0xE7847250A19EF549),
2207    GF255e::w64be(0x07DF0CC5D7C9E88D, 0xADD356D1CA14E352,
2208                  0x53193A718D75331F, 0x6742B67C6086DF92),
2209    GF255e::w64be(0x713B783B3766078D, 0x0D31937E03003B68,
2210                  0x643500CDE6FADF0D, 0x5C9C41C3B8594D9B),
2211    // (2^65)*B * 10
2212    GF255e::w64be(0x5C9329786A90B198, 0x83A3CE92BEFEC84E,
2213                  0x4FD5981D24E25FBE, 0x25F90BCEB299A5D0),
2214    GF255e::w64be(0x79E82E420C17C457, 0x3F6064CC7E287D25,
2215                  0x476A1D01EBBFE2BB, 0x7982C54051C4DF08),
2216    GF255e::w64be(0x1813C6ED70DAFA38, 0x27984BF87B6F0AD1,
2217                  0x73165189E2EF99F8, 0x8CE01EA2E8B54114),
2218    // (2^65)*B * 11
2219    GF255e::w64be(0x4515BBA1AEAFD937, 0x8D0D667D16879C64,
2220                  0x383BFB84CDDA791E, 0x7CAD33020884167D),
2221    GF255e::w64be(0x3CC8BC3168B5A376, 0xB97069DD65593890,
2222                  0x854CBABF2D02F041, 0x00FF128613403E58),
2223    GF255e::w64be(0x058DA5FED462C39D, 0x206DA25D9FE2783E,
2224                  0xF8F2F98E5BEF4381, 0xC303EBB8F65D98BA),
2225    // (2^65)*B * 12
2226    GF255e::w64be(0x419A7DEC26A3D7FA, 0x97A6D06EB281AE98,
2227                  0xB0DF0BF1929E91A1, 0x8EE71CA88021D1F8),
2228    GF255e::w64be(0x2E344D49A48AE286, 0xDCBB82BD08CEE05A,
2229                  0x5AF4A67AE9C4AE24, 0xC97787D39A76E4A1),
2230    GF255e::w64be(0x60570F440CB85A8A, 0x15EB451E43025B6A,
2231                  0xDC1EF290D77A0305, 0x877FB541EB5BEC17),
2232    // (2^65)*B * 13
2233    GF255e::w64be(0x40255DC81F644B88, 0x3CA545A989E728B3,
2234                  0x0DAC5E2EBE8D1017, 0xBF9758CD45295FBE),
2235    GF255e::w64be(0x052051EDAFC87131, 0xAA36C89F8D5B502A,
2236                  0xFDEE555C9009703F, 0x6AF277E67A9FAA68),
2237    GF255e::w64be(0x50C64067319D2237, 0x0F6D233DC4F2C4BA,
2238                  0x9B85D45C9AA3A8E1, 0xDED77C4486AAB04C),
2239    // (2^65)*B * 14
2240    GF255e::w64be(0x1CE1017108071F0B, 0x71830A04FECF5B00,
2241                  0xADED92BC897B71B1, 0xEC2944EFB6EED8F5),
2242    GF255e::w64be(0x0E7D16D056A9DF14, 0xDEBD7D4FDDF67479,
2243                  0x096B209129DDE65F, 0x795B6B03F7146048),
2244    GF255e::w64be(0x136A3753275A04FE, 0x2F8383D036FFDEC3,
2245                  0x6E06A2EFFBF79614, 0x8A96C7C2F4D51B6A),
2246    // (2^65)*B * 15
2247    GF255e::w64be(0x09C0518DA671868A, 0xBF13A51C8C3DB802,
2248                  0x533027C62A4254F0, 0x714774712F78D8DC),
2249    GF255e::w64be(0x406E88577206C6C4, 0xEDF6131ABB08D620,
2250                  0xAE53B9A6D617E037, 0xD25E4076E71417FD),
2251    GF255e::w64be(0x7A35DA9A106BD4A6, 0x69CB583FD3DDA8C2,
2252                  0x5FD6950193780470, 0xA7B19AB7E5261DBE),
2253    // (2^65)*B * 16
2254    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
2262// Points i*(2^95)*B for i = 1 to 16, affine extended format (e, u, t)
2263static PRECOMP_B95: [GF255e; 48] = [
2264    // (2^95)*B * 1
2265    GF255e::w64be(0x064AA342C59C0DA0, 0xFAA44349B6734FEB,
2266                  0xD30B1C84CDE9765C, 0xB766DECCD7834FF7),
2267    GF255e::w64be(0x119D5D1A55EC18E7, 0x28C31FF060305E40,
2268                  0xFD06B4B9CEDAC228, 0x7ACD061D37C3D1D6),
2269    GF255e::w64be(0x0DD8CA46CB20E0DD, 0xE43FA70510BFE509,
2270                  0xECE63FBCDBED83DA, 0x926FC4E7B0289F0D),
2271    // (2^95)*B * 2
2272    GF255e::w64be(0x78FC954AD8D52006, 0x44C3AEC51F2964F2,
2273                  0xC312AE3005158590, 0x18F98B63350A8752),
2274    GF255e::w64be(0x7AD8E671EE17C670, 0x3313ED7AAB04D140,
2275                  0x91B847ED26B6CF94, 0x0BD0148E77CE6A5E),
2276    GF255e::w64be(0x3297466638BBC445, 0xC8B94BDE93D3D902,
2277                  0xCE649E0260C40EFC, 0x698A7797F808A2C7),
2278    // (2^95)*B * 3
2279    GF255e::w64be(0x547CD638F8AF40BB, 0x694F8ED466CC3C37,
2280                  0x16E8ABF34D5A844C, 0x09409889B0E98F27),
2281    GF255e::w64be(0x7D8AD1764CED7A3F, 0x809AF4FF01016ACA,
2282                  0x6148669B1336FCEC, 0xDD11E9CDAF91678A),
2283    GF255e::w64be(0x4B6AD6950FFA9CBA, 0x9B1CB599B9C46D93,
2284                  0xE5BCC800B27EACD0, 0x9B72E257C7E326A2),
2285    // (2^95)*B * 4
2286    GF255e::w64be(0x613C8ECBF0A848FC, 0xA564AA42C0C97700,
2287                  0x38702E4B6A61439F, 0x924CF8F624C8F8B9),
2288    GF255e::w64be(0x63A19A4AC2160C37, 0x11ABC58D9EF7F4CE,
2289                  0xBEB8664E3B46464B, 0xCFA2A379144F4EE3),
2290    GF255e::w64be(0x62DC6DBA747D1E89, 0xA127C8EDEF4200D0,
2291                  0x48056960613E4959, 0x6692BE27FA7A1351),
2292    // (2^95)*B * 5
2293    GF255e::w64be(0x25A6EC411F77CB78, 0xCF69A4B2A11A4469,
2294                  0x6B4EB9B6E6D5AB02, 0x0B43FA3ECF550A24),
2295    GF255e::w64be(0x03C98282001ADFA6, 0x4E9D1C740827ACB5,
2296                  0x5D18C2E1F33671B6, 0xBE3D87A48426EBF8),
2297    GF255e::w64be(0x7115EE66A4C38C36, 0xC01DBE749F798A3C,
2298                  0x6B6A0A0C660809E0, 0x1953D2EF4892BC98),
2299    // (2^95)*B * 6
2300    GF255e::w64be(0x56AE980BD465F711, 0x396287DA54A2D27E,
2301                  0x24B76B26F2E1DC5F, 0x084F3670B14FCFE3),
2302    GF255e::w64be(0x68FE969D595DA557, 0xA5B443E88C8A995B,
2303                  0xCA00F145963AEB78, 0xAD0F1CF8D4A2A9ED),
2304    GF255e::w64be(0x5E30E5A5B1B6CF94, 0x0E53A7329BDB49DB,
2305                  0x20E070005600A972, 0xA34F29143251910F),
2306    // (2^95)*B * 7
2307    GF255e::w64be(0x39DD38009BECF484, 0xCA293874749E2E36,
2308                  0xEC50E5B1342F274F, 0x69D091B933C51A9D),
2309    GF255e::w64be(0x61EA99C35B5C8714, 0x73EB7E911AFAB636,
2310                  0x9592E0C84567F3E0, 0xD0490A8282D23DAC),
2311    GF255e::w64be(0x653961AD8EA3C366, 0x657DED2350C83F99,
2312                  0x13E2CD23184CD0F6, 0xEE17FED2BAD25EAE),
2313    // (2^95)*B * 8
2314    GF255e::w64be(0x2DDAB2D5C942F940, 0xB115E746EE5CE792,
2315                  0xCB08BD516DAF829A, 0xAC1B5F5EC677FCD5),
2316    GF255e::w64be(0x50E1C5CB1035BA92, 0xE61AA40355321930,
2317                  0x769600329037F973, 0x2B462BE2026F26BF),
2318    GF255e::w64be(0x0A74F122D11A9C92, 0x3DD40D9211FE4955,
2319                  0x94C64564B78FC4EE, 0x0D609806ABA20D95),
2320    // (2^95)*B * 9
2321    GF255e::w64be(0x40DE5F775041CCAB, 0x73DD00B07B577D81,
2322                  0x480C472D1D6FD5F9, 0x1B1FBEAECBC67597),
2323    GF255e::w64be(0x7F172F027F7D714B, 0x7ADC900272DBFC13,
2324                  0xF6FA872F9B5F7D84, 0xDFACD7B8DF4BD3FD),
2325    GF255e::w64be(0x64A0666FB8EFAEFD, 0xE43A2E53396F5703,
2326                  0x7B4423C03DA78BB2, 0x1A2ECB81239BA603),
2327    // (2^95)*B * 10
2328    GF255e::w64be(0x483FC465507787CD, 0x6EB1438B4C5E389C,
2329                  0x8A501C2572F5F3FA, 0xA51D77D1040D73BE),
2330    GF255e::w64be(0x67CA12B3AA2B3592, 0x9A613CA0B8D3CC03,
2331                  0x65C3630287E6F750, 0xF143D0A2D8197B12),
2332    GF255e::w64be(0x3CF43FC1A0AACBB2, 0x82DAE17DC8A1D998,
2333                  0x77117A96356E0823, 0x66EA45588D44B244),
2334    // (2^95)*B * 11
2335    GF255e::w64be(0x7FFDB40231B7728D, 0xE467A2F1BBD605FC,
2336                  0x9381100ED4068C36, 0xE9CA1BD79F88055A),
2337    GF255e::w64be(0x4E531B74E4EDBC3B, 0xE53148AEAF77C797,
2338                  0x636E3907AEE17932, 0xE828BF5DAFD9FBA0),
2339    GF255e::w64be(0x3BFF8E3C1DCB6A65, 0x7E88F8DB430F4FCE,
2340                  0xCF59614C8ED50CF4, 0x33176787CD1F7BC6),
2341    // (2^95)*B * 12
2342    GF255e::w64be(0x7DC8FDD36CEC85F6, 0x5EBABED548F85E28,
2343                  0x7EDC5478A24A247C, 0x4FE60DBAC12937B5),
2344    GF255e::w64be(0x14AAD6B599A78A1E, 0x59164ECA80DBC2BC,
2345                  0xA8C14E4C401A8725, 0x66D1C4E7F84DBCB7),
2346    GF255e::w64be(0x6AB96CBAD2CE2586, 0x5EAF9F16DAFF788D,
2347                  0xB1D294C4F04CF4AD, 0x80FD38F7897A80E2),
2348    // (2^95)*B * 13
2349    GF255e::w64be(0x3BC04AFD4061401B, 0x306E5F900F95B543,
2350                  0xA53CBD8CD928AFCF, 0x87DC988002BBDBAF),
2351    GF255e::w64be(0x08D948612F474B91, 0xDF2876502B201BC0,
2352                  0x448EC22797892CBB, 0x7C38EDBD8C233710),
2353    GF255e::w64be(0x1CA7F5781A92A0F3, 0x979AD724BC3DA9A7,
2354                  0x89FC8B82D263BE84, 0x17B5FC58F1356C46),
2355    // (2^95)*B * 14
2356    GF255e::w64be(0x20016465EBA3350C, 0x3FBE5678BAC454E5,
2357                  0x5E2423EAACCF1E4D, 0xF264480132A6E2C3),
2358    GF255e::w64be(0x0E4BBBA7186F99D8, 0x6F473508FECBBD48,
2359                  0xF18F65CE65A3396F, 0x4945F8F959B9DE26),
2360    GF255e::w64be(0x084DC6999483CA11, 0x92A119A8ABB18530,
2361                  0x05FAF50A98B3E130, 0x19015F2BFA19C676),
2362    // (2^95)*B * 15
2363    GF255e::w64be(0x1CEBB3668FBDD74E, 0xDB22A366E6177378,
2364                  0x13BC29C94FAF4AEF, 0x6E86AA974593CF40),
2365    GF255e::w64be(0x772B639D97FD5F72, 0xC1EA09F19EA3A887,
2366                  0xA8938E24467348C8, 0xA71611FBE0733F1D),
2367    GF255e::w64be(0x3155981ADF087198, 0x67B9E52CE3D3192F,
2368                  0x8590411621A233CB, 0x4271B7E0FC853D04),
2369    // (2^95)*B * 16
2370    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
2378// Points i*(2^130)*B for i = 1 to 15 (odd only), affine extended format
2379static PRECOMP_B130_ODD: [PointAffineExtended; 8] = [
2380    // (2^130)*B * 1
2381    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    // (2^130)*B * 3
2390    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    // (2^130)*B * 5
2399    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    // (2^130)*B * 7
2408    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    // (2^130)*B * 9
2417    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    // (2^130)*B * 11
2426    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    // (2^130)*B * 13
2435    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    // (2^130)*B * 15
2444    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// ========================================================================
2455
2456#[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    /* unused
2465
2466    fn print_gf(name: &str, x: GF255e) {
2467        print!("{} = 0x", name);
2468        let bb = x.encode();
2469        for i in (0..32).rev() {
2470            print!("{:02X}", bb[i]);
2471        }
2472        println!();
2473    }
2474
2475    fn print(name: &str, P: Point) {
2476        println!("{}:", name);
2477        print_gf("  E", P.E);
2478        print_gf("  Z", P.Z);
2479        print_gf("  U", P.U);
2480        print_gf("  T", P.T);
2481    }
2482    */
2483
2484    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        // These values cannot be decoded (w is out of range).
2510"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        // These values cannot be decoded (w matches no point).
2532"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        // Each group of 6 values is encodings of points:
2556        // P1, P2, P1+P2, 2*P1, 2*P1+P2, 2*(P1+P2)
2557        [
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            // Build pseudorandom s1 and s2
2827            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            // Build pseudorandom A, u and v
2857            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            // Compute u*A + v*B in two different ways; check that they
2868            // match.
2869            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        // Each group of two values is: input bytes, mapped point
2877        [
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        // For i = 0..99, hash-to-curve using as data the first i bytes
3013        // of the sequence 00 01 02 03 .. 62  (raw data, no hash function)
3014"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        // For i = 0..10, hash-to-curve using as data the BLAKE2s hash of
3118        // a single byte of value i.
3119"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        // Each group of five values is:
3155        //   private key
3156        //   public key
3157        //   seed ("-" for an empty seed)
3158        //   data (BLAKE2s of "sample X" with X = 0, 1,...)
3159        //   signature
3160        [
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        // Each group of five values is:
3302        //   private key
3303        //   public peer point (valid)
3304        //   secret from ECDH with valid peer point
3305        //   public peer point (invalid)
3306        //   secret from ECDH with invalid peer point
3307        [
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}