github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/cmd/hdwallet/hdwallet_test.go (about)

     1  // Copyright (c) 2020 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package hdwallet
     7  
     8  import (
     9  	"encoding/hex"
    10  	"fmt"
    11  	"testing"
    12  
    13  	ecrypt "github.com/ethereum/go-ethereum/crypto"
    14  	"github.com/iotexproject/go-pkgs/crypto"
    15  	"github.com/iotexproject/iotex-core/ioctl/util"
    16  	hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
    17  	"github.com/stretchr/testify/require"
    18  	"github.com/tyler-smith/go-bip39"
    19  )
    20  
    21  func Test_Hdwallet(t *testing.T) {
    22  	require := require.New(t)
    23  
    24  	// simulating 'hdwallet create' here
    25  	password := "123"
    26  
    27  	entropy, _ := bip39.NewEntropy(128)
    28  	mnemonic, _ := bip39.NewMnemonic(entropy)
    29  
    30  	enctxt := append([]byte(mnemonic), util.HashSHA256([]byte(mnemonic))...)
    31  	enckey := util.HashSHA256([]byte(password))
    32  
    33  	out, err := util.Encrypt(enctxt, enckey)
    34  	require.NoError(err)
    35  
    36  	// simulating 'hdwallet use' here
    37  	enckey = util.HashSHA256([]byte(password))
    38  
    39  	dectxt, err := util.Decrypt(out, enckey)
    40  	require.NoError(err)
    41  
    42  	dectxtLen := len(dectxt)
    43  	require.True(dectxtLen > 32)
    44  
    45  	mnemonic1, hash := dectxt[:dectxtLen-32], dectxt[dectxtLen-32:]
    46  
    47  	require.Equal(hash, util.HashSHA256(mnemonic1))
    48  
    49  	wallet, err := hdwallet.NewFromMnemonic(string(mnemonic))
    50  	require.NoError(err)
    51  
    52  	derivationPath := fmt.Sprintf("%s/0'/%d/%d", DefaultRootDerivationPath, 1, 2)
    53  
    54  	path := hdwallet.MustParseDerivationPath(derivationPath)
    55  	account, err := wallet.Derive(path, false)
    56  	require.NoError(err)
    57  
    58  	private1, err := wallet.PrivateKey(account)
    59  	require.NoError(err)
    60  
    61  	// simulating 'hdwallet import' here
    62  	enctxt = append([]byte(mnemonic), util.HashSHA256([]byte(mnemonic))...)
    63  	enckey = util.HashSHA256([]byte(password))
    64  
    65  	_, err = util.Encrypt(enctxt, enckey)
    66  	require.NoError(err)
    67  
    68  	// compare import and create
    69  	wallet, err = hdwallet.NewFromMnemonic(string(mnemonic))
    70  	require.NoError(err)
    71  
    72  	derivationPath = fmt.Sprintf("%s/0'/%d/%d", DefaultRootDerivationPath, 1, 2)
    73  
    74  	path = hdwallet.MustParseDerivationPath(derivationPath)
    75  	account, err = wallet.Derive(path, false)
    76  	require.NoError(err)
    77  
    78  	private2, err := wallet.PrivateKey(account)
    79  	require.NoError(err)
    80  	require.Equal(private1, private2)
    81  
    82  	//test DeriveKey
    83  	account1 := 0
    84  	change := 1
    85  	index := 2
    86  
    87  	derivationPath = fmt.Sprintf("%s/%d'/%d/%d", DefaultRootDerivationPath, account1, change, index)
    88  	path = hdwallet.MustParseDerivationPath(derivationPath)
    89  	account, err = wallet.Derive(path, false)
    90  	require.NoError(err)
    91  
    92  	private3, err := wallet.PrivateKey(account)
    93  	require.NoError(err)
    94  
    95  	require.Equal(private2, private3)
    96  
    97  	account1 = 123
    98  	derivationPath = fmt.Sprintf("%s/%d'/%d/%d", DefaultRootDerivationPath, account1, change, index)
    99  	path = hdwallet.MustParseDerivationPath(derivationPath)
   100  	account, err = wallet.Derive(path, false)
   101  	require.NoError(err)
   102  
   103  	private4, err := wallet.PrivateKey(account)
   104  	require.NoError(err)
   105  	require.NotEqual(private2, private4)
   106  }
   107  
   108  func TestEncryptDecryptWithMnemonic(t *testing.T) {
   109  	require := require.New(t)
   110  
   111  	mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core"
   112  	password := "123"
   113  
   114  	enckey := util.HashSHA256([]byte(password))
   115  
   116  	storedTxt, err := hex.DecodeString("4da6571c2897e88568cbcce59dcf9574355d718da25f2ea6f2e6847b9254fc18eacd852d282f1be7b51024fb05e70ee41bc08c0a8a07c549b0c29f185de0fb35462f98b429ebc4b79bfbcab41b795fe1e59262ae0695a4107dcc57a8bad24eb2323b2c976a9fb3dafc8788a9fccbf5b8c36e3388e458")
   117  	require.NoError(err)
   118  
   119  	dectxt, err := util.Decrypt(storedTxt, enckey)
   120  	require.NoError(err)
   121  
   122  	dectxtLen := len(dectxt)
   123  
   124  	mnemonic1, hash := dectxt[:dectxtLen-32], dectxt[dectxtLen-32:]
   125  
   126  	require.Equal(mnemonic, string(mnemonic1))
   127  	require.Equal(util.HashSHA256(mnemonic1), hash)
   128  }
   129  
   130  func TestFixedMnemonicAndDerivationPath(t *testing.T) {
   131  	require := require.New(t)
   132  
   133  	mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core"
   134  	wallet, err := hdwallet.NewFromMnemonic(mnemonic)
   135  	require.NoError(err)
   136  
   137  	derivationPath := "m/44'/304'/0'/1/3"
   138  
   139  	path := hdwallet.MustParseDerivationPath(derivationPath)
   140  	account, err := wallet.Derive(path, false)
   141  	require.NoError(err)
   142  
   143  	private, err := wallet.PrivateKey(account)
   144  	require.NoError(err)
   145  	prvKey, err := crypto.BytesToPrivateKey(ecrypt.FromECDSA(private))
   146  	require.NoError(err)
   147  	addr := prvKey.PublicKey().Address()
   148  	require.NotNil(addr)
   149  
   150  	require.Equal(addr.String(), "io13hwqt04le40puf73aa9w9zm9fq04qqn7qcjc6z")
   151  
   152  }