github.com/cosmos/cosmos-sdk@v0.50.1/crypto/ledger/ledger_test.go (about)

     1  //go:build ledger
     2  // +build ledger
     3  
     4  package ledger
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/cosmos/cosmos-sdk/codec/legacy"
    13  	"github.com/cosmos/cosmos-sdk/crypto/hd"
    14  	"github.com/cosmos/cosmos-sdk/crypto/types"
    15  	"github.com/cosmos/cosmos-sdk/testutil/testdata"
    16  	sdk "github.com/cosmos/cosmos-sdk/types"
    17  )
    18  
    19  func TestErrorHandling(t *testing.T) {
    20  	// first, try to generate a key, must return an error
    21  	// (no panic)
    22  	path := *hd.NewParams(44, 555, 0, false, 0)
    23  	_, err := NewPrivKeySecp256k1Unsafe(path)
    24  	require.Error(t, err)
    25  }
    26  
    27  func TestPublicKeyUnsafe(t *testing.T) {
    28  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
    29  	priv, err := NewPrivKeySecp256k1Unsafe(path)
    30  	require.NoError(t, err)
    31  	checkDefaultPubKey(t, priv)
    32  }
    33  
    34  func checkDefaultPubKey(t *testing.T, priv types.LedgerPrivKey) {
    35  	require.NotNil(t, priv)
    36  	expectedPkStr := "PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}"
    37  	require.Equal(t, "eb5ae98721034fef9cd7c4c63588d3b03feb5281b9d232cba34d6f3d71aee59211ffbfe1fe87",
    38  		fmt.Sprintf("%x", cdc.Amino.MustMarshalBinaryBare(priv.PubKey())),
    39  		"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
    40  	require.Equal(t, expectedPkStr, priv.PubKey().String())
    41  	addr := sdk.AccAddress(priv.PubKey().Address()).String()
    42  	require.Equal(t, "cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h",
    43  		addr, "Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
    44  }
    45  
    46  func TestPublicKeyUnsafeHDPath(t *testing.T) {
    47  	expectedAnswers := []string{
    48  		"PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}",
    49  		"PubKeySecp256k1{0260D0487A3DFCE9228EEE2D0D83A40F6131F551526C8E52066FE7FE1E4A509666}",
    50  		"PubKeySecp256k1{03A2670393D02B162D0ED06A08041E80D86BE36C0564335254DF7462447EB69AB3}",
    51  		"PubKeySecp256k1{033222FC61795077791665544A90740E8EAD638A391A3B8F9261F4A226B396C042}",
    52  		"PubKeySecp256k1{03F577473348D7B01E7AF2F245E36B98D181BC935EC8B552CDE5932B646DC7BE04}",
    53  		"PubKeySecp256k1{0222B1A5486BE0A2D5F3C5866BE46E05D1BDE8CDA5EA1C4C77A9BC48D2FA2753BC}",
    54  		"PubKeySecp256k1{0377A1C826D3A03CA4EE94FC4DEA6BCCB2BAC5F2AC0419A128C29F8E88F1FF295A}",
    55  		"PubKeySecp256k1{031B75C84453935AB76F8C8D0B6566C3FCC101CC5C59D7000BFC9101961E9308D9}",
    56  		"PubKeySecp256k1{038905A42433B1D677CC8AFD36861430B9A8529171B0616F733659F131C3F80221}",
    57  		"PubKeySecp256k1{038BE7F348902D8C20BC88D32294F4F3B819284548122229DECD1ADF1A7EB0848B}",
    58  	}
    59  
    60  	const numIters = 10
    61  
    62  	privKeys := make([]types.LedgerPrivKey, numIters)
    63  
    64  	// Check with device
    65  	for i := uint32(0); i < 10; i++ {
    66  		path := *hd.NewFundraiserParams(0, sdk.CoinType, i)
    67  		t.Logf("Checking keys at %v\n", path)
    68  
    69  		priv, err := NewPrivKeySecp256k1Unsafe(path)
    70  		require.NoError(t, err)
    71  		require.NotNil(t, priv)
    72  
    73  		// Check other methods
    74  		tmp := priv.(PrivKeyLedgerSecp256k1)
    75  		require.NoError(t, tmp.ValidateKey())
    76  		(&tmp).AssertIsPrivKeyInner()
    77  
    78  		// in this test we are chekcking if the generated keys are correct.
    79  		require.Equal(t, expectedAnswers[i], priv.PubKey().String(),
    80  			"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
    81  
    82  		// Store and restore
    83  		serializedPk := priv.Bytes()
    84  		require.NotNil(t, serializedPk)
    85  		require.True(t, len(serializedPk) >= 50)
    86  
    87  		privKeys[i] = priv
    88  	}
    89  
    90  	// Now check equality
    91  	for i := 0; i < 10; i++ {
    92  		for j := 0; j < 10; j++ {
    93  			require.Equal(t, i == j, privKeys[i].Equals(privKeys[j]))
    94  			require.Equal(t, i == j, privKeys[j].Equals(privKeys[i]))
    95  		}
    96  	}
    97  }
    98  
    99  func TestPublicKeySafe(t *testing.T) {
   100  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
   101  	priv, addr, err := NewPrivKeySecp256k1(path, "cosmos")
   102  
   103  	require.NoError(t, err)
   104  	require.NotNil(t, priv)
   105  	require.Nil(t, ShowAddress(path, priv.PubKey(), sdk.GetConfig().GetBech32AccountAddrPrefix()))
   106  	checkDefaultPubKey(t, priv)
   107  
   108  	addr2 := sdk.AccAddress(priv.PubKey().Address()).String()
   109  	require.Equal(t, addr, addr2)
   110  }
   111  
   112  func TestPublicKeyHDPath(t *testing.T) {
   113  	expectedPubKeys := []string{
   114  		"PubKeySecp256k1{034FEF9CD7C4C63588D3B03FEB5281B9D232CBA34D6F3D71AEE59211FFBFE1FE87}",
   115  		"PubKeySecp256k1{0260D0487A3DFCE9228EEE2D0D83A40F6131F551526C8E52066FE7FE1E4A509666}",
   116  		"PubKeySecp256k1{03A2670393D02B162D0ED06A08041E80D86BE36C0564335254DF7462447EB69AB3}",
   117  		"PubKeySecp256k1{033222FC61795077791665544A90740E8EAD638A391A3B8F9261F4A226B396C042}",
   118  		"PubKeySecp256k1{03F577473348D7B01E7AF2F245E36B98D181BC935EC8B552CDE5932B646DC7BE04}",
   119  		"PubKeySecp256k1{0222B1A5486BE0A2D5F3C5866BE46E05D1BDE8CDA5EA1C4C77A9BC48D2FA2753BC}",
   120  		"PubKeySecp256k1{0377A1C826D3A03CA4EE94FC4DEA6BCCB2BAC5F2AC0419A128C29F8E88F1FF295A}",
   121  		"PubKeySecp256k1{031B75C84453935AB76F8C8D0B6566C3FCC101CC5C59D7000BFC9101961E9308D9}",
   122  		"PubKeySecp256k1{038905A42433B1D677CC8AFD36861430B9A8529171B0616F733659F131C3F80221}",
   123  		"PubKeySecp256k1{038BE7F348902D8C20BC88D32294F4F3B819284548122229DECD1ADF1A7EB0848B}",
   124  	}
   125  
   126  	expectedAddrs := []string{
   127  		"cosmos1w34k53py5v5xyluazqpq65agyajavep2rflq6h",
   128  		"cosmos19ewxwemt6uahejvwf44u7dh6tq859tkyvarh2q",
   129  		"cosmos1a07dzdjgjsntxpp75zg7cgatgq0udh3pcdcxm3",
   130  		"cosmos1qvw52lmn9gpvem8welghrkc52m3zczyhlqjsl7",
   131  		"cosmos17m78ka80fqkkw2c4ww0v4xm5nsu2drgrlm8mn2",
   132  		"cosmos1ferh9ll9c452d2p8k2v7heq084guygkn43up9e",
   133  		"cosmos10vf3sxmjg96rqq36axcphzfsl74dsntuehjlw5",
   134  		"cosmos1cq83av8cmnar79h0rg7duh9gnr7wkh228a7fxg",
   135  		"cosmos1dszhfrt226jy5rsre7e48vw9tgwe90uerfyefa",
   136  		"cosmos1734d7qsylzrdt05muhqqtpd90j8mp4y6rzch8l",
   137  	}
   138  
   139  	const numIters = 10
   140  
   141  	privKeys := make([]types.LedgerPrivKey, numIters)
   142  
   143  	// Check with device
   144  	for i := 0; i < len(expectedAddrs); i++ {
   145  		path := *hd.NewFundraiserParams(0, sdk.CoinType, uint32(i))
   146  		t.Logf("Checking keys at %s\n", path.String())
   147  
   148  		priv, addr, err := NewPrivKeySecp256k1(path, "cosmos")
   149  		require.NoError(t, err)
   150  		require.NotNil(t, addr)
   151  		require.NotNil(t, priv)
   152  
   153  		addr2 := sdk.AccAddress(priv.PubKey().Address()).String()
   154  		require.Equal(t, addr2, addr)
   155  		require.Equal(t,
   156  			expectedAddrs[i], addr,
   157  			"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
   158  
   159  		// Check other methods
   160  		tmp := priv.(PrivKeyLedgerSecp256k1)
   161  		require.NoError(t, tmp.ValidateKey())
   162  		(&tmp).AssertIsPrivKeyInner()
   163  
   164  		// in this test we are chekcking if the generated keys are correct and stored in a right path.
   165  		require.Equal(t,
   166  			expectedPubKeys[i], priv.PubKey().String(),
   167  			"Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
   168  
   169  		// Store and restore
   170  		serializedPk := priv.Bytes()
   171  		require.NotNil(t, serializedPk)
   172  		require.True(t, len(serializedPk) >= 50)
   173  
   174  		privKeys[i] = priv
   175  	}
   176  
   177  	// Now check equality
   178  	for i := 0; i < 10; i++ {
   179  		for j := 0; j < 10; j++ {
   180  			require.Equal(t, i == j, privKeys[i].Equals(privKeys[j]))
   181  			require.Equal(t, i == j, privKeys[j].Equals(privKeys[i]))
   182  		}
   183  	}
   184  }
   185  
   186  func getFakeTx(accountNumber uint32) []byte {
   187  	tmp := fmt.Sprintf(
   188  		`{"account_number":"%d","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"5000"},"memo":"memo","msgs":[[""]],"sequence":"6"}`,
   189  		accountNumber)
   190  
   191  	return []byte(tmp)
   192  }
   193  
   194  func TestSignaturesHD(t *testing.T) {
   195  	for account := uint32(0); account < 100; account += 30 {
   196  		msg := getFakeTx(account)
   197  
   198  		path := *hd.NewFundraiserParams(account, sdk.CoinType, account/5)
   199  		t.Logf("Checking signature at %v    ---   PLEASE REVIEW AND ACCEPT IN THE DEVICE\n", path)
   200  
   201  		priv, err := NewPrivKeySecp256k1Unsafe(path)
   202  		require.NoError(t, err)
   203  
   204  		pub := priv.PubKey()
   205  		sig, err := priv.Sign(msg)
   206  		require.NoError(t, err)
   207  
   208  		valid := pub.VerifySignature(msg, sig)
   209  		require.True(t, valid, "Is your device using test mnemonic: %s ?", testdata.TestMnemonic)
   210  	}
   211  }
   212  
   213  func TestRealDeviceSecp256k1(t *testing.T) {
   214  	msg := getFakeTx(50)
   215  	path := *hd.NewFundraiserParams(0, sdk.CoinType, 0)
   216  	priv, err := NewPrivKeySecp256k1Unsafe(path)
   217  	require.NoError(t, err)
   218  
   219  	pub := priv.PubKey()
   220  	sig, err := priv.Sign(msg)
   221  	require.NoError(t, err)
   222  
   223  	valid := pub.VerifySignature(msg, sig)
   224  	require.True(t, valid)
   225  
   226  	// now, let's serialize the public key and make sure it still works
   227  	bs := cdc.Amino.MustMarshalBinaryBare(priv.PubKey())
   228  	pub2, err := legacy.PubKeyFromBytes(bs)
   229  	require.Nil(t, err, "%+v", err)
   230  
   231  	// make sure we get the same pubkey when we load from disk
   232  	require.Equal(t, pub, pub2)
   233  
   234  	// signing with the loaded key should match the original pubkey
   235  	sig, err = priv.Sign(msg)
   236  	require.NoError(t, err)
   237  	valid = pub.VerifySignature(msg, sig)
   238  	require.True(t, valid)
   239  
   240  	// make sure pubkeys serialize properly as well
   241  	bs = legacy.Cdc.MustMarshal(pub)
   242  	bpub, err := legacy.PubKeyFromBytes(bs)
   243  	require.NoError(t, err)
   244  	require.Equal(t, pub, bpub)
   245  }