Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: simplify the import / export API for the Keybase #3285

Merged
merged 9 commits into from
Dec 18, 2024
4 changes: 2 additions & 2 deletions contribs/gnodev/cmd/gnobro/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
41 changes: 15 additions & 26 deletions tm2/pkg/crypto/keys/client/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

"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 {
Expand Down Expand Up @@ -88,25 +89,25 @@
)
}

var (
armor string
exportErr error
)
var keyArmor string

if cfg.Unsafe {
// Generate the unencrypted armor
armor, exportErr = kb.ExportPrivKeyUnsafe(
cfg.NameOrBech32,
decryptPassword,
)

privk, err := kb.ExportPrivateKeyObject(cfg.NameOrBech32, decryptPassword)
privk, err := kb.ExportPrivKey(cfg.NameOrBech32, decryptPassword)
if err != nil {
panic(err)
return fmt.Errorf("unable to export private key, %w", err)

Check warning on line 97 in tm2/pkg/crypto/keys/client/export.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/crypto/keys/client/export.go#L97

Added line #L97 was not covered by tests
}

io.Printf("privk:\n%x\n", privk.Bytes())

// Generate the private key armor
keyArmor = armor.ArmorPrivateKey(privk)
} else {
// Generate the encrypted armor
privk, err := kb.ExportPrivKey(cfg.NameOrBech32, decryptPassword)
if err != nil {
return fmt.Errorf("unable to export private key, %w", err)
}

Check warning on line 109 in tm2/pkg/crypto/keys/client/export.go

View check run for this annotation

Codecov / codecov/patch

tm2/pkg/crypto/keys/client/export.go#L108-L109

Added lines #L108 - L109 were not covered by tests
aeddi marked this conversation as resolved.
Show resolved Hide resolved

// Get the armor encrypt password
encryptPassword, err := io.GetCheckPassword(
[2]string{
Expand All @@ -122,25 +123,13 @@
)
}

// 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(privk, encryptPassword)
}

// Write the armor to disk
if err := os.WriteFile(
cfg.OutputPath,
[]byte(armor),
[]byte(keyArmor),
0o644,
); err != nil {
return fmt.Errorf(
Expand Down
22 changes: 17 additions & 5 deletions tm2/pkg/crypto/keys/client/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 ImportCfg struct {
Expand Down Expand Up @@ -77,7 +78,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",
Expand Down Expand Up @@ -121,10 +122,16 @@ func execImport(cfg *ImportCfg, io commands.IO) error {
}

if cfg.Unsafe {
// Un-armor the private key
privKey, err := armor.UnarmorPrivateKey(string(keyArmor))
if err != nil {
return fmt.Errorf("unable to unarmor private key, %w", err)
}

// Import the unencrypted private key
if err := kb.ImportPrivKeyUnsafe(
if err := kb.ImportPrivKey(
aeddi marked this conversation as resolved.
Show resolved Hide resolved
cfg.KeyName,
string(armor),
privKey,
encryptPassword,
); err != nil {
return fmt.Errorf(
Expand All @@ -133,11 +140,16 @@ func execImport(cfg *ImportCfg, io commands.IO) error {
)
}
} else {
// Decrypt the armor
privKey, err := armor.UnarmorDecryptPrivKey(string(keyArmor), decryptPassword)
if err != nil {
return fmt.Errorf("unable to decrypt private key armor, %w", err)
}

// Import the encrypted private key
if err := kb.ImportPrivKey(
cfg.KeyName,
string(armor),
decryptPassword,
privKey,
encryptPassword,
); err != nil {
return fmt.Errorf(
Expand Down
75 changes: 75 additions & 0 deletions tm2/pkg/crypto/keys/client/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand All @@ -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")
}
2 changes: 1 addition & 1 deletion tm2/pkg/crypto/keys/client/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading
Loading