From 17615fe28de8cae5f0abf4e2e4dd2f775a003878 Mon Sep 17 00:00:00 2001 From: mrz1836 Date: Wed, 30 Sep 2020 15:20:58 -0400 Subject: [PATCH] Basic private key generation helper methods --- address.go | 2 +- private_key.go | 19 ++++++- private_key_test.go | 127 ++++++++++++++++++++++++++++++++++++++++++++ sign.go | 2 +- 4 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 private_key_test.go diff --git a/address.go b/address.go index fcadddb..a6e3fc9 100644 --- a/address.go +++ b/address.go @@ -73,7 +73,7 @@ func (a *A25) ComputeChecksum() (c [4]byte) { // AddressFromPrivateKey takes a private key string and returns a Bitcoin address func AddressFromPrivateKey(privateKey string) (string, error) { - pubKey, err := PrivateKey(privateKey) + pubKey, err := PrivateKeyFromString(privateKey) if err != nil { return "", err } diff --git a/private_key.go b/private_key.go index 3460e75..607024b 100644 --- a/private_key.go +++ b/private_key.go @@ -8,8 +8,8 @@ import ( "github.com/bitcoinsv/bsvd/bsvec" ) -// PrivateKey turns a private key string into an bsvec.PrivateKey -func PrivateKey(privateKey string) (*bsvec.PrivateKey, error) { +// PrivateKeyFromString turns a private key (hex encoded string) into an bsvec.PrivateKey +func PrivateKeyFromString(privateKey string) (*bsvec.PrivateKey, error) { privateKeyBytes, err := hex.DecodeString(privateKey) if err != nil { return nil, err @@ -22,3 +22,18 @@ func PrivateKey(privateKey string) (*bsvec.PrivateKey, error) { } return &bsvec.PrivateKey{PublicKey: ecdsaPubKey, D: new(big.Int).SetBytes(privateKeyBytes)}, nil } + +// CreatePrivateKey will create a new private key +func CreatePrivateKey() (*bsvec.PrivateKey, error) { + return bsvec.NewPrivateKey(bsvec.S256()) +} + +// CreatePrivateKeyString will create a new private key (hex encoded) +func CreatePrivateKeyString() (string, error) { + privateKey, err := bsvec.NewPrivateKey(bsvec.S256()) + if err != nil { + return "", err + } + + return hex.EncodeToString(privateKey.Serialize()), nil +} diff --git a/private_key_test.go b/private_key_test.go new file mode 100644 index 0000000..7eb4100 --- /dev/null +++ b/private_key_test.go @@ -0,0 +1,127 @@ +package bitcoin + +import ( + "encoding/hex" + "fmt" + "testing" +) + +// TestCreatePrivateKey will test the method CreatePrivateKey() +func TestCreatePrivateKey(t *testing.T) { + rawKey, err := CreatePrivateKey() + if err != nil { + t.Fatalf("error occurred: %s", err.Error()) + } + if rawKey == nil { + t.Fatalf("private key was nil") + } + if len(rawKey.Serialize()) == 0 { + t.Fatalf("key length was invalid") + } +} + +// ExampleCreatePrivateKey example using CreatePrivateKey() +func ExampleCreatePrivateKey() { + rawKey, err := CreatePrivateKey() + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } else if len(rawKey.Serialize()) > 0 { + fmt.Printf("key created successfully!") + } + // Output:key created successfully! +} + +// BenchmarkCreatePrivateKey benchmarks the method CreatePrivateKey() +func BenchmarkCreatePrivateKey(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = CreatePrivateKey() + } +} + +// TestCreatePrivateKeyString will test the method CreatePrivateKeyString() +func TestCreatePrivateKeyString(t *testing.T) { + key, err := CreatePrivateKeyString() + if err != nil { + t.Fatalf("error occurred: %s", err.Error()) + } + if len(key) == 0 { + t.Fatalf("private key is empty") + } + if len(key) != 64 { + t.Fatalf("key length is not 64") + } +} + +// ExampleCreatePrivateKeyString example using CreatePrivateKeyString() +func ExampleCreatePrivateKeyString() { + key, err := CreatePrivateKeyString() + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } else if len(key) > 0 { + fmt.Printf("key created successfully!") + } + // Output:key created successfully! +} + +// BenchmarkCreatePrivateKeyString benchmarks the method CreatePrivateKeyString() +func BenchmarkCreatePrivateKeyString(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = CreatePrivateKeyString() + } +} + +// TestPrivateKeyFromString will test the method PrivateKeyFromString() +func TestPrivateKeyFromString(t *testing.T) { + t.Parallel() + + // Create the list of tests + var tests = []struct { + input string + expectedKey string + expectedNil bool + expectedError bool + }{ + {"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", "54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", false, false}, + {"E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F4650C5F2B75", "e83385af76b2b1997326b567461fb73dd9c27eab9e1e86d26779f4650c5f2b75", false, false}, + {"E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F4650C5F", "0000e83385af76b2b1997326b567461fb73dd9c27eab9e1e86d26779f4650c5f", false, false}, + {"E83385AF76B2B1997326B567461FB73DD9C27EAB9E1E86D26779F", "", true, true}, + {"1234567", "", true, true}, + {"0", "", true, true}, + } + + // Run tests + for _, test := range tests { + if rawKey, err := PrivateKeyFromString(test.input); err != nil && !test.expectedError { + t.Errorf("%s Failed: [%s] inputted and error not expected but got: %s", t.Name(), test.input, err.Error()) + } else if err == nil && test.expectedError { + t.Errorf("%s Failed: [%s] inputted and error was expected", t.Name(), test.input) + } else if rawKey == nil && !test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and was nil but not expected", t.Name(), test.input) + } else if rawKey != nil && test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and was NOT nil but expected to be nil", t.Name(), test.input) + } else if rawKey != nil && hex.EncodeToString(rawKey.Serialize()) != test.expectedKey { + t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedKey, hex.EncodeToString(rawKey.Serialize())) + } + } +} + +// ExamplePrivateKeyFromString example using PrivateKeyFromString() +func ExamplePrivateKeyFromString() { + key, err := PrivateKeyFromString("54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd") + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + fmt.Printf("key converted: %s", hex.EncodeToString(key.Serialize())) + // Output:key converted: 54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd +} + +// BenchmarkPrivateKeyFromString benchmarks the method PrivateKeyFromString() +func BenchmarkPrivateKeyFromString(b *testing.B) { + key, _ := CreatePrivateKeyString() + for i := 0; i < b.N; i++ { + _, _ = PrivateKeyFromString(key) + } +} diff --git a/sign.go b/sign.go index 10ec607..85dfce4 100644 --- a/sign.go +++ b/sign.go @@ -16,7 +16,7 @@ func SignMessage(privateKey string, message string) (string, error) { bytes = append(bytes, prefixBytes...) bytes = append(bytes, byte(len(messageBytes))) bytes = append(bytes, messageBytes...) - ecdsaPrivateKey, err := PrivateKey(privateKey) + ecdsaPrivateKey, err := PrivateKeyFromString(privateKey) if err != nil { return "", err }