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