diff --git a/README.md b/README.md index 996fc05..1e98177 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ View the generated [documentation](https://pkg.go.dev/github.com/bitcoinschema/g - [PubKey from String](pubkey.go) - **Private Keys** - [Create PrivateKey](private_key.go) + - [Create WIF](private_key.go) - [PrivateKey (string) to Address (string)](address.go) - [PrivateKey from string](private_key.go) - [Generate Shared Keypair](private_key.go) diff --git a/examples/create_wif/create_wif.go b/examples/create_wif/create_wif.go new file mode 100644 index 0000000..99ab40d --- /dev/null +++ b/examples/create_wif/create_wif.go @@ -0,0 +1,19 @@ +package main + +import ( + "log" + + "github.com/bitcoinschema/go-bitcoin/v2" +) + +func main() { + + // Create a wif + wifString, err := bitcoin.CreateWifString() + if err != nil { + log.Fatalf("error occurred: %s", err.Error()) + } + + // Success! + log.Printf("wif key: %s", wifString) +} diff --git a/examples/wif_from_string/wif_from_string.go b/examples/wif_from_string/wif_from_string.go new file mode 100644 index 0000000..dd8e66b --- /dev/null +++ b/examples/wif_from_string/wif_from_string.go @@ -0,0 +1,28 @@ +package main + +import ( + "log" + + "github.com/libsv/go-bk/wif" + + "github.com/bitcoinschema/go-bitcoin/v2" +) + +func main() { + + // Create a wif + wifString, err := bitcoin.CreateWifString() + if err != nil { + log.Fatalf("error occurred: %s", err.Error()) + } + + // Create a wif from a string + var wifKey *wif.WIF + wifKey, err = bitcoin.WifFromString(wifString) + if err != nil { + log.Fatalf("error occurred: %s", err.Error()) + } + + // Success! + log.Printf("wif key: %s is also: %s", wifString, wifKey.String()) +} diff --git a/private_key.go b/private_key.go index 1d05cf0..6ae9135 100644 --- a/private_key.go +++ b/private_key.go @@ -3,7 +3,6 @@ package bitcoin import ( "crypto/ecdsa" "encoding/hex" - "errors" "math/big" "github.com/libsv/go-bk/bec" @@ -24,7 +23,7 @@ func GenerateSharedKeyPair(privateKey *bec.PrivateKey, // PrivateKeyFromString turns a private key (hex encoded string) into an bec.PrivateKey func PrivateKeyFromString(privateKey string) (*bec.PrivateKey, error) { if len(privateKey) == 0 { - return nil, errors.New("privateKey is missing") + return nil, ErrPrivateKeyMissing } privateKeyBytes, err := hex.DecodeString(privateKey) if err != nil { @@ -54,13 +53,33 @@ func CreatePrivateKeyString() (string, error) { return hex.EncodeToString(privateKey.Serialise()), nil } +// CreateWif will create a new WIF (*wif.WIF) +func CreateWif() (*wif.WIF, error) { + privateKey, err := CreatePrivateKey() + if err != nil { + return nil, err + } + + return wif.NewWIF(privateKey, &chaincfg.MainNet, false) +} + +// CreateWifString will create a new WIF (string) +func CreateWifString() (string, error) { + wifKey, err := CreateWif() + if err != nil { + return "", err + } + + return wifKey.String(), nil +} + // PrivateAndPublicKeys will return both the private and public key in one method // Expects a hex encoded privateKey func PrivateAndPublicKeys(privateKey string) (*bec.PrivateKey, *bec.PublicKey, error) { // No key? if len(privateKey) == 0 { - return nil, nil, errors.New("missing privateKey") + return nil, nil, ErrPrivateKeyMissing } // Decode the private key into bytes @@ -79,7 +98,7 @@ func PrivateKeyToWif(privateKey string) (*wif.WIF, error) { // Missing private key if len(privateKey) == 0 { - return nil, errors.New("missing privateKey") + return nil, ErrPrivateKeyMissing } // Decode the private key @@ -110,7 +129,7 @@ func WifToPrivateKey(wifKey string) (*bec.PrivateKey, error) { // Missing wif? if len(wifKey) == 0 { - return nil, errors.New("missing wif") + return nil, ErrWifMissing } // Decode the wif @@ -135,3 +154,20 @@ func WifToPrivateKeyString(wif string) (string, error) { // Return the hex (string) version of the private key return hex.EncodeToString(privateKey.Serialise()), nil } + +// WifFromString will convert a WIF (string) to a WIF (*wif.WIF) +func WifFromString(wifKey string) (*wif.WIF, error) { + + // Missing wif? + if len(wifKey) == 0 { + return nil, ErrWifMissing + } + + // Decode the WIF + decodedWif, err := wif.DecodeWIF(wifKey) + if err != nil { + return nil, err + } + + return decodedWif, nil +} diff --git a/private_key_test.go b/private_key_test.go index 8e6dc6b..12a830b 100644 --- a/private_key_test.go +++ b/private_key_test.go @@ -5,7 +5,10 @@ import ( "fmt" "testing" + "github.com/libsv/go-bk/bec" + "github.com/libsv/go-bk/wif" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // TestCreatePrivateKey will test the method CreatePrivateKey() @@ -371,3 +374,203 @@ func BenchmarkWifToPrivateKeyString(b *testing.B) { _, _ = WifToPrivateKeyString("5JTHas7yTFMBLqgFogxZFf8Vc5uKEbkE7yQAQ2g3xPHo2sNG1Ei") } } + +// TestCreateWif will test the method CreateWif() +func TestCreateWif(t *testing.T) { + t.Run("TestCreateWif", func(t *testing.T) { + t.Parallel() + + // Create a WIF + wifKey, err := CreateWif() + require.NoError(t, err) + require.NotNil(t, wifKey) + // t.Log("WIF:", wifKey.String()) + require.Equalf(t, 51, len(wifKey.String()), "WIF should be 51 characters long, got: %d", len(wifKey.String())) + }) + + t.Run("TestWifToPrivateKey", func(t *testing.T) { + t.Parallel() + + // Create a WIF + wifKey, err := CreateWif() + require.NoError(t, err) + require.NotNil(t, wifKey) + // t.Log("WIF:", wifKey.String()) + require.Equalf(t, 51, len(wifKey.String()), "WIF should be 51 characters long, got: %d", len(wifKey.String())) + + // Convert WIF to Private Key + var privateKey *bec.PrivateKey + privateKey, err = WifToPrivateKey(wifKey.String()) + require.NoError(t, err) + require.NotNil(t, privateKey) + privateKeyString := hex.EncodeToString(privateKey.Serialise()) + // t.Log("Private Key:", privateKeyString) + require.Equalf(t, 64, len(privateKeyString), "Private Key should be 64 characters long, got: %d", len(privateKeyString)) + }) +} + +// ExampleCreateWif example using CreateWif() +func ExampleCreateWif() { + wifKey, err := CreateWif() + if err != nil { + fmt.Println(err) + return + } + fmt.Println("WIF Key Generated Length:", len(wifKey.String())) + // Output: WIF Key Generated Length: 51 +} + +// BenchmarkCreateWif benchmarks the method CreateWif() +func BenchmarkCreateWif(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = CreateWif() + } +} + +// TestCreateWifString will test the method CreateWifString() +func TestCreateWifString(t *testing.T) { + t.Run("TestCreateWifString", func(t *testing.T) { + t.Parallel() + + // Create a WIF + wifKey, err := CreateWifString() + require.NoError(t, err) + require.NotNil(t, wifKey) + // t.Log("WIF:", wifKey) + require.Equalf(t, 51, len(wifKey), "WIF should be 51 characters long, got: %d", len(wifKey)) + }) + + t.Run("TestWifToPrivateKeyString", func(t *testing.T) { + t.Parallel() + + // Create a WIF + wifKey, err := CreateWifString() + require.NoError(t, err) + require.NotNil(t, wifKey) + // t.Log("WIF:", wifKey) + require.Equalf(t, 51, len(wifKey), "WIF should be 51 characters long, got: %d", len(wifKey)) + + // Convert WIF to Private Key + var privateKeyString string + privateKeyString, err = WifToPrivateKeyString(wifKey) + require.NoError(t, err) + require.NotNil(t, privateKeyString) + // t.Log("Private Key:", privateKeyString) + require.Equalf(t, 64, len(privateKeyString), "Private Key should be 64 characters long, got: %d", len(privateKeyString)) + + }) +} + +// ExampleCreateWifString example using CreateWifString() +func ExampleCreateWifString() { + wifKey, err := CreateWifString() + if err != nil { + fmt.Println(err) + return + } + fmt.Println("WIF Key Generated Length:", len(wifKey)) + // Output: WIF Key Generated Length: 51 +} + +// BenchmarkCreateWifString benchmarks the method CreateWifString() +func BenchmarkCreateWifString(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _ = CreateWifString() + } +} + +// TestWifFromString will test the method WifFromString() +func TestWifFromString(t *testing.T) { + t.Run("TestCreateWifFromPrivateKey", func(t *testing.T) { + t.Parallel() + + // Create a Private Key + privateKey, err := CreatePrivateKeyString() + require.NoError(t, err) + require.NotNil(t, privateKey) + + // Create a WIF + var wifKey *wif.WIF + wifKey, err = PrivateKeyToWif(privateKey) + require.NoError(t, err) + require.NotNil(t, wifKey) + wifKeyString := wifKey.String() + t.Log("WIF:", wifKeyString) + require.Equalf(t, 51, len(wifKeyString), "WIF should be 51 characters long, got: %d", len(wifKeyString)) + + // Convert WIF to Private Key + var privateKeyString string + privateKeyString, err = WifToPrivateKeyString(wifKeyString) + require.NoError(t, err) + require.NotNil(t, privateKeyString) + t.Log("Private Key:", privateKeyString) + require.Equalf(t, 64, len(privateKeyString), "Private Key should be 64 characters long, got: %d", len(privateKeyString)) + + // Compare Private Keys + require.Equalf(t, privateKey, privateKeyString, "Private Key should be equal, got: %s", privateKeyString) + + // Decode WIF + var decodedWif *wif.WIF + decodedWif, err = WifFromString(wifKeyString) + require.NoError(t, err) + require.NotNil(t, decodedWif) + require.Equalf(t, wifKeyString, decodedWif.String(), "WIF should be equal, got: %s", decodedWif.String()) + }) + + t.Run("TestWifFromStringMissingWIF", func(t *testing.T) { + t.Parallel() + + _, err := WifFromString("") + require.Error(t, err) + require.Equal(t, ErrWifMissing, err) + }) + + t.Run("TestWifFromStringInvalidWIF", func(t *testing.T) { + t.Parallel() + + _, err := WifFromString("invalid") + require.Error(t, err) + require.Equal(t, "malformed private key", err.Error()) + }) +} + +// ExampleWifFromString example using WifFromString() +func ExampleWifFromString() { + // Create a Private Key + privateKey, err := CreatePrivateKeyString() + if err != nil { + fmt.Println(err) + return + } + fmt.Println("Private Key Generated Length:", len(privateKey)) + + // Create a WIF + var wifKey *wif.WIF + wifKey, err = PrivateKeyToWif(privateKey) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("WIF Key Generated Length:", len(wifKey.String())) + + // Decode WIF + var decodedWif *wif.WIF + decodedWif, err = WifFromString(wifKey.String()) + if err != nil { + fmt.Println(err) + return + } + fmt.Println("WIF Key Decoded Length:", len(decodedWif.String())) + // Output: Private Key Generated Length: 64 + // WIF Key Generated Length: 51 + // WIF Key Decoded Length: 51 +} + +// BenchmarkWifFromString benchmarks the method WifFromString() +func BenchmarkWifFromString(b *testing.B) { + wifKey, _ := CreateWif() + wifString := wifKey.String() + for i := 0; i < b.N; i++ { + _, _ = WifFromString(wifString) + } +}