github.com/Finschia/finschia-sdk@v0.48.1/crypto/keyring/keyring_test.go (about) 1 package keyring 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "strings" 7 "testing" 8 9 "github.com/99designs/keyring" 10 bip39 "github.com/cosmos/go-bip39" 11 "github.com/stretchr/testify/require" 12 13 "github.com/Finschia/finschia-sdk/crypto" 14 "github.com/Finschia/finschia-sdk/crypto/hd" 15 "github.com/Finschia/finschia-sdk/crypto/keys/ed25519" 16 "github.com/Finschia/finschia-sdk/crypto/keys/multisig" 17 "github.com/Finschia/finschia-sdk/crypto/keys/secp256k1" 18 "github.com/Finschia/finschia-sdk/crypto/types" 19 sdk "github.com/Finschia/finschia-sdk/types" 20 ) 21 22 const ( 23 someKey = "theKey" 24 theID = "theID" 25 otherID = "otherID" 26 ) 27 28 func init() { 29 crypto.BcryptSecurityParameter = 1 30 } 31 32 func TestNewKeyring(t *testing.T) { 33 dir := t.TempDir() 34 mockIn := strings.NewReader("") 35 36 kr, err := New("cosmos", BackendFile, dir, mockIn) 37 require.NoError(t, err) 38 39 nilKr, err := New("cosmos", "fuzzy", dir, mockIn) 40 require.Error(t, err) 41 require.Nil(t, nilKr) 42 require.Equal(t, "unknown keyring backend fuzzy", err.Error()) 43 44 mockIn.Reset("password\npassword\n") 45 info, _, err := kr.NewMnemonic("foo", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 46 require.NoError(t, err) 47 require.Equal(t, "foo", info.GetName()) 48 } 49 50 func TestKeyManagementKeyRing(t *testing.T) { 51 kb, err := New("keybasename", "test", t.TempDir(), nil) 52 require.NoError(t, err) 53 54 algo := hd.Secp256k1 55 n1, n2, n3 := "personal", "business", "other" 56 57 // Check empty state 58 l, err := kb.List() 59 require.Nil(t, err) 60 require.Empty(t, l) 61 62 _, _, err = kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) 63 require.Error(t, err, "ed25519 keys are currently not supported by keybase") 64 65 // create some keys 66 _, err = kb.Key(n1) 67 require.Error(t, err) 68 i, _, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 69 70 require.NoError(t, err) 71 require.Equal(t, n1, i.GetName()) 72 _, _, err = kb.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 73 require.NoError(t, err) 74 75 // we can get these keys 76 i2, err := kb.Key(n2) 77 require.NoError(t, err) 78 _, err = kb.Key(n3) 79 require.NotNil(t, err) 80 _, err = kb.KeyByAddress(accAddr(i2)) 81 require.NoError(t, err) 82 addr, err := sdk.AccAddressFromBech32("link1yxfu3fldlgux939t0gwaqs82l4x77v2kasa7jf") 83 require.NoError(t, err) 84 _, err = kb.KeyByAddress(addr) 85 require.NotNil(t, err) 86 87 // list shows them in order 88 keyS, err := kb.List() 89 require.NoError(t, err) 90 require.Equal(t, 2, len(keyS)) 91 // note these are in alphabetical order 92 require.Equal(t, n2, keyS[0].GetName()) 93 require.Equal(t, n1, keyS[1].GetName()) 94 require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) 95 96 // deleting a key removes it 97 err = kb.Delete("bad name") 98 require.NotNil(t, err) 99 err = kb.Delete(n1) 100 require.NoError(t, err) 101 keyS, err = kb.List() 102 require.NoError(t, err) 103 require.Equal(t, 1, len(keyS)) 104 _, err = kb.Key(n1) 105 require.Error(t, err) 106 107 // create an offline key 108 o1 := "offline" 109 priv1 := ed25519.GenPrivKey() 110 pub1 := priv1.PubKey() 111 i, err = kb.SavePubKey(o1, pub1, hd.Ed25519Type) 112 require.Nil(t, err) 113 require.Equal(t, pub1, i.GetPubKey()) 114 require.Equal(t, o1, i.GetName()) 115 keyS, err = kb.List() 116 require.NoError(t, err) 117 require.Equal(t, 2, len(keyS)) 118 119 // delete the offline key 120 err = kb.Delete(o1) 121 require.NoError(t, err) 122 keyS, err = kb.List() 123 require.NoError(t, err) 124 require.Equal(t, 1, len(keyS)) 125 126 // addr cache gets nuked - and test skip flag 127 require.NoError(t, kb.Delete(n2)) 128 } 129 130 func TestSignVerifyKeyRing(t *testing.T) { 131 dir := t.TempDir() 132 133 kb, err := New("keybasename", "test", dir, nil) 134 require.NoError(t, err) 135 algo := hd.Secp256k1 136 137 n1, n2, n3 := "some dude", "a dudette", "dude-ish" 138 139 // create two users and get their info 140 i1, _, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 141 require.Nil(t, err) 142 143 i2, _, err := kb.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 144 require.Nil(t, err) 145 146 // let's try to sign some messages 147 d1 := []byte("my first message") 148 d2 := []byte("some other important info!") 149 d3 := []byte("feels like I forgot something...") 150 151 // try signing both data with both .. 152 s11, pub1, err := kb.Sign(n1, d1) 153 require.Nil(t, err) 154 require.Equal(t, i1.GetPubKey(), pub1) 155 156 s12, pub1, err := kb.Sign(n1, d2) 157 require.Nil(t, err) 158 require.Equal(t, i1.GetPubKey(), pub1) 159 160 s21, pub2, err := kb.Sign(n2, d1) 161 require.Nil(t, err) 162 require.Equal(t, i2.GetPubKey(), pub2) 163 164 s22, pub2, err := kb.Sign(n2, d2) 165 require.Nil(t, err) 166 require.Equal(t, i2.GetPubKey(), pub2) 167 168 // let's try to validate and make sure it only works when everything is proper 169 cases := []struct { 170 key types.PubKey 171 data []byte 172 sig []byte 173 valid bool 174 }{ 175 // proper matches 176 {i1.GetPubKey(), d1, s11, true}, 177 // change data, pubkey, or signature leads to fail 178 {i1.GetPubKey(), d2, s11, false}, 179 {i2.GetPubKey(), d1, s11, false}, 180 {i1.GetPubKey(), d1, s21, false}, 181 // make sure other successes 182 {i1.GetPubKey(), d2, s12, true}, 183 {i2.GetPubKey(), d1, s21, true}, 184 {i2.GetPubKey(), d2, s22, true}, 185 } 186 187 for i, tc := range cases { 188 valid := tc.key.VerifySignature(tc.data, tc.sig) 189 require.Equal(t, tc.valid, valid, "%d", i) 190 } 191 192 // Now try to sign data with a secret-less key 193 // Import a public key 194 armor, err := kb.ExportPubKeyArmor(n2) 195 require.NoError(t, err) 196 require.NoError(t, kb.Delete(n2)) 197 198 require.NoError(t, kb.ImportPubKey(n3, armor)) 199 i3, err := kb.Key(n3) 200 require.NoError(t, err) 201 require.Equal(t, i3.GetName(), n3) 202 203 _, _, err = kb.Sign(n3, d3) 204 require.Error(t, err) 205 require.Equal(t, "cannot sign with offline keys", err.Error()) 206 } 207 208 func TestExportImportKeyRing(t *testing.T) { 209 kb, err := New("keybasename", "test", t.TempDir(), nil) 210 require.NoError(t, err) 211 212 info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 213 require.NoError(t, err) 214 require.Equal(t, info.GetName(), "john") 215 216 john, err := kb.Key("john") 217 require.NoError(t, err) 218 require.Equal(t, info.GetName(), "john") 219 johnAddr := info.GetPubKey().Address() 220 221 armor, err := kb.ExportPrivKeyArmor("john", "apassphrase") 222 require.NoError(t, err) 223 err = kb.Delete("john") 224 require.NoError(t, err) 225 226 err = kb.ImportPrivKey("john2", armor, "apassphrase") 227 require.NoError(t, err) 228 229 john2, err := kb.Key("john2") 230 require.NoError(t, err) 231 232 require.Equal(t, john.GetPubKey().Address(), johnAddr) 233 require.Equal(t, john.GetName(), "john") 234 require.Equal(t, john.GetAddress(), john2.GetAddress()) 235 require.Equal(t, john.GetAlgo(), john2.GetAlgo()) 236 require.Equal(t, john.GetPubKey(), john2.GetPubKey()) 237 require.Equal(t, john.GetType(), john2.GetType()) 238 } 239 240 func TestExportImportPubKeyKeyRing(t *testing.T) { 241 kb, err := New("keybasename", "test", t.TempDir(), nil) 242 require.NoError(t, err) 243 algo := hd.Secp256k1 244 245 // CreateMnemonic a private-public key pair and ensure consistency 246 info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 247 require.Nil(t, err) 248 require.NotEqual(t, info, "") 249 require.Equal(t, info.GetName(), "john") 250 addr := info.GetPubKey().Address() 251 john, err := kb.Key("john") 252 require.NoError(t, err) 253 require.Equal(t, john.GetName(), "john") 254 require.Equal(t, john.GetPubKey().Address(), addr) 255 256 // Export the public key only 257 armor, err := kb.ExportPubKeyArmor("john") 258 require.NoError(t, err) 259 err = kb.Delete("john") 260 require.NoError(t, err) 261 262 // Import it under a different name 263 err = kb.ImportPubKey("john-pubkey-only", armor) 264 require.NoError(t, err) 265 266 // Ensure consistency 267 john2, err := kb.Key("john-pubkey-only") 268 require.NoError(t, err) 269 270 // Compare the public keys 271 require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) 272 273 // Ensure keys cannot be overwritten 274 err = kb.ImportPubKey("john-pubkey-only", armor) 275 require.NotNil(t, err) 276 } 277 278 func TestAdvancedKeyManagementKeyRing(t *testing.T) { 279 dir := t.TempDir() 280 281 kb, err := New("keybasename", "test", dir, nil) 282 require.NoError(t, err) 283 284 algo := hd.Secp256k1 285 n1, n2 := "old-name", "new name" 286 287 // make sure key works with initial password 288 _, _, err = kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 289 require.Nil(t, err, "%+v", err) 290 291 _, err = kb.ExportPubKeyArmor(n1 + ".notreal") 292 require.NotNil(t, err) 293 _, err = kb.ExportPubKeyArmor(" " + n1) 294 require.NotNil(t, err) 295 _, err = kb.ExportPubKeyArmor(n1 + " ") 296 require.NotNil(t, err) 297 _, err = kb.ExportPubKeyArmor("") 298 require.NotNil(t, err) 299 exported, err := kb.ExportPubKeyArmor(n1) 300 require.Nil(t, err, "%+v", err) 301 err = kb.Delete(n1) 302 require.NoError(t, err) 303 304 // import succeeds 305 err = kb.ImportPubKey(n2, exported) 306 require.NoError(t, err) 307 308 // second import fails 309 err = kb.ImportPubKey(n2, exported) 310 require.NotNil(t, err) 311 } 312 313 func TestSeedPhraseKeyRing(t *testing.T) { 314 dir := t.TempDir() 315 316 kb, err := New("keybasename", "test", dir, nil) 317 require.NoError(t, err) 318 319 algo := hd.Secp256k1 320 n1, n2 := "lost-key", "found-again" 321 322 // make sure key works with initial password 323 info, mnemonic, err := kb.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 324 require.Nil(t, err, "%+v", err) 325 require.Equal(t, n1, info.GetName()) 326 require.NotEmpty(t, mnemonic) 327 328 // now, let us delete this key 329 err = kb.Delete(n1) 330 require.Nil(t, err, "%+v", err) 331 _, err = kb.Key(n1) 332 require.NotNil(t, err) 333 334 // let us re-create it from the mnemonic-phrase 335 params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) 336 hdPath := params.String() 337 newInfo, err := kb.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, hd.Secp256k1) 338 require.NoError(t, err) 339 require.Equal(t, n2, newInfo.GetName()) 340 require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) 341 require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) 342 } 343 344 func TestKeyringKeybaseExportImportPrivKey(t *testing.T) { 345 kb, err := New("keybasename", "test", t.TempDir(), nil) 346 require.NoError(t, err) 347 348 _, _, err = kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 349 require.NoError(t, err) 350 351 keystr, err := kb.ExportPrivKeyArmor("john", "somepassword") 352 require.NoError(t, err) 353 require.NotEmpty(t, keystr) 354 err = kb.Delete("john") 355 require.NoError(t, err) 356 357 // try import the key - wrong password 358 err = kb.ImportPrivKey("john2", keystr, "bad pass") 359 require.Equal(t, "failed to decrypt private key: ciphertext decryption failed", err.Error()) 360 361 // try import the key with the correct password 362 require.NoError(t, kb.ImportPrivKey("john2", keystr, "somepassword")) 363 364 // overwrite is not allowed 365 err = kb.ImportPrivKey("john2", keystr, "password") 366 require.Equal(t, "cannot overwrite key: john2", err.Error()) 367 368 // try export non existing key 369 _, err = kb.ExportPrivKeyArmor("john3", "wrongpassword") 370 require.EqualError(t, err, "john3.info: key not found") 371 } 372 373 func TestInMemoryLanguage(t *testing.T) { 374 kb := NewInMemory() 375 _, _, err := kb.NewMnemonic("something", Japanese, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 376 require.Error(t, err) 377 require.Equal(t, "unsupported language: only english is supported", err.Error()) 378 } 379 380 func TestInMemoryCreateMultisig(t *testing.T) { 381 kb, err := New("keybasename", "memory", "", nil) 382 require.NoError(t, err) 383 multi := multisig.NewLegacyAminoPubKey( 384 1, []types.PubKey{ 385 secp256k1.GenPrivKey().PubKey(), 386 }, 387 ) 388 _, err = kb.SaveMultisig("multi", multi) 389 require.NoError(t, err) 390 } 391 392 func TestInMemoryCreateAccountInvalidMnemonic(t *testing.T) { 393 kb := NewInMemory() 394 _, err := kb.NewAccount( 395 "some_account", 396 "malarkey pair crucial catch public canyon evil outer stage ten gym tornado", 397 "", hd.CreateHDPath(118, 0, 0).String(), hd.Secp256k1) 398 require.Error(t, err) 399 require.Equal(t, "Invalid mnemonic", err.Error()) 400 } 401 402 // TestInMemoryKeyManagement makes sure we can manipulate these keys well 403 func TestInMemoryKeyManagement(t *testing.T) { 404 // make the storage with reasonable defaults 405 cstore := NewInMemory() 406 407 algo := hd.Secp256k1 408 n1, n2, n3 := "personal", "business", "other" 409 410 // Check empty state 411 l, err := cstore.List() 412 require.Nil(t, err) 413 require.Empty(t, l) 414 415 _, _, err = cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) 416 require.Error(t, err, "ed25519 keys are currently not supported by keybase") 417 418 // create some keys 419 _, err = cstore.Key(n1) 420 require.Error(t, err) 421 i, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 422 423 require.NoError(t, err) 424 require.Equal(t, n1, i.GetName()) 425 _, _, err = cstore.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 426 require.NoError(t, err) 427 428 // we can get these keys 429 i2, err := cstore.Key(n2) 430 require.NoError(t, err) 431 _, err = cstore.Key(n3) 432 require.NotNil(t, err) 433 _, err = cstore.KeyByAddress(accAddr(i2)) 434 require.NoError(t, err) 435 addr, err := sdk.AccAddressFromBech32("link1yxfu3fldlgux939t0gwaqs82l4x77v2kasa7jf") 436 require.NoError(t, err) 437 _, err = cstore.KeyByAddress(addr) 438 require.NotNil(t, err) 439 440 // list shows them in order 441 keyS, err := cstore.List() 442 require.NoError(t, err) 443 require.Equal(t, 2, len(keyS)) 444 // note these are in alphabetical order 445 require.Equal(t, n2, keyS[0].GetName()) 446 require.Equal(t, n1, keyS[1].GetName()) 447 require.Equal(t, i2.GetPubKey(), keyS[0].GetPubKey()) 448 449 // deleting a key removes it 450 err = cstore.Delete("bad name") 451 require.NotNil(t, err) 452 err = cstore.Delete(n1) 453 require.NoError(t, err) 454 keyS, err = cstore.List() 455 require.NoError(t, err) 456 require.Equal(t, 1, len(keyS)) 457 _, err = cstore.Key(n1) 458 require.Error(t, err) 459 460 // create an offline key 461 o1 := "offline" 462 priv1 := ed25519.GenPrivKey() 463 pub1 := priv1.PubKey() 464 i, err = cstore.SavePubKey(o1, pub1, hd.Ed25519Type) 465 require.Nil(t, err) 466 require.Equal(t, pub1, i.GetPubKey()) 467 require.Equal(t, o1, i.GetName()) 468 iOffline := i.(*offlineInfo) 469 require.Equal(t, hd.Ed25519Type, iOffline.GetAlgo()) 470 keyS, err = cstore.List() 471 require.NoError(t, err) 472 require.Equal(t, 2, len(keyS)) 473 474 // delete the offline key 475 err = cstore.Delete(o1) 476 require.NoError(t, err) 477 keyS, err = cstore.List() 478 require.NoError(t, err) 479 require.Equal(t, 1, len(keyS)) 480 481 // addr cache gets nuked - and test skip flag 482 err = cstore.Delete(n2) 483 require.NoError(t, err) 484 } 485 486 // TestInMemorySignVerify does some detailed checks on how we sign and validate 487 // signatures 488 func TestInMemorySignVerify(t *testing.T) { 489 cstore := NewInMemory() 490 algo := hd.Secp256k1 491 492 n1, n2, n3 := "some dude", "a dudette", "dude-ish" 493 494 // create two users and get their info 495 i1, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 496 require.Nil(t, err) 497 498 i2, _, err := cstore.NewMnemonic(n2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 499 require.Nil(t, err) 500 501 // let's try to sign some messages 502 d1 := []byte("my first message") 503 d2 := []byte("some other important info!") 504 d3 := []byte("feels like I forgot something...") 505 506 // try signing both data with both .. 507 s11, pub1, err := cstore.Sign(n1, d1) 508 require.Nil(t, err) 509 require.Equal(t, i1.GetPubKey(), pub1) 510 511 s12, pub1, err := cstore.Sign(n1, d2) 512 require.Nil(t, err) 513 require.Equal(t, i1.GetPubKey(), pub1) 514 515 s21, pub2, err := cstore.Sign(n2, d1) 516 require.Nil(t, err) 517 require.Equal(t, i2.GetPubKey(), pub2) 518 519 s22, pub2, err := cstore.Sign(n2, d2) 520 require.Nil(t, err) 521 require.Equal(t, i2.GetPubKey(), pub2) 522 523 // let's try to validate and make sure it only works when everything is proper 524 cases := []struct { 525 key types.PubKey 526 data []byte 527 sig []byte 528 valid bool 529 }{ 530 // proper matches 531 {i1.GetPubKey(), d1, s11, true}, 532 // change data, pubkey, or signature leads to fail 533 {i1.GetPubKey(), d2, s11, false}, 534 {i2.GetPubKey(), d1, s11, false}, 535 {i1.GetPubKey(), d1, s21, false}, 536 // make sure other successes 537 {i1.GetPubKey(), d2, s12, true}, 538 {i2.GetPubKey(), d1, s21, true}, 539 {i2.GetPubKey(), d2, s22, true}, 540 } 541 542 for i, tc := range cases { 543 valid := tc.key.VerifySignature(tc.data, tc.sig) 544 require.Equal(t, tc.valid, valid, "%d", i) 545 } 546 547 // Import a public key 548 armor, err := cstore.ExportPubKeyArmor(n2) 549 require.Nil(t, err) 550 err = cstore.Delete(n2) 551 require.NoError(t, err) 552 err = cstore.ImportPubKey(n3, armor) 553 require.NoError(t, err) 554 i3, err := cstore.Key(n3) 555 require.NoError(t, err) 556 require.Equal(t, i3.GetName(), n3) 557 558 // Now try to sign data with a secret-less key 559 _, _, err = cstore.Sign(n3, d3) 560 require.Error(t, err) 561 require.Equal(t, "cannot sign with offline keys", err.Error()) 562 } 563 564 // TestInMemoryExportImport tests exporting and importing 565 func TestInMemoryExportImport(t *testing.T) { 566 // make the storage with reasonable defaults 567 cstore := NewInMemory() 568 569 info, _, err := cstore.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 570 require.NoError(t, err) 571 require.Equal(t, info.GetName(), "john") 572 573 john, err := cstore.Key("john") 574 require.NoError(t, err) 575 require.Equal(t, info.GetName(), "john") 576 johnAddr := info.GetPubKey().Address() 577 578 armor, err := cstore.ExportPubKeyArmor("john") 579 require.NoError(t, err) 580 err = cstore.Delete("john") 581 require.NoError(t, err) 582 583 err = cstore.ImportPubKey("john2", armor) 584 require.NoError(t, err) 585 586 john2, err := cstore.Key("john2") 587 require.NoError(t, err) 588 589 require.Equal(t, john.GetPubKey().Address(), johnAddr) 590 require.Equal(t, john.GetName(), "john") 591 require.Equal(t, john.GetAddress(), john2.GetAddress()) 592 require.Equal(t, john.GetAlgo(), john2.GetAlgo()) 593 require.Equal(t, john.GetPubKey(), john2.GetPubKey()) 594 } 595 596 func TestInMemoryExportImportPrivKey(t *testing.T) { 597 kb := NewInMemory() 598 599 info, _, err := kb.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 600 require.NoError(t, err) 601 require.Equal(t, info.GetName(), "john") 602 priv1, err := kb.Key("john") 603 require.NoError(t, err) 604 605 armored, err := kb.ExportPrivKeyArmor("john", "secretcpw") 606 require.NoError(t, err) 607 608 // delete exported key 609 require.NoError(t, kb.Delete("john")) 610 _, err = kb.Key("john") 611 require.Error(t, err) 612 613 // import armored key 614 require.NoError(t, kb.ImportPrivKey("john", armored, "secretcpw")) 615 616 // ensure old and new keys match 617 priv2, err := kb.Key("john") 618 require.NoError(t, err) 619 require.True(t, priv1.GetPubKey().Equals(priv2.GetPubKey())) 620 } 621 622 func TestInMemoryExportImportPubKey(t *testing.T) { 623 // make the storage with reasonable defaults 624 cstore := NewInMemory() 625 626 // CreateMnemonic a private-public key pair and ensure consistency 627 info, _, err := cstore.NewMnemonic("john", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 628 require.Nil(t, err) 629 require.NotEqual(t, info, "") 630 require.Equal(t, info.GetName(), "john") 631 addr := info.GetPubKey().Address() 632 john, err := cstore.Key("john") 633 require.NoError(t, err) 634 require.Equal(t, john.GetName(), "john") 635 require.Equal(t, john.GetPubKey().Address(), addr) 636 637 // Export the public key only 638 armor, err := cstore.ExportPubKeyArmor("john") 639 require.NoError(t, err) 640 err = cstore.Delete("john") 641 require.NoError(t, err) 642 643 // Import it under a different name 644 err = cstore.ImportPubKey("john-pubkey-only", armor) 645 require.NoError(t, err) 646 // Ensure consistency 647 john2, err := cstore.Key("john-pubkey-only") 648 require.NoError(t, err) 649 // Compare the public keys 650 require.True(t, john.GetPubKey().Equals(john2.GetPubKey())) 651 652 // Ensure keys cannot be overwritten 653 err = cstore.ImportPubKey("john-pubkey-only", armor) 654 require.NotNil(t, err) 655 } 656 657 // TestInMemoryAdvancedKeyManagement verifies update, import, export functionality 658 func TestInMemoryAdvancedKeyManagement(t *testing.T) { 659 // make the storage with reasonable defaults 660 cstore := NewInMemory() 661 662 algo := hd.Secp256k1 663 n1, n2 := "old-name", "new name" 664 665 // make sure key works with initial password 666 _, _, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 667 require.Nil(t, err, "%+v", err) 668 669 // exporting requires the proper name and passphrase 670 _, err = cstore.ExportPubKeyArmor(n1 + ".notreal") 671 require.NotNil(t, err) 672 _, err = cstore.ExportPubKeyArmor(" " + n1) 673 require.NotNil(t, err) 674 _, err = cstore.ExportPubKeyArmor(n1 + " ") 675 require.NotNil(t, err) 676 _, err = cstore.ExportPubKeyArmor("") 677 require.NotNil(t, err) 678 exported, err := cstore.ExportPubKeyArmor(n1) 679 require.Nil(t, err, "%+v", err) 680 err = cstore.Delete(n1) 681 require.NoError(t, err) 682 683 // import succeeds 684 err = cstore.ImportPubKey(n2, exported) 685 require.NoError(t, err) 686 687 // second import fails 688 err = cstore.ImportPubKey(n2, exported) 689 require.NotNil(t, err) 690 } 691 692 // TestInMemorySeedPhrase verifies restoring from a seed phrase 693 func TestInMemorySeedPhrase(t *testing.T) { 694 // make the storage with reasonable defaults 695 cstore := NewInMemory() 696 697 algo := hd.Secp256k1 698 n1, n2 := "lost-key", "found-again" 699 700 // make sure key works with initial password 701 info, mnemonic, err := cstore.NewMnemonic(n1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, algo) 702 require.Nil(t, err, "%+v", err) 703 require.Equal(t, n1, info.GetName()) 704 require.NotEmpty(t, mnemonic) 705 706 // now, let us delete this key 707 err = cstore.Delete(n1) 708 require.Nil(t, err, "%+v", err) 709 _, err = cstore.Key(n1) 710 require.NotNil(t, err) 711 712 // let us re-create it from the mnemonic-phrase 713 params := *hd.NewFundraiserParams(0, sdk.CoinType, 0) 714 hdPath := params.String() 715 newInfo, err := cstore.NewAccount(n2, mnemonic, DefaultBIP39Passphrase, hdPath, algo) 716 require.NoError(t, err) 717 require.Equal(t, n2, newInfo.GetName()) 718 require.Equal(t, info.GetPubKey().Address(), newInfo.GetPubKey().Address()) 719 require.Equal(t, info.GetPubKey(), newInfo.GetPubKey()) 720 } 721 722 func TestKeyChain_ShouldFailWhenAddingSameGeneratedAccount(t *testing.T) { 723 kr, err := New(t.Name(), BackendTest, t.TempDir(), nil) 724 require.NoError(t, err) 725 726 // Given we create a mnemonic 727 _, seed, err := kr.NewMnemonic("test", English, "", DefaultBIP39Passphrase, hd.Secp256k1) 728 require.NoError(t, err) 729 730 require.NoError(t, kr.Delete("test")) 731 732 path := hd.CreateHDPath(118, 0, 0).String() 733 _, err = kr.NewAccount("test1", seed, "", path, hd.Secp256k1) 734 require.NoError(t, err) 735 736 // Creating another account with different uid but same seed should fail due to have same pub address 737 _, err = kr.NewAccount("test2", seed, "", path, hd.Secp256k1) 738 require.Error(t, err) 739 } 740 741 func ExampleNew() { 742 // Select the encryption and storage for your cryptostore 743 cstore := NewInMemory() 744 745 sec := hd.Secp256k1 746 747 // Add keys and see they return in alphabetical order 748 bob, _, err := cstore.NewMnemonic("Bob", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, sec) 749 if err != nil { 750 // this should never happen 751 fmt.Println(err) 752 } else { 753 // return info here just like in List 754 fmt.Println(bob.GetName()) 755 } 756 _, _, _ = cstore.NewMnemonic("Alice", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, sec) 757 _, _, _ = cstore.NewMnemonic("Carl", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, sec) 758 info, _ := cstore.List() 759 for _, i := range info { 760 fmt.Println(i.GetName()) 761 } 762 763 // We need to use passphrase to generate a signature 764 tx := []byte("deadbeef") 765 sig, pub, err := cstore.Sign("Bob", tx) 766 if err != nil { 767 fmt.Println("don't accept real passphrase") 768 } 769 770 // and we can validate the signature with publicly available info 771 binfo, _ := cstore.Key("Bob") 772 if !binfo.GetPubKey().Equals(bob.GetPubKey()) { 773 fmt.Println("Get and Create return different keys") 774 } 775 776 if pub.Equals(binfo.GetPubKey()) { 777 fmt.Println("signed by Bob") 778 } 779 if !pub.VerifySignature(tx, sig) { 780 fmt.Println("invalid signature") 781 } 782 783 // Output: 784 // Bob 785 // Alice 786 // Bob 787 // Carl 788 // signed by Bob 789 } 790 791 func TestAltKeyring_List(t *testing.T) { 792 dir := t.TempDir() 793 794 keyring, err := New(t.Name(), BackendTest, dir, nil) 795 require.NoError(t, err) 796 797 list, err := keyring.List() 798 require.NoError(t, err) 799 require.Empty(t, list) 800 801 // Fails on creating unsupported pubKeyType 802 _, _, err = keyring.NewMnemonic("failing", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) 803 require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) 804 805 // Create 3 keys 806 uid1, uid2, uid3 := "Zkey", "Bkey", "Rkey" 807 _, _, err = keyring.NewMnemonic(uid1, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 808 require.NoError(t, err) 809 _, _, err = keyring.NewMnemonic(uid2, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 810 require.NoError(t, err) 811 _, _, err = keyring.NewMnemonic(uid3, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 812 require.NoError(t, err) 813 814 list, err = keyring.List() 815 require.NoError(t, err) 816 require.Len(t, list, 3) 817 818 // Check they are in alphabetical order 819 require.Equal(t, uid2, list[0].GetName()) 820 require.Equal(t, uid3, list[1].GetName()) 821 require.Equal(t, uid1, list[2].GetName()) 822 } 823 824 func TestAltKeyring_NewAccount(t *testing.T) { 825 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 826 require.NoError(t, err) 827 828 entropy, err := bip39.NewEntropy(defaultEntropySize) 829 require.NoError(t, err) 830 831 mnemonic, err := bip39.NewMnemonic(entropy) 832 require.NoError(t, err) 833 834 uid := "newUid" 835 836 // Fails on creating unsupported pubKeyType 837 _, err = keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, notSupportedAlgo{}) 838 require.EqualError(t, err, ErrUnsupportedSigningAlgo.Error()) 839 840 info, err := keyring.NewAccount(uid, mnemonic, DefaultBIP39Passphrase, sdk.FullFundraiserPath, hd.Secp256k1) 841 require.NoError(t, err) 842 843 require.Equal(t, uid, info.GetName()) 844 845 list, err := keyring.List() 846 require.NoError(t, err) 847 require.Len(t, list, 1) 848 } 849 850 func TestAltKeyring_Get(t *testing.T) { 851 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 852 require.NoError(t, err) 853 854 uid := someKey 855 mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 856 require.NoError(t, err) 857 858 key, err := keyring.Key(uid) 859 require.NoError(t, err) 860 requireEqualInfo(t, mnemonic, key) 861 } 862 863 func TestAltKeyring_KeyByAddress(t *testing.T) { 864 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 865 require.NoError(t, err) 866 867 uid := someKey 868 mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 869 require.NoError(t, err) 870 871 key, err := keyring.KeyByAddress(mnemonic.GetAddress()) 872 require.NoError(t, err) 873 requireEqualInfo(t, key, mnemonic) 874 } 875 876 func TestAltKeyring_Delete(t *testing.T) { 877 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 878 require.NoError(t, err) 879 880 uid := someKey 881 _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 882 require.NoError(t, err) 883 884 list, err := keyring.List() 885 require.NoError(t, err) 886 require.Len(t, list, 1) 887 888 err = keyring.Delete(uid) 889 require.NoError(t, err) 890 891 list, err = keyring.List() 892 require.NoError(t, err) 893 require.Empty(t, list) 894 } 895 896 func TestAltKeyring_DeleteByAddress(t *testing.T) { 897 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 898 require.NoError(t, err) 899 900 uid := someKey 901 mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 902 require.NoError(t, err) 903 904 list, err := keyring.List() 905 require.NoError(t, err) 906 require.Len(t, list, 1) 907 908 err = keyring.DeleteByAddress(mnemonic.GetAddress()) 909 require.NoError(t, err) 910 911 list, err = keyring.List() 912 require.NoError(t, err) 913 require.Empty(t, list) 914 } 915 916 func TestAltKeyring_SavePubKey(t *testing.T) { 917 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 918 require.NoError(t, err) 919 920 list, err := keyring.List() 921 require.NoError(t, err) 922 require.Empty(t, list) 923 924 key := someKey 925 priv := ed25519.GenPrivKey() 926 pub := priv.PubKey() 927 928 info, err := keyring.SavePubKey(key, pub, hd.Secp256k1.Name()) 929 require.Nil(t, err) 930 require.Equal(t, pub, info.GetPubKey()) 931 require.Equal(t, key, info.GetName()) 932 require.Equal(t, hd.Secp256k1.Name(), info.GetAlgo()) 933 934 list, err = keyring.List() 935 require.NoError(t, err) 936 require.Equal(t, 1, len(list)) 937 } 938 939 func TestAltKeyring_SaveMultisig(t *testing.T) { 940 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 941 require.NoError(t, err) 942 943 mnemonic1, _, err := keyring.NewMnemonic("key1", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 944 require.NoError(t, err) 945 mnemonic2, _, err := keyring.NewMnemonic("key2", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 946 require.NoError(t, err) 947 948 key := "multi" 949 pub := multisig.NewLegacyAminoPubKey( 950 2, 951 []types.PubKey{ 952 &secp256k1.PubKey{Key: mnemonic1.GetPubKey().Bytes()}, 953 &secp256k1.PubKey{Key: mnemonic2.GetPubKey().Bytes()}, 954 }, 955 ) 956 957 info, err := keyring.SaveMultisig(key, pub) 958 require.Nil(t, err) 959 require.Equal(t, pub, info.GetPubKey()) 960 require.Equal(t, key, info.GetName()) 961 962 list, err := keyring.List() 963 require.NoError(t, err) 964 require.Len(t, list, 3) 965 } 966 967 func TestAltKeyring_Sign(t *testing.T) { 968 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 969 require.NoError(t, err) 970 971 uid := "jack" 972 _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 973 require.NoError(t, err) 974 975 msg := []byte("some message") 976 977 sign, key, err := keyring.Sign(uid, msg) 978 require.NoError(t, err) 979 980 require.True(t, key.VerifySignature(msg, sign)) 981 } 982 983 func TestAltKeyring_SignByAddress(t *testing.T) { 984 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 985 require.NoError(t, err) 986 987 uid := "jack" 988 mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 989 require.NoError(t, err) 990 991 msg := []byte("some message") 992 993 sign, key, err := keyring.SignByAddress(mnemonic.GetAddress(), msg) 994 require.NoError(t, err) 995 996 require.True(t, key.VerifySignature(msg, sign)) 997 } 998 999 func TestAltKeyring_ImportExportPrivKey(t *testing.T) { 1000 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 1001 require.NoError(t, err) 1002 1003 uid := theID 1004 _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 1005 require.NoError(t, err) 1006 1007 passphrase := "somePass" 1008 armor, err := keyring.ExportPrivKeyArmor(uid, passphrase) 1009 require.NoError(t, err) 1010 err = keyring.Delete(uid) 1011 require.NoError(t, err) 1012 newUID := otherID 1013 // Should fail importing with wrong password 1014 err = keyring.ImportPrivKey(newUID, armor, "wrongPass") 1015 require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") 1016 1017 err = keyring.ImportPrivKey(newUID, armor, passphrase) 1018 require.NoError(t, err) 1019 1020 // Should fail importing private key on existing key. 1021 err = keyring.ImportPrivKey(newUID, armor, passphrase) 1022 require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) 1023 } 1024 1025 func TestAltKeyring_ImportExportPrivKey_ByAddress(t *testing.T) { 1026 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 1027 require.NoError(t, err) 1028 1029 uid := theID 1030 mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 1031 require.NoError(t, err) 1032 1033 passphrase := "somePass" 1034 armor, err := keyring.ExportPrivKeyArmorByAddress(mnemonic.GetAddress(), passphrase) 1035 require.NoError(t, err) 1036 err = keyring.Delete(uid) 1037 require.NoError(t, err) 1038 1039 newUID := otherID 1040 // Should fail importing with wrong password 1041 err = keyring.ImportPrivKey(newUID, armor, "wrongPass") 1042 require.EqualError(t, err, "failed to decrypt private key: ciphertext decryption failed") 1043 1044 err = keyring.ImportPrivKey(newUID, armor, passphrase) 1045 require.NoError(t, err) 1046 1047 // Should fail importing private key on existing key. 1048 err = keyring.ImportPrivKey(newUID, armor, passphrase) 1049 require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) 1050 } 1051 1052 func TestAltKeyring_ImportExportPubKey(t *testing.T) { 1053 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 1054 require.NoError(t, err) 1055 1056 uid := theID 1057 _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 1058 require.NoError(t, err) 1059 1060 armor, err := keyring.ExportPubKeyArmor(uid) 1061 require.NoError(t, err) 1062 err = keyring.Delete(uid) 1063 require.NoError(t, err) 1064 1065 newUID := otherID 1066 err = keyring.ImportPubKey(newUID, armor) 1067 require.NoError(t, err) 1068 1069 // Should fail importing private key on existing key. 1070 err = keyring.ImportPubKey(newUID, armor) 1071 require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) 1072 } 1073 1074 func TestAltKeyring_ImportExportPubKey_ByAddress(t *testing.T) { 1075 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 1076 require.NoError(t, err) 1077 1078 uid := theID 1079 mnemonic, _, err := keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 1080 require.NoError(t, err) 1081 1082 armor, err := keyring.ExportPubKeyArmorByAddress(mnemonic.GetAddress()) 1083 require.NoError(t, err) 1084 err = keyring.Delete(uid) 1085 require.NoError(t, err) 1086 1087 newUID := otherID 1088 err = keyring.ImportPubKey(newUID, armor) 1089 require.NoError(t, err) 1090 1091 // Should fail importing private key on existing key. 1092 err = keyring.ImportPubKey(newUID, armor) 1093 require.EqualError(t, err, fmt.Sprintf("cannot overwrite key: %s", newUID)) 1094 } 1095 1096 func TestAltKeyring_UnsafeExportPrivKeyHex(t *testing.T) { 1097 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 1098 require.NoError(t, err) 1099 1100 uid := theID 1101 1102 _, _, err = keyring.NewMnemonic(uid, English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 1103 require.NoError(t, err) 1104 1105 unsafeKeyring := NewUnsafe(keyring) 1106 privKey, err := unsafeKeyring.UnsafeExportPrivKeyHex(uid) 1107 1108 require.NoError(t, err) 1109 require.Equal(t, 64, len(privKey)) 1110 1111 _, err = hex.DecodeString(privKey) 1112 require.NoError(t, err) 1113 1114 // test error on non existing key 1115 _, err = unsafeKeyring.UnsafeExportPrivKeyHex("non-existing") 1116 require.Error(t, err) 1117 } 1118 1119 func TestAltKeyring_ConstructorSupportedAlgos(t *testing.T) { 1120 keyring, err := New(t.Name(), BackendTest, t.TempDir(), nil) 1121 require.NoError(t, err) 1122 1123 // should fail when using unsupported signing algorythm. 1124 _, _, err = keyring.NewMnemonic("test", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) 1125 require.EqualError(t, err, "unsupported signing algo") 1126 1127 // but works with default signing algo. 1128 _, _, err = keyring.NewMnemonic("test", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, hd.Secp256k1) 1129 require.NoError(t, err) 1130 1131 // but we can create a new keybase with our provided algos. 1132 keyring2, err := New(t.Name(), BackendTest, t.TempDir(), nil, func(options *Options) { 1133 options.SupportedAlgos = SigningAlgoList{ 1134 notSupportedAlgo{}, 1135 } 1136 }) 1137 require.NoError(t, err) 1138 1139 // now this new keyring does not fail when signing with provided algo 1140 _, _, err = keyring2.NewMnemonic("test", English, sdk.FullFundraiserPath, DefaultBIP39Passphrase, notSupportedAlgo{}) 1141 require.NoError(t, err) 1142 } 1143 1144 func TestBackendConfigConstructors(t *testing.T) { 1145 backend := newKWalletBackendKeyringConfig("test", "", nil) 1146 require.Equal(t, []keyring.BackendType{keyring.KWalletBackend}, backend.AllowedBackends) 1147 require.Equal(t, "kdewallet", backend.ServiceName) 1148 require.Equal(t, "test", backend.KWalletAppID) 1149 1150 backend = newPassBackendKeyringConfig("test", "directory", nil) 1151 require.Equal(t, []keyring.BackendType{keyring.PassBackend}, backend.AllowedBackends) 1152 require.Equal(t, "test", backend.ServiceName) 1153 require.Equal(t, "keyring-test", backend.PassPrefix) 1154 } 1155 1156 func requireEqualInfo(t *testing.T, key Info, mnemonic Info) { 1157 require.Equal(t, key.GetName(), mnemonic.GetName()) 1158 require.Equal(t, key.GetAddress(), mnemonic.GetAddress()) 1159 require.Equal(t, key.GetPubKey(), mnemonic.GetPubKey()) 1160 require.Equal(t, key.GetAlgo(), mnemonic.GetAlgo()) 1161 require.Equal(t, key.GetType(), mnemonic.GetType()) 1162 } 1163 1164 func accAddr(info Info) sdk.AccAddress { return info.GetAddress() }