Last active
May 13, 2019 11:37
-
-
Save eliquious/5e51207708a8c338274f5aeddc2a8a69 to your computer and use it in GitHub Desktop.
Simple command line experiment with BIP32/BIP39
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto/sha256" | |
"encoding/hex" | |
"fmt" | |
"github.com/alecthomas/kingpin" | |
"github.com/tyler-smith/go-bip32" | |
"github.com/tyler-smith/go-bip39" | |
"golang.org/x/crypto/ripemd160" | |
"hash" | |
) | |
var ( | |
bitLengthFlag = kingpin.Flag("bitlen", "Number of bits in entropy. Determines the number of words").Default("128").Int() | |
mnemonicCommand = kingpin.Command("words", "Generate a list of mnemonic words") | |
keyCommand = kingpin.Command("key", "Generate a master key") | |
keySecret = keyCommand.Flag("secret", "Salts the master key").Default("Secret").String() | |
accountNumber = keyCommand.Flag("account", "Account number").Default("0").Int() | |
addressIndex = keyCommand.Flag("index", "Address index").Default("0").Int() | |
// keyLengthFlag = keyCommand.Flag("bitlen", "Number of bits in entropy. Determines the number of words").Default("128").Int() | |
) | |
func main() { | |
switch kingpin.Parse() { | |
case "words": | |
// Generate a mnemonic for memorization or user-friendly seeds | |
entropy, err := bip39.NewEntropy(*bitLengthFlag) | |
if err != nil { | |
fmt.Println("Entropy error: ", err.Error()) | |
return | |
} | |
mnemonic, err := bip39.NewMnemonic(entropy) | |
if err != nil { | |
fmt.Println("Mnemonic error: ", err.Error()) | |
return | |
} | |
fmt.Println("Mnemonic: ", mnemonic) | |
case "key": | |
// Generate a mnemonic for memorization or user-friendly seeds | |
entropy, err := bip39.NewEntropy(*bitLengthFlag) | |
if err != nil { | |
fmt.Println("Entropy error: ", err.Error()) | |
return | |
} | |
mnemonic, err := bip39.NewMnemonic(entropy) | |
if err != nil { | |
fmt.Println("Mnemonic error: ", err.Error()) | |
return | |
} | |
fmt.Println("Mnemonic: ", mnemonic) | |
// Generate a Bip32 HD wallet for the mnemonic and a user supplied password | |
seed := bip39.NewSeed(mnemonic, "Secret Passphrase") | |
// Master key | |
masterKey, err := bip32.NewMasterKey(seed) | |
if err != nil { | |
fmt.Println("Key Generation error: ", err.Error()) | |
return | |
} | |
publicKey := masterKey.PublicKey() | |
fmt.Println("\nMaster Address: ", hex.EncodeToString(Hash160(masterKey.PublicKey().Key))) | |
fmt.Println("Master private key: ", masterKey) | |
fmt.Println("Master public key: ", publicKey) | |
// BIP44 purpose | |
purpose, err := masterKey.NewChildKey(bip32.FirstHardenedChild + 44) | |
if err != nil { | |
fmt.Println("Purpose Generation error: ", err.Error()) | |
return | |
} | |
accountKey, err := purpose.NewChildKey(bip32.FirstHardenedChild + uint32(*accountNumber)) | |
if err != nil { | |
fmt.Println("Account Generation error: ", err.Error()) | |
return | |
} | |
fmt.Println("\nAccount Address: ", hex.EncodeToString(Hash160(accountKey.PublicKey().Key))) | |
fmt.Println("Account private key: ", accountKey) | |
fmt.Println("Account public key: ", accountKey.PublicKey()) | |
changeKey, err := accountKey.NewChildKey(bip32.FirstHardenedChild) | |
if err != nil { | |
fmt.Println("Change generation error: ", err.Error()) | |
return | |
} | |
addressKey, err := changeKey.NewChildKey(bip32.FirstHardenedChild + uint32(*addressIndex)) | |
if err != nil { | |
fmt.Println("Address generation error: ", err.Error()) | |
return | |
} | |
fmt.Println("\nIndex Address: ", hex.EncodeToString(Hash160(addressKey.PublicKey().Key))) | |
fmt.Println("Index private key: ", addressKey) | |
fmt.Println("Index public key: ", addressKey.PublicKey()) | |
} | |
} | |
// Calculate the hash of hasher over buf. | |
func calcHash(buf []byte, hasher hash.Hash) []byte { | |
hasher.Write(buf) | |
return hasher.Sum(nil) | |
} | |
// Hash160 calculates the hash ripemd160(sha256(b)). | |
func Hash160(buf []byte) []byte { | |
return calcHash(calcHash(buf, sha256.New()), ripemd160.New()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment