You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.8 KiB
111 lines
3.8 KiB
// Copyright (c) 2015-2021 The btcsuite developers |
|
// Copyright (c) 2015-2021 The Decred developers |
|
|
|
package btcec |
|
|
|
import ( |
|
"fmt" |
|
|
|
"crypto.orly/ec/secp256k1" |
|
) |
|
|
|
// JacobianPoint is an element of the group formed by the secp256k1 curve in |
|
// Jacobian projective coordinates and thus represents a point on the curve. |
|
type JacobianPoint = secp256k1.JacobianPoint |
|
|
|
// infinityPoint is the jacobian representation of the point at infinity. |
|
var infinityPoint JacobianPoint |
|
|
|
// MakeJacobianPoint returns a Jacobian point with the provided X, Y, and Z |
|
// coordinates. |
|
func MakeJacobianPoint(x, y, z *FieldVal) JacobianPoint { |
|
return secp256k1.MakeJacobianPoint(x, y, z) |
|
} |
|
|
|
// AddNonConst adds the passed Jacobian points together and stores the result |
|
// in the provided result param in *non-constant* time. |
|
func AddNonConst(p1, p2, result *JacobianPoint) { |
|
secp256k1.AddNonConst(p1, p2, result) |
|
} |
|
|
|
// DecompressY attempts to calculate the Y coordinate for the given X |
|
// coordinate such that the result pair is a point on the secp256k1 curve. It |
|
// adjusts Y based on the desired oddness and returns whether or not it was |
|
// successful since not all X coordinates are valid. |
|
// |
|
// The magnitude of the provided X coordinate field val must be a max of 8 for |
|
// a correct result. The resulting Y field val will have a max magnitude of 2. |
|
func DecompressY(x *FieldVal, odd bool, resultY *FieldVal) bool { |
|
return secp256k1.DecompressY(x, odd, resultY) |
|
} |
|
|
|
// DoubleNonConst doubles the passed Jacobian point and stores the result in |
|
// the provided result parameter in *non-constant* time. |
|
// |
|
// NOTE: The point must be normalized for this function to return the correct |
|
// result. The resulting point will be normalized. |
|
func DoubleNonConst(p, result *JacobianPoint) { |
|
secp256k1.DoubleNonConst(p, result) |
|
} |
|
|
|
// ScalarBaseMultNonConst multiplies k*G where G is the base point of the group |
|
// and k is a big endian integer. The result is stored in Jacobian coordinates |
|
// (x1, y1, z1). |
|
// |
|
// NOTE: The resulting point will be normalized. |
|
func ScalarBaseMultNonConst(k *ModNScalar, result *JacobianPoint) { |
|
secp256k1.ScalarBaseMultNonConst(k, result) |
|
} |
|
|
|
// ScalarMultNonConst multiplies k*P where k is a big endian integer modulo the |
|
// curve order and P is a point in Jacobian projective coordinates and stores |
|
// the result in the provided Jacobian point. |
|
// |
|
// NOTE: The point must be normalized for this function to return the correct |
|
// result. The resulting point will be normalized. |
|
func ScalarMultNonConst(k *ModNScalar, point, result *JacobianPoint) { |
|
secp256k1.ScalarMultNonConst(k, point, result) |
|
} |
|
|
|
// ParseJacobian parses a byte slice point as a secp256k1.Publickey and returns the |
|
// pubkey as a JacobianPoint. If the nonce is a zero slice, the infinityPoint |
|
// is returned. |
|
func ParseJacobian(point []byte) (JacobianPoint, error) { |
|
var result JacobianPoint |
|
if len(point) != 33 { |
|
str := fmt.Sprintf( |
|
"invalid nonce: invalid length: %v", |
|
len(point), |
|
) |
|
return JacobianPoint{}, makeError(secp256k1.ErrPubKeyInvalidLen, str) |
|
} |
|
if point[0] == 0x00 { |
|
return infinityPoint, nil |
|
} |
|
noncePk, err := secp256k1.ParsePubKey(point) |
|
if err != nil { |
|
return JacobianPoint{}, err |
|
} |
|
noncePk.AsJacobian(&result) |
|
return result, nil |
|
} |
|
|
|
// JacobianToByteSlice converts the passed JacobianPoint to a Pubkey |
|
// and serializes that to a byte slice. If the JacobianPoint is the infinity |
|
// point, a zero slice is returned. |
|
func JacobianToByteSlice(point JacobianPoint) []byte { |
|
if point.X == infinityPoint.X && point.Y == infinityPoint.Y { |
|
return make([]byte, 33) |
|
} |
|
point.ToAffine() |
|
return NewPublicKey( |
|
&point.X, &point.Y, |
|
).SerializeCompressed() |
|
} |
|
|
|
// GeneratorJacobian sets the passed JacobianPoint to the Generator Point. |
|
func GeneratorJacobian(jacobian *JacobianPoint) { |
|
var k ModNScalar |
|
k.SetInt(1) |
|
ScalarBaseMultNonConst(&k, jacobian) |
|
}
|
|
|