Fix up PrivateKeyToDER function and add tests

This commit is contained in:
Mark Beamer Jr 2021-03-14 12:26:53 -04:00
parent bd452c421f
commit a365d63d16
No known key found for this signature in database
GPG key ID: 1C314FB89AD76973
2 changed files with 78 additions and 14 deletions

View file

@ -50,30 +50,37 @@ type ecPrivateKey struct {
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
} }
func PrivateKeyToDER(privateKey *btcec.PrivateKey) ([]byte, error) { func PrivateKeyToDER(key *btcec.PrivateKey) ([]byte, error) {
priv := privateKey.ToECDSA() privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
privateKeyBytes := elliptic.Marshal(priv.Curve, priv.X, priv.Y) oid := asn1.ObjectIdentifier{1, 3, 132, 0, 10}
pub := privateKey.PubKey().ToECDSA()
publicKeyBytes := elliptic.Marshal(pub.Curve, pub.X, pub.Y)
return asn1.Marshal(ecPrivateKey{ return asn1.Marshal(ecPrivateKey{
Version: 1, Version: 1,
PrivateKey: priv.D.FillBytes(privateKeyBytes), PrivateKey: key.D.FillBytes(privateKey),
//asn1 encoding oid for secp256k1 https://github.com/bitpay/bitpay-go/blob/v2.2.2/key_utils/key_utils.go#L30 NamedCurveOID: oid,
NamedCurveOID: asn1.ObjectIdentifier{1, 3, 132, 0, 10}, PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
PublicKey: asn1.BitString{
Bytes: publicKeyBytes,
BitLength: 8 * len(publicKeyBytes),
},
}) })
} }
func GetPublicKeyFromBytes(pubKeyBytes []byte) (*btcec.PublicKey, error) { func GetPublicKeyFromBytes(pubKeyBytes []byte) (*btcec.PublicKey, error) {
PKInfo := publicKeyInfo{} PKInfo := publicKeyInfo{}
asn1.Unmarshal(pubKeyBytes, &PKInfo) _, err := asn1.Unmarshal(pubKeyBytes, &PKInfo)
if err != nil {
return nil, errors.Err(err)
}
pubkeyBytes1 := []byte(PKInfo.PublicKey.Bytes) pubkeyBytes1 := []byte(PKInfo.PublicKey.Bytes)
return btcec.ParsePubKey(pubkeyBytes1, btcec.S256()) return btcec.ParsePubKey(pubkeyBytes1, btcec.S256())
} }
func GetPrivateKeyFromBytes(privKeyBytes []byte) (*btcec.PrivateKey, *btcec.PublicKey, error) {
ecPK := ecPrivateKey{}
_, err := asn1.Unmarshal(privKeyBytes, &ecPK)
if err != nil {
return nil, nil, errors.Err(err)
}
priv, publ := btcec.PrivKeyFromBytes(btcec.S256(), ecPK.PrivateKey)
return priv, publ, nil
}
//Returns a btec.Private key object if provided a correct secp256k1 encoded pem. //Returns a btec.Private key object if provided a correct secp256k1 encoded pem.
func ExtractKeyFromPem(pm string) (*btcec.PrivateKey, *btcec.PublicKey) { func ExtractKeyFromPem(pm string) (*btcec.PrivateKey, *btcec.PublicKey) {
byta := []byte(pm) byta := []byte(pm)

View file

@ -1,9 +1,12 @@
package keys package keys
import ( import (
"bytes"
"encoding/hex" "encoding/hex"
"encoding/pem"
"testing" "testing"
"github.com/btcsuite/btcd/btcec"
"gotest.tools/assert" "gotest.tools/assert"
) )
@ -36,3 +39,57 @@ func TestPublicKeyToDER(t *testing.T) {
} }
assert.Assert(t, p1.IsEqual(p2), "The keys produced must be the same key!") assert.Assert(t, p1.IsEqual(p2), "The keys produced must be the same key!")
} }
func TestPrivateKeyToDER(t *testing.T) {
private1, err := btcec.NewPrivateKey(btcec.S256())
if err != nil {
t.Fatal(err)
}
bytes, err := PrivateKeyToDER(private1)
if err != nil {
t.Fatal(err)
}
private2, _, err := GetPrivateKeyFromBytes(bytes)
if err != nil {
t.Error(err)
}
if !private1.ToECDSA().Equal(private2.ToECDSA()) {
t.Error("private keys dont match")
}
}
func TestGetPrivateKeyFromBytes(t *testing.T) {
private, err := btcec.NewPrivateKey(btcec.S256())
if err != nil {
t.Fatal(err)
}
bytes, err := PrivateKeyToDER(private)
private2, _, err := GetPrivateKeyFromBytes(bytes)
if !private.ToECDSA().Equal(private2.ToECDSA()) {
t.Error("private keys dont match")
}
}
func TestEncodePEMAndBack(t *testing.T) {
private1, err := btcec.NewPrivateKey(btcec.S256())
if err != nil {
t.Fatal(err)
}
b := bytes.NewBuffer(nil)
derBytes, err := PrivateKeyToDER(private1)
if err != nil {
t.Fatal(err)
}
err = pem.Encode(b, &pem.Block{Type: "PRIVATE KEY", Bytes: derBytes})
if err != nil {
t.Fatal(err)
}
println(string(b.Bytes()))
private2, _ := ExtractKeyFromPem(string(b.Bytes()))
if err != nil {
t.Fatal(err)
}
if !private1.ToECDSA().Equal(private2.ToECDSA()) {
t.Error("private keys dont match")
}
}