1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Package elliptic implements several standard elliptic curves over prime
9 // This package operates, internally, on Jacobian coordinates. For a given
10 // (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
11 // where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
12 // calculation can be performed within the transform (as in ScalarMult and
13 // ScalarBaseMult). But even for Add and Double, it's faster to apply and
14 // reverse the transform than to operate in affine coordinates.
22 // A Curve represents a short-form Weierstrass curve with a=-3.
23 // See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
24 type Curve
interface {
25 // Params returns the parameters for the curve.
27 // IsOnCurve reports whether the given (x,y) lies on the curve.
28 IsOnCurve(x
, y
*big
.Int
) bool
29 // Add returns the sum of (x1,y1) and (x2,y2)
30 Add(x1
, y1
, x2
, y2
*big
.Int
) (x
, y
*big
.Int
)
31 // Double returns 2*(x,y)
32 Double(x1
, y1
*big
.Int
) (x
, y
*big
.Int
)
33 // ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
34 ScalarMult(x1
, y1
*big
.Int
, k
[]byte) (x
, y
*big
.Int
)
35 // ScalarBaseMult returns k*G, where G is the base point of the group
36 // and k is an integer in big-endian form.
37 ScalarBaseMult(k
[]byte) (x
, y
*big
.Int
)
40 // CurveParams contains the parameters of an elliptic curve and also provides
41 // a generic, non-constant time implementation of Curve.
42 type CurveParams
struct {
43 P
*big
.Int
// the order of the underlying field
44 N
*big
.Int
// the order of the base point
45 B
*big
.Int
// the constant of the curve equation
46 Gx
, Gy
*big
.Int
// (x,y) of the base point
47 BitSize
int // the size of the underlying field
48 Name
string // the canonical name of the curve
51 func (curve
*CurveParams
) Params() *CurveParams
{
55 func (curve
*CurveParams
) IsOnCurve(x
, y
*big
.Int
) bool {
57 y2
:= new(big
.Int
).Mul(y
, y
)
60 x3
:= new(big
.Int
).Mul(x
, x
)
63 threeX
:= new(big
.Int
).Lsh(x
, 1)
70 return x3
.Cmp(y2
) == 0
73 // zForAffine returns a Jacobian Z value for the affine point (x, y). If x and
74 // y are zero, it assumes that they represent the point at infinity because (0,
75 // 0) is not on the any of the curves handled here.
76 func zForAffine(x
, y
*big
.Int
) *big
.Int
{
78 if x
.Sign() != 0 || y
.Sign() != 0 {
84 // affineFromJacobian reverses the Jacobian transform. See the comment at the
85 // top of the file. If the point is ∞ it returns 0, 0.
86 func (curve
*CurveParams
) affineFromJacobian(x
, y
, z
*big
.Int
) (xOut
, yOut
*big
.Int
) {
88 return new(big
.Int
), new(big
.Int
)
91 zinv
:= new(big
.Int
).ModInverse(z
, curve
.P
)
92 zinvsq
:= new(big
.Int
).Mul(zinv
, zinv
)
94 xOut
= new(big
.Int
).Mul(x
, zinvsq
)
95 xOut
.Mod(xOut
, curve
.P
)
96 zinvsq
.Mul(zinvsq
, zinv
)
97 yOut
= new(big
.Int
).Mul(y
, zinvsq
)
98 yOut
.Mod(yOut
, curve
.P
)
102 func (curve
*CurveParams
) Add(x1
, y1
, x2
, y2
*big
.Int
) (*big
.Int
, *big
.Int
) {
103 z1
:= zForAffine(x1
, y1
)
104 z2
:= zForAffine(x2
, y2
)
105 return curve
.affineFromJacobian(curve
.addJacobian(x1
, y1
, z1
, x2
, y2
, z2
))
108 // addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
109 // (x2, y2, z2) and returns their sum, also in Jacobian form.
110 func (curve
*CurveParams
) addJacobian(x1
, y1
, z1
, x2
, y2
, z2
*big
.Int
) (*big
.Int
, *big
.Int
, *big
.Int
) {
111 // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
112 x3
, y3
, z3
:= new(big
.Int
), new(big
.Int
), new(big
.Int
)
126 z1z1
:= new(big
.Int
).Mul(z1
, z1
)
127 z1z1
.Mod(z1z1
, curve
.P
)
128 z2z2
:= new(big
.Int
).Mul(z2
, z2
)
129 z2z2
.Mod(z2z2
, curve
.P
)
131 u1
:= new(big
.Int
).Mul(x1
, z2z2
)
133 u2
:= new(big
.Int
).Mul(x2
, z1z1
)
135 h
:= new(big
.Int
).Sub(u2
, u1
)
136 xEqual
:= h
.Sign() == 0
140 i
:= new(big
.Int
).Lsh(h
, 1)
142 j
:= new(big
.Int
).Mul(h
, i
)
144 s1
:= new(big
.Int
).Mul(y1
, z2
)
147 s2
:= new(big
.Int
).Mul(y2
, z1
)
150 r
:= new(big
.Int
).Sub(s2
, s1
)
154 yEqual
:= r
.Sign() == 0
155 if xEqual
&& yEqual
{
156 return curve
.doubleJacobian(x1
, y1
, z1
)
159 v
:= new(big
.Int
).Mul(u1
, i
)
186 func (curve
*CurveParams
) Double(x1
, y1
*big
.Int
) (*big
.Int
, *big
.Int
) {
187 z1
:= zForAffine(x1
, y1
)
188 return curve
.affineFromJacobian(curve
.doubleJacobian(x1
, y1
, z1
))
191 // doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
192 // returns its double, also in Jacobian form.
193 func (curve
*CurveParams
) doubleJacobian(x
, y
, z
*big
.Int
) (*big
.Int
, *big
.Int
, *big
.Int
) {
194 // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
195 delta
:= new(big
.Int
).Mul(z
, z
)
196 delta
.Mod(delta
, curve
.P
)
197 gamma
:= new(big
.Int
).Mul(y
, y
)
198 gamma
.Mod(gamma
, curve
.P
)
199 alpha
:= new(big
.Int
).Sub(x
, delta
)
200 if alpha
.Sign() == -1 {
201 alpha
.Add(alpha
, curve
.P
)
203 alpha2
:= new(big
.Int
).Add(x
, delta
)
204 alpha
.Mul(alpha
, alpha2
)
207 alpha
.Add(alpha
, alpha2
)
209 beta
:= alpha2
.Mul(x
, gamma
)
211 x3
:= new(big
.Int
).Mul(alpha
, alpha
)
212 beta8
:= new(big
.Int
).Lsh(beta
, 3)
214 for x3
.Sign() == -1 {
219 z3
:= new(big
.Int
).Add(y
, z
)
233 if beta
.Sign() == -1 {
234 beta
.Add(beta
, curve
.P
)
236 y3
:= alpha
.Mul(alpha
, beta
)
238 gamma
.Mul(gamma
, gamma
)
240 gamma
.Mod(gamma
, curve
.P
)
251 func (curve
*CurveParams
) ScalarMult(Bx
, By
*big
.Int
, k
[]byte) (*big
.Int
, *big
.Int
) {
252 Bz
:= new(big
.Int
).SetInt64(1)
253 x
, y
, z
:= new(big
.Int
), new(big
.Int
), new(big
.Int
)
255 for _
, byte := range k
{
256 for bitNum
:= 0; bitNum
< 8; bitNum
++ {
257 x
, y
, z
= curve
.doubleJacobian(x
, y
, z
)
258 if byte&0x80 == 0x80 {
259 x
, y
, z
= curve
.addJacobian(Bx
, By
, Bz
, x
, y
, z
)
265 return curve
.affineFromJacobian(x
, y
, z
)
268 func (curve
*CurveParams
) ScalarBaseMult(k
[]byte) (*big
.Int
, *big
.Int
) {
269 return curve
.ScalarMult(curve
.Gx
, curve
.Gy
, k
)
272 var mask
= []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
274 // GenerateKey returns a public/private key pair. The private key is
275 // generated using the given reader, which must return random data.
276 func GenerateKey(curve Curve
, rand io
.Reader
) (priv
[]byte, x
, y
*big
.Int
, err error
) {
277 N
:= curve
.Params().N
278 bitSize
:= N
.BitLen()
279 byteLen
:= (bitSize
+ 7) >> 3
280 priv
= make([]byte, byteLen
)
283 _
, err
= io
.ReadFull(rand
, priv
)
287 // We have to mask off any excess bits in the case that the size of the
288 // underlying field is not a whole number of bytes.
289 priv
[0] &= mask
[bitSize%8
]
290 // This is because, in tests, rand will return all zeros and we don't
291 // want to get the point at infinity and loop forever.
294 // If the scalar is out of range, sample another random number.
295 if new(big
.Int
).SetBytes(priv
).Cmp(N
) >= 0 {
299 x
, y
= curve
.ScalarBaseMult(priv
)
304 // Marshal converts a point into the form specified in section 4.3.6 of ANSI X9.62.
305 func Marshal(curve Curve
, x
, y
*big
.Int
) []byte {
306 byteLen
:= (curve
.Params().BitSize
+ 7) >> 3
308 ret
:= make([]byte, 1+2*byteLen
)
309 ret
[0] = 4 // uncompressed point
312 copy(ret
[1+byteLen
-len(xBytes
):], xBytes
)
314 copy(ret
[1+2*byteLen
-len(yBytes
):], yBytes
)
318 // Unmarshal converts a point, serialized by Marshal, into an x, y pair.
319 // It is an error if the point is not on the curve. On error, x = nil.
320 func Unmarshal(curve Curve
, data
[]byte) (x
, y
*big
.Int
) {
321 byteLen
:= (curve
.Params().BitSize
+ 7) >> 3
322 if len(data
) != 1+2*byteLen
{
325 if data
[0] != 4 { // uncompressed form
328 x
= new(big
.Int
).SetBytes(data
[1 : 1+byteLen
])
329 y
= new(big
.Int
).SetBytes(data
[1+byteLen
:])
330 if !curve
.IsOnCurve(x
, y
) {
336 var initonce sync
.Once
337 var p384
*CurveParams
338 var p521
*CurveParams
348 // See FIPS 186-3, section D.2.4
349 p384
= &CurveParams
{Name
: "P-384"}
350 p384
.P
, _
= new(big
.Int
).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10)
351 p384
.N
, _
= new(big
.Int
).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10)
352 p384
.B
, _
= new(big
.Int
).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16)
353 p384
.Gx
, _
= new(big
.Int
).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16)
354 p384
.Gy
, _
= new(big
.Int
).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16)
359 // See FIPS 186-3, section D.2.5
360 p521
= &CurveParams
{Name
: "P-521"}
361 p521
.P
, _
= new(big
.Int
).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10)
362 p521
.N
, _
= new(big
.Int
).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10)
363 p521
.B
, _
= new(big
.Int
).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16)
364 p521
.Gx
, _
= new(big
.Int
).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16)
365 p521
.Gy
, _
= new(big
.Int
).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16)
369 // P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3)
371 // The cryptographic operations are implemented using constant-time algorithms.
377 // P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4)
379 // The cryptographic operations do not use constant-time algorithms.
385 // P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5)
387 // The cryptographic operations do not use constant-time algorithms.