-
Notifications
You must be signed in to change notification settings - Fork 8
/
vartime.go
117 lines (102 loc) · 2 KB
/
vartime.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package edwards25519
func load8u(in []byte) uint64 {
var r uint64
r = uint64(in[0])
r |= uint64(in[1]) << 8
r |= uint64(in[2]) << 16
r |= uint64(in[3]) << 24
r |= uint64(in[4]) << 32
r |= uint64(in[5]) << 40
r |= uint64(in[6]) << 48
r |= uint64(in[7]) << 56
return r
}
// Computes the w=5 w-NAF of s and store it into naf.
// naf is assumed to be zero-initialized and the highest three bits of s
// have to be cleared.
func computeScalar5NAF(s *[32]byte, naf *[256]int8) {
var x [5]uint64
for i := 0; i < 4; i++ {
x[i] = load8u(s[i*8 : (i+1)*8])
}
pos := uint16(0)
carry := uint64(0)
for pos < 256 {
idx := pos / 64
bit_idx := pos % 64
var bit_buf uint64
if bit_idx < 59 {
bit_buf = x[idx] >> bit_idx
} else {
bit_buf = (x[idx] >> bit_idx) | (x[1+idx] << (64 - bit_idx))
}
window := carry + (bit_buf & 31)
if window&1 == 0 {
pos += 1
continue
}
if window < 16 {
carry = 0
naf[pos] = int8(window)
} else {
carry = 1
naf[pos] = int8(window) - int8(32)
}
pos += 5
}
}
func (p *ExtendedPoint) VarTimeScalarMult(q *ExtendedPoint, s *[32]byte) *ExtendedPoint {
var lut [8]ExtendedPoint
// Precomputations
var dblQ ExtendedPoint
dblQ.Double(q)
lut[0].Set(q)
for i := 1; i < 8; i++ {
lut[i].Add(&lut[i-1], &dblQ)
}
// Compute non-adjacent form of s
var naf [256]int8
computeScalar5NAF(s, &naf)
// Skip the trailing zeroes
i := 255
for ; i >= 0; i-- {
if naf[i] != 0 {
break
}
}
// Corner-case: s is zero.
p.SetZero()
if i == -1 {
return p
}
var pp ProjectivePoint
var cp CompletedPoint
for {
if naf[i] > 0 {
cp.AddExtended(p, &lut[(naf[i]+1)/2-1])
} else {
cp.SubExtended(p, &lut[(1-naf[i])/2-1])
}
if i == 0 {
p.SetCompleted(&cp)
break
}
i -= 1
pp.SetCompleted(&cp)
cp.DoubleProjective(&pp)
// Find next non-zero digit
for {
if i == 0 || naf[i] != 0 {
break
}
i -= 1
pp.SetCompleted(&cp)
cp.DoubleProjective(&pp)
}
p.SetCompleted(&cp)
if naf[i] == 0 {
break
}
}
return p
}