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

Keybase: Multiple Signature Algorithms #5439

Merged
merged 31 commits into from
Jan 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7970983
in progress
sunnya97 Dec 4, 2019
90b1f5c
in progress
sunnya97 Dec 10, 2019
a16e40f
in progress
sunnya97 Dec 19, 2019
2923b54
in progress
sunnya97 Dec 19, 2019
97fc60a
in progress
sunnya97 Dec 20, 2019
4b056de
fixed defaults
sunnya97 Dec 20, 2019
8934b61
fixed unconvert
sunnya97 Dec 20, 2019
1a7c67b
with functions
sunnya97 Dec 20, 2019
ef203f6
modularize full key derivation process
sunnya97 Dec 21, 2019
f32a1a4
exposed StdDerive and StdGenerate functions
sunnya97 Dec 21, 2019
86c5618
hdpath fix
sunnya97 Dec 21, 2019
11a9117
expose ConsumeMultisignatureVerificationGas
sunnya97 Dec 23, 2019
f417acf
improve code cov
sunnya97 Dec 24, 2019
b164ca0
CHANGELOG
sunnya97 Dec 24, 2019
1a8ffb2
CHANGELOG updates
sunnya97 Dec 24, 2019
b130d52
tests fix
sunnya97 Dec 25, 2019
7fd09ca
constant
sunnya97 Dec 25, 2019
c3c30e8
Merge branch 'master' into keybase_multi_algo
sunnya97 Dec 27, 2019
a3d1c97
fixed lint issue
sunnya97 Dec 29, 2019
08059ce
address some comments review
sunnya97 Jan 3, 2020
6e50c29
Merge branch 'master' into keybase_multi_algo
sunnya97 Jan 6, 2020
8faaca3
Update crypto/keys/keybase_base.go
fedekunze Jan 6, 2020
6777c23
added err check
sunnya97 Jan 7, 2020
906a5ee
added return type info to godoc of UnarmorDecryptPrivKey
sunnya97 Jan 7, 2020
318c145
Merge branch 'master' into keybase_multi_algo
sunnya97 Jan 9, 2020
959575a
Cleanup changelog
alexanderbez Jan 9, 2020
2c3aa4e
address @alexanderbez comments
sunnya97 Jan 11, 2020
e10933a
added constants for header keys
sunnya97 Jan 13, 2020
59874b4
added errors
sunnya97 Jan 13, 2020
930c3be
Merge branch 'master' into keybase_multi_algo
alexanderbez Jan 13, 2020
fe70610
Merge branch 'master' into keybase_multi_algo
fedekunze Jan 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,16 @@ if the provided arguments are invalid.
* (modules) [\#5299](https://github.com/cosmos/cosmos-sdk/pull/5299) `HandleDoubleSign` along with params `MaxEvidenceAge`
and `DoubleSignJailEndTime` have moved from the `x/slashing` module to the `x/evidence` module.
* (keys) [\#4941](https://github.com/cosmos/cosmos-sdk/issues/4941) Initializing a new keybase through `NewKeyringFromHomeFlag`, `NewKeyringFromDir`, `NewKeyBaseFromHomeFlag`, `NewKeyBaseFromDir`, or `NewInMemory` functions now accept optional parameters of type `KeybaseOption`. These optional parameters are also added on the keys subcommands functions, which are now public, and allows these options to be set on the commands or ignored to default to previous behavior.
* The option introduced in this PR is `WithKeygenFunc` which allows a custom bytes to key implementation to be defined when keys are created.
* [\#5439](https://github.com/cosmos/cosmos-sdk/pull/5439) Further modularization was done to the `keybase`
package to make it more suitable for use with different key formats and algorithms:
* The `WithKeygenFunc` function added as a `KeybaseOption` which allows a custom bytes to key
implementation to be defined when keys are created.
* The `WithDeriveFunc` function added as a `KeybaseOption` allows custom logic for deriving a key
from a mnemonic, bip39 password, and HD Path.
* BIP44 is no longer build into `keybase.CreateAccount()`. It is however the default when using
the `client/keys` add command.
* `SupportedAlgos` and `SupportedAlgosLedger` functions return a slice of `SigningAlgo`s that are
supported by the keybase and the ledger integration respectively.
* (simapp) [\#5419](https://github.com/cosmos/cosmos-sdk/pull/5419) simapp/helpers.GenTx() now accepts a gas argument.
* (baseapp) [\#5455](https://github.com/cosmos/cosmos-sdk/issues/5455) An `sdk.Context` is passed into the `router.Route()`
function.
Expand Down Expand Up @@ -177,10 +186,13 @@ that allows for arbitrary vesting periods.
* `IncrementSequenceDecorator`: Increments the account sequence for each signer to prevent replay attacks.
* (cli) [\#5223](https://github.com/cosmos/cosmos-sdk/issues/5223) Cosmos Ledger App v2.0.0 is now supported. The changes are backwards compatible and App v1.5.x is still supported.
* (x/staking) [\#5380](https://github.com/cosmos/cosmos-sdk/pull/5380) Introduced ability to store historical info entries in staking keeper, allows applications to introspect specified number of past headers and validator sets
* Introduces new parameter `HistoricalEntries` which allows applications to determine how many recent historical info entries they want to persist in store. Default value is 0.
* Introduces cli commands and rest routes to query historical information at a given height
* Introduces new parameter `HistoricalEntries` which allows applications to determine how many recent historical info entries they want to persist in store. Default value is 0.
* Introduces cli commands and rest routes to query historical information at a given height
* (modules) [\#5249](https://github.com/cosmos/cosmos-sdk/pull/5249) Funds are now allowed to be directly sent to the community pool (via the distribution module account).
* (keys) [\#4941](https://github.com/cosmos/cosmos-sdk/issues/4941) Introduce keybase option to allow overriding the default private key implementation of a key generated through the `keys add` cli command.
* (keys) [\#5439](https://github.com/cosmos/cosmos-sdk/pull/5439) Flags `--algo` and `--hd-path` are added to
`keys add` command in order to make use of keybase modularized. By default, it uses (0, 0) bip44
HD path and secp256k1 keys, so is non-breaking.
* (types) [\#5447](https://github.com/cosmos/cosmos-sdk/pull/5447) Added `ApproxRoot` function to sdk.Decimal type in order to get the nth root for a decimal number, where n is a positive integer.
* An `ApproxSqrt` function was also added for convenience around the common case of n=2.

Expand Down
34 changes: 32 additions & 2 deletions client/keys/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ const (
flagIndex = "index"
flagMultisig = "multisig"
flagNoSort = "nosort"
flagHDPath = "hd-path"
flagKeyAlgo = "algo"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
flagKeyAlgo = "algo"
flagKeyAlgorithm = "algorithm"


// DefaultKeyPass contains the default key password for genesis transactions
DefaultKeyPass = "12345678"
Expand Down Expand Up @@ -71,9 +73,11 @@ the flag --nosort is set.
cmd.Flags().Bool(flagRecover, false, "Provide seed phrase to recover existing key instead of creating")
cmd.Flags().Bool(flagNoBackup, false, "Don't print out seed phrase (if others are watching the terminal)")
cmd.Flags().Bool(flagDryRun, false, "Perform action, but don't add key to local keystore")
cmd.Flags().String(flagHDPath, "", "Manual HD Path derivation (overrides BIP44 config)")
cmd.Flags().Uint32(flagAccount, 0, "Account number for HD derivation")
cmd.Flags().Uint32(flagIndex, 0, "Address index number for HD derivation")
cmd.Flags().Bool(flags.FlagIndentResponse, false, "Add indent to JSON response")
cmd.Flags().String(flagKeyAlgo, string(keys.Secp256k1), "Key signing algorithm to generate keys for")
return cmd
}

Expand Down Expand Up @@ -112,6 +116,14 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keys.Keybase, inBuf *bufio.
interactive := viper.GetBool(flagInteractive)
showMnemonic := !viper.GetBool(flagNoBackup)

algo := keys.SigningAlgo(viper.GetString(flagKeyAlgo))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Secp256k1 is already the default. Why manually do this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting Secp256k1 as the default wasn't working for me, something weird with cobra.

if algo == keys.SigningAlgo("") {
algo = keys.Secp256k1
}
if !keys.IsSupportedAlgorithm(kb.SupportedAlgos(), algo) {
return keys.ErrUnsupportedSigningAlgo
}

if !viper.GetBool(flagDryRun) {
_, err = kb.Get(name)
if err == nil {
Expand Down Expand Up @@ -164,7 +176,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keys.Keybase, inBuf *bufio.
if err != nil {
return err
}
_, err = kb.CreateOffline(name, pk)
_, err = kb.CreateOffline(name, pk, algo)
if err != nil {
return err
}
Expand All @@ -174,8 +186,26 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keys.Keybase, inBuf *bufio.
account := uint32(viper.GetInt(flagAccount))
index := uint32(viper.GetInt(flagIndex))

useBIP44 := !viper.IsSet(flagHDPath)
var hdPath string

if useBIP44 {
hdPath = keys.CreateHDPath(account, index).String()
} else {
hdPath = viper.GetString(flagHDPath)
}

// If we're using ledger, only thing we need is the path and the bech32 prefix.
if viper.GetBool(flags.FlagUseLedger) {

if !useBIP44 {
return errors.New("cannot set custom bip32 path with ledger")
}

if !keys.IsSupportedAlgorithm(kb.SupportedAlgosLedger(), algo) {
return keys.ErrUnsupportedSigningAlgo
}

bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix()
info, err := kb.CreateLedger(name, keys.Secp256k1, bech32PrefixAccAddr, account, index)
if err != nil {
Expand Down Expand Up @@ -240,7 +270,7 @@ func RunAddCmd(cmd *cobra.Command, args []string, kb keys.Keybase, inBuf *bufio.
}
}

info, err := kb.CreateAccount(name, mnemonic, bip39Passphrase, DefaultKeyPass, account, index)
info, err := kb.CreateAccount(name, mnemonic, bip39Passphrase, DefaultKeyPass, hdPath, algo)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions client/keys/delete_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/tests"
)

Expand Down Expand Up @@ -44,13 +45,13 @@ func Test_runDeleteCmd(t *testing.T) {
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", "0", keys.Secp256k1)
require.NoError(t, err)

if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", "1", keys.Secp256k1)
require.NoError(t, err)

if runningUnattended {
Expand Down
3 changes: 2 additions & 1 deletion client/keys/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/tests"
)

Expand All @@ -32,7 +33,7 @@ func Test_runExportCmd(t *testing.T) {
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount("keyname1", tests.TestMnemonic, "", "123456789", 0, 0)
_, err = kb.CreateAccount("keyname1", tests.TestMnemonic, "", "123456789", "", keys.Secp256k1)
require.NoError(t, err)

// Now enter password
Expand Down
3 changes: 2 additions & 1 deletion client/keys/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/tests"
)

Expand Down Expand Up @@ -36,7 +37,7 @@ func Test_runListCmd(t *testing.T) {
mockIn.Reset("testpass1\ntestpass1\n")
}

_, err = kb.CreateAccount("something", tests.TestMnemonic, "", "", 0, 0)
_, err = kb.CreateAccount("something", tests.TestMnemonic, "", "", "", keys.Secp256k1)
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, err)

defer func() {
Expand Down
4 changes: 2 additions & 2 deletions client/keys/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ func Test_runShowCmd(t *testing.T) {
if runningUnattended {
mockIn.Reset("testpass1\ntestpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", "0", keys.Secp256k1)
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, err)

if runningUnattended {
mockIn.Reset("testpass1\n")
}
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", "1", keys.Secp256k1)
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, err)

// Now try single key
Expand Down
5 changes: 3 additions & 2 deletions client/keys/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"

"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/crypto/keys"
"github.com/cosmos/cosmos-sdk/tests"
)

Expand Down Expand Up @@ -38,9 +39,9 @@ func Test_runUpdateCmd(t *testing.T) {

kb, err := NewKeyBaseFromHomeFlag()
assert.NoError(t, err)
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", 0, 0)
_, err = kb.CreateAccount(fakeKeyName1, tests.TestMnemonic, "", "", "0", keys.Secp256k1)
assert.NoError(t, err)
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", 0, 1)
_, err = kb.CreateAccount(fakeKeyName2, tests.TestMnemonic, "", "", "1", keys.Secp256k1)
assert.NoError(t, err)

// Try again now that we have keys
Expand Down
62 changes: 34 additions & 28 deletions crypto/keys/keybase.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
cryptoAmino "github.com/tendermint/tendermint/crypto/encoding/amino"
dbm "github.com/tendermint/tm-db"

"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
"github.com/cosmos/cosmos-sdk/crypto/keys/keyerror"
"github.com/cosmos/cosmos-sdk/crypto/keys/mintkey"
"github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -57,7 +56,7 @@ const (
var (
// ErrUnsupportedSigningAlgo is raised when the caller tries to use a
// different signing scheme than secp256k1.
ErrUnsupportedSigningAlgo = errors.New("unsupported signing algo: only secp256k1 is supported")
ErrUnsupportedSigningAlgo = errors.New("unsupported signing algo")

// ErrUnsupportedLanguage is raised when the caller tries to use a
// different language than english for creating a mnemonic sentence.
Expand Down Expand Up @@ -101,18 +100,10 @@ func (kb dbKeybase) CreateMnemonic(
// CreateAccount converts a mnemonic to a private key and persists it, encrypted
// with the given password.
func (kb dbKeybase) CreateAccount(
name, mnemonic, bip39Passwd, encryptPasswd string, account uint32, index uint32,
name, mnemonic, bip39Passwd, encryptPasswd, hdPath string, algo SigningAlgo,
) (Info, error) {

return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, account, index)
}

// Derive computes a BIP39 seed from th mnemonic and bip39Passwd.
func (kb dbKeybase) Derive(
name, mnemonic, bip39Passphrase, encryptPasswd string, params hd.BIP44Params,
) (Info, error) {

return kb.base.Derive(kb, name, mnemonic, bip39Passphrase, encryptPasswd, params)
return kb.base.CreateAccount(kb, name, mnemonic, bip39Passwd, encryptPasswd, hdPath, algo)
}

// CreateLedger creates a new locally-stored reference to a Ledger keypair.
Expand All @@ -126,8 +117,8 @@ func (kb dbKeybase) CreateLedger(

// CreateOffline creates a new reference to an offline keypair. It returns the
// created key info.
func (kb dbKeybase) CreateOffline(name string, pub tmcrypto.PubKey) (Info, error) {
return kb.base.writeOfflineKey(kb, name, pub), nil
func (kb dbKeybase) CreateOffline(name string, pub tmcrypto.PubKey, algo SigningAlgo) (Info, error) {
return kb.base.writeOfflineKey(kb, name, pub, algo), nil
}

// CreateMulti creates a new reference to a multisig (offline) keypair. It
Expand Down Expand Up @@ -199,7 +190,7 @@ func (kb dbKeybase) Sign(name, passphrase string, msg []byte) (sig []byte, pub t
return
}

priv, err = mintkey.UnarmorDecryptPrivKey(i.PrivKeyArmor, passphrase)
priv, _, err = mintkey.UnarmorDecryptPrivKey(i.PrivKeyArmor, passphrase)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -238,7 +229,7 @@ func (kb dbKeybase) ExportPrivateKeyObject(name string, passphrase string) (tmcr
return nil, err
}

priv, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase)
priv, _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -272,7 +263,7 @@ func (kb dbKeybase) ExportPubKey(name string) (armor string, err error) {
return
}

return mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes()), nil
return mintkey.ArmorPubKeyBytes(info.GetPubKey().Bytes(), string(info.GetAlgo())), nil
}

// ExportPrivKey returns a private key in ASCII armored format.
Expand All @@ -285,7 +276,12 @@ func (kb dbKeybase) ExportPrivKey(name string, decryptPassphrase string,
return "", err
}

return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase), nil
info, err := kb.Get(name)
if err != nil {
return "", err
}

return mintkey.EncryptArmorPrivKey(priv, encryptPassphrase, string(info.GetAlgo())), nil
}

// ImportPrivKey imports a private key in ASCII armor format. It returns an
Expand All @@ -296,12 +292,12 @@ func (kb dbKeybase) ImportPrivKey(name string, armor string, passphrase string)
return errors.New("Cannot overwrite key " + name)
}

privKey, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase)
privKey, algo, err := mintkey.UnarmorDecryptPrivKey(armor, passphrase)
if err != nil {
return errors.Wrap(err, "couldn't import private key")
}

kb.writeLocalKey(name, privKey, passphrase)
kb.writeLocalKey(name, privKey, passphrase, SigningAlgo(algo))
return nil
}

Expand Down Expand Up @@ -329,7 +325,7 @@ func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) {
return errors.New("Cannot overwrite data for name " + name)
}

pubBytes, err := mintkey.UnarmorPubKeyBytes(armor)
pubBytes, algo, err := mintkey.UnarmorPubKeyBytes(armor)
if err != nil {
return
}
Expand All @@ -339,7 +335,7 @@ func (kb dbKeybase) ImportPubKey(name string, armor string) (err error) {
return
}

kb.base.writeOfflineKey(kb, name, pubKey)
kb.base.writeOfflineKey(kb, name, pubKey, SigningAlgo(algo))
return
}

Expand All @@ -355,7 +351,7 @@ func (kb dbKeybase) Delete(name, passphrase string, skipPass bool) error {
}

if linfo, ok := info.(localInfo); ok && !skipPass {
if _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase); err != nil {
if _, _, err = mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, passphrase); err != nil {
return err
}
}
Expand All @@ -382,7 +378,7 @@ func (kb dbKeybase) Update(name, oldpass string, getNewpass func() (string, erro
case localInfo:
linfo := i

key, err := mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass)
key, _, err := mintkey.UnarmorDecryptPrivKey(linfo.PrivKeyArmor, oldpass)
if err != nil {
return err
}
Expand All @@ -392,7 +388,7 @@ func (kb dbKeybase) Update(name, oldpass string, getNewpass func() (string, erro
return err
}

kb.writeLocalKey(name, key, newpass)
kb.writeLocalKey(name, key, newpass, i.GetAlgo())
return nil

default:
Expand All @@ -405,13 +401,23 @@ func (kb dbKeybase) CloseDB() {
kb.db.Close()
}

func (kb dbKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string) Info {
// SupportedAlgos returns a list of supported signing algorithms.
func (kb dbKeybase) SupportedAlgos() []SigningAlgo {
sunnya97 marked this conversation as resolved.
Show resolved Hide resolved
return kb.base.SupportedAlgos()
}

// SupportedAlgosLedger returns a list of supported ledger signing algorithms.
func (kb dbKeybase) SupportedAlgosLedger() []SigningAlgo {
return kb.base.SupportedAlgosLedger()
}

func (kb dbKeybase) writeLocalKey(name string, priv tmcrypto.PrivKey, passphrase string, algo SigningAlgo) Info {
// encrypt private key using passphrase
privArmor := mintkey.EncryptArmorPrivKey(priv, passphrase)
privArmor := mintkey.EncryptArmorPrivKey(priv, passphrase, string(algo))

// make Info
pub := priv.PubKey()
info := newLocalInfo(name, pub, privArmor)
info := newLocalInfo(name, pub, privArmor, algo)

kb.writeInfo(name, info)
return info
Expand Down
Loading