-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
field.go
171 lines (142 loc) · 5 KB
/
field.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// Package secp256k1 is an implementation of the kyber.{Group,Point,Scalar}
// //////////////////////////////////////////////////////////////////////////////
//
// XXX: Do not use in production until this code has been audited.
//
// //////////////////////////////////////////////////////////////////////////////
// interfaces, based on btcd/btcec and kyber/group/mod
//
// XXX: NOT CONSTANT TIME!
package secp256k1
// Arithmetic operations in the base field of secp256k1, i.e. ℤ/qℤ, where q is
// the base field characteristic.
import (
"crypto/cipher"
"fmt"
"math/big"
"go.dedis.ch/kyber/v3/util/random"
)
// q is the field characteristic (cardinality) of the secp256k1 base field. All
// arithmetic operations on the field are modulo this.
var q = s256.P
type fieldElt big.Int
// newFieldZero returns a newly allocated field element.
func newFieldZero() *fieldElt { return (*fieldElt)(big.NewInt(0)) }
// Int returns f as a big.Int
func (f *fieldElt) int() *big.Int { return (*big.Int)(f) }
// modQ reduces f's underlying big.Int modulo q, and returns it
func (f *fieldElt) modQ() *fieldElt {
if f.int().Cmp(q) != -1 || f.int().Cmp(bigZero) == -1 {
// f ∉ {0, ..., q-1}. Find the representative of f+qℤ in that set.
//
// Per Mod docstring, "Mod implements Euclidean modulus", meaning that after
// this, f will be the smallest non-negative representative of its
// equivalence class in ℤ/qℤ. TODO(alx): Make this faster
f.int().Mod(f.int(), q)
}
return f
}
// This differs from SetInt below, in that it does not take a copy of v.
func fieldEltFromBigInt(v *big.Int) *fieldElt { return (*fieldElt)(v).modQ() }
func fieldEltFromInt(v int64) *fieldElt {
return fieldEltFromBigInt(big.NewInt(int64(v))).modQ()
}
var fieldZero = fieldEltFromInt(0)
var bigZero = big.NewInt(0)
// String returns the string representation of f
func (f *fieldElt) String() string {
return fmt.Sprintf("fieldElt{%x}", f.int())
}
// Equal returns true iff f=g, i.e. the backing big.Ints satisfy f ≡ g mod q
func (f *fieldElt) Equal(g *fieldElt) bool {
if f == (*fieldElt)(nil) && g == (*fieldElt)(nil) {
return true
}
if f == (*fieldElt)(nil) { // f is nil, g is not
return false
}
if g == (*fieldElt)(nil) { // g is nil, f is not
return false
}
return bigZero.Cmp(newFieldZero().Sub(f, g).modQ().int()) == 0
}
// Add sets f to the sum of a and b modulo q, and returns it.
func (f *fieldElt) Add(a, b *fieldElt) *fieldElt {
f.int().Add(a.int(), b.int())
return f.modQ()
}
// Sub sets f to a-b mod q, and returns it.
func (f *fieldElt) Sub(a, b *fieldElt) *fieldElt {
f.int().Sub(a.int(), b.int())
return f.modQ()
}
// Set sets f's value to v, and returns f.
func (f *fieldElt) Set(v *fieldElt) *fieldElt {
f.int().Set(v.int())
return f.modQ()
}
// SetInt sets f's value to v mod q, and returns f.
func (f *fieldElt) SetInt(v *big.Int) *fieldElt {
f.int().Set(v)
return f.modQ()
}
// Pick samples uniformly from {0, ..., q-1}, assigns sample to f, and returns f
func (f *fieldElt) Pick(rand cipher.Stream) *fieldElt {
return f.SetInt(random.Int(q, rand)) // random.Int safe because q≅2²⁵⁶, q<2²⁵⁶
}
// Neg sets f to the negation of g modulo q, and returns it
func (f *fieldElt) Neg(g *fieldElt) *fieldElt {
f.int().Neg(g.int())
return f.modQ()
}
// Clone returns a new fieldElt, backed by a clone of f
func (f *fieldElt) Clone() *fieldElt { return newFieldZero().Set(f.modQ()) }
// SetBytes sets f to the 32-byte big-endian value represented by buf, reduces
// it, and returns it.
func (f *fieldElt) SetBytes(buf [32]byte) *fieldElt {
f.int().SetBytes(buf[:])
return f.modQ()
}
// Bytes returns the 32-byte big-endian representation of f
func (f *fieldElt) Bytes() [32]byte {
bytes := f.modQ().int().Bytes()
if len(bytes) > 32 {
panic("field element longer than 256 bits")
}
var rv [32]byte
copy(rv[32-len(bytes):], bytes) // leftpad w zeros
return rv
}
var two = big.NewInt(2)
// square returns y² mod q
func fieldSquare(y *fieldElt) *fieldElt {
return fieldEltFromBigInt(newFieldZero().int().Exp(y.int(), two, q))
}
// sqrtPower is s.t. n^sqrtPower≡sqrt(n) mod q, if n has a root at all. See
// https://math.stackexchange.com/a/1816280, for instance
//
// What I'm calling sqrtPower is called q on the s256 struct. (See
// btcec.initS256), which is confusing because the "Q" in "QPlus1Div4" refers to
// the field characteristic
var sqrtPower = s256.QPlus1Div4()
// maybeSqrtInField returns a square root of v, if it has any, else nil
func maybeSqrtInField(v *fieldElt) *fieldElt {
s := newFieldZero()
s.int().Exp(v.int(), sqrtPower, q)
if !fieldSquare(s).Equal(v) {
return nil
}
return s
}
var three = big.NewInt(3)
var seven = fieldEltFromInt(7)
// rightHandSide returns the RHS of the secp256k1 equation, x³+7 mod q, given x
func rightHandSide(x *fieldElt) *fieldElt {
xCubed := newFieldZero()
xCubed.int().Exp(x.int(), three, q)
return xCubed.Add(xCubed, seven)
}
// isEven returns true if f is even, false otherwise
func (f *fieldElt) isEven() bool {
return big.NewInt(0).Mod(f.int(), two).Cmp(big.NewInt(0)) == 0
}