Skip to content

Commit ba440ab

Browse files
authored
Store Hashed Password to Wallet Path (#7295)
* store wallet pass on creation * store wallet hash * save hash to wallet dir * initialize wallet hash * gaz * imports spacing * remove mentions of hashed pass from db schema * simplify the wallet hash code * comment removal * Merge branch 'master' into fix-password-override * pass tests * test fix * Merge branch 'fix-password-override' of github.com:prysmaticlabs/prysm into fix-password-override * remove extraneous printfs * tests passing * require auth for create wallet * gaz * fix signup logic * Merge refs/heads/master into fix-password-override * Merge refs/heads/master into fix-password-override * Merge refs/heads/master into fix-password-override * Merge refs/heads/master into fix-password-override * Merge branch 'master' into fix-password-override
1 parent 09640ae commit ba440ab

22 files changed

+162
-135
lines changed

validator/accounts/v2/accounts_create_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (p *passwordReader) passwordReaderFunc(file *os.File) ([]byte, error) {
8080
func Test_KeysConsistency_Direct(t *testing.T) {
8181
walletDir, passwordsDir, walletPasswordFile := setupWalletAndPasswordsDir(t)
8282

83-
//Specify the 'initial'/correct password locally to this file for convenience.
83+
// Specify the 'initial'/correct password locally to this file for convenience.
8484
require.NoError(t, ioutil.WriteFile(walletPasswordFile, []byte("Pa$sW0rD0__Fo0xPr"), os.ModePerm))
8585

8686
cliCtx := setupWalletCtx(t, &testWalletConfig{
@@ -106,7 +106,10 @@ func Test_KeysConsistency_Direct(t *testing.T) {
106106

107107
// Now we change the password to "SecoNDxyzPass__9!@#"
108108
require.NoError(t, ioutil.WriteFile(walletPasswordFile, []byte("SecoNDxyzPass__9!@#"), os.ModePerm))
109-
// OpenWalletOrElseCli() doesn't really 'challenge' the wrong password
109+
w, err = wallet.OpenWalletOrElseCli(cliCtx, CreateAndSaveWalletCli)
110+
require.ErrorContains(t, "wrong password for wallet", err)
111+
112+
require.NoError(t, ioutil.WriteFile(walletPasswordFile, []byte("Pa$sW0rD0__Fo0xPr"), os.ModePerm))
110113
w, err = wallet.OpenWalletOrElseCli(cliCtx, CreateAndSaveWalletCli)
111114
require.NoError(t, err)
112115

validator/accounts/v2/accounts_exit_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,5 @@ func TestPrepareWallet_EmptyWalletReturnsError(t *testing.T) {
125125
})
126126
require.NoError(t, err)
127127
_, _, err = prepareWallet(cliCtx)
128-
assert.ErrorContains(t, "wallet is empty, no accounts to perform voluntary exit", err)
128+
assert.ErrorContains(t, "please recreate your wallet", err)
129129
}

validator/accounts/v2/accounts_import.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ func ImportAccountsCli(cliCtx *cli.Context) error {
9090
if err = createDirectKeymanagerWallet(cliCtx.Context, w); err != nil {
9191
return nil, errors.Wrap(err, "could not create keymanager")
9292
}
93+
// We store the hashed password to disk.
94+
if err := w.SaveHashedPassword(cliCtx.Context); err != nil {
95+
return nil, err
96+
}
9397
log.WithField("wallet-path", cfg.WalletCfg.WalletDir).Info(
9498
"Successfully created new wallet",
9599
)

validator/accounts/v2/wallet/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ go_library(
2121
"@com_github_pkg_errors//:go_default_library",
2222
"@com_github_sirupsen_logrus//:go_default_library",
2323
"@com_github_urfave_cli_v2//:go_default_library",
24+
"@org_golang_x_crypto//bcrypt:go_default_library",
2425
],
2526
)
2627

validator/accounts/v2/wallet/wallet.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ import (
2323
"github.com/prysmaticlabs/prysm/validator/keymanager/v2/remote"
2424
"github.com/sirupsen/logrus"
2525
"github.com/urfave/cli/v2"
26+
"golang.org/x/crypto/bcrypt"
2627
)
2728

2829
var log = logrus.WithField("prefix", "wallet")
2930

3031
const (
3132
// KeymanagerConfigFileName for the keymanager used by the wallet: direct, derived, or remote.
3233
KeymanagerConfigFileName = "keymanageropts.json"
34+
// HashedPasswordFileName for the wallet.
35+
HashedPasswordFileName = "hash"
3336
// DirectoryPermissions for directories created under the wallet path.
3437
DirectoryPermissions = os.ModePerm
3538
// NewWalletPasswordPromptText for wallet creation.
@@ -38,6 +41,7 @@ const (
3841
WalletPasswordPromptText = "Wallet password"
3942
// ConfirmPasswordPromptText for confirming a wallet password.
4043
ConfirmPasswordPromptText = "Confirm password"
44+
hashCost = 8
4145
)
4246

4347
var (
@@ -136,6 +140,16 @@ func OpenWalletOrElseCli(cliCtx *cli.Context, otherwise func(cliCtx *cli.Context
136140
false, /* Do not confirm password */
137141
ValidateExistingPass,
138142
)
143+
if fileutil.FileExists(filepath.Join(walletDir, HashedPasswordFileName)) {
144+
hashedPassword, err := fileutil.ReadFileAsBytes(filepath.Join(walletDir, HashedPasswordFileName))
145+
if err != nil {
146+
return nil, err
147+
}
148+
// Compare the wallet password here.
149+
if err := bcrypt.CompareHashAndPassword(hashedPassword, []byte(walletPassword)); err != nil {
150+
return nil, errors.Wrap(err, "wrong password for wallet")
151+
}
152+
}
139153
return OpenWallet(cliCtx.Context, &Config{
140154
WalletDir: walletDir,
141155
WalletPassword: walletPassword,
@@ -217,6 +231,18 @@ func (w *Wallet) InitializeKeymanager(
217231
if err != nil {
218232
return nil, errors.Wrap(err, "could not initialize direct keymanager")
219233
}
234+
if !fileutil.FileExists(filepath.Join(w.walletDir, HashedPasswordFileName)) {
235+
keys, err := keymanager.FetchValidatingPublicKeys(ctx)
236+
if err != nil {
237+
return nil, err
238+
}
239+
if keys == nil || len(keys) == 0 {
240+
return nil, errors.New("please recreate your wallet with wallet-v2 create")
241+
}
242+
if err := w.SaveHashedPassword(ctx); err != nil {
243+
return nil, errors.Wrap(err, "could not save hashed password to disk")
244+
}
245+
}
220246
case v2keymanager.Derived:
221247
opts, err := derived.UnmarshalOptionsFile(configFile)
222248
if err != nil {
@@ -230,6 +256,11 @@ func (w *Wallet) InitializeKeymanager(
230256
if err != nil {
231257
return nil, errors.Wrap(err, "could not initialize derived keymanager")
232258
}
259+
if !fileutil.FileExists(filepath.Join(w.walletDir, HashedPasswordFileName)) {
260+
if err := w.SaveHashedPassword(ctx); err != nil {
261+
return nil, errors.Wrap(err, "could not save hashed password to disk")
262+
}
263+
}
233264
case v2keymanager.Remote:
234265
opts, err := remote.UnmarshalOptionsFile(configFile)
235266
if err != nil {
@@ -375,6 +406,20 @@ func (w *Wallet) WriteEncryptedSeedToDisk(ctx context.Context, encoded []byte) e
375406
return nil
376407
}
377408

409+
// SaveHashedPassword to disk for the wallet.
410+
func (w *Wallet) SaveHashedPassword(ctx context.Context) error {
411+
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(w.walletPassword), hashCost)
412+
if err != nil {
413+
return errors.Wrap(err, "could not generate hashed password")
414+
}
415+
hashFilePath := filepath.Join(w.walletDir, HashedPasswordFileName)
416+
// Write the config file to disk.
417+
if err := ioutil.WriteFile(hashFilePath, hashedPassword, params.BeaconIoConfig().ReadWritePermissions); err != nil {
418+
return errors.Wrap(err, "could not write hashed password for wallet to disk")
419+
}
420+
return nil
421+
}
422+
378423
func readKeymanagerKindFromWalletPath(walletPath string) (v2keymanager.Kind, error) {
379424
walletItem, err := os.Open(walletPath)
380425
if err != nil {

validator/accounts/v2/wallet_create.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,15 @@ func CreateAndSaveWalletCli(cliCtx *cli.Context) (*wallet.Wallet, error) {
5151
return nil, errors.New("a wallet of this type already exists at this location. Please input an" +
5252
" alternative location for the new wallet or remove the current wallet")
5353
}
54-
return CreateWalletWithKeymanager(cliCtx.Context, createWalletConfig)
54+
w, err := CreateWalletWithKeymanager(cliCtx.Context, createWalletConfig)
55+
if err != nil {
56+
return nil, errors.Wrap(err, "could not create wallet with keymanager")
57+
}
58+
// We store the hashed password to disk.
59+
if err := w.SaveHashedPassword(cliCtx.Context); err != nil {
60+
return nil, errors.Wrap(err, "could not save hashed password to database")
61+
}
62+
return w, nil
5563
}
5664

5765
// CreateWalletWithKeymanager specified by configuration options.

validator/accounts/v2/wallet_recover.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,17 @@ func RecoverWalletCli(cliCtx *cli.Context) error {
6262
if err != nil {
6363
return errors.Wrap(err, "could not get number of accounts to recover")
6464
}
65-
if _, err := RecoverWallet(cliCtx.Context, &RecoverWalletConfig{
65+
w, err := RecoverWallet(cliCtx.Context, &RecoverWalletConfig{
6666
WalletDir: walletDir,
6767
WalletPassword: walletPassword,
6868
Mnemonic: mnemonic,
6969
NumAccounts: numAccounts,
70-
}); err != nil {
70+
})
71+
if err != nil {
72+
return err
73+
}
74+
// We store the hashed password to disk.
75+
if err := w.SaveHashedPassword(cliCtx.Context); err != nil {
7176
return err
7277
}
7378
log.Infof(

validator/accounts/v2/wallet_recover_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ func TestRecoverDerivedWallet(t *testing.T) {
5656

5757
ctx := context.Background()
5858
w, err := wallet.OpenWallet(cliCtx.Context, &wallet.Config{
59-
WalletDir: walletDir,
59+
WalletDir: walletDir,
60+
WalletPassword: password,
6061
})
6162
assert.NoError(t, err)
6263

validator/db/iface/interface.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,4 @@ type ValidatorDB interface {
2525
// Attester protection related methods.
2626
AttestationHistoryForPubKeys(ctx context.Context, publicKeys [][48]byte) (map[[48]byte]*slashpb.AttestationHistory, error)
2727
SaveAttestationHistoryForPubKeys(ctx context.Context, historyByPubKey map[[48]byte]*slashpb.AttestationHistory) error
28-
// Validator RPC authentication methods.
29-
SaveHashedPasswordForAPI(ctx context.Context, hashedPassword []byte) error
30-
HashedPasswordForAPI(ctx context.Context) ([]byte, error)
3128
}

validator/db/kv/BUILD.bazel

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ go_library(
1010
"new_proposal_history.go",
1111
"proposal_history.go",
1212
"schema.go",
13-
"web_api.go",
1413
],
1514
importpath = "github.com/prysmaticlabs/prysm/validator/db/kv",
1615
visibility = ["//validator:__subpackages__"],
@@ -36,7 +35,6 @@ go_test(
3635
"manage_test.go",
3736
"new_proposal_history_test.go",
3837
"proposal_history_test.go",
39-
"web_api_test.go",
4038
],
4139
embed = [":go_default_library"],
4240
deps = [

0 commit comments

Comments
 (0)