Skip to content

Commit

Permalink
Problem: no exposed db keyring used in the keystore
Browse files Browse the repository at this point in the history
simpily new keyring
  • Loading branch information
mmsqe committed May 2, 2024
1 parent 662c643 commit 3209689
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 165 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* (versiondb) [#1387](https://github.com/crypto-org-chain/cronos/pull/1387) Add dedicated config section for versiondb, prepare for sdk 0.50 integration.
* (e2ee)[#1413](https://github.com/crypto-org-chain/cronos/pull/1413) Add custom keyring implementation for e2ee module.
* (e2ee)[#1415](https://github.com/crypto-org-chain/cronos/pull/1415) Add batch keys query for e2ee module.
* (e2ee)[#](https://github.com/crypto-org-chain/cronos/pull/) Simpily new keyring for e2ee module.

### Bug Fixes

Expand Down
5 changes: 2 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ require (
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
github.com/test-go/testify v1.1.4
golang.org/x/crypto v0.21.0
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de
google.golang.org/grpc v1.63.2
google.golang.org/protobuf v1.33.0
Expand Down Expand Up @@ -228,6 +226,7 @@ require (
go.opentelemetry.io/otel/metric v1.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
golang.org/x/mod v0.15.0 // indirect
golang.org/x/net v0.23.0 // indirect
Expand Down Expand Up @@ -256,7 +255,7 @@ replace (
cosmossdk.io/client/v2 => github.com/crypto-org-chain/cosmos-sdk/client/v2 v2.0.0-20240415105151-0108877a3201
cosmossdk.io/store => github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20240415105151-0108877a3201
cosmossdk.io/x/tx => github.com/crypto-org-chain/cosmos-sdk/x/tx v0.0.0-20240415105151-0108877a3201
github.com/cosmos/cosmos-sdk => github.com/crypto-org-chain/cosmos-sdk v0.0.0-20240415105151-0108877a3201
github.com/cosmos/cosmos-sdk => github.com/mmsqe/cosmos-sdk v0.0.0-20240502014533-3bccb68a77be
)

replace (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,6 @@ github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c h1:MOgfS4+F
github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/crypto-org-chain/cometbft-db v0.0.0-20231011055109-57922ac52a63 h1:R1QJ9a3XdYMSKo+1RdFifxb/g3lNypC52L/rpYrWoKo=
github.com/crypto-org-chain/cometbft-db v0.0.0-20231011055109-57922ac52a63/go.mod h1:rocwIfnS+kA060x64gkSIRvWB9StSppIkJuo5MWzL24=
github.com/crypto-org-chain/cosmos-sdk v0.0.0-20240415105151-0108877a3201 h1:3R54xSBI4geLX3H5Ljk0FSVDMPRpywq5L5K//aHwo8s=
github.com/crypto-org-chain/cosmos-sdk v0.0.0-20240415105151-0108877a3201/go.mod h1:DkCxCPi3veciROiq36PbpXDhboMjqHAS0Xyv2dEEW04=
github.com/crypto-org-chain/cosmos-sdk/client/v2 v2.0.0-20240415105151-0108877a3201 h1:O1qN/jmh/BZK6JiEADgwDK7jwSQNKqvs5qVYjo0UFa4=
github.com/crypto-org-chain/cosmos-sdk/client/v2 v2.0.0-20240415105151-0108877a3201/go.mod h1:GjpaaxatOEnkSlNKjYxSbzVVtHHAG0tWm26AoPA1g9Q=
github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20240415105151-0108877a3201 h1:0T8U5tgQLfD8k8kxisez5ks9s7yxU2JSRhi5MUQ0Cp0=
Expand Down Expand Up @@ -901,6 +899,8 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/mmsqe/cosmos-sdk v0.0.0-20240502014533-3bccb68a77be h1:hg5bYubHlIAb/F+9TUG8iYsquy6ZnS3FuWxQl9faWGs=
github.com/mmsqe/cosmos-sdk v0.0.0-20240502014533-3bccb68a77be/go.mod h1:DkCxCPi3veciROiq36PbpXDhboMjqHAS0Xyv2dEEW04=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
Expand Down
9 changes: 3 additions & 6 deletions gomod2nix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,9 @@ schema = 3
version = "v1.0.0-beta.4"
hash = "sha256-5Kn82nsZfiEtuwhhLZqmMxdAY1tX/Fi3HJ0/MEaRohw="
[mod."github.com/cosmos/cosmos-sdk"]
version = "v0.0.0-20240415105151-0108877a3201"
hash = "sha256-qgfVUWIH2nX4l339+e1SVQ1iVQkv8Ew4Aj6zcHH2tPg="
replaced = "github.com/crypto-org-chain/cosmos-sdk"
version = "v0.0.0-20240502014533-3bccb68a77be"
hash = "sha256-Mdw7biEUIzKFD6WQr607ZOoklWJkvR/ZLBN3jexhppA="
replaced = "github.com/mmsqe/cosmos-sdk"
[mod."github.com/cosmos/go-bip39"]
version = "v1.0.0"
hash = "sha256-Qm2aC2vaS8tjtMUbHmlBSagOSqbduEEDwc51qvQaBmA="
Expand Down Expand Up @@ -578,9 +578,6 @@ schema = 3
[mod."github.com/tendermint/go-amino"]
version = "v0.16.0"
hash = "sha256-JW4zO/0vMzf1dXLePOqaMtiLUZgNbuIseh9GV+jQlf0="
[mod."github.com/test-go/testify"]
version = "v1.1.4"
hash = "sha256-8xygO1Rd4eTrmRe/g7zaifpNkeb6EmjNfUvTWbjDtPg="
[mod."github.com/tidwall/btree"]
version = "v0.0.0-20240406140148-2687063b042c"
hash = "sha256-8eDLGHhw4qXG6MEa7w5Q9KLwOobXr8Vn5qqyQhuipQw="
Expand Down
158 changes: 9 additions & 149 deletions x/e2ee/keyring/keyring.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
package keyring

import (
"bufio"
"fmt"
"io"
"os"
"path/filepath"

"github.com/99designs/keyring"
"golang.org/x/crypto/bcrypt"

errorsmod "cosmossdk.io/errors"
"github.com/cosmos/cosmos-sdk/client/input"
sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
)

const (
keyringFileDirName = "e2ee-keyring-file"
keyringTestDirName = "e2ee-keyring-test"
passKeyringPrefix = "e2ee-keyring-%s" //nolint: gosec
maxPassphraseEntryAttempts = 3
)

type Keyring interface {
Get(string) ([]byte, error)
Set(string, []byte) error
Expand All @@ -30,60 +16,17 @@ type Keyring interface {
func New(
appName, backend, rootDir string, userInput io.Reader,
) (Keyring, error) {
var (
db keyring.Keyring
err error
)
serviceName := appName + "-e2ee"
switch backend {
case sdkkeyring.BackendMemory:
return newKeystore(keyring.NewArrayKeyring(nil), sdkkeyring.BackendMemory), nil
case sdkkeyring.BackendTest:
db, err = keyring.Open(keyring.Config{
AllowedBackends: []keyring.BackendType{keyring.FileBackend},
ServiceName: serviceName,
FileDir: filepath.Join(rootDir, keyringTestDirName),
FilePasswordFunc: func(_ string) (string, error) {
return "test", nil
},
})
case sdkkeyring.BackendFile:
fileDir := filepath.Join(rootDir, keyringFileDirName)
db, err = keyring.Open(keyring.Config{
AllowedBackends: []keyring.BackendType{keyring.FileBackend},
ServiceName: serviceName,
FileDir: fileDir,
FilePasswordFunc: newRealPrompt(fileDir, userInput),
})
case sdkkeyring.BackendOS:
db, err = keyring.Open(keyring.Config{
ServiceName: serviceName,
FileDir: rootDir,
KeychainTrustApplication: true,
FilePasswordFunc: newRealPrompt(rootDir, userInput),
})
case sdkkeyring.BackendKWallet:
db, err = keyring.Open(keyring.Config{
AllowedBackends: []keyring.BackendType{keyring.KWalletBackend},
ServiceName: "kdewallet",
KWalletAppID: serviceName,
KWalletFolder: "",
})
case sdkkeyring.BackendPass:
prefix := fmt.Sprintf(passKeyringPrefix, serviceName)
db, err = keyring.Open(keyring.Config{
AllowedBackends: []keyring.BackendType{keyring.PassBackend},
ServiceName: serviceName,
PassPrefix: prefix,
})
default:
return nil, errorsmod.Wrap(sdkkeyring.ErrUnknownBacked, backend)
}

if err != nil {
return nil, err
var db keyring.Keyring
if backend == sdkkeyring.BackendMemory {
db = keyring.NewArrayKeyring(nil)

Check warning on line 22 in x/e2ee/keyring/keyring.go

View check run for this annotation

Codecov / codecov/patch

x/e2ee/keyring/keyring.go#L22

Added line #L22 was not covered by tests
} else {
kr, err := sdkkeyring.New(serviceName, backend, rootDir, userInput, nil)
if err != nil {
return nil, err

Check warning on line 26 in x/e2ee/keyring/keyring.go

View check run for this annotation

Codecov / codecov/patch

x/e2ee/keyring/keyring.go#L26

Added line #L26 was not covered by tests
}
db = kr.DB()
}

return newKeystore(db, backend), nil
}

Expand Down Expand Up @@ -117,86 +60,3 @@ func (ks keystore) Set(name string, secret []byte) error {
Label: name,
})
}

func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) {
return func(prompt string) (string, error) {
keyhashStored := false
keyhashFilePath := filepath.Join(dir, "keyhash")

var keyhash []byte

_, err := os.Stat(keyhashFilePath)

switch {
case err == nil:
keyhash, err = os.ReadFile(keyhashFilePath)
if err != nil {
return "", errorsmod.Wrap(err, fmt.Sprintf("failed to read %s", keyhashFilePath))
}

keyhashStored = true

case os.IsNotExist(err):
keyhashStored = false

default:
return "", errorsmod.Wrap(err, fmt.Sprintf("failed to open %s", keyhashFilePath))
}

failureCounter := 0

for {
failureCounter++
if failureCounter > maxPassphraseEntryAttempts {
return "", sdkkeyring.ErrMaxPassPhraseAttempts
}

buf := bufio.NewReader(buf)
pass, err := input.GetPassword(fmt.Sprintf("Enter keyring passphrase (attempt %d/%d):", failureCounter, maxPassphraseEntryAttempts), buf)
if err != nil {
// NOTE: LGTM.io reports a false positive alert that states we are printing the password,
// but we only log the error.
//
// lgtm [go/clear-text-logging]
fmt.Fprintln(os.Stderr, err)
continue
}

if keyhashStored {
if err := bcrypt.CompareHashAndPassword(keyhash, []byte(pass)); err != nil {
fmt.Fprintln(os.Stderr, "incorrect passphrase")
continue
}

return pass, nil
}

reEnteredPass, err := input.GetPassword("Re-enter keyring passphrase:", buf)
if err != nil {
// NOTE: LGTM.io reports a false positive alert that states we are printing the password,
// but we only log the error.
//
// lgtm [go/clear-text-logging]
fmt.Fprintln(os.Stderr, err)
continue
}

if pass != reEnteredPass {
fmt.Fprintln(os.Stderr, "passphrase do not match")
continue
}

passwordHash, err := bcrypt.GenerateFromPassword([]byte(pass), 2)
if err != nil {
fmt.Fprintln(os.Stderr, err)
continue
}

if err := os.WriteFile(keyhashFilePath, passwordHash, 0o600); err != nil {
return "", err
}

return pass, nil
}
}
}
10 changes: 5 additions & 5 deletions x/e2ee/keyring/keyring_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package keyring
package keyring_test

import (
"bytes"
"io"
"testing"

"filippo.io/age"
"github.com/test-go/testify/require"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/crypto-org-chain/cronos/v2/x/e2ee/keyring"
"github.com/stretchr/testify/require"
)

func TestKeyring(t *testing.T) {
kr, err := New("cronosd", keyring.BackendTest, t.TempDir(), nil)
kr, err := keyring.New("cronosd", sdkkeyring.BackendTest, t.TempDir(), nil)
require.NoError(t, err)

identity, err := age.GenerateX25519Identity()
Expand Down

0 comments on commit 3209689

Please sign in to comment.