Skip to content

Commit cbc27e0

Browse files
authored
Refactor Wallet Password Handling, Preventing Wallet Corruption (#6933)
* wallet should no longer deal with account passwords * ensure tests are fixed * Merge branch 'master' into corrupted-pass * move mnemonic logic into right place * rem fmts * add fileutil * gazelle * imports * move seed logic to derived * fix tests * imports * gaz * Merge refs/heads/master into corrupted-pass * merge confs * Merge refs/heads/master into corrupted-pass * ivan's feedback * Merge branch 'corrupted-pass' of github.com:prysmaticlabs/prysm into corrupted-pass * gaz * fix shared test * Merge refs/heads/master into corrupted-pass * resolve conflicts * fix test build
1 parent a7f4293 commit cbc27e0

40 files changed

+544
-802
lines changed

shared/cmd/BUILD.bazel

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ go_library(
55
name = "go_default_library",
66
srcs = [
77
"config.go",
8-
"customflags.go",
98
"defaults.go",
109
"flags.go",
1110
"helpers.go",
@@ -16,6 +15,7 @@ go_library(
1615
importpath = "github.com/prysmaticlabs/prysm/shared/cmd",
1716
visibility = ["//visibility:public"],
1817
deps = [
18+
"//shared/fileutil:go_default_library",
1919
"//shared/params:go_default_library",
2020
"@com_github_golang_mock//gomock:go_default_library",
2121
"@com_github_pkg_errors//:go_default_library",
@@ -31,7 +31,6 @@ go_test(
3131
size = "small",
3232
srcs = [
3333
"config_test.go",
34-
"customflags_test.go",
3534
"helpers_test.go",
3635
],
3736
embed = [":go_default_library"],

shared/cmd/customflags.go

Lines changed: 0 additions & 32 deletions
This file was deleted.

shared/cmd/defaults.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ package cmd
1919
import (
2020
"path/filepath"
2121
"runtime"
22+
23+
"github.com/prysmaticlabs/prysm/shared/fileutil"
2224
)
2325

2426
// DefaultDataDir is the default data directory to use for the databases and other
2527
// persistence requirements.
2628
func DefaultDataDir() string {
2729
// Try to place the data folder in the user's home dir
28-
home := homeDir()
30+
home := fileutil.HomeDir()
2931
if home != "" {
3032
if runtime.GOOS == "darwin" {
3133
return filepath.Join(home, "Library", "Eth2")

shared/fileutil/BUILD.bazel

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
load("@io_bazel_rules_go//go:def.bzl", "go_test")
2+
load("@prysm//tools/go:def.bzl", "go_library")
3+
4+
go_library(
5+
name = "go_default_library",
6+
srcs = ["fileutil.go"],
7+
importpath = "github.com/prysmaticlabs/prysm/shared/fileutil",
8+
visibility = ["//visibility:public"],
9+
deps = ["@com_github_pkg_errors//:go_default_library"],
10+
)
11+
12+
go_test(
13+
name = "go_default_test",
14+
srcs = ["fileutil_test.go"],
15+
embed = [":go_default_library"],
16+
deps = [
17+
"//shared/testutil/assert:go_default_library",
18+
"//shared/testutil/require:go_default_library",
19+
],
20+
)

shared/fileutil/fileutil.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package fileutil
2+
3+
import (
4+
"io/ioutil"
5+
"os"
6+
"os/user"
7+
"path"
8+
"path/filepath"
9+
"strings"
10+
11+
"github.com/pkg/errors"
12+
)
13+
14+
// ExpandPath given a string which may be a relative path.
15+
// 1. replace tilde with users home dir
16+
// 2. expands embedded environment variables
17+
// 3. cleans the path, e.g. /a/b/../c -> /a/c
18+
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
19+
func ExpandPath(p string) (string, error) {
20+
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
21+
if home := HomeDir(); home != "" {
22+
p = home + p[1:]
23+
}
24+
}
25+
return filepath.Abs(path.Clean(os.ExpandEnv(p)))
26+
}
27+
28+
// HomeDir for a user.
29+
func HomeDir() string {
30+
if home := os.Getenv("HOME"); home != "" {
31+
return home
32+
}
33+
if usr, err := user.Current(); err == nil {
34+
return usr.HomeDir
35+
}
36+
return ""
37+
}
38+
39+
// HasDir checks if a directory indeed exists at the specified path.
40+
func HasDir(dirPath string) (bool, error) {
41+
fullPath, err := ExpandPath(dirPath)
42+
if err != nil {
43+
return false, err
44+
}
45+
info, err := os.Stat(fullPath)
46+
if os.IsNotExist(err) {
47+
return false, nil
48+
}
49+
if info == nil {
50+
return false, err
51+
}
52+
return info.IsDir(), err
53+
}
54+
55+
// FileExists returns true if a file is not a directory and exists
56+
// at the specified path.
57+
func FileExists(filename string) bool {
58+
filePath, err := ExpandPath(filename)
59+
if err != nil {
60+
return false
61+
}
62+
info, err := os.Stat(filePath)
63+
if os.IsNotExist(err) {
64+
return false
65+
}
66+
return !info.IsDir()
67+
}
68+
69+
// ReadFileAsBytes expands a file name's absolute path and reads it as bytes from disk.
70+
func ReadFileAsBytes(filename string) ([]byte, error) {
71+
filePath, err := ExpandPath(filename)
72+
if err != nil {
73+
return nil, errors.Wrap(err, "could not determine absolute path of password file")
74+
}
75+
return ioutil.ReadFile(filePath)
76+
}
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
//
1414
// You should have received a copy of the GNU General Public License
1515
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
16-
17-
package cmd
16+
package fileutil
1817

1918
import (
2019
"os"
2120
"os/user"
2221
"testing"
2322

2423
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
24+
"github.com/prysmaticlabs/prysm/shared/testutil/require"
2525
)
2626

2727
func TestPathExpansion(t *testing.T) {
@@ -32,7 +32,6 @@ func TestPathExpansion(t *testing.T) {
3232
tests := map[string]string{
3333
"/home/someuser/tmp": "/home/someuser/tmp",
3434
"~/tmp": user.HomeDir + "/tmp",
35-
"~thisOtherUser/b/": "~thisOtherUser/b",
3635
"$DDDXXX/a/b": "/tmp/a/b",
3736
"/a/b/": "/a/b",
3837
}
@@ -41,6 +40,8 @@ func TestPathExpansion(t *testing.T) {
4140
t.Error(err)
4241
}
4342
for test, expected := range tests {
44-
assert.Equal(t, expected, expandPath(test))
43+
expanded, err := ExpandPath(test)
44+
require.NoError(t, err)
45+
assert.Equal(t, expected, expanded)
4546
}
4647
}

tools/keystores/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ go_library(
88
visibility = ["//visibility:private"],
99
deps = [
1010
"//shared/bls:go_default_library",
11+
"//shared/fileutil:go_default_library",
1112
"//shared/params:go_default_library",
1213
"//shared/promptutil:go_default_library",
1314
"//validator/keymanager/v2:go_default_library",

tools/keystores/main.go

Lines changed: 5 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import (
1111
"io/ioutil"
1212
"log"
1313
"os"
14-
"os/user"
15-
"path"
1614
"path/filepath"
1715
"strings"
1816

1917
"github.com/google/uuid"
2018
"github.com/logrusorgru/aurora"
2119
"github.com/pkg/errors"
2220
"github.com/prysmaticlabs/prysm/shared/bls"
21+
"github.com/prysmaticlabs/prysm/shared/fileutil"
2322
"github.com/prysmaticlabs/prysm/shared/params"
2423
"github.com/prysmaticlabs/prysm/shared/promptutil"
2524
v2keymanager "github.com/prysmaticlabs/prysm/validator/keymanager/v2"
@@ -92,7 +91,7 @@ func decrypt(cliCtx *cli.Context) error {
9291
if keystorePath == "" {
9392
return errors.New("--keystore must be set")
9493
}
95-
fullPath, err := expandPath(keystorePath)
94+
fullPath, err := fileutil.ExpandPath(keystorePath)
9695
if err != nil {
9796
return errors.Wrapf(err, "could not expand path: %s", keystorePath)
9897
}
@@ -104,7 +103,7 @@ func decrypt(cliCtx *cli.Context) error {
104103
return nil
105104
})
106105
}
107-
isDir, err := hasDir(fullPath)
106+
isDir, err := fileutil.HasDir(fullPath)
108107
if err != nil {
109108
return errors.Wrapf(err, "could not check if path exists: %s", fullPath)
110109
}
@@ -149,15 +148,11 @@ func encrypt(cliCtx *cli.Context) error {
149148
if outputPath == "" {
150149
return errors.New("--output-path must be set")
151150
}
152-
fullPath, err := expandPath(outputPath)
151+
fullPath, err := fileutil.ExpandPath(outputPath)
153152
if err != nil {
154153
return errors.Wrapf(err, "could not expand path: %s", outputPath)
155154
}
156-
exists, err := fileExists(fullPath)
157-
if err != nil {
158-
return errors.Wrapf(err, "could not check if file exists: %s", fullPath)
159-
}
160-
if exists {
155+
if fileutil.FileExists(fullPath) {
161156
response, err := promptutil.ValidatePrompt(
162157
fmt.Sprintf("file at path %s already exists, are you sure you want to overwrite it? [y/n]", fullPath),
163158
func(s string) error {
@@ -263,58 +258,3 @@ func readAndDecryptKeystore(fullPath string, password string) error {
263258
fmt.Printf("Pubkey: %#x\n", au.BrightGreen(pubKeyBytes))
264259
return nil
265260
}
266-
267-
// Checks if the item at the specified path exists and is a directory.
268-
func hasDir(dirPath string) (bool, error) {
269-
fullPath, err := expandPath(dirPath)
270-
if err != nil {
271-
return false, err
272-
}
273-
info, err := os.Stat(fullPath)
274-
if err != nil {
275-
if os.IsNotExist(err) {
276-
return false, nil
277-
}
278-
return false, err
279-
}
280-
return info.IsDir(), nil
281-
}
282-
283-
// Check if a file at the specified path exists.
284-
func fileExists(filePath string) (bool, error) {
285-
fullPath, err := expandPath(filePath)
286-
if err != nil {
287-
return false, err
288-
}
289-
if _, err := os.Stat(fullPath); err != nil {
290-
if os.IsNotExist(err) {
291-
return false, nil
292-
}
293-
return false, err
294-
}
295-
return true, nil
296-
}
297-
298-
// Expands a file path
299-
// 1. replace tilde with users home dir
300-
// 2. expands embedded environment variables
301-
// 3. cleans the path, e.g. /a/b/../c -> /a/c
302-
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
303-
func expandPath(p string) (string, error) {
304-
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
305-
if home := homeDir(); home != "" {
306-
p = home + p[1:]
307-
}
308-
}
309-
return filepath.Abs(path.Clean(os.ExpandEnv(p)))
310-
}
311-
312-
func homeDir() string {
313-
if home := os.Getenv("HOME"); home != "" {
314-
return home
315-
}
316-
if usr, err := user.Current(); err == nil {
317-
return usr.HomeDir
318-
}
319-
return ""
320-
}

validator/accounts/v1/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ go_library(
1616
"//contracts/deposit-contract:go_default_library",
1717
"//shared/cmd:go_default_library",
1818
"//shared/depositutil:go_default_library",
19+
"//shared/fileutil:go_default_library",
1920
"//shared/keystore:go_default_library",
2021
"//shared/params:go_default_library",
2122
"//validator/db/kv:go_default_library",

validator/accounts/v1/account.go

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"fmt"
99
"io"
1010
"os"
11-
"os/user"
1211
"path/filepath"
1312
"runtime"
1413
"strings"
@@ -17,6 +16,7 @@ import (
1716
contract "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
1817
"github.com/prysmaticlabs/prysm/shared/cmd"
1918
"github.com/prysmaticlabs/prysm/shared/depositutil"
19+
"github.com/prysmaticlabs/prysm/shared/fileutil"
2020
"github.com/prysmaticlabs/prysm/shared/keystore"
2121
"github.com/prysmaticlabs/prysm/shared/params"
2222
"github.com/prysmaticlabs/prysm/validator/db/kv"
@@ -190,7 +190,7 @@ func PrintPublicAndPrivateKeys(path string, passphrase string) error {
190190
// DefaultValidatorDir returns OS-specific default keystore directory.
191191
func DefaultValidatorDir() string {
192192
// Try to place the data folder in the user's home dir
193-
home := homeDir()
193+
home := fileutil.HomeDir()
194194
if home != "" {
195195
if runtime.GOOS == "darwin" {
196196
return filepath.Join(home, "Library", "Eth2Validators")
@@ -336,17 +336,6 @@ func changePasswordForKeyType(keystorePath string, filePrefix string, oldPasswor
336336
return nil
337337
}
338338

339-
// homeDir returns home directory path.
340-
func homeDir() string {
341-
if home := os.Getenv("HOME"); home != "" {
342-
return home
343-
}
344-
if usr, err := user.Current(); err == nil {
345-
return usr.HomeDir
346-
}
347-
return ""
348-
}
349-
350339
// ExtractPublicKeysFromKeyStore extracts only the public keys from the decrypted keys from the keystore.
351340
func ExtractPublicKeysFromKeyStore(keystorePath string, passphrase string) ([][]byte, error) {
352341
decryptedKeys, err := DecryptKeysFromKeystore(keystorePath, params.BeaconConfig().ValidatorPrivkeyFileName, passphrase)

0 commit comments

Comments
 (0)