diff --git a/README.md b/README.md index e6f157f..102c703 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,8 @@ View the generated [documentation](https://pkg.go.dev/github.com/bitcoinschema/g - [Create PrivateKey](private_key.go) - [Create PubKey from PrivateKey](pubkey.go) - [Script from Address](script.go) +- [WIF to PrivateKey](private_key.go) +- [PrivateKey to WIF](private_key.go)
diff --git a/examples/private_key_to_wif/private_key_to_wif.go b/examples/private_key_to_wif/private_key_to_wif.go new file mode 100644 index 0000000..704dcf3 --- /dev/null +++ b/examples/private_key_to_wif/private_key_to_wif.go @@ -0,0 +1,24 @@ +package main + +import ( + "log" + + "github.com/bitcoinschema/go-bitcoin" +) + +func main() { + // Start with a private key + privateKey, err := bitcoin.CreatePrivateKeyString() + if err != nil { + log.Fatalf("error occurred: %s", err.Error()) + } + + // Create a wif + var wif string + if wif, err = bitcoin.PrivateKeyToWifString(privateKey); err != nil { + log.Fatalf("error occurred: %s", err.Error()) + } + + // Success! + log.Printf("private key: %s converted to wif: %s", privateKey, wif) +} diff --git a/examples/wif_to_private_key/wif_to_private_key.go b/examples/wif_to_private_key/wif_to_private_key.go new file mode 100644 index 0000000..3cbe5f0 --- /dev/null +++ b/examples/wif_to_private_key/wif_to_private_key.go @@ -0,0 +1,19 @@ +package main + +import ( + "log" + + "github.com/bitcoinschema/go-bitcoin" +) + +func main() { + + // Convert the wif into a private key + privateKey, err := bitcoin.WifToPrivateKeyString("5KgHn2qiftW5LQgCYFtkbrLYB1FuvisDtacax8NCvumw3UTKdcP") + if err != nil { + log.Fatalf("error occurred: %s", err.Error()) + } + + // Success! + log.Printf("private key: %s", privateKey) +} diff --git a/private_key.go b/private_key.go index bb59c4b..1d2430c 100644 --- a/private_key.go +++ b/private_key.go @@ -7,6 +7,8 @@ import ( "math/big" "github.com/bitcoinsv/bsvd/bsvec" + "github.com/bitcoinsv/bsvd/chaincfg" + "github.com/bitcoinsv/bsvutil" ) // PrivateKeyFromString turns a private key (hex encoded string) into an bsvec.PrivateKey @@ -27,7 +29,7 @@ func PrivateKeyFromString(privateKey string) (*bsvec.PrivateKey, error) { return &bsvec.PrivateKey{PublicKey: ecdsaPubKey, D: new(big.Int).SetBytes(privateKeyBytes)}, nil } -// CreatePrivateKey will create a new private key +// CreatePrivateKey will create a new private key (*bsvec.PrivateKey) func CreatePrivateKey() (*bsvec.PrivateKey, error) { return bsvec.NewPrivateKey(bsvec.S256()) } @@ -61,3 +63,65 @@ func PrivateAndPublicKeys(privateKey string) (*bsvec.PrivateKey, *bsvec.PublicKe rawKey, publicKey := bsvec.PrivKeyFromBytes(bsvec.S256(), privateKeyBytes) return rawKey, publicKey, nil } + +// PrivateKeyToWif will convert a private key to a WIF (*bsvutil.WIF) +func PrivateKeyToWif(privateKey string) (*bsvutil.WIF, error) { + + // Missing private key + if len(privateKey) == 0 { + return nil, errors.New("missing privateKey") + } + + // Decode the private key + decodedKey, err := hex.DecodeString(privateKey) + if err != nil { + return nil, err + } + + // Get the private key from bytes + rawKey, _ := bsvec.PrivKeyFromBytes(bsvec.S256(), decodedKey) + + // Create a new WIF (error never gets hit since (net) is set correctly) + return bsvutil.NewWIF(rawKey, &chaincfg.MainNetParams, false) +} + +// PrivateKeyToWifString will convert a private key to a WIF (string) +func PrivateKeyToWifString(privateKey string) (string, error) { + wif, err := PrivateKeyToWif(privateKey) + if err != nil { + return "", err + } + + return wif.String(), nil +} + +// WifToPrivateKey will convert a WIF to a private key (*bsvec.PrivateKey) +func WifToPrivateKey(wif string) (*bsvec.PrivateKey, error) { + + // Missing wif? + if len(wif) == 0 { + return nil, errors.New("missing wif") + } + + // Decode the wif + decodedWif, err := bsvutil.DecodeWIF(wif) + if err != nil { + return nil, err + } + + // Return the private key + return decodedWif.PrivKey, nil +} + +// WifToPrivateKeyString will convert a WIF to private key (string) +func WifToPrivateKeyString(wif string) (string, error) { + + // Convert the wif to private key + privateKey, err := WifToPrivateKey(wif) + if err != nil { + return "", err + } + + // Return the hex (string) version of the private key + return hex.EncodeToString(privateKey.Serialize()), nil +} diff --git a/private_key_test.go b/private_key_test.go index cd77b87..ad7ae20 100644 --- a/private_key_test.go +++ b/private_key_test.go @@ -182,3 +182,215 @@ func BenchmarkPrivateAndPublicKeys(b *testing.B) { _, _, _ = PrivateAndPublicKeys(key) } } + +// TestPrivateKeyToWif will test the method PrivateKeyToWif() +func TestPrivateKeyToWif(t *testing.T) { + + t.Parallel() + + // Create the list of tests + var tests = []struct { + input string + expectedWif string + expectedNil bool + expectedError bool + }{ + {"", "", true, true}, + {"0", "", true, true}, + {"000000", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", false, false}, + {"6D792070726976617465206B6579", "5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", false, false}, + {"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true, true}, + {"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", "5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", false, false}, + } + + // Run tests + for _, test := range tests { + if wif, err := PrivateKeyToWif(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 wif == nil && !test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and was nil but not expected", t.Name(), test.input) + } else if wif != nil && test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and was NOT nil but expected to be nil", t.Name(), test.input) + } else if wif != nil && wif.String() != test.expectedWif { + t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedWif, wif.String()) + } + } + +} + +// ExamplePrivateKeyToWif example using PrivateKeyToWif() +func ExamplePrivateKeyToWif() { + wif, err := PrivateKeyToWif("54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd") + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + fmt.Printf("converted wif: %s", wif.String()) + + // Output:converted wif: 5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei +} + +// BenchmarkPrivateKeyToWif benchmarks the method PrivateKeyToWif() +func BenchmarkPrivateKeyToWif(b *testing.B) { + key, _ := CreatePrivateKeyString() + for i := 0; i < b.N; i++ { + _, _ = PrivateKeyToWif(key) + } +} + +// TestPrivateKeyToWifString will test the method PrivateKeyToWifString() +func TestPrivateKeyToWifString(t *testing.T) { + + t.Parallel() + + // Create the list of tests + var tests = []struct { + input string + expectedWif string + expectedError bool + }{ + {"", "", true}, + {"0", "", true}, + {"000000", "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", false}, + {"6D792070726976617465206B6579", "5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", false}, + {"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true}, + {"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", "5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", false}, + } + + // Run tests + for _, test := range tests { + if wif, err := PrivateKeyToWifString(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 wif != test.expectedWif { + t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedWif, wif) + } + } + +} + +// ExamplePrivateKeyToWifString example using PrivateKeyToWifString() +func ExamplePrivateKeyToWifString() { + wif, err := PrivateKeyToWifString("54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd") + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + fmt.Printf("converted wif: %s", wif) + + // Output:converted wif: 5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei +} + +// BenchmarkPrivateKeyToWifString benchmarks the method PrivateKeyToWifString() +func BenchmarkPrivateKeyToWifString(b *testing.B) { + key, _ := CreatePrivateKeyString() + for i := 0; i < b.N; i++ { + _, _ = PrivateKeyToWifString(key) + } +} + +// TestWifToPrivateKey will test the method WifToPrivateKey() +func TestWifToPrivateKey(t *testing.T) { + t.Parallel() + + // Create the list of tests + var tests = []struct { + input string + expectedKey string + expectedNil bool + expectedError bool + }{ + {"", "", true, true}, + {"0", "", true, true}, + {"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", "0000000000000000000000000000000000000000000000000000000000000000", false, false}, + {"5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", "0000000000000000000000000000000000006d792070726976617465206b6579", false, false}, + {"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true, true}, + {"5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", "54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", false, false}, + } + + // Run tests + for _, test := range tests { + if privateKey, err := WifToPrivateKey(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 privateKey == nil && !test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and was nil but not expected", t.Name(), test.input) + } else if privateKey != nil && test.expectedNil { + t.Errorf("%s Failed: [%s] inputted and was NOT nil but expected to be nil", t.Name(), test.input) + } else if privateKey != nil && hex.EncodeToString(privateKey.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(privateKey.Serialize())) + } + } +} + +// ExampleWifToPrivateKey example using WifToPrivateKey() +func ExampleWifToPrivateKey() { + privateKey, err := WifToPrivateKey("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei") + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + fmt.Printf("private key: %s", hex.EncodeToString(privateKey.Serialize())) + + // Output:private key: 54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd +} + +// BenchmarkWifToPrivateKey benchmarks the method WifToPrivateKey() +func BenchmarkWifToPrivateKey(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = WifToPrivateKey("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei") + } +} + +// TestWifToPrivateKeyString will test the method WifToPrivateKeyString() +func TestWifToPrivateKeyString(t *testing.T) { + t.Parallel() + + // Create the list of tests + var tests = []struct { + input string + expectedKey string + expectedError bool + }{ + {"", "", true}, + {"0", "", true}, + {"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAbuatmU", "0000000000000000000000000000000000000000000000000000000000000000", false}, + {"5HpHagT65TZzG1PH3CSu63k8DbuTZnNJf6HgyQNymvXmALAsm9s", "0000000000000000000000000000000000006d792070726976617465206b6579", false}, + {"54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8azz", "", true}, + {"5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei", "54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd", false}, + } + + // Run tests + for _, test := range tests { + if privateKey, err := WifToPrivateKeyString(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 privateKey != test.expectedKey { + t.Errorf("%s Failed: [%s] inputted [%s] expected but failed comparison of keys, got: %s", t.Name(), test.input, test.expectedKey, privateKey) + } + } +} + +// ExampleWifToPrivateKeyString example using WifToPrivateKeyString() +func ExampleWifToPrivateKeyString() { + privateKey, err := WifToPrivateKeyString("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei") + if err != nil { + fmt.Printf("error occurred: %s", err.Error()) + return + } + fmt.Printf("private key: %s", privateKey) + + // Output:private key: 54035dd4c7dda99ac473905a3d82f7864322b49bab1ff441cc457183b9bd8abd +} + +// BenchmarkWifToPrivateKeyString benchmarks the method WifToPrivateKeyString() +func BenchmarkWifToPrivateKeyString(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = WifToPrivateKeyString("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei") + } +}