initial addition of essential crypto, encoders, workflows and LLM instructions
This commit is contained in:
247
pkg/crypto/ec/secp256k1/ellipticadaptor.go
Normal file
247
pkg/crypto/ec/secp256k1/ellipticadaptor.go
Normal file
@@ -0,0 +1,247 @@
|
||||
// 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 (
|
||||
"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) {
|
||||
// The 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 secret key as a *ecdsa.SecretKey.
|
||||
func (p *SecretKey) ToECDSA() *ecdsa.PrivateKey {
|
||||
var secretKeyBytes [SecKeyBytesLen]byte
|
||||
p.Key.PutBytes(&secretKeyBytes)
|
||||
var result JacobianPoint
|
||||
ScalarBaseMultNonConst(&p.Key, &result)
|
||||
x, y := jacobianToBigAffine(&result)
|
||||
newSecKey := &ecdsa.PrivateKey{
|
||||
PublicKey: ecdsa.PublicKey{
|
||||
Curve: S256(),
|
||||
X: x,
|
||||
Y: y,
|
||||
},
|
||||
D: new(big.Int).SetBytes(secretKeyBytes[:]),
|
||||
}
|
||||
zeroArray32(&secretKeyBytes)
|
||||
return newSecKey
|
||||
}
|
||||
|
||||
// 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 an elliptic.Curve which implements secp256k1.
|
||||
func S256() *KoblitzCurve {
|
||||
return secp256k1
|
||||
}
|
||||
Reference in New Issue
Block a user