Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(BUX-190): add keys generation #166

Merged
merged 6 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
pawellewandowski98 marked this conversation as resolved.
Show resolved Hide resolved

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, "foo@domain.com", "", "Foo", nil)
err = buxClient.NewPaymail(context.Background(), keys.XPub().String(), "foo@domain.com", "", "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
}
Loading