github.com/insolar/x-crypto@v0.0.0-20191031140942-75fab8a325f6/elliptic/elliptic.go (about) 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. 4 5 // Package elliptic implements several standard elliptic curves over prime 6 // fields. 7 package elliptic 8 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. 15 16 import ( 17 "io" 18 "math/big" 19 "sync" 20 ) 21 22 // A Curve represents a short-form Weierstrass curve. 23 // See https://www.hyperelliptic.org/EFD/g1p/auto-shortw.html 24 type Curve interface { 25 // Params returns the parameters for the curve. 26 Params() *CurveParams 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) 38 } 39 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 A *big.Int // the coefficient of x in the curve equation 46 B *big.Int // the constant of the curve equation 47 Gx, Gy *big.Int // (x,y) of the base point 48 BitSize int // the size of the underlying field 49 Name string // the canonical name of the curve 50 } 51 52 // Params returns the elliptic CurveParams of the implemented curve. 53 func (curve *CurveParams) Params() *CurveParams { 54 return curve 55 } 56 57 // IsOnCurve returns whether or not a (x, y) point is on the curve. 58 func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool { 59 // y² = x³ + ax + b 60 y2 := new(big.Int).Mul(y, y) 61 y2.Mod(y2, curve.P) 62 63 x3 := new(big.Int).Mul(x, x) 64 x3.Mul(x3, x) 65 66 aX := new(big.Int).Mul(curve.A, x) 67 aX.Mod(aX, curve.P) 68 69 x3.Add(x3, aX) 70 x3.Add(x3, curve.B) 71 x3.Mod(x3, curve.P) 72 73 return x3.Cmp(y2) == 0 74 } 75 76 // zForAffine returns a Jacobian Z value for the affine point (x, y). If x and 77 // y are zero, it assumes that they represent the point at infinity because (0, 78 // 0) is not on the any of the curves handled here. 79 func zForAffine(x, y *big.Int) *big.Int { 80 z := new(big.Int) 81 if x.Sign() != 0 || y.Sign() != 0 { 82 z.SetInt64(1) 83 } 84 return z 85 } 86 87 // affineFromJacobian reverses the Jacobian transform. See the comment at the 88 // top of the file. If the point is ∞ it returns 0, 0. 89 func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { 90 if z.Sign() == 0 { 91 return new(big.Int), new(big.Int) 92 } 93 94 zinv := new(big.Int).ModInverse(z, curve.P) 95 zinvsq := new(big.Int).Mul(zinv, zinv) 96 97 xOut = new(big.Int).Mul(x, zinvsq) 98 xOut.Mod(xOut, curve.P) 99 zinvsq.Mul(zinvsq, zinv) 100 yOut = new(big.Int).Mul(y, zinvsq) 101 yOut.Mod(yOut, curve.P) 102 return 103 } 104 105 // Add returns the sum of two affine points. 106 func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { 107 z1 := zForAffine(x1, y1) 108 z2 := zForAffine(x2, y2) 109 return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2)) 110 } 111 112 // addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and 113 // (x2, y2, z2) and returns their sum, also in Jacobian form. 114 func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { 115 // See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-2007-bl 116 x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int) 117 if z1.Sign() == 0 { 118 x3.Set(x2) 119 y3.Set(y2) 120 z3.Set(z2) 121 return x3, y3, z3 122 } 123 if z2.Sign() == 0 { 124 x3.Set(x1) 125 y3.Set(y1) 126 z3.Set(z1) 127 return x3, y3, z3 128 } 129 130 z1z1 := new(big.Int).Mul(z1, z1) 131 z1z1.Mod(z1z1, curve.P) 132 z2z2 := new(big.Int).Mul(z2, z2) 133 z2z2.Mod(z2z2, curve.P) 134 135 u1 := new(big.Int).Mul(x1, z2z2) 136 u1.Mod(u1, curve.P) 137 u2 := new(big.Int).Mul(x2, z1z1) 138 u2.Mod(u2, curve.P) 139 h := new(big.Int).Sub(u2, u1) 140 xEqual := h.Sign() == 0 141 if h.Sign() == -1 { 142 h.Add(h, curve.P) 143 } 144 i := new(big.Int).Lsh(h, 1) 145 i.Mul(i, i) 146 j := new(big.Int).Mul(h, i) 147 148 s1 := new(big.Int).Mul(y1, z2) 149 s1.Mul(s1, z2z2) 150 s1.Mod(s1, curve.P) 151 s2 := new(big.Int).Mul(y2, z1) 152 s2.Mul(s2, z1z1) 153 s2.Mod(s2, curve.P) 154 r := new(big.Int).Sub(s2, s1) 155 if r.Sign() == -1 { 156 r.Add(r, curve.P) 157 } 158 yEqual := r.Sign() == 0 159 if xEqual && yEqual { 160 return curve.doubleJacobian(x1, y1, z1) 161 } 162 r.Lsh(r, 1) 163 v := new(big.Int).Mul(u1, i) 164 165 x3.Set(r) 166 x3.Mul(x3, x3) 167 x3.Sub(x3, j) 168 x3.Sub(x3, v) 169 x3.Sub(x3, v) 170 x3.Mod(x3, curve.P) 171 172 y3.Set(r) 173 v.Sub(v, x3) 174 y3.Mul(y3, v) 175 s1.Mul(s1, j) 176 s1.Lsh(s1, 1) 177 y3.Sub(y3, s1) 178 y3.Mod(y3, curve.P) 179 180 z3.Add(z1, z2) 181 z3.Mul(z3, z3) 182 z3.Sub(z3, z1z1) 183 z3.Sub(z3, z2z2) 184 z3.Mul(z3, h) 185 z3.Mod(z3, curve.P) 186 187 return x3, y3, z3 188 } 189 190 // Double returns the double of an affine point. 191 func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { 192 z1 := zForAffine(x1, y1) 193 return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1)) 194 } 195 196 // doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and 197 // returns its double, also in Jacobian form. 198 func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { 199 // See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl 200 xx := new(big.Int).Mul(x, x) 201 xx.Mod(xx, curve.P) 202 203 yy := new(big.Int).Mul(y, y) 204 yy.Mod(yy, curve.P) 205 206 yyyy := new(big.Int).Mul(yy, yy) 207 yyyy.Mod(yyyy, curve.P) 208 209 zz := new(big.Int).Mul(z, z) 210 zz.Mod(zz, curve.P) 211 212 s := new(big.Int).Add(x, yy) 213 s.Mul(s, s) 214 s.Sub(s, xx) 215 if s.Sign() == -1 { 216 s.Add(s, curve.P) 217 } 218 s.Sub(s, yyyy) 219 if s.Sign() == -1 { 220 s.Add(s, curve.P) 221 } 222 s.Lsh(s, 1) 223 s.Mod(s, curve.P) 224 225 m := new(big.Int).Lsh(xx, 1) 226 m.Add(m, xx) 227 m2 := new(big.Int).Mul(zz, zz) 228 m2.Mul(curve.A, m2) 229 m.Add(m, m2) 230 m.Mod(m, curve.P) 231 232 t := new(big.Int).Mul(m, m) 233 t2 := new(big.Int).Lsh(s, 1) 234 t.Sub(t, t2) 235 if t.Sign() == -1 { 236 t.Add(t, curve.P) 237 } 238 t.Mod(t, curve.P) 239 240 x3 := new(big.Int).Set(t) 241 242 y3 := new(big.Int).Sub(s, t) 243 if y3.Sign() == -1 { 244 y3.Add(y3, curve.P) 245 } 246 y3.Mul(y3, m) 247 yyyy8 := new(big.Int).Lsh(yyyy, 3) 248 y3.Sub(y3, yyyy8) 249 if y3.Sign() == -1 { 250 y3.Add(y3, curve.P) 251 } 252 y3.Mod(y3, curve.P) 253 254 z3 := new(big.Int).Add(y, z) 255 z3.Mul(z3, z3) 256 z3.Sub(z3, yy) 257 if z3.Sign() == -1 { 258 z3.Add(z3, curve.P) 259 } 260 z3.Sub(z3, zz) 261 if z3.Sign() == -1 { 262 z3.Add(z3, curve.P) 263 } 264 z3.Mod(z3, curve.P) 265 266 return x3, y3, z3 267 } 268 269 // ScalarMult multiplies the point (Bx, By) by the scalar k using repeated doubling. 270 func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { 271 Bz := new(big.Int).SetInt64(1) 272 x, y, z := new(big.Int), new(big.Int), new(big.Int) 273 274 for _, byte := range k { 275 for bitNum := 0; bitNum < 8; bitNum++ { 276 x, y, z = curve.doubleJacobian(x, y, z) 277 if byte&0x80 == 0x80 { 278 x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z) 279 } 280 byte <<= 1 281 } 282 } 283 284 return curve.affineFromJacobian(x, y, z) 285 } 286 287 // ScalarBaseMult multiplies the base point by the scalar k using repeated doubling. 288 func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { 289 return curve.ScalarMult(curve.Gx, curve.Gy, k) 290 } 291 292 var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} 293 294 // GenerateKey returns a public/private key pair. The private key is 295 // generated using the given reader, which must return random data. 296 func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) { 297 N := curve.Params().N 298 bitSize := N.BitLen() 299 byteLen := (bitSize + 7) >> 3 300 priv = make([]byte, byteLen) 301 302 for x == nil { 303 _, err = io.ReadFull(rand, priv) 304 if err != nil { 305 return 306 } 307 // We have to mask off any excess bits in the case that the size of the 308 // underlying field is not a whole number of bytes. 309 priv[0] &= mask[bitSize%8] 310 // This is because, in tests, rand will return all zeros and we don't 311 // want to get the point at infinity and loop forever. 312 priv[1] ^= 0x42 313 314 // If the scalar is out of range, sample another random number. 315 if new(big.Int).SetBytes(priv).Cmp(N) >= 0 { 316 continue 317 } 318 319 x, y = curve.ScalarBaseMult(priv) 320 } 321 return 322 } 323 324 // Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62. 325 func Marshal(curve Curve, x, y *big.Int) []byte { 326 byteLen := (curve.Params().BitSize + 7) >> 3 327 328 ret := make([]byte, 1+2*byteLen) 329 ret[0] = 4 // uncompressed point 330 331 xBytes := x.Bytes() 332 copy(ret[1+byteLen-len(xBytes):], xBytes) 333 yBytes := y.Bytes() 334 copy(ret[1+2*byteLen-len(yBytes):], yBytes) 335 return ret 336 } 337 338 // Unmarshal converts a point, serialized by Marshal, into an x, y pair. 339 // It is an error if the point is not in uncompressed form or is not on the curve. 340 // On error, x = nil. 341 func Unmarshal(curve Curve, data []byte) (x, y *big.Int) { 342 byteLen := (curve.Params().BitSize + 7) >> 3 343 if len(data) != 1+2*byteLen { 344 return 345 } 346 if data[0] != 4 { // uncompressed form 347 return 348 } 349 p := curve.Params().P 350 x = new(big.Int).SetBytes(data[1 : 1+byteLen]) 351 y = new(big.Int).SetBytes(data[1+byteLen:]) 352 if x.Cmp(p) >= 0 || y.Cmp(p) >= 0 { 353 return nil, nil 354 } 355 if !curve.IsOnCurve(x, y) { 356 return nil, nil 357 } 358 return 359 } 360 361 var initonce sync.Once 362 var p384 *CurveParams 363 var p521 *CurveParams 364 var p256k *CurveParams 365 var p256 *CurveParams 366 367 func initAll() { 368 initP224() 369 initP256() 370 initP384() 371 initP521() 372 initP256() 373 initP256K() 374 } 375 376 func initP256() { 377 // See FIPS 186-3, section D.2.3 378 p256 = &CurveParams{Name: "P-256"} 379 p256.P, _ = new(big.Int).SetString("115792089210356248762697446949407573530086143415290314195533631308867097853951", 10) 380 p256.N, _ = new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10) 381 p256.A, _ = new(big.Int).SetString("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16) 382 p256.B, _ = new(big.Int).SetString("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16) 383 p256.Gx, _ = new(big.Int).SetString("6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", 16) 384 p256.Gy, _ = new(big.Int).SetString("4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5", 16) 385 p256.BitSize = 256 386 } 387 388 func initP384() { 389 // See FIPS 186-3, section D.2.4 390 p384 = &CurveParams{Name: "P-384"} 391 p384.P, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667948293404245721771496870329047266088258938001861606973112319", 10) 392 p384.N, _ = new(big.Int).SetString("39402006196394479212279040100143613805079739270465446667946905279627659399113263569398956308152294913554433653942643", 10) 393 p384.A, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc", 16) 394 p384.B, _ = new(big.Int).SetString("b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef", 16) 395 p384.Gx, _ = new(big.Int).SetString("aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab7", 16) 396 p384.Gy, _ = new(big.Int).SetString("3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5f", 16) 397 p384.BitSize = 384 398 } 399 400 func initP521() { 401 // See FIPS 186-3, section D.2.5 402 p521 = &CurveParams{Name: "P-521"} 403 p521.P, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151", 10) 404 p521.N, _ = new(big.Int).SetString("6864797660130609714981900799081393217269435300143305409394463459185543183397655394245057746333217197532963996371363321113864768612440380340372808892707005449", 10) 405 p521.A, _ = new(big.Int).SetString("01fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc", 16) 406 p521.B, _ = new(big.Int).SetString("051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00", 16) 407 p521.Gx, _ = new(big.Int).SetString("c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66", 16) 408 p521.Gy, _ = new(big.Int).SetString("11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650", 16) 409 p521.BitSize = 521 410 } 411 412 func initP256K() { 413 p256k = &CurveParams{Name: "P-256K"} 414 p256k.P, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 16) 415 p256k.N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) 416 p256k.A = new(big.Int) 417 p256k.B = new(big.Int).SetInt64(7) 418 p256k.Gx, _ = new(big.Int).SetString("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 16) 419 p256k.Gy, _ = new(big.Int).SetString("483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", 16) 420 p256k.BitSize = 256 421 } 422 423 // P256 returns a Curve which implements P-256 (see FIPS 186-3, section D.2.3) 424 // 425 // The cryptographic operations are implemented using constant-time algorithms. 426 func P256() Curve { 427 initonce.Do(initAll) 428 return p256 429 } 430 431 // P384 returns a Curve which implements P-384 (see FIPS 186-3, section D.2.4) 432 // 433 // The cryptographic operations do not use constant-time algorithms. 434 func P384() Curve { 435 initonce.Do(initAll) 436 return p384 437 } 438 439 // P521 returns a Curve which implements P-521 (see FIPS 186-3, section D.2.5) 440 // 441 // The cryptographic operations do not use constant-time algorithms. 442 func P521() Curve { 443 initonce.Do(initAll) 444 return p521 445 } 446 447 // P256K returns a Curve which implements p256k (see SEC 2, section 2.4.1) 448 // 449 // The cryptographic operations do not use constant-time algorithms. 450 func P256K() Curve { 451 initonce.Do(initAll) 452 return p256k 453 }