diff --git a/crypto/ecdsa.go b/crypto/ecdsa.go index 9ea7695..3b7a425 100644 --- a/crypto/ecdsa.go +++ b/crypto/ecdsa.go @@ -37,6 +37,8 @@ var ( ErrNilSig = errors.New("sig is nil") // ErrNilPrivateKey is returned when a nil private key is provided ErrNilPrivateKey = errors.New("private key is nil") + // ErrNilPublicKey is returned when a nil public key is provided + ErrNilPublicKey = errors.New("public key is nil") // ECDSACurve is the default ecdsa curve used ECDSACurve = elliptic.P256() ) diff --git a/crypto/key_not_openssl.go b/crypto/key_not_openssl.go index fb1e36a..1499fea 100644 --- a/crypto/key_not_openssl.go +++ b/crypto/key_not_openssl.go @@ -38,3 +38,43 @@ func KeyPairFromStdKey(priv crypto.PrivateKey) (PrivKey, PubKey, error) { return nil, nil, ErrBadKeyType } } + +// PrivKeyToStdKey converts libp2p/go-libp2p-core/crypto private keys to standard library (and secp256k1) private keys +func PrivKeyToStdKey(priv PrivKey) (crypto.PrivateKey, error) { + if priv == nil { + return nil, ErrNilPrivateKey + } + + switch p := priv.(type) { + case *RsaPrivateKey: + return &p.sk, nil + case *ECDSAPrivateKey: + return p.priv, nil + case *Ed25519PrivateKey: + return &p.k, nil + case *Secp256k1PrivateKey: + return p, nil + default: + return nil, ErrBadKeyType + } +} + +// PubKeyToStdKey converts libp2p/go-libp2p-core/crypto private keys to standard library (and secp256k1) public keys +func PubKeyToStdKey(pub PubKey) (crypto.PublicKey, error) { + if pub == nil { + return nil, ErrNilPublicKey + } + + switch p := pub.(type) { + case *RsaPublicKey: + return &p.k, nil + case *ECDSAPublicKey: + return p.pub, nil + case *Ed25519PublicKey: + return p.k, nil + case *Secp256k1PublicKey: + return p, nil + default: + return nil, ErrBadKeyType + } +} diff --git a/crypto/key_openssl.go b/crypto/key_openssl.go index 5b1e360..8d7810c 100644 --- a/crypto/key_openssl.go +++ b/crypto/key_openssl.go @@ -45,3 +45,50 @@ func KeyPairFromStdKey(priv crypto.PrivateKey) (PrivKey, PubKey, error) { return nil, nil, ErrBadKeyType } } + +// PrivKeyToStdKey converts libp2p/go-libp2p-core/crypto private keys to standard library (and secp256k1) private keys +func PrivKeyToStdKey(priv PrivKey) (crypto.PrivateKey, error) { + if priv == nil { + return nil, ErrNilPrivateKey + } + switch p := priv.(type) { + case *opensslPrivateKey: + raw, err := p.Raw() + if err != nil { + return nil, err + } + return x509.ParsePKCS1PrivateKey(raw) + case *ECDSAPrivateKey: + return p.priv, nil + case *Ed25519PrivateKey: + return &p.k, nil + case *Secp256k1PrivateKey: + return p, nil + default: + return nil, ErrBadKeyType + } +} + +// PubKeyToStdKey converts libp2p/go-libp2p-core/crypto private keys to standard library (and secp256k1) public keys +func PubKeyToStdKey(pub PubKey) (crypto.PublicKey, error) { + if pub == nil { + return nil, ErrNilPublicKey + } + + switch p := pub.(type) { + case *opensslPublicKey: + raw, err := p.Raw() + if err != nil { + return nil, err + } + return x509.ParsePKIXPublicKey(raw) + case *ECDSAPublicKey: + return p.pub, nil + case *Ed25519PublicKey: + return p.k, nil + case *Secp256k1PublicKey: + return p, nil + default: + return nil, ErrBadKeyType + } +} diff --git a/crypto/key_test.go b/crypto/key_test.go index 984eaa1..97ab024 100644 --- a/crypto/key_test.go +++ b/crypto/key_test.go @@ -8,7 +8,9 @@ import ( "crypto/elliptic" "crypto/rand" "crypto/rsa" + "crypto/x509" "fmt" + "reflect" "testing" btcec "github.com/btcsuite/btcd/btcec" @@ -111,6 +113,65 @@ func TestKeyPairFromKey(t *testing.T) { if !v { t.Error("signature was not verified") } + + stdPub, err := PubKeyToStdKey(pub) + if stdPub == nil { + t.Errorf("err getting std public key from key: %v", err) + } + + var stdPubBytes []byte + + switch p := stdPub.(type) { + case *Secp256k1PublicKey: + stdPubBytes, err = p.Raw() + case ed25519.PublicKey: + stdPubBytes = []byte(p) + default: + stdPubBytes, err = x509.MarshalPKIXPublicKey(stdPub) + } + + if err != nil { + t.Errorf("Error while marshaling %v key: %v", reflect.TypeOf(stdPub), err) + } + + pubBytes, err := pub.Raw() + if err != nil { + t.Errorf("err getting raw bytes for %v key: %v", reflect.TypeOf(pub), err) + } + if !bytes.Equal(stdPubBytes, pubBytes) { + t.Errorf("err roundtripping %v key", reflect.TypeOf(pub)) + } + + stdPriv, err := PrivKeyToStdKey(priv) + if stdPub == nil { + t.Errorf("err getting std private key from key: %v", err) + } + + var stdPrivBytes []byte + + switch p := stdPriv.(type) { + case *Secp256k1PrivateKey: + stdPrivBytes, err = p.Raw() + case *ecdsa.PrivateKey: + stdPrivBytes, err = x509.MarshalECPrivateKey(p) + case *ed25519.PrivateKey: + stdPrivBytes = *p + case *rsa.PrivateKey: + stdPrivBytes = x509.MarshalPKCS1PrivateKey(p) + } + + if err != nil { + t.Errorf("err marshaling %v key: %v", reflect.TypeOf(stdPriv), err) + } + + privBytes, err := priv.Raw() + if err != nil { + t.Errorf("err getting raw bytes for %v key: %v", reflect.TypeOf(priv), err) + } + + if !bytes.Equal(stdPrivBytes, privBytes) { + t.Errorf("err roundtripping %v key", reflect.TypeOf(priv)) + } }) } }