secp256k1: Add AsJacobian method to pubkey.
This add a new method to the PublicKey type named AsJacobian which converts the public key into a Jacobian point with Z=1. This allows the public key to be treated a Jacobian point in the secp256k1 group in calculations. It also adds an associated test to ensure proper functionality.
This commit is contained in:
parent
b9695b4828
commit
990076ec2e
@ -134,6 +134,16 @@ func ParsePubKey(pubKeyStr []byte) (key *PublicKey, err error) {
|
||||
return &pubkey, nil
|
||||
}
|
||||
|
||||
// paddedAppend appends the src byte slice to dst, returning the new slice.
|
||||
// If the length of the source is smaller than the passed size, leading zero
|
||||
// bytes are appended to the dst slice before appending src.
|
||||
func paddedAppend(size uint, dst, src []byte) []byte {
|
||||
for i := 0; i < int(size)-len(src); i++ {
|
||||
dst = append(dst, 0)
|
||||
}
|
||||
return append(dst, src...)
|
||||
}
|
||||
|
||||
// SerializeUncompressed serializes a public key in a 65-byte uncompressed
|
||||
// format.
|
||||
func (p PublicKey) SerializeUncompressed() []byte {
|
||||
@ -161,12 +171,9 @@ func (p *PublicKey) IsEqual(otherPubKey *PublicKey) bool {
|
||||
return p.x.Cmp(otherPubKey.x) == 0 && p.y.Cmp(otherPubKey.y) == 0
|
||||
}
|
||||
|
||||
// paddedAppend appends the src byte slice to dst, returning the new slice.
|
||||
// If the length of the source is smaller than the passed size, leading zero
|
||||
// bytes are appended to the dst slice before appending src.
|
||||
func paddedAppend(size uint, dst, src []byte) []byte {
|
||||
for i := 0; i < int(size)-len(src); i++ {
|
||||
dst = append(dst, 0)
|
||||
}
|
||||
return append(dst, src...)
|
||||
// AsJacobian converts the public key into a Jacobian point with Z=1 and stores
|
||||
// the result in the provided result param. This allows the public key to be
|
||||
// treated a Jacobian point in the secp256k1 group in calculations.
|
||||
func (p *PublicKey) AsJacobian(result *JacobianPoint) {
|
||||
bigAffineToJacobian(p.x, p.y, result)
|
||||
}
|
||||
|
||||
@ -277,3 +277,62 @@ func TestPublicKeyIsEqual(t *testing.T) {
|
||||
"equal to %v", pubKey1, pubKey2)
|
||||
}
|
||||
}
|
||||
|
||||
// TestPublicKeyAsJacobian ensures converting a public key to a jacobian point
|
||||
// with a Z coordinate of 1 works as expected.
|
||||
func TestPublicKeyAsJacobian(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string // test description
|
||||
pubKey string // hex encoded serialized compressed pubkey
|
||||
wantX string // hex encoded expected X coordinate
|
||||
wantY string // hex encoded expected Y coordinate
|
||||
|
||||
}{{
|
||||
name: "public key for private key 0x01",
|
||||
pubKey: "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||
wantX: "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||
wantY: "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
|
||||
}, {
|
||||
name: "public for private key 0x03",
|
||||
pubKey: "02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
|
||||
wantX: "f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9",
|
||||
wantY: "388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672",
|
||||
}, {
|
||||
name: "public for private key 0x06",
|
||||
pubKey: "03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556",
|
||||
wantX: "fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556",
|
||||
wantY: "ae12777aacfbb620f3be96017f45c560de80f0f6518fe4a03c870c36b075f297",
|
||||
}}
|
||||
|
||||
for _, test := range tests {
|
||||
// Parse the test data.
|
||||
pubKeyBytes := hexToBytes(test.pubKey)
|
||||
wantX := hexToFieldVal(test.wantX)
|
||||
wantY := hexToFieldVal(test.wantY)
|
||||
pubKey, err := ParsePubKey(pubKeyBytes)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to parse public key: %v", test.name, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Convert the public key to a jacobian point and ensure the coordinates
|
||||
// match the expected values.
|
||||
var point JacobianPoint
|
||||
pubKey.AsJacobian(&point)
|
||||
if !point.Z.IsOne() {
|
||||
t.Errorf("%s: invalid Z coordinate -- got %v, want 1", test.name,
|
||||
point.Z)
|
||||
continue
|
||||
}
|
||||
if !point.X.Equals(wantX) {
|
||||
t.Errorf("%s: invalid X coordinate - got %v, want %v", test.name,
|
||||
point.X, wantX)
|
||||
continue
|
||||
}
|
||||
if !point.Y.Equals(wantY) {
|
||||
t.Errorf("%s: invalid Y coordinate - got %v, want %v", test.name,
|
||||
point.Y, wantY)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user