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  }