2020-08-06 05:26:52 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
2022-04-18 20:42:07 +00:00
|
|
|
"io"
|
2020-08-06 05:26:52 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
2022-08-16 12:20:13 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/v3/config/params"
|
|
|
|
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
|
|
|
|
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
|
|
|
"github.com/prysmaticlabs/prysm/v3/testing/require"
|
|
|
|
"github.com/prysmaticlabs/prysm/v3/validator/keymanager"
|
2020-08-06 05:26:52 +00:00
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
|
|
|
)
|
|
|
|
|
2021-03-02 11:39:54 +00:00
|
|
|
const password = "secretPassw0rd$1999"
|
|
|
|
|
2020-08-06 05:26:52 +00:00
|
|
|
type cliConfig struct {
|
|
|
|
keystoresPath string
|
|
|
|
password string
|
|
|
|
privateKey string
|
|
|
|
outputPath string
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupCliContext(
|
|
|
|
tb testing.TB,
|
|
|
|
conf *cliConfig,
|
|
|
|
) *cli.Context {
|
|
|
|
app := cli.App{}
|
|
|
|
set := flag.NewFlagSet("test", 0)
|
|
|
|
set.String(keystoresFlag.Name, conf.keystoresPath, "")
|
|
|
|
set.String(passwordFlag.Name, conf.password, "")
|
|
|
|
set.String(privateKeyFlag.Name, conf.privateKey, "")
|
|
|
|
set.String(outputPathFlag.Name, conf.outputPath, "")
|
|
|
|
assert.NoError(tb, set.Set(keystoresFlag.Name, conf.keystoresPath))
|
|
|
|
assert.NoError(tb, set.Set(passwordFlag.Name, conf.password))
|
|
|
|
assert.NoError(tb, set.Set(privateKeyFlag.Name, conf.privateKey))
|
|
|
|
assert.NoError(tb, set.Set(outputPathFlag.Name, conf.outputPath))
|
|
|
|
return cli.NewContext(&app, set, nil)
|
|
|
|
}
|
|
|
|
|
2020-10-15 22:31:52 +00:00
|
|
|
func createRandomKeystore(t testing.TB, password string) (*keymanager.Keystore, bls.SecretKey) {
|
2020-08-06 05:26:52 +00:00
|
|
|
encryptor := keystorev4.New()
|
|
|
|
id, err := uuid.NewRandom()
|
|
|
|
require.NoError(t, err)
|
2020-10-30 19:06:33 +00:00
|
|
|
validatingKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2020-08-06 05:26:52 +00:00
|
|
|
pubKey := validatingKey.PublicKey().Marshal()
|
|
|
|
cryptoFields, err := encryptor.Encrypt(validatingKey.Marshal(), password)
|
|
|
|
require.NoError(t, err)
|
2020-10-15 22:31:52 +00:00
|
|
|
return &keymanager.Keystore{
|
2020-08-06 05:26:52 +00:00
|
|
|
Crypto: cryptoFields,
|
|
|
|
Pubkey: fmt.Sprintf("%x", pubKey),
|
|
|
|
ID: id.String(),
|
|
|
|
Version: encryptor.Version(),
|
|
|
|
Name: encryptor.Name(),
|
|
|
|
}, validatingKey
|
|
|
|
}
|
|
|
|
|
|
|
|
func setupRandomDir(t testing.TB) string {
|
2020-11-10 22:45:17 +00:00
|
|
|
randDir := t.TempDir()
|
2020-08-06 05:26:52 +00:00
|
|
|
require.NoError(t, os.MkdirAll(randDir, os.ModePerm))
|
|
|
|
return randDir
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDecrypt(t *testing.T) {
|
|
|
|
keystoresDir := setupRandomDir(t)
|
|
|
|
keystore, privKey := createRandomKeystore(t, password)
|
|
|
|
// We write a random keystore to a keystores directory.
|
|
|
|
encodedKeystore, err := json.MarshalIndent(keystore, "", "\t")
|
|
|
|
require.NoError(t, err)
|
|
|
|
keystoreFilePath := filepath.Join(keystoresDir, "keystore.json")
|
2022-04-18 20:42:07 +00:00
|
|
|
require.NoError(t, os.WriteFile(
|
2020-08-06 05:26:52 +00:00
|
|
|
keystoreFilePath, encodedKeystore, params.BeaconIoConfig().ReadWritePermissions),
|
|
|
|
)
|
|
|
|
|
|
|
|
cliCtx := setupCliContext(t, &cliConfig{
|
|
|
|
keystoresPath: keystoreFilePath,
|
|
|
|
password: password,
|
|
|
|
})
|
|
|
|
|
|
|
|
rescueStdout := os.Stdout
|
|
|
|
r, w, err := os.Pipe()
|
|
|
|
require.NoError(t, err)
|
|
|
|
os.Stdout = w
|
|
|
|
|
|
|
|
// We attempt to decrypt the keystore file we just wrote to disk.
|
|
|
|
require.NoError(t, decrypt(cliCtx))
|
|
|
|
|
|
|
|
require.NoError(t, w.Close())
|
2022-04-18 20:42:07 +00:00
|
|
|
out, err := io.ReadAll(r)
|
2020-08-06 05:26:52 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// We capture output from stdout.
|
|
|
|
os.Stdout = rescueStdout
|
|
|
|
stringOutput := string(out)
|
|
|
|
|
|
|
|
// We capture the results of stdout to check the public key and private keys
|
|
|
|
// were both printed to stdout.
|
2020-10-01 14:38:53 +00:00
|
|
|
assert.Equal(t, true, strings.Contains(stringOutput, keystore.Pubkey))
|
|
|
|
assert.Equal(t, true, strings.Contains(stringOutput, fmt.Sprintf("%#x", privKey.Marshal())))
|
2020-08-06 05:26:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEncrypt(t *testing.T) {
|
|
|
|
keystoresDir := setupRandomDir(t)
|
|
|
|
keystoreFilePath := filepath.Join(keystoresDir, "keystore.json")
|
2020-10-30 19:06:33 +00:00
|
|
|
privKey, err := bls.RandKey()
|
|
|
|
require.NoError(t, err)
|
2020-08-06 05:26:52 +00:00
|
|
|
|
|
|
|
cliCtx := setupCliContext(t, &cliConfig{
|
|
|
|
outputPath: keystoreFilePath,
|
|
|
|
password: password,
|
|
|
|
privateKey: fmt.Sprintf("%#x", privKey.Marshal()),
|
|
|
|
})
|
|
|
|
|
|
|
|
rescueStdout := os.Stdout
|
|
|
|
r, w, err := os.Pipe()
|
|
|
|
require.NoError(t, err)
|
|
|
|
os.Stdout = w
|
|
|
|
|
|
|
|
// We attempt to encrypt the secret key and save it to the output path.
|
|
|
|
require.NoError(t, encrypt(cliCtx))
|
|
|
|
|
|
|
|
require.NoError(t, w.Close())
|
2022-04-18 20:42:07 +00:00
|
|
|
out, err := io.ReadAll(r)
|
2020-08-06 05:26:52 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// We capture output from stdout.
|
|
|
|
os.Stdout = rescueStdout
|
|
|
|
stringOutput := string(out)
|
|
|
|
|
|
|
|
// We capture the results of stdout to check the public key was printed to stdout.
|
2020-10-01 14:38:53 +00:00
|
|
|
res := strings.Contains(stringOutput, fmt.Sprintf("%x", privKey.PublicKey().Marshal()))
|
|
|
|
assert.Equal(t, true, res)
|
2020-08-06 05:26:52 +00:00
|
|
|
}
|