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

     1  // nolint: goconst
     2  package keys
     3  
     4  import (
     5  	"testing"
     6  
     7  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
     8  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/ed25519"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/crypto/keys/hd"
    13  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/tests"
    14  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    15  )
    16  
    17  func TestLazyKeyManagementKeyRing(t *testing.T) {
    18  	dir, cleanup := tests.NewTestCaseDir(t)
    19  	defer cleanup()
    20  	kb, err := NewKeyring("keybasename", "test", dir, nil)
    21  	require.NoError(t, err)
    22  
    23  	algo := Secp256k1
    24  	n1, n2, n3 := "personal", "business", "other"
    25  	p1, p2 := "1234", "really-secure!@#$"
    26  
    27  	// Check empty state
    28  	l, err := kb.List()
    29  	require.Nil(t, err)
    30  	assert.Empty(t, l)
    31  
    32  	_, _, err = kb.CreateMnemonic(n1, English, p1, Ed25519, "")
    33  	require.Error(t, err, "ed25519 keys are currently not supported by keybase")
    34  
    35  	// create some keys
    36  	_, err = kb.Get(n1)
    37  	require.Error(t, err)
    38  	i, _, err := kb.CreateMnemonic(n1, English, p1, algo, "")
    39  
    40  	require.NoError(t, err)
    41  	require.Equal(t, n1, i.GetName())
    42  	_, _, err = kb.CreateMnemonic(n2, English, p2, algo, "")
    43  	require.NoError(t, err)
    44  
    45  	// we can get these keys
    46  	i2, err := kb.Get(n2)
    47  	require.NoError(t, err)
    48  	_, err = kb.Get(n3)
    49  	require.NotNil(t, err)
    50  	_, err = kb.GetByAddress(accAddr(i2))
    51  	require.NoError(t, err)
    52  	addr, err := sdk.AccAddressFromBech32("cosmos1yq8lgssgxlx9smjhes6ryjasmqmd3ts2559g0t")
    53  	require.NoError(t, err)
    54  	_, err = kb.GetByAddress(addr)
    55  	require.NotNil(t, err)
    56  
    57  	// list shows them in order
    58  	keyS, err := kb.List()
    59  	require.NoError(t, err)
    60  	require.Equal(t, 2, len(keyS))
    61  	// note these are in alphabetical order
    62  	require.Equal(t, n2, keyS[0].GetName())
    63  	require.Equal(t, n1, keyS[1].GetName())
    64  	require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey())
    65  
    66  	// deleting a key removes it
    67  	err = kb.Delete("bad name", "foo", false)
    68  	require.NotNil(t, err)
    69  	err = kb.Delete(n1, p1, false)
    70  	require.NoError(t, err)
    71  	keyS, err = kb.List()
    72  	require.NoError(t, err)
    73  	require.Equal(t, 1, len(keyS))
    74  	_, err = kb.Get(n1)
    75  	require.Error(t, err)
    76  
    77  	// create an offline key
    78  	o1 := "offline"
    79  	priv1 := ed25519.GenPrivKey()
    80  	pub1 := priv1.PubKey()
    81  	i, err = kb.CreateOffline(o1, pub1, Ed25519)
    82  	require.Nil(t, err)
    83  	require.Equal(t, pub1, i.GetPubKey())
    84  	require.Equal(t, o1, i.GetName())
    85  	keyS, err = kb.List()
    86  	require.NoError(t, err)
    87  	require.Equal(t, 2, len(keyS))
    88  
    89  	// delete the offline key
    90  	err = kb.Delete(o1, "", false)
    91  	require.NoError(t, err)
    92  	keyS, err = kb.List()
    93  	require.NoError(t, err)
    94  	require.Equal(t, 1, len(keyS))
    95  
    96  	// addr cache gets nuked - and test skip flag
    97  	err = kb.Delete(n2, "", true)
    98  	require.NoError(t, err)
    99  }
   100  
   101  func TestLazySignVerifyKeyRing(t *testing.T) {
   102  	dir, cleanup := tests.NewTestCaseDir(t)
   103  	defer cleanup()
   104  	kb, err := NewKeyring("keybasename", "test", dir, nil)
   105  	require.NoError(t, err)
   106  	algo := Secp256k1
   107  
   108  	n1, n2, n3 := "some dude", "a dudette", "dude-ish"
   109  	p1, p2, p3 := "1234", "foobar", "foobar"
   110  
   111  	// create two users and get their info
   112  	i1, _, err := kb.CreateMnemonic(n1, English, p1, algo, "")
   113  	require.Nil(t, err)
   114  
   115  	i2, _, err := kb.CreateMnemonic(n2, English, p2, algo, "")
   116  	require.Nil(t, err)
   117  
   118  	// Import a public key
   119  	armor, err := kb.ExportPubKey(n2)
   120  	require.Nil(t, err)
   121  	kb.ImportPubKey(n3, armor)
   122  	i3, err := kb.Get(n3)
   123  	require.NoError(t, err)
   124  	require.Equal(t, i3.GetName(), n3)
   125  
   126  	// let's try to sign some messages
   127  	d1 := []byte("my first message")
   128  	d2 := []byte("some other important info!")
   129  	d3 := []byte("feels like I forgot something...")
   130  
   131  	// try signing both data with both ..
   132  	s11, pub1, err := kb.Sign(n1, p1, d1)
   133  	require.Nil(t, err)
   134  	require.Equal(t, i1.GetPubKey(), pub1)
   135  
   136  	s12, pub1, err := kb.Sign(n1, p1, d2)
   137  	require.Nil(t, err)
   138  	require.Equal(t, i1.GetPubKey(), pub1)
   139  
   140  	s21, pub2, err := kb.Sign(n2, p2, d1)
   141  	require.Nil(t, err)
   142  	require.Equal(t, i2.GetPubKey(), pub2)
   143  
   144  	s22, pub2, err := kb.Sign(n2, p2, d2)
   145  	require.Nil(t, err)
   146  	require.Equal(t, i2.GetPubKey(), pub2)
   147  
   148  	// let's try to validate and make sure it only works when everything is proper
   149  	cases := []struct {
   150  		key   crypto.PubKey
   151  		data  []byte
   152  		sig   []byte
   153  		valid bool
   154  	}{
   155  		// proper matches
   156  		{i1.GetPubKey(), d1, s11, true},
   157  		// change data, pubkey, or signature leads to fail
   158  		{i1.GetPubKey(), d2, s11, false},
   159  		{i2.GetPubKey(), d1, s11, false},
   160  		{i1.GetPubKey(), d1, s21, false},
   161  		// make sure other successes
   162  		{i1.GetPubKey(), d2, s12, true},
   163  		{i2.GetPubKey(), d1, s21, true},
   164  		{i2.GetPubKey(), d2, s22, true},
   165  	}
   166  
   167  	for i, tc := range cases {
   168  		valid := tc.key.VerifyBytes(tc.data, tc.sig)
   169  		require.Equal(t, tc.valid, valid, "%d", i)
   170  	}
   171  
   172  	// Now try to sign data with a secret-less key
   173  	_, _, err = kb.Sign(n3, p3, d3)
   174  	require.NotNil(t, err)
   175  }
   176  
   177  func TestLazyExportImportKeyRing(t *testing.T) {
   178  	dir, cleanup := tests.NewTestCaseDir(t)
   179  	defer cleanup()
   180  	kb, err := NewKeyring("keybasename", "test", dir, nil)
   181  	require.NoError(t, err)
   182  
   183  	info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "")
   184  	require.NoError(t, err)
   185  	require.Equal(t, info.GetName(), "john")
   186  
   187  	john, err := kb.Get("john")
   188  	require.NoError(t, err)
   189  	require.Equal(t, info.GetName(), "john")
   190  	johnAddr := info.GetPubKey().Address()
   191  
   192  	armor, err := kb.Export("john")
   193  	require.NoError(t, err)
   194  
   195  	err = kb.Import("john2", armor)
   196  	require.NoError(t, err)
   197  
   198  	john2, err := kb.Get("john2")
   199  	require.NoError(t, err)
   200  
   201  	require.Equal(t, john.GetPubKey().Address(), johnAddr)
   202  	require.Equal(t, john.GetName(), "john")
   203  	require.Equal(t, john, john2)
   204  }
   205  
   206  func TestLazyExportImportPubKeyKeyRing(t *testing.T) {
   207  	dir, cleanup := tests.NewTestCaseDir(t)
   208  	defer cleanup()
   209  	kb, err := NewKeyring("keybasename", "test", dir, nil)
   210  	require.NoError(t, err)
   211  	algo := Secp256k1
   212  
   213  	// CreateMnemonic a private-public key pair and ensure consistency
   214  	notPasswd := "n9y25ah7"
   215  	info, _, err := kb.CreateMnemonic("john", English, notPasswd, algo, "")
   216  	require.Nil(t, err)
   217  	require.NotEqual(t, info, "")
   218  	require.Equal(t, info.GetName(), "john")
   219  	addr := info.GetPubKey().Address()
   220  	john, err := kb.Get("john")
   221  	require.NoError(t, err)
   222  	require.Equal(t, john.GetName(), "john")
   223  	require.Equal(t, john.GetPubKey().Address(), addr)
   224  
   225  	// Export the public key only
   226  	armor, err := kb.ExportPubKey("john")
   227  	require.NoError(t, err)
   228  	// Import it under a different name
   229  	err = kb.ImportPubKey("john-pubkey-only", armor)
   230  	require.NoError(t, err)
   231  	// Ensure consistency
   232  	john2, err := kb.Get("john-pubkey-only")
   233  	require.NoError(t, err)
   234  	// Compare the public keys
   235  	require.True(t, john.GetPubKey().Equals(john2.GetPubKey()))
   236  	// Ensure the original key hasn't changed
   237  	john, err = kb.Get("john")
   238  	require.NoError(t, err)
   239  	require.Equal(t, john.GetPubKey().Address(), addr)
   240  	require.Equal(t, john.GetName(), "john")
   241  
   242  	// Ensure keys cannot be overwritten
   243  	err = kb.ImportPubKey("john-pubkey-only", armor)
   244  	require.NotNil(t, err)
   245  }
   246  
   247  func TestLazyExportPrivateKeyObjectKeyRing(t *testing.T) {
   248  	dir, cleanup := tests.NewTestCaseDir(t)
   249  	defer cleanup()
   250  	kb, err := NewKeyring("keybasename", "test", dir, nil)
   251  	require.NoError(t, err)
   252  
   253  	info, _, err := kb.CreateMnemonic("john", English, "secretcpw", Secp256k1, "")
   254  	require.NoError(t, err)
   255  	require.Equal(t, info.GetName(), "john")
   256  
   257  	// export private key object
   258  	exported, err := kb.ExportPrivateKeyObject("john", "secretcpw")
   259  	require.Nil(t, err, "%+v", err)
   260  	require.True(t, exported.PubKey().Equals(info.GetPubKey()))
   261  }
   262  
   263  func TestLazyAdvancedKeyManagementKeyRing(t *testing.T) {
   264  	dir, cleanup := tests.NewTestCaseDir(t)
   265  	defer cleanup()
   266  	kb, err := NewKeyring("keybasename", "test", dir, nil)
   267  	require.NoError(t, err)
   268  
   269  	algo := Secp256k1
   270  	n1, n2 := "old-name", "new name"
   271  	p1 := "1234"
   272  
   273  	// make sure key works with initial password
   274  	_, _, err = kb.CreateMnemonic(n1, English, p1, algo, "")
   275  	require.Nil(t, err, "%+v", err)
   276  
   277  	_, err = kb.Export(n1 + ".notreal")
   278  	require.NotNil(t, err)
   279  	_, err = kb.Export(" " + n1)
   280  	require.NotNil(t, err)
   281  	_, err = kb.Export(n1 + " ")
   282  	require.NotNil(t, err)
   283  	_, err = kb.Export("")
   284  	require.NotNil(t, err)
   285  	exported, err := kb.Export(n1)
   286  	require.Nil(t, err, "%+v", err)
   287  
   288  	// import succeeds
   289  	err = kb.Import(n2, exported)
   290  	require.NoError(t, err)
   291  
   292  	// second import fails
   293  	err = kb.Import(n2, exported)
   294  	require.NotNil(t, err)
   295  }
   296  
   297  func TestLazySeedPhraseKeyRing(t *testing.T) {
   298  	dir, cleanup := tests.NewTestCaseDir(t)
   299  	defer cleanup()
   300  	kb, err := NewKeyring("keybasename", "test", dir, nil)
   301  	require.NoError(t, err)
   302  
   303  	algo := Secp256k1
   304  	n1, n2 := "lost-key", "found-again"
   305  	p1, p2 := "1234", "foobar"
   306  
   307  	// make sure key works with initial password
   308  	info, mnemonic, err := kb.CreateMnemonic(n1, English, p1, algo, "")
   309  	require.Nil(t, err, "%+v", err)
   310  	require.Equal(t, n1, info.GetName())
   311  	assert.NotEmpty(t, mnemonic)
   312  
   313  	// now, let us delete this key
   314  	err = kb.Delete(n1, p1, false)
   315  	require.Nil(t, err, "%+v", err)
   316  	_, err = kb.Get(n1)
   317  	require.NotNil(t, err)
   318  
   319  	// let us re-create it from the mnemonic-phrase
   320  	params := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
   321  	hdPath := params.String()
   322  	newInfo, err := kb.CreateAccount(n2, mnemonic, DefaultBIP39Passphrase, p2, hdPath, Secp256k1)
   323  	require.NoError(t, err)
   324  	require.Equal(t, n2, newInfo.GetName())
   325  	require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address())
   326  	require.Equal(t, info.GetPubKey(), newInfo.GetPubKey())
   327  }