Skip to content

Commit

Permalink
feat(BUX-190): add keys generation (#166)
Browse files Browse the repository at this point in the history
* feat(BUX-190): add keys generation

* chore(BUX-190): move new methods into separate package

* chore(BUX-190): refactor code

* chore(BUX-190): replace String method with XPriv

* chore(BUX-190): return named parametr in createXPrivAndXPub method

* chore(BUX-190): refactor PublicKey struct
  • Loading branch information
pawellewandowski98 authored Dec 21, 2023
1 parent 07fecdf commit d4d7543
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 25 deletions.
12 changes: 7 additions & 5 deletions examples/graphql/graphql.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package main

import (
"github.com/BuxOrg/go-buxclient/xpriv"
"log"

"github.com/BuxOrg/go-buxclient"
"github.com/bitcoinschema/go-bitcoin/v2"
)

func main() {

// Example xPub
masterKey, _ := bitcoin.GenerateHDKey(bitcoin.SecureSeedLength)
// rawXPub, _ := bitcoin.GetExtendedPublicKey(masterKey)
// Generate keys
keys, resErr := xpriv.Generate()
if resErr != nil {
log.Fatalln(resErr.Error())
}

// Create a client
buxClient, err := buxclient.New(
buxclient.WithXPriv(masterKey.String()),
buxclient.WithXPriv(keys.XPriv()),
buxclient.WithGraphQL("localhost:3001"),
buxclient.WithDebugging(true),
buxclient.WithSignRequest(true),
Expand Down
12 changes: 7 additions & 5 deletions examples/http/http.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package main

import (
"github.com/BuxOrg/go-buxclient/xpriv"
"log"

"github.com/BuxOrg/go-buxclient"
"github.com/bitcoinschema/go-bitcoin/v2"
)

func main() {

// Example xPub
masterKey, _ := bitcoin.GenerateHDKey(bitcoin.SecureSeedLength)
// rawXPub, _ := bitcoin.GetExtendedPublicKey(masterKey)
// Generate keys
keys, resErr := xpriv.Generate()
if resErr != nil {
log.Fatalln(resErr.Error())
}

// Create a client
buxClient, err := buxclient.New(
buxclient.WithXPriv(masterKey.String()),
buxclient.WithXPriv(keys.XPriv()),
buxclient.WithHTTP("localhost:3001"),
buxclient.WithDebugging(true),
buxclient.WithSignRequest(true),
Expand Down
41 changes: 41 additions & 0 deletions examples/keys/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"fmt"
"github.com/BuxOrg/go-buxclient/xpriv"
)

func main() {
//Generate keys
keys, err := xpriv.Generate()
if err != nil {
panic(err)
}

fmt.Println("<-- Generate method")
fmt.Println("XPriv: ", keys.XPriv())
fmt.Println("XPub: ", keys.XPub().String())
fmt.Println("Mnemonic: ", keys.Mnemonic())

//Generate keys from mnemonic string
xpriv3, err := xpriv.FromMnemonic(keys.Mnemonic())
if err != nil {
panic(err)
}

fmt.Println("<-- FromMnemonic method")
fmt.Println("XPriv: ", xpriv3.XPriv())
fmt.Println("XPub: ", xpriv3.XPub().String())
fmt.Println("Mnemonic: ", xpriv3.Mnemonic())

//Generate keys from string
xpriv2, err := xpriv.FromString(keys.XPriv())
if err != nil {
panic(err)
}

fmt.Println("<-- FromString method")
fmt.Println("XPriv: ", xpriv2.XPriv())
fmt.Println("XPub: ", xpriv2.XPub().String())
fmt.Println("Can not get mnemonic from keys generated from string")
}
16 changes: 8 additions & 8 deletions examples/new_paymail/new_paymail.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ package main

import (
"context"
"github.com/BuxOrg/go-buxclient/xpriv"
"log"

"github.com/bitcoinschema/go-bitcoin/v2"

"github.com/BuxOrg/go-buxclient"
)

func main() {

// Example xPub
masterKey, _ := bitcoin.GenerateHDKey(bitcoin.SecureSeedLength)

rawXPub, _ := bitcoin.GetExtendedPublicKey(masterKey)
// Generate keys
keys, resErr := xpriv.Generate()
if resErr != nil {
log.Fatalln(resErr.Error())
}

// Create a client
buxClient, err := buxclient.New(
buxclient.WithXPriv(masterKey.String()),
buxclient.WithXPriv(keys.XPriv()),
buxclient.WithHTTP("localhost:3001"),
buxclient.WithDebugging(true),
buxclient.WithSignRequest(true),
Expand All @@ -28,7 +28,7 @@ func main() {
}

log.Printf("client loaded - bux debug: %v", buxClient.IsDebug())
err = buxClient.NewPaymail(context.Background(), rawXPub, "[email protected]", "", "Foo", nil)
err = buxClient.NewPaymail(context.Background(), keys.XPub().String(), "[email protected]", "", "Foo", nil)

if err != nil {
log.Fatalln(err.Error())
Expand Down
16 changes: 9 additions & 7 deletions examples/register_xpub/register_xpub.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@ package main

import (
"context"
"github.com/BuxOrg/go-buxclient/xpriv"
"log"

buxmodels "github.com/BuxOrg/bux-models"
"github.com/BuxOrg/go-buxclient"
"github.com/bitcoinschema/go-bitcoin/v2"
)

func main() {
// Example xPub
masterKey, _ := bitcoin.GenerateHDKey(bitcoin.SecureSeedLength)
rawXPub, _ := bitcoin.GetExtendedPublicKey(masterKey)
// Generate keys
keys, resErr := xpriv.Generate()
if resErr != nil {
log.Fatalln(resErr.Error())
}

// Create a client
buxClient, err := buxclient.New(
buxclient.WithXPriv(masterKey.String()),
buxclient.WithXPriv(keys.XPriv()),
buxclient.WithHTTP("localhost:3001"),
buxclient.WithDebugging(true),
buxclient.WithSignRequest(true),
Expand All @@ -26,10 +28,10 @@ func main() {
}

if err = buxClient.NewXpub(
context.Background(), rawXPub, &buxmodels.Metadata{"example_field": "example_data"},
context.Background(), keys.XPub().String(), &buxmodels.Metadata{"example_field": "example_data"},
); err != nil {
log.Fatalln(err.Error())
}

log.Println("registered xPub: " + rawXPub)
log.Println("registered xPub: " + keys.XPub().String())
}
137 changes: 137 additions & 0 deletions xpriv/xpriv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package xpriv

import (
"fmt"

"github.com/libsv/go-bk/bip32"
"github.com/libsv/go-bk/bip39"
"github.com/libsv/go-bk/chaincfg"
)

// Keys is a struct containing the xpriv, xpub and mnemonic
type Keys struct {
xpriv string
xpub PublicKey
mnemonic string
}

// PublicKey is a struct containing public key information
type PublicKey string

// Key represents basic key methods
type Key interface {
XPriv() string
XPub() PubKey
}

// PubKey represents public key methods
type PubKey interface {
String() string
}

// KeyWithMnemonic represents methods for generated keys
type KeyWithMnemonic interface {
Key
Mnemonic() string
}

// XPub return hierarchical struct which contain xpub info
func (k *Keys) XPub() PubKey {
return k.xpub
}

// XPriv return hierarchical deterministic private key
func (k *Keys) XPriv() string {
return k.xpriv
}

// Mnemonic return mnemonic from which keys where generated
func (k *Keys) Mnemonic() string {
return k.mnemonic
}

// String return hierarchical deterministic publick ey
func (k PublicKey) String() string {
return string(k)
}

// Generate generates a random set of keys - xpriv, xpb and mnemonic
func Generate() (KeyWithMnemonic, error) {
entropy, err := bip39.GenerateEntropy(160)
if err != nil {
return nil, fmt.Errorf("generate method: key generation error when creating entropy: %w", err)
}

mnemonic, seed, err := bip39.Mnemonic(entropy, "")

if err != nil {
return nil, fmt.Errorf("generate method: key generation error when creating mnemonic: %w", err)
}

hdXpriv, hdXpub, err := createXPrivAndXPub(seed)
if err != nil {
return nil, err
}

keys := &Keys{
xpriv: hdXpriv.String(),
xpub: PublicKey(hdXpub.String()),
mnemonic: mnemonic,
}

return keys, nil
}

// FromMnemonic generates Keys based on given mnemonic
func FromMnemonic(mnemonic string) (KeyWithMnemonic, error) {
seed, err := bip39.MnemonicToSeed(mnemonic, "")
if err != nil {
return nil, fmt.Errorf("FromMnemonic method: error when creating seed: %w", err)
}

hdXpriv, hdXpub, err := createXPrivAndXPub(seed)
if err != nil {
return nil, fmt.Errorf("FromMnemonic method: %w", err)
}

keys := &Keys{
xpriv: hdXpriv.String(),
xpub: PublicKey(hdXpub.String()),
mnemonic: mnemonic,
}

return keys, nil
}

// FromString generates keys from given xpriv
func FromString(xpriv string) (Key, error) {
hdXpriv, err := bip32.NewKeyFromString(xpriv)
if err != nil {
return nil, fmt.Errorf("FromString method: key generation error when creating hd private key: %w", err)
}

hdXpub, err := hdXpriv.Neuter()
if err != nil {
return nil, fmt.Errorf("FromString method: key generation error when creating hd public hey: %w", err)
}

keys := &Keys{
xpriv: hdXpriv.String(),
xpub: PublicKey(hdXpub.String()),
}

return keys, nil
}

func createXPrivAndXPub(seed []byte) (hdXpriv *bip32.ExtendedKey, hdXpub *bip32.ExtendedKey, err error) {
hdXpriv, err = bip32.NewMaster(seed, &chaincfg.MainNet)
if err != nil {
return nil, nil, fmt.Errorf("key generation error when creating hd private key: %w", err)
}

hdXpub, err = hdXpriv.Neuter()
if err != nil {
return nil, nil, fmt.Errorf("key generation error when creating hd public hey: %w", err)
}
return hdXpriv, hdXpub, nil
}

0 comments on commit d4d7543

Please sign in to comment.