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 }