// Copyright 2020-2022 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 ()// CurveParams contains the parameters for the secp256k1 curve.typeCurveParamsstruct {// 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 () *CurveParams {return &curveParams}// KoblitzCurve provides an implementation for secp256k1 that fits the ECC Curve// interface from crypto/elliptic.typeKoblitzCurvestruct { *elliptic.CurveParams}// bigAffineToJacobian takes an affine point (x, y) as big integers and converts// it to Jacobian point with Z=1.func bigAffineToJacobian(, *big.Int, *JacobianPoint) { .X.SetByteSlice(.Bytes()) .Y.SetByteSlice(.Bytes()) .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( *JacobianPoint) (*big.Int, *big.Int) { .ToAffine()// Convert the field values for the now affine point to big.Ints. , := new(big.Int), new(big.Int) .SetBytes(.X.Bytes()[:]) .SetBytes(.Y.Bytes()[:])return , }// Params returns the parameters for the curve.//// This is part of the elliptic.Curve interface implementation.func ( *KoblitzCurve) () *elliptic.CurveParams {return .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 ( *KoblitzCurve) (, *big.Int) bool {// Convert big ints to a Jacobian point for faster arithmetic.varJacobianPointbigAffineToJacobian(, , &)returnisOnCurve(&.X, &.Y)}// Add returns the sum of (x1,y1) and (x2,y2).//// This is part of the elliptic.Curve interface implementation.func ( *KoblitzCurve) (, , , *big.Int) (*big.Int, *big.Int) {// The point at infinity is the identity according to the group law for // elliptic curve cryptography. Thus, ∞ + P = P and P + ∞ = P.if .Sign() == 0 && .Sign() == 0 {return , }if .Sign() == 0 && .Sign() == 0 {return , }// 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 , , JacobianPointbigAffineToJacobian(, , &)bigAffineToJacobian(, , &)AddNonConst(&, &, &)returnjacobianToBigAffine(&)}// Double returns 2*(x1,y1).//// This is part of the elliptic.Curve interface implementation.func ( *KoblitzCurve) (, *big.Int) (*big.Int, *big.Int) {if .Sign() == 0 {returnnew(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 , JacobianPointbigAffineToJacobian(, , &)DoubleNonConst(&, &)returnjacobianToBigAffine(&)}// 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( []byte) []byte {// Since the order of G is curve.N, we can use a much smaller number by // doing modulo curve.Niflen() > curveParams.ByteSize { := new(big.Int).SetBytes() .Mod(, curveParams.N)return .Bytes() }return}// ScalarMult returns k*(bx, by) where k is a big endian integer.//// This is part of the elliptic.Curve interface implementation.func ( *KoblitzCurve) (, *big.Int, []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.varModNScalar .SetByteSlice(moduloReduce())var , JacobianPointbigAffineToJacobian(, , &)ScalarMultNonConst(&, &, &)returnjacobianToBigAffine(&)}// 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 ( *KoblitzCurve) ( []byte) (*big.Int, *big.Int) {// Perform the multiplication and convert the Jacobian point back to affine // big.Ints.varModNScalar .SetByteSlice(moduloReduce())varJacobianPointScalarBaseMultNonConst(&, &)returnjacobianToBigAffine(&)}// X returns the x coordinate of the public key.func ( *PublicKey) () *big.Int {returnnew(big.Int).SetBytes(.x.Bytes()[:])}// Y returns the y coordinate of the public key.func ( *PublicKey) () *big.Int {returnnew(big.Int).SetBytes(.y.Bytes()[:])}// ToECDSA returns the public key as a *ecdsa.PublicKey.func ( *PublicKey) () *ecdsa.PublicKey {return &ecdsa.PublicKey{Curve: S256(),X: .X(),Y: .Y(), }}// ToECDSA returns the private key as a *ecdsa.PrivateKey.func ( *PrivateKey) () *ecdsa.PrivateKey {var [PrivKeyBytesLen]byte .Key.PutBytes(&)varJacobianPointScalarBaseMultNonConst(&.Key, &) , := jacobianToBigAffine(&) := &ecdsa.PrivateKey{PublicKey: ecdsa.PublicKey{Curve: S256(),X: ,Y: , },D: new(big.Int).SetBytes([:]), }zeroArray32(&)return}// 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( string) *big.Int {if == "" {returnbig.NewInt(0) } , := new(big.Int).SetString(, 16)if ! {panic("invalid hex in source file: " + ) }return}// 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 an elliptic.Curve which implements secp256k1.func () *KoblitzCurve {returnsecp256k1}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.