Skip to content

Commit 6796a79

Browse files
committed
crypto/elliptic: refactor package structure
Not quite golang.org/wiki/TargetSpecific compliant, but almost. The only substantial code change is in randFieldElement: it used to use Params().BitSize instead of Params().N.BitLen(), which is semantically incorrect, even if the two values are the same for all named curves. For #52182 Change-Id: Ibc47450552afe23ea74fcf55d1d799d5d7e5487c Reviewed-on: https://go-review.googlesource.com/c/go/+/315273 Run-TryBot: Filippo Valsorda <[email protected]> Reviewed-by: Than McIntosh <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent 24b5703 commit 6796a79

File tree

9 files changed

+1496
-1502
lines changed

9 files changed

+1496
-1502
lines changed

src/crypto/ecdsa/ecdsa.go

+7-9
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error)
128128
params := c.Params()
129129
// Note that for P-521 this will actually be 63 bits more than the order, as
130130
// division rounds down, but the extra bit is inconsequential.
131-
b := make([]byte, params.BitSize/8+8) // TODO: use params.N.BitLen()
131+
b := make([]byte, params.N.BitLen()/8+8)
132132
_, err = io.ReadFull(rand, b)
133133
if err != nil {
134134
return
@@ -228,13 +228,13 @@ func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err err
228228

229229
// Create a CSPRNG that xors a stream of zeros with
230230
// the output of the AES-CTR instance.
231-
csprng := cipher.StreamReader{
231+
csprng := &cipher.StreamReader{
232232
R: zeroReader,
233233
S: cipher.NewCTR(block, []byte(aesIV)),
234234
}
235235

236236
c := priv.PublicKey.Curve
237-
return sign(priv, &csprng, c, hash)
237+
return sign(priv, csprng, c, hash)
238238
}
239239

240240
func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) {
@@ -353,16 +353,14 @@ func VerifyASN1(pub *PublicKey, hash, sig []byte) bool {
353353
return Verify(pub, hash, r, s)
354354
}
355355

356-
type zr struct {
357-
io.Reader
358-
}
356+
type zr struct{}
359357

360-
// Read replaces the contents of dst with zeros.
361-
func (z *zr) Read(dst []byte) (n int, err error) {
358+
// Read replaces the contents of dst with zeros. It is safe for concurrent use.
359+
func (zr) Read(dst []byte) (n int, err error) {
362360
for i := range dst {
363361
dst[i] = 0
364362
}
365363
return len(dst), nil
366364
}
367365

368-
var zeroReader = &zr{}
366+
var zeroReader = zr{}

src/crypto/elliptic/elliptic.go

-289
Original file line numberDiff line numberDiff line change
@@ -36,295 +36,6 @@ type Curve interface {
3636
ScalarBaseMult(k []byte) (x, y *big.Int)
3737
}
3838

39-
func matchesSpecificCurve(params *CurveParams, available ...Curve) (Curve, bool) {
40-
for _, c := range available {
41-
if params == c.Params() {
42-
return c, true
43-
}
44-
}
45-
return nil, false
46-
}
47-
48-
// CurveParams contains the parameters of an elliptic curve and also provides
49-
// a generic, non-constant time implementation of Curve.
50-
type CurveParams struct {
51-
P *big.Int // the order of the underlying field
52-
N *big.Int // the order of the base point
53-
B *big.Int // the constant of the curve equation
54-
Gx, Gy *big.Int // (x,y) of the base point
55-
BitSize int // the size of the underlying field
56-
Name string // the canonical name of the curve
57-
}
58-
59-
func (curve *CurveParams) Params() *CurveParams {
60-
return curve
61-
}
62-
63-
// CurveParams operates, internally, on Jacobian coordinates. For a given
64-
// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
65-
// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
66-
// calculation can be performed within the transform (as in ScalarMult and
67-
// ScalarBaseMult). But even for Add and Double, it's faster to apply and
68-
// reverse the transform than to operate in affine coordinates.
69-
70-
// polynomial returns x³ - 3x + b.
71-
func (curve *CurveParams) polynomial(x *big.Int) *big.Int {
72-
x3 := new(big.Int).Mul(x, x)
73-
x3.Mul(x3, x)
74-
75-
threeX := new(big.Int).Lsh(x, 1)
76-
threeX.Add(threeX, x)
77-
78-
x3.Sub(x3, threeX)
79-
x3.Add(x3, curve.B)
80-
x3.Mod(x3, curve.P)
81-
82-
return x3
83-
}
84-
85-
func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
86-
// If there is a dedicated constant-time implementation for this curve operation,
87-
// use that instead of the generic one.
88-
if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
89-
return specific.IsOnCurve(x, y)
90-
}
91-
92-
if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
93-
y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
94-
return false
95-
}
96-
97-
// y² = x³ - 3x + b
98-
y2 := new(big.Int).Mul(y, y)
99-
y2.Mod(y2, curve.P)
100-
101-
return curve.polynomial(x).Cmp(y2) == 0
102-
}
103-
104-
// zForAffine returns a Jacobian Z value for the affine point (x, y). If x and
105-
// y are zero, it assumes that they represent the point at infinity because (0,
106-
// 0) is not on the any of the curves handled here.
107-
func zForAffine(x, y *big.Int) *big.Int {
108-
z := new(big.Int)
109-
if x.Sign() != 0 || y.Sign() != 0 {
110-
z.SetInt64(1)
111-
}
112-
return z
113-
}
114-
115-
// affineFromJacobian reverses the Jacobian transform. See the comment at the
116-
// top of the file. If the point is ∞ it returns 0, 0.
117-
func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
118-
if z.Sign() == 0 {
119-
return new(big.Int), new(big.Int)
120-
}
121-
122-
zinv := new(big.Int).ModInverse(z, curve.P)
123-
zinvsq := new(big.Int).Mul(zinv, zinv)
124-
125-
xOut = new(big.Int).Mul(x, zinvsq)
126-
xOut.Mod(xOut, curve.P)
127-
zinvsq.Mul(zinvsq, zinv)
128-
yOut = new(big.Int).Mul(y, zinvsq)
129-
yOut.Mod(yOut, curve.P)
130-
return
131-
}
132-
133-
func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
134-
// If there is a dedicated constant-time implementation for this curve operation,
135-
// use that instead of the generic one.
136-
if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
137-
return specific.Add(x1, y1, x2, y2)
138-
}
139-
140-
z1 := zForAffine(x1, y1)
141-
z2 := zForAffine(x2, y2)
142-
return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2))
143-
}
144-
145-
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
146-
// (x2, y2, z2) and returns their sum, also in Jacobian form.
147-
func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
148-
// See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
149-
x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int)
150-
if z1.Sign() == 0 {
151-
x3.Set(x2)
152-
y3.Set(y2)
153-
z3.Set(z2)
154-
return x3, y3, z3
155-
}
156-
if z2.Sign() == 0 {
157-
x3.Set(x1)
158-
y3.Set(y1)
159-
z3.Set(z1)
160-
return x3, y3, z3
161-
}
162-
163-
z1z1 := new(big.Int).Mul(z1, z1)
164-
z1z1.Mod(z1z1, curve.P)
165-
z2z2 := new(big.Int).Mul(z2, z2)
166-
z2z2.Mod(z2z2, curve.P)
167-
168-
u1 := new(big.Int).Mul(x1, z2z2)
169-
u1.Mod(u1, curve.P)
170-
u2 := new(big.Int).Mul(x2, z1z1)
171-
u2.Mod(u2, curve.P)
172-
h := new(big.Int).Sub(u2, u1)
173-
xEqual := h.Sign() == 0
174-
if h.Sign() == -1 {
175-
h.Add(h, curve.P)
176-
}
177-
i := new(big.Int).Lsh(h, 1)
178-
i.Mul(i, i)
179-
j := new(big.Int).Mul(h, i)
180-
181-
s1 := new(big.Int).Mul(y1, z2)
182-
s1.Mul(s1, z2z2)
183-
s1.Mod(s1, curve.P)
184-
s2 := new(big.Int).Mul(y2, z1)
185-
s2.Mul(s2, z1z1)
186-
s2.Mod(s2, curve.P)
187-
r := new(big.Int).Sub(s2, s1)
188-
if r.Sign() == -1 {
189-
r.Add(r, curve.P)
190-
}
191-
yEqual := r.Sign() == 0
192-
if xEqual && yEqual {
193-
return curve.doubleJacobian(x1, y1, z1)
194-
}
195-
r.Lsh(r, 1)
196-
v := new(big.Int).Mul(u1, i)
197-
198-
x3.Set(r)
199-
x3.Mul(x3, x3)
200-
x3.Sub(x3, j)
201-
x3.Sub(x3, v)
202-
x3.Sub(x3, v)
203-
x3.Mod(x3, curve.P)
204-
205-
y3.Set(r)
206-
v.Sub(v, x3)
207-
y3.Mul(y3, v)
208-
s1.Mul(s1, j)
209-
s1.Lsh(s1, 1)
210-
y3.Sub(y3, s1)
211-
y3.Mod(y3, curve.P)
212-
213-
z3.Add(z1, z2)
214-
z3.Mul(z3, z3)
215-
z3.Sub(z3, z1z1)
216-
z3.Sub(z3, z2z2)
217-
z3.Mul(z3, h)
218-
z3.Mod(z3, curve.P)
219-
220-
return x3, y3, z3
221-
}
222-
223-
func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
224-
// If there is a dedicated constant-time implementation for this curve operation,
225-
// use that instead of the generic one.
226-
if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok {
227-
return specific.Double(x1, y1)
228-
}
229-
230-
z1 := zForAffine(x1, y1)
231-
return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1))
232-
}
233-
234-
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
235-
// returns its double, also in Jacobian form.
236-
func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
237-
// See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
238-
delta := new(big.Int).Mul(z, z)
239-
delta.Mod(delta, curve.P)
240-
gamma := new(big.Int).Mul(y, y)
241-
gamma.Mod(gamma, curve.P)
242-
alpha := new(big.Int).Sub(x, delta)
243-
if alpha.Sign() == -1 {
244-
alpha.Add(alpha, curve.P)
245-
}
246-
alpha2 := new(big.Int).Add(x, delta)
247-
alpha.Mul(alpha, alpha2)
248-
alpha2.Set(alpha)
249-
alpha.Lsh(alpha, 1)
250-
alpha.Add(alpha, alpha2)
251-
252-
beta := alpha2.Mul(x, gamma)
253-
254-
x3 := new(big.Int).Mul(alpha, alpha)
255-
beta8 := new(big.Int).Lsh(beta, 3)
256-
beta8.Mod(beta8, curve.P)
257-
x3.Sub(x3, beta8)
258-
if x3.Sign() == -1 {
259-
x3.Add(x3, curve.P)
260-
}
261-
x3.Mod(x3, curve.P)
262-
263-
z3 := new(big.Int).Add(y, z)
264-
z3.Mul(z3, z3)
265-
z3.Sub(z3, gamma)
266-
if z3.Sign() == -1 {
267-
z3.Add(z3, curve.P)
268-
}
269-
z3.Sub(z3, delta)
270-
if z3.Sign() == -1 {
271-
z3.Add(z3, curve.P)
272-
}
273-
z3.Mod(z3, curve.P)
274-
275-
beta.Lsh(beta, 2)
276-
beta.Sub(beta, x3)
277-
if beta.Sign() == -1 {
278-
beta.Add(beta, curve.P)
279-
}
280-
y3 := alpha.Mul(alpha, beta)
281-
282-
gamma.Mul(gamma, gamma)
283-
gamma.Lsh(gamma, 3)
284-
gamma.Mod(gamma, curve.P)
285-
286-
y3.Sub(y3, gamma)
287-
if y3.Sign() == -1 {
288-
y3.Add(y3, curve.P)
289-
}
290-
y3.Mod(y3, curve.P)
291-
292-
return x3, y3, z3
293-
}
294-
295-
func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
296-
// If there is a dedicated constant-time implementation for this curve operation,
297-
// use that instead of the generic one.
298-
if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok {
299-
return specific.ScalarMult(Bx, By, k)
300-
}
301-
302-
Bz := new(big.Int).SetInt64(1)
303-
x, y, z := new(big.Int), new(big.Int), new(big.Int)
304-
305-
for _, byte := range k {
306-
for bitNum := 0; bitNum < 8; bitNum++ {
307-
x, y, z = curve.doubleJacobian(x, y, z)
308-
if byte&0x80 == 0x80 {
309-
x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z)
310-
}
311-
byte <<= 1
312-
}
313-
}
314-
315-
return curve.affineFromJacobian(x, y, z)
316-
}
317-
318-
func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
319-
// If there is a dedicated constant-time implementation for this curve operation,
320-
// use that instead of the generic one.
321-
if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok {
322-
return specific.ScalarBaseMult(k)
323-
}
324-
325-
return curve.ScalarMult(curve.Gx, curve.Gy, k)
326-
}
327-
32839
var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
32940

33041
// GenerateKey returns a public/private key pair. The private key is

0 commit comments

Comments
 (0)