2020-10-28 06:36:49 +01:00
|
|
|
package keys
|
2019-04-07 06:29:12 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/elliptic"
|
|
|
|
"crypto/x509/pkix"
|
|
|
|
"encoding/asn1"
|
2020-11-18 07:30:50 +01:00
|
|
|
"encoding/pem"
|
2019-04-07 06:29:12 +02:00
|
|
|
|
2021-10-06 20:00:59 +02:00
|
|
|
"github.com/cockroachdb/errors"
|
|
|
|
"github.com/lbryio/lbcd/btcec"
|
2019-04-07 06:29:12 +02:00
|
|
|
)
|
|
|
|
|
2020-10-28 06:36:49 +01:00
|
|
|
type publicKeyInfo struct {
|
|
|
|
Raw asn1.RawContent
|
|
|
|
Algorithm pkix.AlgorithmIdentifier
|
|
|
|
PublicKey asn1.BitString
|
|
|
|
}
|
|
|
|
|
2019-04-07 06:29:12 +02:00
|
|
|
func PublicKeyToDER(publicKey *btcec.PublicKey) ([]byte, error) {
|
|
|
|
var publicKeyBytes []byte
|
|
|
|
var publicKeyAlgorithm pkix.AlgorithmIdentifier
|
2021-10-06 20:00:59 +02:00
|
|
|
|
2019-04-07 06:29:12 +02:00
|
|
|
pub := publicKey.ToECDSA()
|
|
|
|
publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
|
|
|
|
//ans1 encoding oid for ecdsa public key https://github.com/golang/go/blob/release-branch.go1.12/src/crypto/x509/x509.go#L457
|
|
|
|
publicKeyAlgorithm.Algorithm = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
|
|
|
|
//asn1 encoding oid for secp256k1 https://github.com/bitpay/bitpay-go/blob/v2.2.2/key_utils/key_utils.go#L30
|
|
|
|
paramBytes, err := asn1.Marshal(asn1.ObjectIdentifier{1, 3, 132, 0, 10})
|
|
|
|
if err != nil {
|
2021-10-06 20:00:59 +02:00
|
|
|
return nil, errors.WithStack(err)
|
2019-04-07 06:29:12 +02:00
|
|
|
}
|
|
|
|
publicKeyAlgorithm.Parameters.FullBytes = paramBytes
|
|
|
|
|
|
|
|
return asn1.Marshal(publicKeyInfo{
|
|
|
|
Algorithm: publicKeyAlgorithm,
|
|
|
|
PublicKey: asn1.BitString{
|
|
|
|
Bytes: publicKeyBytes,
|
|
|
|
BitLength: 8 * len(publicKeyBytes),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2021-03-14 09:17:27 +01:00
|
|
|
//This type provides compatibility with the btcec package
|
|
|
|
type ecPrivateKey struct {
|
|
|
|
Version int
|
|
|
|
PrivateKey []byte
|
|
|
|
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
|
|
|
|
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
|
|
|
|
}
|
|
|
|
|
2021-03-14 17:26:53 +01:00
|
|
|
func PrivateKeyToDER(key *btcec.PrivateKey) ([]byte, error) {
|
|
|
|
privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
|
|
|
|
oid := asn1.ObjectIdentifier{1, 3, 132, 0, 10}
|
2021-03-14 09:17:27 +01:00
|
|
|
return asn1.Marshal(ecPrivateKey{
|
2021-03-14 17:26:53 +01:00
|
|
|
Version: 1,
|
|
|
|
PrivateKey: key.D.FillBytes(privateKey),
|
|
|
|
NamedCurveOID: oid,
|
|
|
|
PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
|
2021-03-14 09:17:27 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-10-28 06:36:49 +01:00
|
|
|
func GetPublicKeyFromBytes(pubKeyBytes []byte) (*btcec.PublicKey, error) {
|
2019-04-07 06:29:12 +02:00
|
|
|
PKInfo := publicKeyInfo{}
|
2021-03-14 17:26:53 +01:00
|
|
|
_, err := asn1.Unmarshal(pubKeyBytes, &PKInfo)
|
|
|
|
if err != nil {
|
2021-10-06 20:00:59 +02:00
|
|
|
return nil, errors.WithStack(err)
|
2021-03-14 17:26:53 +01:00
|
|
|
}
|
2021-10-06 20:00:59 +02:00
|
|
|
pubkeyBytes1 := PKInfo.PublicKey.Bytes
|
2019-04-07 06:29:12 +02:00
|
|
|
return btcec.ParsePubKey(pubkeyBytes1, btcec.S256())
|
|
|
|
}
|
2020-11-18 07:30:50 +01:00
|
|
|
|
2021-03-14 17:26:53 +01:00
|
|
|
func GetPrivateKeyFromBytes(privKeyBytes []byte) (*btcec.PrivateKey, *btcec.PublicKey, error) {
|
|
|
|
ecPK := ecPrivateKey{}
|
|
|
|
_, err := asn1.Unmarshal(privKeyBytes, &ecPK)
|
|
|
|
if err != nil {
|
2021-10-06 20:00:59 +02:00
|
|
|
return nil, nil, errors.WithStack(err)
|
2021-03-14 17:26:53 +01:00
|
|
|
}
|
|
|
|
priv, publ := btcec.PrivKeyFromBytes(btcec.S256(), ecPK.PrivateKey)
|
|
|
|
return priv, publ, nil
|
|
|
|
}
|
|
|
|
|
2021-10-06 20:00:59 +02:00
|
|
|
//ExtractKeyFromPem returns a btec.Private key object if provided a correct secp256k1 encoded pem.
|
2020-11-18 07:30:50 +01:00
|
|
|
func ExtractKeyFromPem(pm string) (*btcec.PrivateKey, *btcec.PublicKey) {
|
|
|
|
byta := []byte(pm)
|
|
|
|
blck, _ := pem.Decode(byta)
|
|
|
|
var ecp ecPrivateKey
|
|
|
|
asn1.Unmarshal(blck.Bytes, &ecp)
|
|
|
|
return btcec.PrivKeyFromBytes(btcec.S256(), ecp.PrivateKey)
|
|
|
|
}
|
2021-03-16 01:00:44 +01:00
|
|
|
|
|
|
|
type Signature struct {
|
|
|
|
btcec.Signature
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Signature) LBRYSDKEncode() ([]byte, error) {
|
|
|
|
if s.R == nil || s.S == nil {
|
2021-10-06 20:00:59 +02:00
|
|
|
return nil, errors.WithStack(errors.New("invalid signature, both S & R are nil"))
|
2021-03-16 01:00:44 +01:00
|
|
|
}
|
|
|
|
rBytes := s.R.Bytes()
|
|
|
|
sBytes := s.S.Bytes()
|
|
|
|
|
|
|
|
return append(rBytes, sBytes...), nil
|
|
|
|
}
|