summaryrefslogtreecommitdiff
path: root/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor.go
diff options
context:
space:
mode:
Diffstat (limited to 'cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor.go')
-rw-r--r--cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor.go255
1 files changed, 255 insertions, 0 deletions
diff --git a/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor.go b/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor.go
new file mode 100644
index 0000000..a271ff6
--- /dev/null
+++ b/cli/vendor/github.com/decred/dcrd/dcrec/secp256k1/v4/ellipticadaptor.go
@@ -0,0 +1,255 @@
+// Copyright 2020-2021 The Decred developers
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package secp256k1
+
+// References:
+// [SECG]: Recommended Elliptic Curve Domain Parameters
+// https://www.secg.org/sec2-v2.pdf
+//
+// [GECC]: Guide to Elliptic Curve Cryptography (Hankerson, Menezes, Vanstone)
+
+import (
+ "crypto/ecdsa"
+ "crypto/elliptic"
+ "math/big"
+)
+
+// CurveParams contains the parameters for the secp256k1 curve.
+type CurveParams struct {
+ // P is the prime used in the secp256k1 field.
+ P *big.Int
+
+ // N is the order of the secp256k1 curve group generated by the base point.
+ N *big.Int
+
+ // Gx and Gy are the x and y coordinate of the base point, respectively.
+ Gx, Gy *big.Int
+
+ // BitSize is the size of the underlying secp256k1 field in bits.
+ BitSize int
+
+ // H is the cofactor of the secp256k1 curve.
+ H int
+
+ // ByteSize is simply the bit size / 8 and is provided for convenience
+ // since it is calculated repeatedly.
+ ByteSize int
+}
+
+// Curve parameters taken from [SECG] section 2.4.1.
+var curveParams = CurveParams{
+ P: fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"),
+ N: fromHex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"),
+ Gx: fromHex("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"),
+ Gy: fromHex("483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"),
+ BitSize: 256,
+ H: 1,
+ ByteSize: 256 / 8,
+}
+
+// Params returns the secp256k1 curve parameters for convenience.
+func Params() *CurveParams {
+ return &curveParams
+}
+
+// KoblitzCurve provides an implementation for secp256k1 that fits the ECC Curve
+// interface from crypto/elliptic.
+type KoblitzCurve struct {
+ *elliptic.CurveParams
+}
+
+// bigAffineToJacobian takes an affine point (x, y) as big integers and converts
+// it to Jacobian point with Z=1.
+func bigAffineToJacobian(x, y *big.Int, result *JacobianPoint) {
+ result.X.SetByteSlice(x.Bytes())
+ result.Y.SetByteSlice(y.Bytes())
+ result.Z.SetInt(1)
+}
+
+// jacobianToBigAffine takes a Jacobian point (x, y, z) as field values and
+// converts it to an affine point as big integers.
+func jacobianToBigAffine(point *JacobianPoint) (*big.Int, *big.Int) {
+ point.ToAffine()
+
+ // Convert the field values for the now affine point to big.Ints.
+ x3, y3 := new(big.Int), new(big.Int)
+ x3.SetBytes(point.X.Bytes()[:])
+ y3.SetBytes(point.Y.Bytes()[:])
+ return x3, y3
+}
+
+// Params returns the parameters for the curve.
+//
+// This is part of the elliptic.Curve interface implementation.
+func (curve *KoblitzCurve) Params() *elliptic.CurveParams {
+ return curve.CurveParams
+}
+
+// IsOnCurve returns whether or not the affine point (x,y) is on the curve.
+//
+// This is part of the elliptic.Curve interface implementation. This function
+// differs from the crypto/elliptic algorithm since a = 0 not -3.
+func (curve *KoblitzCurve) IsOnCurve(x, y *big.Int) bool {
+ // Convert big ints to a Jacobian point for faster arithmetic.
+ var point JacobianPoint
+ bigAffineToJacobian(x, y, &point)
+ return isOnCurve(&point.X, &point.Y)
+}
+
+// Add returns the sum of (x1,y1) and (x2,y2).
+//
+// This is part of the elliptic.Curve interface implementation.
+func (curve *KoblitzCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
+ // A point at infinity is the identity according to the group law for
+ // elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P.
+ if x1.Sign() == 0 && y1.Sign() == 0 {
+ return x2, y2
+ }
+ if x2.Sign() == 0 && y2.Sign() == 0 {
+ return x1, y1
+ }
+
+ // Convert the affine coordinates from big integers to Jacobian points,
+ // do the point addition in Jacobian projective space, and convert the
+ // Jacobian point back to affine big.Ints.
+ var p1, p2, result JacobianPoint
+ bigAffineToJacobian(x1, y1, &p1)
+ bigAffineToJacobian(x2, y2, &p2)
+ AddNonConst(&p1, &p2, &result)
+ return jacobianToBigAffine(&result)
+}
+
+// Double returns 2*(x1,y1).
+//
+// This is part of the elliptic.Curve interface implementation.
+func (curve *KoblitzCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
+ if y1.Sign() == 0 {
+ return new(big.Int), new(big.Int)
+ }
+
+ // Convert the affine coordinates from big integers to Jacobian points,
+ // do the point doubling in Jacobian projective space, and convert the
+ // Jacobian point back to affine big.Ints.
+ var point, result JacobianPoint
+ bigAffineToJacobian(x1, y1, &point)
+ DoubleNonConst(&point, &result)
+ return jacobianToBigAffine(&result)
+}
+
+// moduloReduce reduces k from more than 32 bytes to 32 bytes and under. This
+// is done by doing a simple modulo curve.N. We can do this since G^N = 1 and
+// thus any other valid point on the elliptic curve has the same order.
+func moduloReduce(k []byte) []byte {
+ // Since the order of G is curve.N, we can use a much smaller number by
+ // doing modulo curve.N
+ if len(k) > curveParams.ByteSize {
+ tmpK := new(big.Int).SetBytes(k)
+ tmpK.Mod(tmpK, curveParams.N)
+ return tmpK.Bytes()
+ }
+
+ return k
+}
+
+// ScalarMult returns k*(Bx, By) where k is a big endian integer.
+//
+// This is part of the elliptic.Curve interface implementation.
+func (curve *KoblitzCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
+ // Convert the affine coordinates from big integers to Jacobian points,
+ // do the multiplication in Jacobian projective space, and convert the
+ // Jacobian point back to affine big.Ints.
+ var kModN ModNScalar
+ kModN.SetByteSlice(moduloReduce(k))
+ var point, result JacobianPoint
+ bigAffineToJacobian(Bx, By, &point)
+ ScalarMultNonConst(&kModN, &point, &result)
+ return jacobianToBigAffine(&result)
+}
+
+// ScalarBaseMult returns k*G where G is the base point of the group and k is a
+// big endian integer.
+//
+// This is part of the elliptic.Curve interface implementation.
+func (curve *KoblitzCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
+ // Perform the multiplication and convert the Jacobian point back to affine
+ // big.Ints.
+ var kModN ModNScalar
+ kModN.SetByteSlice(moduloReduce(k))
+ var result JacobianPoint
+ ScalarBaseMultNonConst(&kModN, &result)
+ return jacobianToBigAffine(&result)
+}
+
+// X returns the x coordinate of the public key.
+func (p *PublicKey) X() *big.Int {
+ return new(big.Int).SetBytes(p.x.Bytes()[:])
+}
+
+// Y returns the y coordinate of the public key.
+func (p *PublicKey) Y() *big.Int {
+ return new(big.Int).SetBytes(p.y.Bytes()[:])
+}
+
+// ToECDSA returns the public key as a *ecdsa.PublicKey.
+func (p *PublicKey) ToECDSA() *ecdsa.PublicKey {
+ return &ecdsa.PublicKey{
+ Curve: S256(),
+ X: p.X(),
+ Y: p.Y(),
+ }
+}
+
+// ToECDSA returns the private key as a *ecdsa.PrivateKey.
+func (p *PrivateKey) ToECDSA() *ecdsa.PrivateKey {
+ var privKeyBytes [PrivKeyBytesLen]byte
+ p.Key.PutBytes(&privKeyBytes)
+ var result JacobianPoint
+ ScalarBaseMultNonConst(&p.Key, &result)
+ x, y := jacobianToBigAffine(&result)
+ newPrivKey := &ecdsa.PrivateKey{
+ PublicKey: ecdsa.PublicKey{
+ Curve: S256(),
+ X: x,
+ Y: y,
+ },
+ D: new(big.Int).SetBytes(privKeyBytes[:]),
+ }
+ zeroArray32(&privKeyBytes)
+ return newPrivKey
+}
+
+// fromHex converts the passed hex string into a big integer pointer and will
+// panic is there is an error. This is only provided for the hard-coded
+// constants so errors in the source code can bet detected. It will only (and
+// must only) be called for initialization purposes.
+func fromHex(s string) *big.Int {
+ if s == "" {
+ return big.NewInt(0)
+ }
+ r, ok := new(big.Int).SetString(s, 16)
+ if !ok {
+ panic("invalid hex in source file: " + s)
+ }
+ return r
+}
+
+// secp256k1 is a global instance of the KoblitzCurve implementation which in
+// turn embeds and implements elliptic.CurveParams.
+var secp256k1 = &KoblitzCurve{
+ CurveParams: &elliptic.CurveParams{
+ P: curveParams.P,
+ N: curveParams.N,
+ B: fromHex("0000000000000000000000000000000000000000000000000000000000000007"),
+ Gx: curveParams.Gx,
+ Gy: curveParams.Gy,
+ BitSize: curveParams.BitSize,
+ Name: "secp256k1",
+ },
+}
+
+// S256 returns a Curve which implements secp256k1.
+func S256() *KoblitzCurve {
+ return secp256k1
+}