소스 검색

cmd/utils, crypto: add --lightkdf flag for lighter KDF

Drake Burroughs 10 년 전
부모
커밋
05ea8926c3
7개의 변경된 파일41개의 추가작업 그리고 22개의 파일을 삭제
  1. 11 1
      cmd/utils/flags.go
  2. 1 1
      common/natspec/natspec_e2e_test.go
  3. 1 1
      common/natspec/natspec_e2e_test.go.orig
  4. 1 1
      crypto/crypto.go
  5. 22 13
      crypto/key_store_passphrase.go
  6. 4 4
      crypto/key_store_test.go
  7. 1 1
      tests/block_test_util.go

+ 11 - 1
cmd/utils/flags.go

@@ -157,6 +157,10 @@ var (
 		Name:  "fast",
 		Usage: "Enables fast syncing through state downloads",
 	}
+	LightKDFFlag = cli.BoolFlag{
+		Name:  "lightkdf",
+		Usage: "Reduce KDF memory & CPU usage at some expense of KDF strength",
+	}
 
 	// miner settings
 	// TODO: refactor CPU vs GPU mining flags
@@ -579,7 +583,13 @@ func MakeAccountManager(ctx *cli.Context) *accounts.Manager {
 	if ctx.GlobalBool(TestNetFlag.Name) {
 		dataDir += "/testnet"
 	}
-	ks := crypto.NewKeyStorePassphrase(filepath.Join(dataDir, "keystore"))
+	scryptN := crypto.StandardScryptN
+	scryptP := crypto.StandardScryptP
+	if ctx.GlobalBool(LightKDFFlag.Name) {
+		scryptN = crypto.LightScryptN
+		scryptP = crypto.LightScryptP
+	}
+	ks := crypto.NewKeyStorePassphrase(filepath.Join(dataDir, "keystore"), scryptN, scryptP)
 	return accounts.NewManager(ks)
 }
 

+ 1 - 1
common/natspec/natspec_e2e_test.go

