2015-05-01 01:28:01 -05:00
|
|
|
// Copyright (c) 2013-2014 The btcsuite developers
|
2013-06-13 13:27:23 -05:00
|
|
|
// Use of this source code is governed by an ISC
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package btcec
|
|
|
|
|
|
|
|
import (
|
2021-11-18 18:25:56 -08:00
|
|
|
secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
|
2013-06-13 13:27:23 -05:00
|
|
|
)
|
|
|
|
|
Optimize public key serialization.
This change removes the internal pad function in favor a more opimized
paddedAppend function. Unlike pad, which would always alloate a new
slice of the desired size and copy the bytes into it, paddedAppend
only appends the leading padding when necesary, and uses the builtin
append to copy the remaining source bytes. pad was also used in
combination with another call to the builtin copy func to copy into a
zeroed byte slice. As the slice is now created using make with an
initial length of zero, this copy can also be removed.
As confirmed by poking the bytes with the unsafe package, gc does not
zero array elements between the len and cap when allocating slices
with make(). In combination with the paddedAppend func, this results
in only a single copy of each byte, with no unnecssary zeroing, when
creating the serialized pubkeys. This has not been tested with other
Go compilers (namely, gccgo and llgo), but the new behavior is still
functionally correct regardless of compiler optimizations.
The TestPad function has been removed as the pad func it tested has
likewise been removed.
ok @davecgh
2014-05-19 21:24:48 -05:00
|
|
|
// These constants define the lengths of serialized public keys.
|
|
|
|
const (
|
2021-11-18 18:25:56 -08:00
|
|
|
PubKeyBytesLenCompressed = 33
|
Optimize public key serialization.
This change removes the internal pad function in favor a more opimized
paddedAppend function. Unlike pad, which would always alloate a new
slice of the desired size and copy the bytes into it, paddedAppend
only appends the leading padding when necesary, and uses the builtin
append to copy the remaining source bytes. pad was also used in
combination with another call to the builtin copy func to copy into a
zeroed byte slice. As the slice is now created using make with an
initial length of zero, this copy can also be removed.
As confirmed by poking the bytes with the unsafe package, gc does not
zero array elements between the len and cap when allocating slices
with make(). In combination with the paddedAppend func, this results
in only a single copy of each byte, with no unnecssary zeroing, when
creating the serialized pubkeys. This has not been tested with other
Go compilers (namely, gccgo and llgo), but the new behavior is still
functionally correct regardless of compiler optimizations.
The TestPad function has been removed as the pad func it tested has
likewise been removed.
ok @davecgh
2014-05-19 21:24:48 -05:00
|
|
|
)
|
|
|
|
|
2013-06-13 13:27:23 -05:00
|
|
|
const (
|
|
|
|
pubkeyCompressed byte = 0x2 // y_bit + x coord
|
2013-09-10 23:14:30 -04:00
|
|
|
pubkeyUncompressed byte = 0x4 // x coord + y coord
|
|
|
|
pubkeyHybrid byte = 0x6 // y_bit + x coord + y coord
|
2013-06-13 13:27:23 -05:00
|
|
|
)
|
|
|
|
|
2017-04-26 16:21:40 -07:00
|
|
|
// IsCompressedPubKey returns true the the passed serialized public key has
|
|
|
|
// been encoded in compressed format, and false otherwise.
|
|
|
|
func IsCompressedPubKey(pubKey []byte) bool {
|
|
|
|
// The public key is only compressed if it is the correct length and
|
|
|
|
// the format (first byte) is one of the compressed pubkey values.
|
|
|
|
return len(pubKey) == PubKeyBytesLenCompressed &&
|
|
|
|
(pubKey[0]&^byte(0x1) == pubkeyCompressed)
|
|
|
|
}
|
|
|
|
|
2013-08-06 18:22:16 +01:00
|
|
|
// ParsePubKey parses a public key for a koblitz curve from a bytestring into a
|
|
|
|
// ecdsa.Publickey, verifying that it is valid. It supports compressed,
|
|
|
|
// uncompressed and hybrid signature formats.
|
2021-11-18 18:25:56 -08:00
|
|
|
func ParsePubKey(pubKeyStr []byte) (*PublicKey, error) {
|
|
|
|
return secp.ParsePubKey(pubKeyStr)
|
2013-06-13 13:27:23 -05:00
|
|
|
}
|
2013-09-10 23:14:30 -04:00
|
|
|
|
|
|
|
// PublicKey is an ecdsa.PublicKey with additional functions to
|
|
|
|
// serialize in uncompressed, compressed, and hybrid formats.
|
2021-11-18 18:25:56 -08:00
|
|
|
type PublicKey = secp.PublicKey
|
|
|
|
|
|
|
|
// NewPublicKey instantiates a new public key with the given x and y
|
|
|
|
// coordinates.
|
|
|
|
//
|
|
|
|
// It should be noted that, unlike ParsePubKey, since this accepts arbitrary x
|
|
|
|
// and y coordinates, it allows creation of public keys that are not valid
|
|
|
|
// points on the secp256k1 curve. The IsOnCurve method of the returned instance
|
|
|
|
// can be used to determine validity.
|
|
|
|
func NewPublicKey(x, y *FieldVal) *PublicKey {
|
|
|
|
return secp.NewPublicKey(x, y)
|
2013-11-01 16:09:46 -04:00
|
|
|
}
|