...

Source file src/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor.go

Documentation: github.com/decred/dcrd/dcrec/secp256k1/v4

     1  // Copyright 2020-2022 The Decred developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package secp256k1
     6  
     7  // References:
     8  //   [SECG]: Recommended Elliptic Curve Domain Parameters
     9  //     https://www.secg.org/sec2-v2.pdf
    10  //
    11  //   [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone)
    12  
    13  import (
    14  	"crypto/ecdsa"
    15  	"crypto/elliptic"
    16  	"math/big"
    17  )
    18  
    19  // CurveParams contains the parameters for the secp256k1 curve.
    20  type CurveParams struct {
    21  	// P is the prime used in the secp256k1 field.
    22  	P *big.Int
    23  
    24  	// N is the order of the secp256k1 curve group generated by the base point.
    25  	N *big.Int
    26  
    27  	// Gx and Gy are the x and y coordinate of the base point, respectively.
    28  	Gx, Gy *big.Int
    29  
    30  	// BitSize is the size of the underlying secp256k1 field in bits.
    31  	BitSize int
    32  
    33  	// H is the cofactor of the secp256k1 curve.
    34  	H int
    35  
    36  	// ByteSize is simply the bit size / 8 and is provided for convenience
    37  	// since it is calculated repeatedly.
    38  	ByteSize int
    39  }
    40  
    41  // Curve parameters taken from [SECG] section 2.4.1.
    42  var curveParams = CurveParams{
    43  	P:        fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),
    44  	N:        fromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
    45  	Gx:       fromHex("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),
    46  	Gy:       fromHex("483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"),
    47  	BitSize:  256,
    48  	H:        1,
    49  	ByteSize: 256 / 8,
    50  }
    51  
    52  // Params returns the secp256k1 curve parameters for convenience.
    53  func Params() *CurveParams {
    54  	return &curveParams
    55  }
    56  
    57  // KoblitzCurve provides an implementation for secp256k1 that fits the ECC Curve
    58  // interface from crypto/elliptic.
    59  type KoblitzCurve struct {
    60  	*elliptic.CurveParams
    61  }
    62  
    63  // bigAffineToJacobian takes an affine point (x, y) as big integers and converts
    64  // it to Jacobian point with Z=1.
    65  func bigAffineToJacobian(x, y *big.Int, result *JacobianPoint) {
    66  	result.X.SetByteSlice(x.Bytes())
    67  	result.Y.SetByteSlice(y.Bytes())
    68  	result.Z.SetInt(1)
    69  }
    70  
    71  // jacobianToBigAffine takes a Jacobian point (x, y, z) as field values and
    72  // converts it to an affine point as big integers.
    73  func jacobianToBigAffine(point *JacobianPoint) (*big.Int, *big.Int) {
    74  	point.ToAffine()
    75  
    76  	// Convert the field values for the now affine point to big.Ints.
    77  	x3, y3 := new(big.Int), new(big.Int)
    78  	x3.SetBytes(point.X.Bytes()[:])
    79  	y3.SetBytes(point.Y.Bytes()[:])
    80  	return x3, y3
    81  }
    82  
    83  // Params returns the parameters for the curve.
    84  //
    85  // This is part of the elliptic.Curve interface implementation.
    86  func (curve *KoblitzCurve) Params() *elliptic.CurveParams {
    87  	return curve.CurveParams
    88  }
    89  
    90  // IsOnCurve returns whether or not the affine point (x,y) is on the curve.
    91  //
    92  // This is part of the elliptic.Curve interface implementation.  This function
    93  // differs from the crypto/elliptic algorithm since a = 0 not -3.
    94  func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool {
    95  	// Convert big ints to a Jacobian point for faster arithmetic.
    96  	var point JacobianPoint
    97  	bigAffineToJacobian(x, y, &point)
    98  	return isOnCurve(&point.X, &point.Y)
    99  }
   100  
   101  // Add returns the sum of (x1,y1) and (x2,y2).
   102  //
   103  // This is part of the elliptic.Curve interface implementation.
   104  func (curve *KoblitzCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
   105  	// The point at infinity is the identity according to the group law for
   106  	// elliptic curve cryptography.  Thus, ∞ + P = P and P + ∞ = P.
   107  	if x1.Sign() == 0 && y1.Sign() == 0 {
   108  		return x2, y2
   109  	}
   110  	if x2.Sign() == 0 && y2.Sign() == 0 {
   111  		return x1, y1
   112  	}
   113  
   114  	// Convert the affine coordinates from big integers to Jacobian points,
   115  	// do the point addition in Jacobian projective space, and convert the
   116  	// Jacobian point back to affine big.Ints.
   117  	var p1, p2, result JacobianPoint
   118  	bigAffineToJacobian(x1, y1, &p1)
   119  	bigAffineToJacobian(x2, y2, &p2)
   120  	AddNonConst(&p1, &p2, &result)
   121  	return jacobianToBigAffine(&result)
   122  }
   123  
   124  // Double returns 2*(x1,y1).
   125  //
   126  // This is part of the elliptic.Curve interface implementation.
   127  func (curve *KoblitzCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
   128  	if y1.Sign() == 0 {
   129  		return new(big.Int), new(big.Int)
   130  	}
   131  
   132  	// Convert the affine coordinates from big integers to Jacobian points,
   133  	// do the point doubling in Jacobian projective space, and convert the
   134  	// Jacobian point back to affine big.Ints.
   135  	var point, result JacobianPoint
   136  	bigAffineToJacobian(x1, y1, &point)
   137  	DoubleNonConst(&point, &result)
   138  	return jacobianToBigAffine(&result)
   139  }
   140  
   141  // moduloReduce reduces k from more than 32 bytes to 32 bytes and under.  This
   142  // is done by doing a simple modulo curve.N.  We can do this since G^N = 1 and
   143  // thus any other valid point on the elliptic curve has the same order.
   144  func moduloReduce(k []byte) []byte {
   145  	// Since the order of G is curve.N, we can use a much smaller number by
   146  	// doing modulo curve.N
   147  	if len(k) > curveParams.ByteSize {
   148  		tmpK := new(big.Int).SetBytes(k)
   149  		tmpK.Mod(tmpK, curveParams.N)
   150  		return tmpK.Bytes()
   151  	}
   152  
   153  	return k
   154  }
   155  
   156  // ScalarMult returns k*(Bx, By) where k is a big endian integer.
   157  //
   158  // This is part of the elliptic.Curve interface implementation.
   159  func (curve *KoblitzCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
   160  	// Convert the affine coordinates from big integers to Jacobian points,
   161  	// do the multiplication in Jacobian projective space, and convert the
   162  	// Jacobian point back to affine big.Ints.
   163  	var kModN ModNScalar
   164  	kModN.SetByteSlice(moduloReduce(k))
   165  	var point, result JacobianPoint
   166  	bigAffineToJacobian(Bx, By, &point)
   167  	ScalarMultNonConst(&kModN, &point, &result)
   168  	return jacobianToBigAffine(&result)
   169  }
   170  
   171  // ScalarBaseMult returns k*G where G is the base point of the group and k is a
   172  // big endian integer.
   173  //
   174  // This is part of the elliptic.Curve interface implementation.
   175  func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
   176  	// Perform the multiplication and convert the Jacobian point back to affine
   177  	// big.Ints.
   178  	var kModN ModNScalar
   179  	kModN.SetByteSlice(moduloReduce(k))
   180  	var result JacobianPoint
   181  	ScalarBaseMultNonConst(&kModN, &result)
   182  	return jacobianToBigAffine(&result)
   183  }
   184  
   185  // X returns the x coordinate of the public key.
   186  func (p *PublicKey) X() *big.Int {
   187  	return new(big.Int).SetBytes(p.x.Bytes()[:])
   188  }
   189  
   190  // Y returns the y coordinate of the public key.
   191  func (p *PublicKey) Y() *big.Int {
   192  	return new(big.Int).SetBytes(p.y.Bytes()[:])
   193  }
   194  
   195  // ToECDSA returns the public key as a *ecdsa.PublicKey.
   196  func (p *PublicKey) ToECDSA() *ecdsa.PublicKey {
   197  	return &ecdsa.PublicKey{
   198  		Curve: S256(),
   199  		X:     p.X(),
   200  		Y:     p.Y(),
   201  	}
   202  }
   203  
   204  // ToECDSA returns the private key as a *ecdsa.PrivateKey.
   205  func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey {
   206  	var privKeyBytes [PrivKeyBytesLen]byte
   207  	p.Key.PutBytes(&privKeyBytes)
   208  	var result JacobianPoint
   209  	ScalarBaseMultNonConst(&p.Key, &result)
   210  	x, y := jacobianToBigAffine(&result)
   211  	newPrivKey := &ecdsa.PrivateKey{
   212  		PublicKey: ecdsa.PublicKey{
   213  			Curve: S256(),
   214  			X:     x,
   215  			Y:     y,
   216  		},
   217  		D: new(big.Int).SetBytes(privKeyBytes[:]),
   218  	}
   219  	zeroArray32(&privKeyBytes)
   220  	return newPrivKey
   221  }
   222  
   223  // fromHex converts the passed hex string into a big integer pointer and will
   224  // panic is there is an error.  This is only provided for the hard-coded
   225  // constants so errors in the source code can bet detected. It will only (and
   226  // must only) be called for initialization purposes.
   227  func fromHex(s string) *big.Int {
   228  	if s == "" {
   229  		return big.NewInt(0)
   230  	}
   231  	r, ok := new(big.Int).SetString(s, 16)
   232  	if !ok {
   233  		panic("invalid hex in source file: " + s)
   234  	}
   235  	return r
   236  }
   237  
   238  // secp256k1 is a global instance of the KoblitzCurve implementation which in
   239  // turn embeds and implements elliptic.CurveParams.
   240  var secp256k1 = &KoblitzCurve{
   241  	CurveParams: &elliptic.CurveParams{
   242  		P:       curveParams.P,
   243  		N:       curveParams.N,
   244  		B:       fromHex("0000000000000000000000000000000000000000000000000000000000000007"),
   245  		Gx:      curveParams.Gx,
   246  		Gy:      curveParams.Gy,
   247  		BitSize: curveParams.BitSize,
   248  		Name:    "secp256k1",
   249  	},
   250  }
   251  
   252  // S256 returns an elliptic.Curve which implements secp256k1.
   253  func S256() *KoblitzCurve {
   254  	return secp256k1
   255  }
   256  

View as plain text