v
Зеркало из https://github.com/vlang/v
1module edwards25519
2
3import crypto.internal.subtle
4
5// A precomputed lookup table for fixed-base, constant-time scalar muls.
6struct AffineLookupTable {
7mut:
8points [8]AffineCached
9}
10
11// A dynamic lookup table for variable-base, constant-time scalar muls.
12struct ProjLookupTable {
13mut:
14points [8]ProjectiveCached
15}
16
17// A dynamic lookup table for variable-base, variable-time scalar muls.
18struct NafLookupTable5 {
19mut:
20points [8]ProjectiveCached
21}
22
23// A precomputed lookup table for fixed-base, variable-time scalar muls.
24struct NafLookupTable8 {
25mut:
26points [64]AffineCached
27}
28
29// Constructors.
30
31// Builds a lookup table at runtime. Fast.
32fn (mut v ProjLookupTable) from_p3(q Point) {
33// Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
34// This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
35v.points[0].from_p3(q)
36mut tmp_p3 := Point{}
37mut tmp_p1 := ProjectiveP1{}
38for i := 0; i < 7; i++ {
39// Compute (i+1)*Q as Q + i*Q and convert to a ProjCached
40// This is needlessly complicated because the API has explicit
41// receivers instead of creating stack objects and relying on RVO
42v.points[i + 1].from_p3(tmp_p3.from_p1(tmp_p1.add(q, v.points[i])))
43}
44}
45
46// This is not optimised for speed; fixed-base tables should be precomputed.
47fn (mut v AffineLookupTable) from_p3(q Point) {
48// Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q
49// This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q
50v.points[0].from_p3(q)
51mut tmp_p3 := Point{}
52mut tmp_p1 := ProjectiveP1{}
53for i := 0; i < 7; i++ {
54// Compute (i+1)*Q as Q + i*Q and convert to AffineCached
55v.points[i + 1].from_p3(tmp_p3.from_p1(tmp_p1.add_affine(q, v.points[i])))
56}
57}
58
59// Builds a lookup table at runtime. Fast.
60fn (mut v NafLookupTable5) from_p3(q Point) {
61// Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q
62// This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q
63v.points[0].from_p3(q)
64mut q2 := Point{}
65q2.add(q, q)
66mut tmp_p3 := Point{}
67mut tmp_p1 := ProjectiveP1{}
68for i := 0; i < 7; i++ {
69v.points[i + 1].from_p3(tmp_p3.from_p1(tmp_p1.add(q2, v.points[i])))
70}
71}
72
73// This is not optimised for speed; fixed-base tables should be precomputed.
74fn (mut v NafLookupTable8) from_p3(q Point) {
75v.points[0].from_p3(q)
76mut q2 := Point{}
77q2.add(q, q)
78mut tmp_p3 := Point{}
79mut tmp_p1 := ProjectiveP1{}
80for i := 0; i < 63; i++ {
81v.points[i + 1].from_p3(tmp_p3.from_p1(tmp_p1.add_affine(q2, v.points[i])))
82}
83}
84
85// Selectors.
86
87// Set dest to x*Q, where -8 <= x <= 8, in constant time.
88fn (mut v ProjLookupTable) select_into(mut dest ProjectiveCached, x i8) {
89// Compute xabs = |x|
90xmask := x >> 7
91xabs := u8((x + xmask) ^ xmask)
92
93dest.zero()
94for j := 1; j <= 8; j++ {
95// Set dest = j*Q if |x| = j
96cond := subtle.constant_time_byte_eq(xabs, u8(j))
97dest.selected(v.points[j - 1], dest, cond)
98}
99// Now dest = |x|*Q, conditionally negate to get x*Q
100dest.cond_neg(int(xmask & 1))
101}
102
103// Set dest to x*Q, where -8 <= x <= 8, in constant time.
104fn (mut v AffineLookupTable) select_into(mut dest AffineCached, x i8) {
105// Compute xabs = |x|
106xmask := x >> 7
107xabs := u8((x + xmask) ^ xmask)
108
109dest.zero()
110for j := 1; j <= 8; j++ {
111// Set dest = j*Q if |x| = j
112cond := subtle.constant_time_byte_eq(xabs, u8(j))
113dest.selected(v.points[j - 1], dest, cond)
114}
115// Now dest = |x|*Q, conditionally negate to get x*Q
116dest.cond_neg(int(xmask & 1))
117}
118
119// Given odd x with 0 < x < 2^4, return x*Q (in variable time).
120fn (mut v NafLookupTable5) select_into(mut dest ProjectiveCached, x i8) {
121dest = v.points[x / 2]
122}
123
124// Given odd x with 0 < x < 2^7, return x*Q (in variable time).
125fn (mut v NafLookupTable8) select_into(mut dest AffineCached, x i8) {
126dest = v.points[x / 2]
127}
128