github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/crypto/keys/lazy_keybase_test.go (about)

     1  package keys
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
     7  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519"
     8  	tmamino "github.com/fibonacci-chain/fbc/libs/tendermint/crypto/encoding/amino"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  	amino "github.com/tendermint/go-amino"
    12  
    13  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec"
    14  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys/hd"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/tests"
    16  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    17  )
    18  
    19  func TestNew(t *testing.T) {
    20  	dir, cleanup := tests.NewTestCaseDir(t)
    21  	defer cleanup()
    22  	kb := New("keybasename", dir)
    23  	lazykb, ok := kb.(lazyKeybase)
    24  	require.True(t, ok)
    25  	require.Equal(t, lazykb.name, "keybasename")
    26  	require.Equal(t, lazykb.dir, dir)
    27  }
    28  
    29  func TestLazyKeyManagement(t *testing.T) {
    30  	dir, cleanup := tests.NewTestCaseDir(t)
    31  	defer cleanup()
    32  	kb := New("keybasename", dir)
    33  
    34  	algo := Secp256k1
    35  	n1, n2, n3 := "personal", "business", "other"
    36  	p1, p2 := nums, "really-secure!@#$"
    37  
    38  	// Check empty state
    39  	l, err := kb.List()
    40  	require.Nil(t, err)
    41  	assert.Empty(t, l)
    42  
    43  	_, _, err = kb.CreateMnemonic(n1, English, p1, Ed25519, "")
    44  	require.Error(t, err, "ed25519 keys are currently not supported by keybase")
    45  
    46  	// create some keys
    47  	_, err = kb.Get(n1)
    48  	require.Error(t, err)
    49  	i, _, err := kb.CreateMnemonic(n1, English, p1, algo, "")
    50  
    51  	require.NoError(t, err)
    52  	require.Equal(t, n1, i.GetName())
    53  	_, _, err = kb.CreateMnemonic(n2, English, p2, algo, "")
    54  	require.NoError(t, err)
    55  
    56  	// we can get these keys
    57  	i2, err := kb.Get(n2)
    58  	require.NoError(t, err)
    59  	_, err = kb.Get(n3)
    60  	require.NotNil(t, err)
    61  	_, err = kb.GetByAddress(accAddr(i2))
    62  	require.NoError(t, err)
    63  	addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t")
    64  	require.NoError(t, err)
    65  	_, err = kb.GetByAddress(addr)
    66  	require.NotNil(t, err)
    67  
    68  	// list shows them in order
    69  	keyS, err := kb.List()
    70  	require.NoError(t, err)
    71  	require.Equal(t, 2, len(keyS))
    72  	// note these are in alphabetical order
    73  	require.Equal(t, n2, keyS[0].GetName())
    74  	require.Equal(t, n1, keyS[1].GetName())
    75  	require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey())
    76  
    77  	// deleting a key removes it
    78  	err = kb.Delete("bad name", "foo", false)
    79  	require.NotNil(t, err)
    80  	err = kb.Delete(n1, p1, false)
    81  	require.NoError(t, err)
    82  	keyS, err = kb.List()
    83  	require.NoError(t, err)
    84  	require.Equal(t, 1, len(keyS))
    85  	_, err = kb.Get(n1)
    86  	require.Error(t, err)
    87  
    88  	// create an offline key
    89  	o1 := "offline"
    90  	priv1 := ed25519.GenPrivKey()
    91  	pub1 := priv1.PubKey()
    92  	i, err = kb.CreateOffline(o1, pub1, algo)
    93  	require.Nil(t, err)
    94  	require.Equal(t, pub1, i.GetPubKey())
    95  	require.Equal(t, o1, i.GetName())
    96  	keyS, err = kb.List()
    97  	require.NoError(t, err)
    98  	require.Equal(t, 2, len(keyS))
    99  
   100  	// delete the offline key
   101  	err = kb.Delete(o1, "", false)
   102  	require.NoError(t, err)
   103  	keyS, err = kb.List()
   104  	require.NoError(t, err)
   105  	require.Equal(t, 1, len(keyS))
   106  
   107  	// addr cache gets nuked - and test skip flag
   108  	err = kb.Delete(n2, "", true)
   109  	require.NoError(t, err)
   110  }
   111  
   112  func TestLazySignVerify(t *testing.T) {
   113  	dir, cleanup := tests.NewTestCaseDir(t)
   114  	defer cleanup()
   115  	kb := New("keybasename", dir)
   116  	algo := Secp256k1
   117  
   118  	n1, n2, n3 := "some dude", "a dudette", "dude-ish"
   119  	p1, p2, p3 := nums, foobar, foobar
   120  
   121  	// create two users and get their info
   122  	i1, _, err := kb.CreateMnemonic(n1, English, p1, algo, "")
   123  	require.Nil(t, err)
   124  
   125  	i2, _, err := kb.CreateMnemonic(n2, English, p2, algo, "")
   126  	require.Nil(t, err)
   127  
   128  	// Import a public key
   129  	armor, err := kb.ExportPubKey(n2)
   130  	require.Nil(t, err)
   131  	kb.ImportPubKey(n3, armor)
   132  	i3, err := kb.Get(n3)
   133  	require.NoError(t, err)
   134  	require.Equal(t, i3.GetName(), n3)
   135  
   136  	// let's try to sign some messages
   137  	d1 := []byte("my first message")
   138  	d2 := []byte("some other important info!")
   139  	d3 := []byte("feels like I forgot something...")
   140  
   141  	// try signing both data with both ..
   142  	s11, pub1, err := kb.Sign(n1, p1, d1)
   143  	require.Nil(t, err)
   144  	require.Equal(t, i1.GetPubKey(), pub1)
   145  
   146  	s12, pub1, err := kb.Sign(n1, p1, d2)
   147  	require.Nil(t, err)
   148  	require.Equal(t, i1.GetPubKey(), pub1)
   149  
   150  	s21, pub2, err := kb.Sign(n2, p2, d1)
   151  	require.Nil(t, err)
   152  	require.Equal(t, i2.GetPubKey(), pub2)
   153  
   154  	s22, pub2, err := kb.Sign(n2, p2, d2)
   155  	require.Nil(t, err)
   156  	require.Equal(t, i2.GetPubKey(), pub2)
   157  
   158  	// let's try to validate and make sure it only works when everything is proper
   159  	cases := []struct {
   160  		key   crypto.PubKey
   161  		data  []byte
   162  		sig   []byte
   163  		valid bool
   164  	}{
   165  		// proper matches
   166  		{i1.GetPubKey(), d1, s11, true},
   167  		// change data, pubkey, or signature leads to fail
   168  		{i1.GetPubKey(), d2, s11, false},
   169  		{i2.GetPubKey(), d1, s11, false},
   170  		{i1.GetPubKey(), d1, s21, false},
   171  		// make sure other successes
   172  		{i1.GetPubKey(), d2, s12, true},
   173  		{i2.GetPubKey(), d1, s21, true},
   174  		{i2.GetPubKey(), d2, s22, true},
   175  	}
   176  
   177  	for i, tc := range cases {
   178  		valid := tc.key.VerifyBytes(tc.data, tc.sig)
   179  		require.Equal(t, tc.valid, valid, "%d", i)
   180  	}
   181  
   182  	// Now try to sign data with a secret-less key
   183  	_, _, err = kb.Sign(n3, p3, d3)
   184  	require.NotNil(t, err)
   185  }
   186  
   187  func TestLazyExportImport(t *testing.T) {
   188  	dir, cleanup := tests.NewTestCaseDir(t)
   189  	defer cleanup()
   190  	kb := New("keybasename", dir)
   191  
   192  	info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "")
   193  	require.NoError(t, err)
   194  	require.Equal(t, info.GetName(), "john")
   195  
   196  	john, err := kb.Get("john")
   197  	require.NoError(t, err)
   198  	require.Equal(t, info.GetName(), "john")
   199  	johnAddr := info.GetPubKey().Address()
   200  
   201  	armor, err := kb.Export("john")
   202  	require.NoError(t, err)
   203  
   204  	err = kb.Import("john2", armor)
   205  	require.NoError(t, err)
   206  
   207  	john2, err := kb.Get("john2")
   208  	require.NoError(t, err)
   209  
   210  	require.Equal(t, john.GetPubKey().Address(), johnAddr)
   211  	require.Equal(t, john.GetName(), "john")
   212  	require.Equal(t, john, john2)
   213  }
   214  
   215  func TestLazyExportImportPrivKey(t *testing.T) {
   216  	dir, cleanup := tests.NewTestCaseDir(t)
   217  	defer cleanup()
   218  	kb := New("keybasename", dir)
   219  
   220  	info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "")
   221  	require.NoError(t, err)
   222  	require.Equal(t, info.GetName(), "john")
   223  	priv1, err := kb.Get("john")
   224  	require.NoError(t, err)
   225  
   226  	// decrypt local private key, and produce encrypted ASCII armored output
   227  	armored, err := kb.ExportPrivKey("john", "secretcpw", "new_secretcpw")
   228  	require.NoError(t, err)
   229  
   230  	// delete exported key
   231  	require.NoError(t, kb.Delete("john", "", true))
   232  	_, err = kb.Get("john")
   233  	require.Error(t, err)
   234  
   235  	// import armored key
   236  	require.NoError(t, kb.ImportPrivKey("john", armored, "new_secretcpw"))
   237  
   238  	// ensure old and new keys match
   239  	priv2, err := kb.Get("john")
   240  	require.NoError(t, err)
   241  	require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey()))
   242  }
   243  
   244  func TestLazyExportImportPubKey(t *testing.T) {
   245  	dir, cleanup := tests.NewTestCaseDir(t)
   246  	defer cleanup()
   247  	kb := New("keybasename", dir)
   248  	algo := Secp256k1
   249  
   250  	// CreateMnemonic a private-public key pair and ensure consistency
   251  	notPasswd := "n9y25ah7"
   252  	info, _, err := kb.CreateMnemonic("john", English, notPasswd, algo, "")
   253  	require.Nil(t, err)
   254  	require.NotEqual(t, info, "")
   255  	require.Equal(t, info.GetName(), "john")
   256  	addr := info.GetPubKey().Address()
   257  	john, err := kb.Get("john")
   258  	require.NoError(t, err)
   259  	require.Equal(t, john.GetName(), "john")
   260  	require.Equal(t, john.GetPubKey().Address(), addr)
   261  
   262  	// Export the public key only
   263  	armor, err := kb.ExportPubKey("john")
   264  	require.NoError(t, err)
   265  	// Import it under a different name
   266  	err = kb.ImportPubKey("john-pubkey-only", armor)
   267  	require.NoError(t, err)
   268  	// Ensure consistency
   269  	john2, err := kb.Get("john-pubkey-only")
   270  	require.NoError(t, err)
   271  	// Compare the public keys
   272  	require.True(t, john.GetPubKey().Equals(john2.GetPubKey()))
   273  	// Ensure the original key hasn't changed
   274  	john, err = kb.Get("john")
   275  	require.NoError(t, err)
   276  	require.Equal(t, john.GetPubKey().Address(), addr)
   277  	require.Equal(t, john.GetName(), "john")
   278  
   279  	// Ensure keys cannot be overwritten
   280  	err = kb.ImportPubKey("john-pubkey-only", armor)
   281  	require.NotNil(t, err)
   282  }
   283  
   284  func TestLazyExportPrivateKeyObject(t *testing.T) {
   285  	dir, cleanup := tests.NewTestCaseDir(t)
   286  	defer cleanup()
   287  	kb := New("keybasename", dir)
   288  
   289  	info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "")
   290  	require.NoError(t, err)
   291  	require.Equal(t, info.GetName(), "john")
   292  
   293  	// export private key object
   294  	_, err = kb.ExportPrivateKeyObject("john", "invalid")
   295  	require.NotNil(t, err, "%+v", err)
   296  	exported, err := kb.ExportPrivateKeyObject("john", "secretcpw")
   297  	require.Nil(t, err, "%+v", err)
   298  	require.True(t, exported.PubKey().Equals(info.GetPubKey()))
   299  }
   300  
   301  func TestLazyAdvancedKeyManagement(t *testing.T) {
   302  	dir, cleanup := tests.NewTestCaseDir(t)
   303  	defer cleanup()
   304  	kb := New("keybasename", dir)
   305  
   306  	algo := Secp256k1
   307  	n1, n2 := "old-name", "new name"
   308  	p1, p2 := nums, foobar
   309  
   310  	// make sure key works with initial password
   311  	_, _, err := kb.CreateMnemonic(n1, English, p1, algo, "")
   312  	require.Nil(t, err, "%+v", err)
   313  	assertPassword(t, kb, n1, p1, p2)
   314  
   315  	// update password requires the existing password
   316  	getNewpass := func() (string, error) { return p2, nil }
   317  	err = kb.Update(n1, "jkkgkg", getNewpass)
   318  	require.NotNil(t, err)
   319  	assertPassword(t, kb, n1, p1, p2)
   320  
   321  	// then it changes the password when correct
   322  	err = kb.Update(n1, p1, getNewpass)
   323  	require.NoError(t, err)
   324  	// p2 is now the proper one!
   325  	assertPassword(t, kb, n1, p2, p1)
   326  
   327  	// exporting requires the proper name and passphrase
   328  	_, err = kb.Export(n1 + ".notreal")
   329  	require.NotNil(t, err)
   330  	_, err = kb.Export(" " + n1)
   331  	require.NotNil(t, err)
   332  	_, err = kb.Export(n1 + " ")
   333  	require.NotNil(t, err)
   334  	_, err = kb.Export("")
   335  	require.NotNil(t, err)
   336  	exported, err := kb.Export(n1)
   337  	require.Nil(t, err, "%+v", err)
   338  
   339  	// import succeeds
   340  	err = kb.Import(n2, exported)
   341  	require.NoError(t, err)
   342  
   343  	// second import fails
   344  	err = kb.Import(n2, exported)
   345  	require.NotNil(t, err)
   346  }
   347  
   348  // TestSeedPhrase verifies restoring from a seed phrase
   349  func TestLazySeedPhrase(t *testing.T) {
   350  	dir, cleanup := tests.NewTestCaseDir(t)
   351  	defer cleanup()
   352  	kb := New("keybasename", dir)
   353  
   354  	algo := Secp256k1
   355  	n1, n2 := "lost-key", "found-again"
   356  	p1, p2 := nums, foobar
   357  
   358  	// make sure key works with initial password
   359  	info, mnemonic, err := kb.CreateMnemonic(n1, English, p1, algo, "")
   360  	require.Nil(t, err, "%+v", err)
   361  	require.Equal(t, n1, info.GetName())
   362  	assert.NotEmpty(t, mnemonic)
   363  
   364  	// now, let us delete this key
   365  	err = kb.Delete(n1, p1, false)
   366  	require.Nil(t, err, "%+v", err)
   367  	_, err = kb.Get(n1)
   368  	require.NotNil(t, err)
   369  
   370  	// let us re-create it from the mnemonic-phrase
   371  	params := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
   372  	hdPath := params.String()
   373  	newInfo, err := kb.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, algo)
   374  	require.NoError(t, err)
   375  	require.Equal(t, n2, newInfo.GetName())
   376  	require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address())
   377  	require.Equal(t, info.GetPubKey(), newInfo.GetPubKey())
   378  }
   379  
   380  var _ crypto.PrivKey = testPriv{}
   381  var _ crypto.PubKey = testPub{}
   382  var testCdc *amino.Codec
   383  
   384  type testPriv []byte
   385  
   386  func (privkey testPriv) PubKey() crypto.PubKey { return testPub{} }
   387  func (privkey testPriv) Bytes() []byte {
   388  	return testCdc.MustMarshalBinaryBare(privkey)
   389  }
   390  func (privkey testPriv) Sign(msg []byte) ([]byte, error)  { return []byte{}, nil }
   391  func (privkey testPriv) Equals(other crypto.PrivKey) bool { return true }
   392  
   393  type testPub []byte
   394  
   395  func (key testPub) Address() crypto.Address { return crypto.Address{} }
   396  func (key testPub) Bytes() []byte {
   397  	return testCdc.MustMarshalBinaryBare(key)
   398  }
   399  func (key testPub) VerifyBytes(msg []byte, sig []byte) bool { return true }
   400  func (key testPub) Equals(other crypto.PubKey) bool         { return true }
   401  
   402  func TestKeygenOverride(t *testing.T) {
   403  	dir, cleanup := tests.NewTestCaseDir(t)
   404  	defer cleanup()
   405  
   406  	// Save existing codec and reset after test
   407  	cryptoCdc := CryptoCdc
   408  	defer func() {
   409  		CryptoCdc = cryptoCdc
   410  	}()
   411  
   412  	// Setup testCdc encoding and decoding new key type
   413  	testCdc = codec.New()
   414  	RegisterCodec(testCdc)
   415  	tmamino.RegisterAmino(testCdc)
   416  
   417  	// Set up codecs for using new key types
   418  	privName, pubName := "test/priv_name", "test/pub_name"
   419  	tmamino.RegisterKeyType(testPriv{}, privName)
   420  	tmamino.RegisterKeyType(testPub{}, pubName)
   421  	testCdc.RegisterConcrete(testPriv{}, privName, nil)
   422  	testCdc.RegisterConcrete(testPub{}, pubName, nil)
   423  	CryptoCdc = testCdc
   424  
   425  	overrideCalled := false
   426  	dummyFunc := func(bz []byte, algo SigningAlgo) (crypto.PrivKey, error) {
   427  		overrideCalled = true
   428  		return testPriv(bz), nil
   429  	}
   430  
   431  	kb := New("keybasename", dir, WithKeygenFunc(dummyFunc))
   432  
   433  	testName, pw := "name", "testPassword"
   434  
   435  	// create new key which will generate with
   436  	info, _, err := kb.CreateMnemonic(testName, English, pw, Secp256k1, "")
   437  	require.NoError(t, err)
   438  	require.Equal(t, info.GetName(), testName)
   439  
   440  	// Assert overridden function was called
   441  	require.True(t, overrideCalled)
   442  
   443  	// export private key object
   444  	exported, err := kb.ExportPrivateKeyObject(testName, pw)
   445  	require.Nil(t, err, "%+v", err)
   446  
   447  	// require that the key type is the new key
   448  	_, ok := exported.(testPriv)
   449  	require.True(t, ok)
   450  
   451  	require.True(t, exported.PubKey().Equals(info.GetPubKey()))
   452  }