github.com/AESNooper/go/src@v0.0.0-20220218095104-b56a4ab1bbbb/crypto/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 with a=-3. 23 // 24 // The output of Add, Double, and ScalarMult when the input is not a point on 25 // the curve is undefined. 26 // 27 // Note that the conventional point at infinity (0, 0) is not considered on the 28 // curve, although it can be returned by Add, Double, ScalarMult, or 29 // ScalarBaseMult (but not Unmarshal or UnmarshalCompressed). 30 type Curve interface { 31 // Params returns the parameters for the curve. 32 Params() *CurveParams 33 // IsOnCurve reports whether the given (x,y) lies on the curve. 34 IsOnCurve(x, y *big.Int) bool 35 // Add returns the sum of (x1,y1) and (x2,y2) 36 Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) 37 // Double returns 2*(x,y) 38 Double(x1, y1 *big.Int) (x, y *big.Int) 39 // ScalarMult returns k*(Bx,By) where k is a number in big-endian form. 40 ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int) 41 // ScalarBaseMult returns k*G, where G is the base point of the group 42 // and k is an integer in big-endian form. 43 ScalarBaseMult(k []byte) (x, y *big.Int) 44 } 45 46 func matchesSpecificCurve(params *CurveParams, available ...Curve) (Curve, bool) { 47 for _, c := range available { 48 if params == c.Params() { 49 return c, true 50 } 51 } 52 return nil, false 53 } 54 55 // CurveParams contains the parameters of an elliptic curve and also provides 56 // a generic, non-constant time implementation of Curve. 57 type CurveParams struct { 58 P *big.Int // the order of the underlying field 59 N *big.Int // the order of the base point 60 B *big.Int // the constant of the curve equation 61 Gx, Gy *big.Int // (x,y) of the base point 62 BitSize int // the size of the underlying field 63 Name string // the canonical name of the curve 64 } 65 66 func (curve *CurveParams) Params() *CurveParams { 67 return curve 68 } 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 // y² = x³ - 3x + b 93 y2 := new(big.Int).Mul(y, y) 94 y2.Mod(y2, curve.P) 95 96 return curve.polynomial(x).Cmp(y2) == 0 97 } 98 99 // zForAffine returns a Jacobian Z value for the affine point (x, y). If x and 100 // y are zero, it assumes that they represent the point at infinity because (0, 101 // 0) is not on the any of the curves handled here. 102 func zForAffine(x, y *big.Int) *big.Int { 103 z := new(big.Int) 104 if x.Sign() != 0 || y.Sign() != 0 { 105 z.SetInt64(1) 106 } 107 return z 108 } 109 110 // affineFromJacobian reverses the Jacobian transform. See the comment at the 111 // top of the file. If the point is ∞ it returns 0, 0. 112 func (curve *CurveParams) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) { 113 if z.Sign() == 0 { 114 return new(big.Int), new(big.Int) 115 } 116 117 zinv := new(big.Int).ModInverse(z, curve.P) 118 zinvsq := new(big.Int).Mul(zinv, zinv) 119 120 xOut = new(big.Int).Mul(x, zinvsq) 121 xOut.Mod(xOut, curve.P) 122 zinvsq.Mul(zinvsq, zinv) 123 yOut = new(big.Int).Mul(y, zinvsq) 124 yOut.Mod(yOut, curve.P) 125 return 126 } 127 128 func (curve *CurveParams) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { 129 // If there is a dedicated constant-time implementation for this curve operation, 130 // use that instead of the generic one. 131 if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { 132 return specific.Add(x1, y1, x2, y2) 133 } 134 135 z1 := zForAffine(x1, y1) 136 z2 := zForAffine(x2, y2) 137 return curve.affineFromJacobian(curve.addJacobian(x1, y1, z1, x2, y2, z2)) 138 } 139 140 // addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and 141 // (x2, y2, z2) and returns their sum, also in Jacobian form. 142 func (curve *CurveParams) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) { 143 // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl 144 x3, y3, z3 := new(big.Int), new(big.Int), new(big.Int) 145 if z1.Sign() == 0 { 146 x3.Set(x2) 147 y3.Set(y2) 148 z3.Set(z2) 149 return x3, y3, z3 150 } 151 if z2.Sign() == 0 { 152 x3.Set(x1) 153 y3.Set(y1) 154 z3.Set(z1) 155 return x3, y3, z3 156 } 157 158 z1z1 := new(big.Int).Mul(z1, z1) 159 z1z1.Mod(z1z1, curve.P) 160 z2z2 := new(big.Int).Mul(z2, z2) 161 z2z2.Mod(z2z2, curve.P) 162 163 u1 := new(big.Int).Mul(x1, z2z2) 164 u1.Mod(u1, curve.P) 165 u2 := new(big.Int).Mul(x2, z1z1) 166 u2.Mod(u2, curve.P) 167 h := new(big.Int).Sub(u2, u1) 168 xEqual := h.Sign() == 0 169 if h.Sign() == -1 { 170 h.Add(h, curve.P) 171 } 172 i := new(big.Int).Lsh(h, 1) 173 i.Mul(i, i) 174 j := new(big.Int).Mul(h, i) 175 176 s1 := new(big.Int).Mul(y1, z2) 177 s1.Mul(s1, z2z2) 178 s1.Mod(s1, curve.P) 179 s2 := new(big.Int).Mul(y2, z1) 180 s2.Mul(s2, z1z1) 181 s2.Mod(s2, curve.P) 182 r := new(big.Int).Sub(s2, s1) 183 if r.Sign() == -1 { 184 r.Add(r, curve.P) 185 } 186 yEqual := r.Sign() == 0 187 if xEqual && yEqual { 188 return curve.doubleJacobian(x1, y1, z1) 189 } 190 r.Lsh(r, 1) 191 v := new(big.Int).Mul(u1, i) 192 193 x3.Set(r) 194 x3.Mul(x3, x3) 195 x3.Sub(x3, j) 196 x3.Sub(x3, v) 197 x3.Sub(x3, v) 198 x3.Mod(x3, curve.P) 199 200 y3.Set(r) 201 v.Sub(v, x3) 202 y3.Mul(y3, v) 203 s1.Mul(s1, j) 204 s1.Lsh(s1, 1) 205 y3.Sub(y3, s1) 206 y3.Mod(y3, curve.P) 207 208 z3.Add(z1, z2) 209 z3.Mul(z3, z3) 210 z3.Sub(z3, z1z1) 211 z3.Sub(z3, z2z2) 212 z3.Mul(z3, h) 213 z3.Mod(z3, curve.P) 214 215 return x3, y3, z3 216 } 217 218 func (curve *CurveParams) Double(x1, y1 *big.Int) (*big.Int, *big.Int) { 219 // If there is a dedicated constant-time implementation for this curve operation, 220 // use that instead of the generic one. 221 if specific, ok := matchesSpecificCurve(curve, p224, p384, p521); ok { 222 return specific.Double(x1, y1) 223 } 224 225 z1 := zForAffine(x1, y1) 226 return curve.affineFromJacobian(curve.doubleJacobian(x1, y1, z1)) 227 } 228 229 // doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and 230 // returns its double, also in Jacobian form. 231 func (curve *CurveParams) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) { 232 // See https://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b 233 delta := new(big.Int).Mul(z, z) 234 delta.Mod(delta, curve.P) 235 gamma := new(big.Int).Mul(y, y) 236 gamma.Mod(gamma, curve.P) 237 alpha := new(big.Int).Sub(x, delta) 238 if alpha.Sign() == -1 { 239 alpha.Add(alpha, curve.P) 240 } 241 alpha2 := new(big.Int).Add(x, delta) 242 alpha.Mul(alpha, alpha2) 243 alpha2.Set(alpha) 244 alpha.Lsh(alpha, 1) 245 alpha.Add(alpha, alpha2) 246 247 beta := alpha2.Mul(x, gamma) 248 249 x3 := new(big.Int).Mul(alpha, alpha) 250 beta8 := new(big.Int).Lsh(beta, 3) 251 beta8.Mod(beta8, curve.P) 252 x3.Sub(x3, beta8) 253 if x3.Sign() == -1 { 254 x3.Add(x3, curve.P) 255 } 256 x3.Mod(x3, curve.P) 257 258 z3 := new(big.Int).Add(y, z) 259 z3.Mul(z3, z3) 260 z3.Sub(z3, gamma) 261 if z3.Sign() == -1 { 262 z3.Add(z3, curve.P) 263 } 264 z3.Sub(z3, delta) 265 if z3.Sign() == -1 { 266 z3.Add(z3, curve.P) 267 } 268 z3.Mod(z3, curve.P) 269 270 beta.Lsh(beta, 2) 271 beta.Sub(beta, x3) 272 if beta.Sign() == -1 { 273 beta.Add(beta, curve.P) 274 } 275 y3 := alpha.Mul(alpha, beta) 276 277 gamma.Mul(gamma, gamma) 278 gamma.Lsh(gamma, 3) 279 gamma.Mod(gamma, curve.P) 280 281 y3.Sub(y3, gamma) 282 if y3.Sign() == -1 { 283 y3.Add(y3, curve.P) 284 } 285 y3.Mod(y3, curve.P) 286 287 return x3, y3, z3 288 } 289 290 func (curve *CurveParams) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) { 291 // If there is a dedicated constant-time implementation for this curve operation, 292 // use that instead of the generic one. 293 if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok { 294 return specific.ScalarMult(Bx, By, k) 295 } 296 297 Bz := new(big.Int).SetInt64(1) 298 x, y, z := new(big.Int), new(big.Int), new(big.Int) 299 300 for _, byte := range k { 301 for bitNum := 0; bitNum < 8; bitNum++ { 302 x, y, z = curve.doubleJacobian(x, y, z) 303 if byte&0x80 == 0x80 { 304 x, y, z = curve.addJacobian(Bx, By, Bz, x, y, z) 305 } 306 byte <<= 1 307 } 308 } 309 310 return curve.affineFromJacobian(x, y, z) 311 } 312 313 func (curve *CurveParams) ScalarBaseMult(k []byte) (*big.Int, *big.Int) { 314 // If there is a dedicated constant-time implementation for this curve operation, 315 // use that instead of the generic one. 316 if specific, ok := matchesSpecificCurve(curve, p224, p256, p384, p521); ok { 317 return specific.ScalarBaseMult(k) 318 } 319 320 return curve.ScalarMult(curve.Gx, curve.Gy, k) 321 } 322 323 var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} 324 325 // GenerateKey returns a public/private key pair. The private key is 326 // generated using the given reader, which must return random data. 327 func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) { 328 N := curve.Params().N 329 bitSize := N.BitLen() 330 byteLen := (bitSize + 7) / 8 331 priv = make([]byte, byteLen) 332 333 for x == nil { 334 _, err = io.ReadFull(rand, priv) 335 if err != nil { 336 return 337 } 338 // We have to mask off any excess bits in the case that the size of the 339 // underlying field is not a whole number of bytes. 340 priv[0] &= mask[bitSize%8] 341 // This is because, in tests, rand will return all zeros and we don't 342 // want to get the point at infinity and loop forever. 343 priv[1] ^= 0x42 344 345 // If the scalar is out of range, sample another random number. 346 if new(big.Int).SetBytes(priv).Cmp(N) >= 0 { 347 continue 348 } 349 350 x, y = curve.ScalarBaseMult(priv) 351 } 352 return 353 } 354 355 // Marshal converts a point on the curve into the uncompressed form specified in 356 // section 4.3.6 of ANSI X9.62. 357 func Marshal(curve Curve, x, y *big.Int) []byte { 358 byteLen := (curve.Params().BitSize + 7) / 8 359 360 ret := make([]byte, 1+2*byteLen) 361 ret[0] = 4 // uncompressed point 362 363 x.FillBytes(ret[1 : 1+byteLen]) 364 y.FillBytes(ret[1+byteLen : 1+2*byteLen]) 365 366 return ret 367 } 368 369 // MarshalCompressed converts a point on the curve into the compressed form 370 // specified in section 4.3.6 of ANSI X9.62. 371 func MarshalCompressed(curve Curve, x, y *big.Int) []byte { 372 byteLen := (curve.Params().BitSize + 7) / 8 373 compressed := make([]byte, 1+byteLen) 374 compressed[0] = byte(y.Bit(0)) | 2 375 x.FillBytes(compressed[1:]) 376 return compressed 377 } 378 379 // Unmarshal converts a point, serialized by Marshal, into an x, y pair. 380 // It is an error if the point is not in uncompressed form or is not on the curve. 381 // On error, x = nil. 382 func Unmarshal(curve Curve, data []byte) (x, y *big.Int) { 383 byteLen := (curve.Params().BitSize + 7) / 8 384 if len(data) != 1+2*byteLen { 385 return nil, nil 386 } 387 if data[0] != 4 { // uncompressed form 388 return nil, nil 389 } 390 p := curve.Params().P 391 x = new(big.Int).SetBytes(data[1 : 1+byteLen]) 392 y = new(big.Int).SetBytes(data[1+byteLen:]) 393 if x.Cmp(p) >= 0 || y.Cmp(p) >= 0 { 394 return nil, nil 395 } 396 if !curve.IsOnCurve(x, y) { 397 return nil, nil 398 } 399 return 400 } 401 402 // UnmarshalCompressed converts a point, serialized by MarshalCompressed, into an x, y pair. 403 // It is an error if the point is not in compressed form or is not on the curve. 404 // On error, x = nil. 405 func UnmarshalCompressed(curve Curve, data []byte) (x, y *big.Int) { 406 byteLen := (curve.Params().BitSize + 7) / 8 407 if len(data) != 1+byteLen { 408 return nil, nil 409 } 410 if data[0] != 2 && data[0] != 3 { // compressed form 411 return nil, nil 412 } 413 p := curve.Params().P 414 x = new(big.Int).SetBytes(data[1:]) 415 if x.Cmp(p) >= 0 { 416 return nil, nil 417 } 418 // y² = x³ - 3x + b 419 y = curve.Params().polynomial(x) 420 y = y.ModSqrt(y, p) 421 if y == nil { 422 return nil, nil 423 } 424 if byte(y.Bit(0)) != data[0]&1 { 425 y.Neg(y).Mod(y, p) 426 } 427 if !curve.IsOnCurve(x, y) { 428 return nil, nil 429 } 430 return 431 } 432 433 var initonce sync.Once 434 435 func initAll() { 436 initP224() 437 initP256() 438 initP384() 439 initP521() 440 } 441 442 // P224 returns a Curve which implements NIST P-224 (FIPS 186-3, section D.2.2), 443 // also known as secp224r1. The CurveParams.Name of this Curve is "P-224". 444 // 445 // Multiple invocations of this function will return the same value, so it can 446 // be used for equality checks and switch statements. 447 // 448 // The cryptographic operations are implemented using constant-time algorithms. 449 func P224() Curve { 450 initonce.Do(initAll) 451 return p224 452 } 453 454 // P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), 455 // also known as secp256r1 or prime256v1. The CurveParams.Name of this Curve is 456 // "P-256". 457 // 458 // Multiple invocations of this function will return the same value, so it can 459 // be used for equality checks and switch statements. 460 // 461 // ScalarMult and ScalarBaseMult are implemented using constant-time algorithms. 462 func P256() Curve { 463 initonce.Do(initAll) 464 return p256 465 } 466 467 // P384 returns a Curve which implements NIST P-384 (FIPS 186-3, section D.2.4), 468 // also known as secp384r1. The CurveParams.Name of this Curve is "P-384". 469 // 470 // Multiple invocations of this function will return the same value, so it can 471 // be used for equality checks and switch statements. 472 // 473 // The cryptographic operations are implemented using constant-time algorithms. 474 func P384() Curve { 475 initonce.Do(initAll) 476 return p384 477 } 478 479 // P521 returns a Curve which implements NIST P-521 (FIPS 186-3, section D.2.5), 480 // also known as secp521r1. The CurveParams.Name of this Curve is "P-521". 481 // 482 // Multiple invocations of this function will return the same value, so it can 483 // be used for equality checks and switch statements. 484 // 485 // The cryptographic operations are implemented using constant-time algorithms. 486 func P521() Curve { 487 initonce.Do(initAll) 488 return p521 489 }