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  }