@@ -128,7 +128,7 @@ func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) {
 	db, _ := ethdb.NewMemDatabase()
 	addr := common.HexToAddress(testAddress)
 	core.WriteGenesisBlockForTesting(db, core.GenesisAccount{addr, common.String2Big(testBalance)})
-	ks := crypto.NewKeyStorePassphrase(filepath.Join(tmp, "keystore"))
+	ks := crypto.NewKeyStorePassphrase(filepath.Join(tmp, "keystore"), crypto.LightScryptN, crypto.LightScryptP)
 	am := accounts.NewManager(ks)
 	keyb, err := crypto.HexToECDSA(testKey)
 	if err != nil {

+ 1 - 1
common/natspec/natspec_e2e_test.go.orig

@@ -106,7 +106,7 @@ func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) {
   }
 
   // create a testAddress
-  ks := crypto.NewKeyStorePassphrase("/tmp/eth-natspec/keystore")
+  ks := crypto.NewKeyStorePassphrase("/tmp/eth-natspec/keystore", crypto.LightScryptN, crypto.LightScryptP)
   am := accounts.NewManager(ks)
   testAccount, err := am.NewAccount("password")
   if err != nil {

+ 1 - 1
crypto/crypto.go

@@ -215,7 +215,7 @@ func Decrypt(prv *ecdsa.PrivateKey, ct []byte) ([]byte, error) {
 
 // Used only by block tests.
 func ImportBlockTestKey(privKeyBytes []byte) error {
-	ks := NewKeyStorePassphrase(common.DefaultDataDir() + "/keystore")
+	ks := NewKeyStorePassphrase(common.DefaultDataDir()+"/keystore", LightScryptN, LightScryptP)
 	ecKey := ToECDSA(privKeyBytes)
 	key := &Key{
 		Id:         uuid.NewRandom(),

+ 22 - 13
crypto/key_store_passphrase.go

@@ -45,19 +45,29 @@ import (
 
 const (
 	keyHeaderKDF = "scrypt"
-	// 2^18 / 8 / 1 uses 256MB memory and approx 1s CPU time on a modern CPU.
-	scryptN     = 1 << 18
-	scryptr     = 8
-	scryptp     = 1
-	scryptdkLen = 32
+
+	// n,r,p = 2^18, 8, 1 uses 256MB memory and approx 1s CPU time on a modern CPU.
+	StandardScryptN = 1 << 18
+	StandardScryptP = 1
+
+	// n,r,p = 2^12, 8, 6 uses 4MB memory and approx 100ms CPU time on a modern CPU.
+	LightScryptN = 1 << 12
+	LightScryptP = 6
+
+	scryptR     = 8
+	scryptDKLen = 32
 )
 
 type keyStorePassphrase struct {
 	keysDirPath string
+	scryptN     int
+	scryptP     int
+	scryptR     int
+	scryptDKLen int
 }
 
-func NewKeyStorePassphrase(path string) KeyStore {
-	return &keyStorePassphrase{path}
+func NewKeyStorePassphrase(path string, scryptN int, scryptP int) KeyStore {
+	return &keyStorePassphrase{path, scryptN, scryptP, scryptR, scryptDKLen}
 }
 
 func (ks keyStorePassphrase) GenerateNewKey(rand io.Reader, auth string) (key *Key, err error) {
@@ -87,11 +97,10 @@ func (ks keyStorePassphrase) GetKeyAddresses() (addresses []common.Address, err
 func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) {
 	authArray := []byte(auth)
 	salt := randentropy.GetEntropyCSPRNG(32)
-	derivedKey, err := scrypt.Key(authArray, salt, scryptN, scryptr, scryptp, scryptdkLen)
+	derivedKey, err := scrypt.Key(authArray, salt, ks.scryptN, ks.scryptR, ks.scryptP, ks.scryptDKLen)
 	if err != nil {
 		return err
 	}
-
 	encryptKey := derivedKey[:16]
 	keyBytes := FromECDSA(key.PrivateKey)
 
@@ -104,10 +113,10 @@ func (ks keyStorePassphrase) StoreKey(key *Key, auth string) (err error) {
 	mac := Sha3(derivedKey[16:32], cipherText)
 
 	scryptParamsJSON := make(map[string]interface{}, 5)
-	scryptParamsJSON["n"] = scryptN
-	scryptParamsJSON["r"] = scryptr
-	scryptParamsJSON["p"] = scryptp
-	scryptParamsJSON["dklen"] = scryptdkLen
+	scryptParamsJSON["n"] = ks.scryptN
+	scryptParamsJSON["r"] = ks.scryptR
+	scryptParamsJSON["p"] = ks.scryptP
+	scryptParamsJSON["dklen"] = ks.scryptDKLen
 	scryptParamsJSON["salt"] = hex.EncodeToString(salt)
 
 	cipherParamsJSON := cipherparamsJSON{

+ 4 - 4
crypto/key_store_test.go

@@ -56,7 +56,7 @@ func TestKeyStorePlain(t *testing.T) {
 }
 
 func TestKeyStorePassphrase(t *testing.T) {
-	ks := NewKeyStorePassphrase(common.DefaultDataDir())
+	ks := NewKeyStorePassphrase(common.DefaultDataDir(), LightScryptN, LightScryptP)
 	pass := "foo"
 	k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
 	if err != nil {
@@ -82,7 +82,7 @@ func TestKeyStorePassphrase(t *testing.T) {
 }
 
 func TestKeyStorePassphraseDecryptionFail(t *testing.T) {
-	ks := NewKeyStorePassphrase(common.DefaultDataDir())
+	ks := NewKeyStorePassphrase(common.DefaultDataDir(), LightScryptN, LightScryptP)
 	pass := "foo"
 	k1, err := ks.GenerateNewKey(randentropy.Reader, pass)
 	if err != nil {
@@ -110,7 +110,7 @@ func TestImportPreSaleKey(t *testing.T) {
 	// python pyethsaletool.py genwallet
 	// with password "foo"
 	fileContent := "{\"encseed\": \"26d87f5f2bf9835f9a47eefae571bc09f9107bb13d54ff12a4ec095d01f83897494cf34f7bed2ed34126ecba9db7b62de56c9d7cd136520a0427bfb11b8954ba7ac39b90d4650d3448e31185affcd74226a68f1e94b1108e6e0a4a91cdd83eba\", \"ethaddr\": \"d4584b5f6229b7be90727b0fc8c6b91bb427821f\", \"email\": \"gustav.simonsson@gmail.com\", \"btcaddr\": \"1EVknXyFC68kKNLkh6YnKzW41svSRoaAcx\"}"
-	ks := NewKeyStorePassphrase(common.DefaultDataDir())
+	ks := NewKeyStorePassphrase(common.DefaultDataDir(), LightScryptN, LightScryptP)
 	pass := "foo"
 	_, err := ImportPreSaleKey(ks, []byte(fileContent), pass)
 	if err != nil {
@@ -168,7 +168,7 @@ func TestV1_1(t *testing.T) {
 }
 
 func TestV1_2(t *testing.T) {
-	ks := NewKeyStorePassphrase("tests/v1")
+	ks := NewKeyStorePassphrase("tests/v1", LightScryptN, LightScryptP)
 	addr := common.HexToAddress("cb61d5a9c4896fb9658090b597ef0e7be6f7b67e")
 	k, err := ks.GetKey(addr, "g")
 	if err != nil {

+ 1 - 1
tests/block_test_util.go

@@ -162,7 +162,7 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
 
 }
 func runBlockTest(test *BlockTest) error {
-	ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"))
+	ks := crypto.NewKeyStorePassphrase(filepath.Join(common.DefaultDataDir(), "keystore"), crypto.StandardScryptN, crypto.StandardScryptP)
 	am := accounts.NewManager(ks)
 	db, _ := ethdb.NewMemDatabase()
 	cfg := &eth.Config{