diff --git a/contribs/gnodev/cmd/gnobro/main.go b/contribs/gnodev/cmd/gnobro/main.go index 092a441542a..91713d6c6d8 100644 --- a/contribs/gnodev/cmd/gnobro/main.go +++ b/contribs/gnodev/cmd/gnobro/main.go @@ -429,14 +429,14 @@ func getSignerForAccount(io commands.IO, address string, kb keys.Keybase, cfg *b } // try empty password first - if _, err := kb.ExportPrivKeyUnsafe(address, ""); err != nil { + if _, err := kb.ExportPrivKey(address, ""); err != nil { prompt := fmt.Sprintf("[%.10s] Enter password:", address) signer.Password, err = io.GetPassword(prompt, true) if err != nil { return nil, fmt.Errorf("error while reading password: %w", err) } - if _, err := kb.ExportPrivKeyUnsafe(address, signer.Password); err != nil { + if _, err := kb.ExportPrivKey(address, signer.Password); err != nil { return nil, fmt.Errorf("invalid password: %w", err) } } diff --git a/tm2/pkg/crypto/keys/client/export.go b/tm2/pkg/crypto/keys/client/export.go index b7a82a5af6e..98a681d30b8 100644 --- a/tm2/pkg/crypto/keys/client/export.go +++ b/tm2/pkg/crypto/keys/client/export.go @@ -9,6 +9,7 @@ import ( "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/crypto/keys" + "github.com/gnolang/gno/tm2/pkg/crypto/keys/armor" ) type ExportCfg struct { @@ -88,24 +89,19 @@ func execExport(cfg *ExportCfg, io commands.IO) error { ) } - var ( - armor string - exportErr error - ) + var keyArmor string - if cfg.Unsafe { - // Generate the unencrypted armor - armor, exportErr = kb.ExportPrivKeyUnsafe( - cfg.NameOrBech32, - decryptPassword, - ) + // Export the private key from the keybase + privateKey, err := kb.ExportPrivKey(cfg.NameOrBech32, decryptPassword) + if err != nil { + return fmt.Errorf("unable to export private key, %w", err) + } - privk, err := kb.ExportPrivateKeyObject(cfg.NameOrBech32, decryptPassword) - if err != nil { - panic(err) - } + if cfg.Unsafe { + io.Printf("privk:\n%x\n", privateKey.Bytes()) - io.Printf("privk:\n%x\n", privk.Bytes()) + // Generate the private key armor + keyArmor = armor.ArmorPrivateKey(privateKey) } else { // Get the armor encrypt password encryptPassword, err := io.GetCheckPassword( @@ -122,25 +118,13 @@ func execExport(cfg *ExportCfg, io commands.IO) error { ) } - // Generate the encrypted armor - armor, exportErr = kb.ExportPrivKey( - cfg.NameOrBech32, - decryptPassword, - encryptPassword, - ) - } - - if exportErr != nil { - return fmt.Errorf( - "unable to export the private key, %w", - exportErr, - ) + keyArmor = armor.EncryptArmorPrivKey(privateKey, encryptPassword) } // Write the armor to disk if err := os.WriteFile( cfg.OutputPath, - []byte(armor), + []byte(keyArmor), 0o644, ); err != nil { return fmt.Errorf( diff --git a/tm2/pkg/crypto/keys/client/import.go b/tm2/pkg/crypto/keys/client/import.go index a3f78526729..3c90b056137 100644 --- a/tm2/pkg/crypto/keys/client/import.go +++ b/tm2/pkg/crypto/keys/client/import.go @@ -8,7 +8,9 @@ import ( "os" "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/crypto" "github.com/gnolang/gno/tm2/pkg/crypto/keys" + "github.com/gnolang/gno/tm2/pkg/crypto/keys/armor" ) type ImportCfg struct { @@ -77,7 +79,7 @@ func execImport(cfg *ImportCfg, io commands.IO) error { } // Read the raw encrypted armor - armor, err := os.ReadFile(cfg.ArmorPath) + keyArmor, err := os.ReadFile(cfg.ArmorPath) if err != nil { return fmt.Errorf( "unable to read armor from path %s, %w", @@ -120,33 +122,34 @@ func execImport(cfg *ImportCfg, io commands.IO) error { ) } + var privateKey crypto.PrivKey + if cfg.Unsafe { - // Import the unencrypted private key - if err := kb.ImportPrivKeyUnsafe( - cfg.KeyName, - string(armor), - encryptPassword, - ); err != nil { - return fmt.Errorf( - "unable to import the unencrypted private key, %w", - err, - ) + // Un-armor the private key + privateKey, err = armor.UnarmorPrivateKey(string(keyArmor)) + if err != nil { + return fmt.Errorf("unable to unarmor private key, %w", err) } } else { - // Import the encrypted private key - if err := kb.ImportPrivKey( - cfg.KeyName, - string(armor), - decryptPassword, - encryptPassword, - ); err != nil { - return fmt.Errorf( - "unable to import the encrypted private key, %w", - err, - ) + // Decrypt the armor + privateKey, err = armor.UnarmorDecryptPrivKey(string(keyArmor), decryptPassword) + if err != nil { + return fmt.Errorf("unable to decrypt private key armor, %w", err) } } + // Import the private key + if err := kb.ImportPrivKey( + cfg.KeyName, + privateKey, + encryptPassword, + ); err != nil { + return fmt.Errorf( + "unable to import the encrypted private key, %w", + err, + ) + } + io.Printfln("Successfully imported private key %s", cfg.KeyName) return nil diff --git a/tm2/pkg/crypto/keys/client/import_test.go b/tm2/pkg/crypto/keys/client/import_test.go index 9788f3d700c..14946b29444 100644 --- a/tm2/pkg/crypto/keys/client/import_test.go +++ b/tm2/pkg/crypto/keys/client/import_test.go @@ -3,12 +3,14 @@ package client import ( "fmt" "io" + "os" "strings" "testing" "github.com/gnolang/gno/tm2/pkg/commands" "github.com/gnolang/gno/tm2/pkg/testutils" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type testImportKeyOpts struct { @@ -154,6 +156,8 @@ func TestImport_ImportKey(t *testing.T) { } func TestImport_ImportKeyWithEmptyName(t *testing.T) { + t.Parallel() + // Generate a temporary key-base directory _, kbHome := newTestKeybase(t) err := importKey( @@ -168,3 +172,74 @@ func TestImport_ImportKeyWithEmptyName(t *testing.T) { assert.Error(t, err) assert.EqualError(t, err, "name shouldn't be empty") } + +func TestImport_ImportKeyInvalidArmor(t *testing.T) { + t.Parallel() + + _, kbHome := newTestKeybase(t) + + armorFile, err := os.CreateTemp("", "armor.key") + require.NoError(t, err) + + defer os.Remove(armorFile.Name()) + + // Write invalid armor + _, err = armorFile.Write([]byte("totally valid tendermint armor")) + require.NoError(t, err) + + err = importKey( + testImportKeyOpts{ + testCmdKeyOptsBase: testCmdKeyOptsBase{ + kbHome: kbHome, + keyName: "key-name", + unsafe: true, // expect an unencrypted private key armor + }, + armorPath: armorFile.Name(), + }, + strings.NewReader( + fmt.Sprintf( + "%s\n%s\n", + "", + "", + ), + ), + ) + + assert.ErrorContains(t, err, "unable to unarmor private key") +} + +func TestImport_ImportKeyInvalidPKArmor(t *testing.T) { + t.Parallel() + + _, kbHome := newTestKeybase(t) + + armorFile, err := os.CreateTemp("", "armor.key") + require.NoError(t, err) + + defer os.Remove(armorFile.Name()) + + // Write invalid armor + _, err = armorFile.Write([]byte("totally valid tendermint armor")) + require.NoError(t, err) + + err = importKey( + testImportKeyOpts{ + testCmdKeyOptsBase: testCmdKeyOptsBase{ + kbHome: kbHome, + keyName: "key-name", + unsafe: false, // expect an encrypted private key armor + }, + armorPath: armorFile.Name(), + }, + strings.NewReader( + fmt.Sprintf( + "%s\n%s\n%s\n", + "", + "", + "", + ), + ), + ) + + assert.ErrorContains(t, err, "unable to decrypt private key armor") +} diff --git a/tm2/pkg/crypto/keys/client/verify_test.go b/tm2/pkg/crypto/keys/client/verify_test.go index 796f6344852..dfdd191055b 100644 --- a/tm2/pkg/crypto/keys/client/verify_test.go +++ b/tm2/pkg/crypto/keys/client/verify_test.go @@ -45,7 +45,7 @@ func Test_execVerify(t *testing.T) { assert.NoError(t, err) // sign test message. - priv, err := kb.ExportPrivateKeyObject(fakeKeyName1, encPassword) + priv, err := kb.ExportPrivKey(fakeKeyName1, encPassword) assert.NoError(t, err) testSig, err := priv.Sign([]byte(testMsg)) assert.NoError(t, err) diff --git a/tm2/pkg/crypto/keys/keybase.go b/tm2/pkg/crypto/keys/keybase.go index 23c4237151a..2bb386fd88b 100644 --- a/tm2/pkg/crypto/keys/keybase.go +++ b/tm2/pkg/crypto/keys/keybase.go @@ -17,6 +17,11 @@ import ( "github.com/gnolang/gno/tm2/pkg/errors" ) +var ( + errCannotOverwrite = errors.New("cannot overwrite existing key") + errKeyNotAvailable = errors.New("private key not available") +) + var _ Keybase = dbKeybase{} // Language is a language to create the BIP 39 mnemonic in. @@ -222,7 +227,7 @@ func (kb dbKeybase) Sign(nameOrBech32, passphrase string, msg []byte) (sig []byt case localInfo: linfo := info.(localInfo) if linfo.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") + err = fmt.Errorf("%w: %s", errKeyNotAvailable, nameOrBech32) return } @@ -268,7 +273,17 @@ func (kb dbKeybase) Verify(nameOrBech32 string, msg []byte, sig []byte) (err err return nil } -func (kb dbKeybase) ExportPrivateKeyObject(nameOrBech32 string, passphrase string) (crypto.PrivKey, error) { +func (kb dbKeybase) ImportPrivKey(name string, key crypto.PrivKey, encryptPass string) error { + if _, err := kb.GetByNameOrAddress(name); err == nil { + return fmt.Errorf("%w: %s", errCannotOverwrite, name) + } + + _, err := kb.writeLocalKey(name, key, encryptPass) + + return err +} + +func (kb dbKeybase) ExportPrivKey(nameOrBech32 string, passphrase string) (crypto.PrivKey, error) { info, err := kb.GetByNameOrAddress(nameOrBech32) if err != nil { return nil, err @@ -280,14 +295,13 @@ func (kb dbKeybase) ExportPrivateKeyObject(nameOrBech32 string, passphrase strin case localInfo: linfo := info.(localInfo) if linfo.PrivKeyArmor == "" { - err = fmt.Errorf("private key not available") - return nil, err + return nil, fmt.Errorf("%w: %s", errKeyNotAvailable, nameOrBech32) } + priv, err = armor.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase) if err != nil { return nil, err } - case ledgerInfo, offlineInfo, multiInfo: return nil, errors.New("only works on local private keys") } @@ -295,129 +309,6 @@ func (kb dbKeybase) ExportPrivateKeyObject(nameOrBech32 string, passphrase strin return priv, nil } -func (kb dbKeybase) Export(nameOrBech32 string) (astr string, err error) { - info, err := kb.GetByNameOrAddress(nameOrBech32) - if err != nil { - return "", errors.Wrapf(err, "getting info for name %s", nameOrBech32) - } - bz := kb.db.Get(infoKey(info.GetName())) - if bz == nil { - return "", fmt.Errorf("no key to export with name %s", nameOrBech32) - } - return armor.ArmorInfoBytes(bz), nil -} - -// ExportPubKey returns public keys in ASCII armored format. -// Retrieve a Info object by its name and return the public key in -// a portable format. -func (kb dbKeybase) ExportPubKey(nameOrBech32 string) (astr string, err error) { - info, err := kb.GetByNameOrAddress(nameOrBech32) - if err != nil { - return "", errors.Wrapf(err, "getting info for name %s", nameOrBech32) - } - return armor.ArmorPubKeyBytes(info.GetPubKey().Bytes()), nil -} - -// ExportPrivKey returns a private key in ASCII armored format. -// It returns an error if the key does not exist or a wrong encryption passphrase is supplied. -func (kb dbKeybase) ExportPrivKey( - name, - decryptPassphrase, - encryptPassphrase string, -) (astr string, err error) { - priv, err := kb.ExportPrivateKeyObject(name, decryptPassphrase) - if err != nil { - return "", err - } - - return armor.EncryptArmorPrivKey(priv, encryptPassphrase), nil -} - -// ExportPrivKeyUnsafe returns a private key in ASCII armored format. -// The returned armor is unencrypted. -// It returns an error if the key does not exist -func (kb dbKeybase) ExportPrivKeyUnsafe( - name, - decryptPassphrase string, -) (string, error) { - priv, err := kb.ExportPrivateKeyObject(name, decryptPassphrase) - if err != nil { - return "", err - } - - return armor.ArmorPrivateKey(priv), nil -} - -// ImportPrivKey imports a private key in ASCII armor format. -// It returns an error if a key with the same name exists or a wrong encryption passphrase is -// supplied. -func (kb dbKeybase) ImportPrivKey( - name, - astr, - decryptPassphrase, - encryptPassphrase string, -) error { - if _, err := kb.GetByNameOrAddress(name); err == nil { - return errors.New("Cannot overwrite key " + name) - } - privKey, err := armor.UnarmorDecryptPrivKey(astr, decryptPassphrase) - if err != nil { - return errors.Wrap(err, "couldn't import private key") - } - - kb.writeLocalKey(name, privKey, encryptPassphrase) - return nil -} - -func (kb dbKeybase) ImportPrivKeyUnsafe( - name, - armorStr, - encryptPassphrase string, -) error { - if _, err := kb.GetByNameOrAddress(name); err == nil { - return fmt.Errorf("cannot overwrite key %s", name) - } - - privKey, err := armor.UnarmorPrivateKey(armorStr) - if err != nil { - return errors.Wrap(err, "couldn't import private key") - } - - kb.writeLocalKey(name, privKey, encryptPassphrase) - return nil -} - -func (kb dbKeybase) Import(name, astr string) (err error) { - if _, err := kb.GetByNameOrAddress(name); err == nil { - return errors.New("Cannot overwrite key " + name) - } - infoBytes, err := armor.UnarmorInfoBytes(astr) - if err != nil { - return - } - kb.db.Set(infoKey(name), infoBytes) - return nil -} - -// ImportPubKey imports ASCII-armored public keys. -// Store a new Info object holding a public key only, i.e. it will -// not be possible to sign with it as it lacks the secret key. -func (kb dbKeybase) ImportPubKey(name, astr string) (err error) { - if _, err := kb.GetByNameOrAddress(name); err == nil { - return errors.New("Cannot overwrite data for name " + name) - } - pubBytes, err := armor.UnarmorPubKeyBytes(astr) - if err != nil { - return - } - pubKey, err := crypto.PubKeyFromBytes(pubBytes) - if err != nil { - return - } - kb.writeOfflineKey(name, pubKey) - return -} - // Delete removes key forever, but we must present the // proper passphrase before deleting it (for security). // It returns an error if the key doesn't exist or diff --git a/tm2/pkg/crypto/keys/keybase_test.go b/tm2/pkg/crypto/keys/keybase_test.go index 25306e62635..a5fb61f2b9b 100644 --- a/tm2/pkg/crypto/keys/keybase_test.go +++ b/tm2/pkg/crypto/keys/keybase_test.go @@ -58,11 +58,11 @@ func TestKeyManagement(t *testing.T) { has, err = cstore.HasByName(n3) require.NoError(t, err) require.False(t, has) - has, err = cstore.HasByAddress(toAddr(i2)) + has, err = cstore.HasByAddress(i2.GetPubKey().Address()) require.NoError(t, err) require.True(t, has) // Also check with HasByNameOrAddress - has, err = cstore.HasByNameOrAddress(crypto.AddressToBech32(toAddr(i2))) + has, err = cstore.HasByNameOrAddress(crypto.AddressToBech32(i2.GetPubKey().Address())) require.NoError(t, err) require.True(t, has) addr, err := crypto.AddressFromBech32("g1frtkxv37nq7arvyz5p0mtjqq7hwuvd4dnt892p") @@ -149,12 +149,12 @@ func TestSignVerify(t *testing.T) { i2, err := cstore.CreateAccount(n2, mn2, bip39Passphrase, p2, 0, 0) require.Nil(t, err) - // Import a public key into a new store - armor, err := cstore.ExportPubKey(n2) - require.Nil(t, err) - cstore2 := NewInMemory() - cstore2.ImportPubKey(n3, armor) - i3, err := cstore2.GetByName(n3) + i3Key := ed25519.GenPrivKey() + + // Import a public key + _, err = cstore.CreateOffline(n3, i3Key.PubKey()) + require.NoError(t, err) + i3, err := cstore.GetByName(n3) require.NoError(t, err) require.Equal(t, i3.GetName(), n3) @@ -175,7 +175,7 @@ func TestSignVerify(t *testing.T) { s21, pub2, err := cstore.Sign(n2, p2, d1) require.Nil(t, err) require.Equal(t, i2.GetPubKey(), pub2) - require.Equal(t, i3.GetPubKey(), pub2) + require.Equal(t, i3.GetPubKey(), i3Key.PubKey()) s22, pub2, err := cstore.Sign(n2, p2, d2) require.Nil(t, err) @@ -220,39 +220,6 @@ func assertPassword(t *testing.T, cstore Keybase, name, pass, badpass string) { require.Nil(t, err, "%+v", err) } -// TestExportImport tests exporting and importing -func TestExportImport(t *testing.T) { - t.Parallel() - - // make the storage with reasonable defaults - cstore := NewInMemory() - - mn1 := `lounge napkin all odor tilt dove win inject sleep jazz uncover traffic hint require cargo arm rocket round scan bread report squirrel step lake` - bip39Passphrase := "" - - info, err := cstore.CreateAccount("john", mn1, bip39Passphrase, "secretcpw", 0, 0) - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - - john, err := cstore.GetByName("john") - require.NoError(t, err) - require.Equal(t, info.GetName(), "john") - johnAddr := info.GetPubKey().Address() - - armor, err := cstore.Export("john") - require.NoError(t, err) - - err = cstore.Import("john2", armor) - require.NoError(t, err) - - john2, err := cstore.GetByName("john2") - require.NoError(t, err) - - require.Equal(t, john.GetPubKey().Address(), johnAddr) - require.Equal(t, john.GetName(), "john") - require.Equal(t, john, john2) -} - func TestExportImportPubKey(t *testing.T) { t.Parallel() @@ -273,11 +240,8 @@ func TestExportImportPubKey(t *testing.T) { require.Equal(t, john.GetName(), "john") require.Equal(t, john.GetPubKey().Address(), addr) - // Export the public key only - armor, err := cstore.ExportPubKey("john") - require.NoError(t, err) // Import it under a different name - err = cstore.ImportPubKey("john-pubkey-only", armor) + _, err = cstore.CreateOffline("john-pubkey-only", john.GetPubKey()) require.NoError(t, err) // Ensure consistency john2, err := cstore.GetByName("john-pubkey-only") @@ -288,20 +252,16 @@ func TestExportImportPubKey(t *testing.T) { has, err := cstore.HasByName("john") require.NoError(t, err) require.False(t, has) - - // Ensure keys cannot be overwritten - err = cstore.ImportPubKey("john-pubkey-only", armor) - require.NotNil(t, err) } -// TestAdvancedKeyManagement verifies rotate, import, export functionality +// TestAdvancedKeyManagement verifies rotate functionality func TestAdvancedKeyManagement(t *testing.T) { t.Parallel() // make the storage with reasonable defaults cstore := NewInMemory() - n1, n2 := "old-name", "new name" + n1 := "old-name" p1, p2 := "1234", "foobar" mn1 := `lounge napkin all odor tilt dove win inject sleep jazz uncover traffic hint require cargo arm rocket round scan bread report squirrel step lake` bip39Passphrase := "" @@ -322,26 +282,6 @@ func TestAdvancedKeyManagement(t *testing.T) { require.NoError(t, err) // p2 is now the proper one! assertPassword(t, cstore, n1, p2, p1) - - // exporting requires the proper name and passphrase - _, err = cstore.Export(n1 + ".notreal") - require.NotNil(t, err) - _, err = cstore.Export(" " + n1) - require.NotNil(t, err) - _, err = cstore.Export(n1 + " ") - require.NotNil(t, err) - _, err = cstore.Export("") - require.NotNil(t, err) - exported, err := cstore.Export(n1) - require.Nil(t, err, "%+v", err) - - // import succeeds - err = cstore.Import(n2, exported) - require.NoError(t, err) - - // second import fails - err = cstore.Import(n2, exported) - require.NotNil(t, err) } // TestSeedPhrase verifies restoring from a seed phrase @@ -422,6 +362,92 @@ func ExampleNew() { // signed by Bob } -func toAddr(info Info) crypto.Address { - return info.GetPubKey().Address() +func TestKeybase_ImportPrivKey(t *testing.T) { + t.Parallel() + + t.Run("unable to overwrite key", func(t *testing.T) { + t.Parallel() + + var ( + cstore = NewInMemory() + privKey = ed25519.GenPrivKey() + name = "key-name" + encryptPass = "password" + ) + + // Import the private key + require.NoError(t, cstore.ImportPrivKey(name, privKey, encryptPass)) + + // Attempt to import a key with the same name + assert.ErrorIs( + t, + cstore.ImportPrivKey(name, ed25519.GenPrivKey(), encryptPass), + errCannotOverwrite, + ) + }) + + t.Run("valid key import", func(t *testing.T) { + t.Parallel() + + var ( + cstore = NewInMemory() + privKey = ed25519.GenPrivKey() + name = "key-name" + encryptPass = "password" + ) + + // Import the private key + require.NoError(t, cstore.ImportPrivKey(name, privKey, encryptPass)) + + // Make sure the key is present + info, err := cstore.GetByName(name) + require.NoError(t, err) + + assert.Equal(t, name, info.GetName()) + assert.True(t, privKey.PubKey().Equals(info.GetPubKey())) + }) +} + +func TestKeybase_ExportPrivKey(t *testing.T) { + t.Parallel() + + t.Run("missing key", func(t *testing.T) { + t.Parallel() + + var ( + cstore = NewInMemory() + name = "key-name" + decryptPass = "password" + ) + + keys, err := cstore.List() + require.NoError(t, err) + + // Make sure the keybase is empty + require.Empty(t, keys) + + // Attempt to export a missing key + _, err = cstore.ExportPrivKey(name, decryptPass) + assert.True(t, keyerror.IsErrKeyNotFound(err)) + }) + + t.Run("valid key export", func(t *testing.T) { + t.Parallel() + + var ( + cstore = NewInMemory() + name = "key-name" + key = ed25519.GenPrivKey() + encryptPass = "password" + ) + + // Add the key + require.NoError(t, cstore.ImportPrivKey(name, key, encryptPass)) + + // Export the key + exportedKey, err := cstore.ExportPrivKey(name, encryptPass) + require.NoError(t, err) + + assert.True(t, key.Equals(exportedKey)) + }) } diff --git a/tm2/pkg/crypto/keys/lazy_keybase.go b/tm2/pkg/crypto/keys/lazy_keybase.go index 38cec501135..2f058851bb8 100644 --- a/tm2/pkg/crypto/keys/lazy_keybase.go +++ b/tm2/pkg/crypto/keys/lazy_keybase.go @@ -189,106 +189,25 @@ func (lkb lazyKeybase) Rotate(name, oldpass string, getNewpass func() (string, e return NewDBKeybase(db).Rotate(name, oldpass, getNewpass) } -func (lkb lazyKeybase) Import(name string, armor string) (err error) { +func (lkb lazyKeybase) ImportPrivKey(name string, key crypto.PrivKey, encryptPass string) error { db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) if err != nil { return err } - defer db.Close() - - return NewDBKeybase(db).Import(name, armor) -} - -func (lkb lazyKeybase) ImportPrivKey( - name string, - armor string, - decryptPassphrase, - encryptPassphrase string, -) error { - db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return NewDBKeybase(db).ImportPrivKey(name, armor, decryptPassphrase, encryptPassphrase) -} - -func (lkb lazyKeybase) ImportPrivKeyUnsafe( - name string, - armor string, - encryptPassphrase string, -) error { - db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return NewDBKeybase(db).ImportPrivKeyUnsafe(name, armor, encryptPassphrase) -} - -func (lkb lazyKeybase) ImportPubKey(name string, armor string) (err error) { - db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) - if err != nil { - return err - } - defer db.Close() - - return NewDBKeybase(db).ImportPubKey(name, armor) -} -func (lkb lazyKeybase) Export(name string) (armor string, err error) { - db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) - if err != nil { - return "", err - } defer db.Close() - return NewDBKeybase(db).Export(name) + return NewDBKeybase(db).ImportPrivKey(name, key, encryptPass) } -func (lkb lazyKeybase) ExportPubKey(name string) (armor string, err error) { - db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) - if err != nil { - return "", err - } - defer db.Close() - - return NewDBKeybase(db).ExportPubKey(name) -} - -func (lkb lazyKeybase) ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error) { +func (lkb lazyKeybase) ExportPrivKey(name string, passphrase string) (crypto.PrivKey, error) { db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) if err != nil { return nil, err } defer db.Close() - return NewDBKeybase(db).ExportPrivateKeyObject(name, passphrase) -} - -func (lkb lazyKeybase) ExportPrivKey(name string, decryptPassphrase string, - encryptPassphrase string, -) (armor string, err error) { - db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) - if err != nil { - return "", err - } - defer db.Close() - - return NewDBKeybase(db).ExportPrivKey(name, decryptPassphrase, encryptPassphrase) -} - -func (lkb lazyKeybase) ExportPrivKeyUnsafe(name string, decryptPassphrase string) (string, error) { - db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) - if err != nil { - return "", err - } - - defer db.Close() - - return NewDBKeybase(db).ExportPrivKeyUnsafe(name, decryptPassphrase) + return NewDBKeybase(db).ExportPrivKey(name, passphrase) } func (lkb lazyKeybase) CloseDB() {} diff --git a/tm2/pkg/crypto/keys/types.go b/tm2/pkg/crypto/keys/types.go index bdaf39caa54..87cecb4a87c 100644 --- a/tm2/pkg/crypto/keys/types.go +++ b/tm2/pkg/crypto/keys/types.go @@ -44,20 +44,15 @@ type Keybase interface { // CreateMulti creates, stores, and returns a new multsig (offline) key reference CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error) - // The following operations will *only* work on locally-stored keys - // In all import operations, if an account exists with the same address but a different name, it is replaced by the new name. + // Rotate replaces the encryption password for a given key Rotate(name, oldpass string, getNewpass func() (string, error)) error - Import(name string, armor string) (err error) - ImportPrivKey(name, armor, decryptPassphrase, encryptPassphrase string) error - ImportPrivKeyUnsafe(name, armor, encryptPassphrase string) error - ImportPubKey(name string, armor string) (err error) - Export(name string) (armor string, err error) - ExportPubKey(name string) (armor string, err error) - ExportPrivKey(name, decryptPassphrase, encryptPassphrase string) (armor string, err error) - ExportPrivKeyUnsafe(name, decryptPassphrase string) (armor string, err error) - - // ExportPrivateKeyObject *only* works on locally-stored keys. Temporary method until we redo the exporting API - ExportPrivateKeyObject(name string, passphrase string) (crypto.PrivKey, error) + + // ImportPrivKey imports the given private key into the keybase. + // In all import operations, if an account exists with the same address but a different name, it is replaced by the new name + ImportPrivKey(name string, key crypto.PrivKey, encryptPass string) error + + // ExportPrivKey exports the private key from the keybase. It *only* works on locally-stored keys + ExportPrivKey(name string, decryptPass string) (crypto.PrivKey, error) // CloseDB closes the database. CloseDB()