diff --git a/core/crypto/key.go b/core/crypto/key.go index 6cd9dc0be..5a0058f3c 100644 --- a/core/crypto/key.go +++ b/core/crypto/key.go @@ -4,9 +4,12 @@ package crypto import ( + "crypto" + "crypto/ecdsa" "crypto/elliptic" "crypto/hmac" "crypto/rand" + "crypto/rsa" "crypto/sha1" "crypto/sha512" "crypto/subtle" @@ -15,11 +18,14 @@ import ( "fmt" "hash" "io" + "log" pb "github.com/libp2p/go-libp2p-core/crypto/pb" + btcec "github.com/btcsuite/btcd/btcec" "github.com/gogo/protobuf/proto" sha256 "github.com/minio/sha256-simd" + "golang.org/x/crypto/ed25519" ) const ( @@ -174,6 +180,42 @@ func GenerateEKeyPair(curveName string) ([]byte, GenSharedKey, error) { return pubKey, done, nil } +// KeyPairFromKey generates a new private and public key from an input private key +func KeyPairFromKey(priv crypto.PrivateKey) (PrivKey, PubKey, error) { + if priv == nil { + return nil, nil, ErrNilPrivateKey + } + + switch priv.(type) { + case *rsa.PrivateKey: + log.Println("1") + rPriv, _ := priv.(*rsa.PrivateKey) + return &RsaPrivateKey{*rPriv}, &RsaPublicKey{rPriv.PublicKey}, nil + + case *ecdsa.PrivateKey: + log.Println("2") + ePriv, _ := priv.(*ecdsa.PrivateKey) + return &ECDSAPrivateKey{ePriv}, &ECDSAPublicKey{&ePriv.PublicKey}, nil + + case *ed25519.PrivateKey: + log.Println("3") + ePriv, _ := priv.(*ed25519.PrivateKey) + pubIfc := ePriv.Public() + pub, _ := pubIfc.(ed25519.PublicKey) + return &Ed25519PrivateKey{*ePriv}, &Ed25519PublicKey{pub}, nil + + case *btcec.PrivateKey: + log.Println("4") + bPriv, _ := priv.(*btcec.PrivateKey) + sPriv := Secp256k1PrivateKey(*bPriv) + sPub := Secp256k1PublicKey(*bPriv.PubKey()) + return &sPriv, &sPub, nil + + default: + return nil, nil, ErrBadKeyType + } +} + // StretchedKeys ... type StretchedKeys struct { IV []byte diff --git a/core/crypto/key_test.go b/core/crypto/key_test.go index 05e66ed30..470d067b8 100644 --- a/core/crypto/key_test.go +++ b/core/crypto/key_test.go @@ -2,12 +2,20 @@ package crypto_test import ( "bytes" + "crypto" + "crypto/ecdsa" + "crypto/elliptic" "crypto/rand" + "crypto/rsa" + "fmt" "testing" + btcec "github.com/btcsuite/btcd/btcec" . "github.com/libp2p/go-libp2p-core/crypto" pb "github.com/libp2p/go-libp2p-core/crypto/pb" "github.com/libp2p/go-libp2p-core/test" + sha256 "github.com/minio/sha256-simd" + "golang.org/x/crypto/ed25519" ) func TestKeys(t *testing.T) { @@ -16,6 +24,97 @@ func TestKeys(t *testing.T) { } } +func TestKeyPairFromKey(t *testing.T) { + var ( + data = []byte(`hello world`) + hashed = sha256.Sum256(data) + ) + + privk, err := btcec.NewPrivateKey(btcec.S256()) + if err != nil { + t.Fatalf("err generating btcec priv key:\n%v", err) + } + sigK, err := privk.Sign(hashed[:]) + if err != nil { + t.Fatalf("err generating btcec sig:\n%v", err) + } + + eKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + if err != nil { + t.Fatalf("err generating ecdsa priv key:\n%v", err) + } + sigE, err := eKey.Sign(rand.Reader, hashed[:], crypto.SHA256) + if err != nil { + t.Fatalf("err generating ecdsa sig:\n%v", err) + } + + rKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + t.Fatalf("err generating rsa priv key:\n%v", err) + } + sigR, err := rKey.Sign(rand.Reader, hashed[:], crypto.SHA256) + if err != nil { + t.Fatalf("err generating rsa sig:\n%v", err) + } + + _, edKey, err := ed25519.GenerateKey(rand.Reader) + sigEd := ed25519.Sign(edKey, data[:]) + if err != nil { + t.Fatalf("err generating ed25519 sig:\n%v", err) + } + + for i, tt := range []struct { + in crypto.PrivateKey + typ pb.KeyType + sig []byte + }{ + { + eKey, + ECDSA, + sigE, + }, + { + privk, + Secp256k1, + sigK.Serialize(), + }, + { + rKey, + RSA, + sigR, + }, + { + &edKey, + Ed25519, + sigEd, + }, + } { + t.Run(fmt.Sprintf("%v", i), func(t *testing.T) { + priv, pub, err := KeyPairFromKey(tt.in) + if err != nil { + t.Fatal(err) + } + + if priv == nil || pub == nil { + t.Errorf("received nil private key or public key: %v, %v", priv, pub) + } + + if priv == nil || priv.Type() != tt.typ { + t.Errorf("want %v; got %v", tt.typ, priv.Type()) + } + + v, err := pub.Verify(data[:], tt.sig) + if err != nil { + t.Error(err) + } + + if !v { + t.Error("signature was not verified") + } + }) + } +} + func testKeyType(typ int, t *testing.T) { bits := 512 if typ == RSA {