diff --git a/package.json b/package.json index 3a0824cd..3eb69900 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "oboe": "2.1.3", "request": "2.87.0", "requestretry": "^2.0.2", - "scrypt.js": "0.2.0", + "scryptsy": "2.1.0", "underscore": "^1.9.1", "utf8": "2.1.1", "uuid": "2.0.1", diff --git a/packages/caver-klay/caver-klay-accounts/src/index.js b/packages/caver-klay/caver-klay-accounts/src/index.js index 060792a6..97335207 100644 --- a/packages/caver-klay/caver-klay-accounts/src/index.js +++ b/packages/caver-klay/caver-klay-accounts/src/index.js @@ -35,7 +35,7 @@ var RLP = require("eth-lib/lib/rlp"); var Nat = require("eth-lib/lib/nat"); var Bytes = require("eth-lib/lib/bytes"); var cryp = (typeof global === 'undefined') ? require('crypto-browserify') : require('crypto'); -var scryptsy = require('scrypt.js'); +var scrypt = require('./scrypt'); var uuid = require('uuid'); var utils = require('../../../caver-utils'); var helpers = require('../../../caver-core-helpers'); @@ -470,7 +470,7 @@ Accounts.prototype.decrypt = function (v3Keystore, password, nonStrict) { kdfparams = json.crypto.kdfparams; // FIXME: support progress reporting callback - derivedKey = scryptsy(new Buffer(password), new Buffer(kdfparams.salt, 'hex'), kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen); + derivedKey = scrypt(new Buffer(password), new Buffer(kdfparams.salt, 'hex'), kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen); } else if (json.crypto.kdf === 'pbkdf2') { kdfparams = json.crypto.kdfparams; @@ -589,7 +589,7 @@ Accounts.prototype.encrypt = function (privateKey, password, options) { kdfparams.n = options.n || 4096; // 2048 4096 8192 16384 kdfparams.r = options.r || 8; kdfparams.p = options.p || 1; - derivedKey = scryptsy(new Buffer(password), salt, kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen); + derivedKey = scrypt(new Buffer(password), salt, kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen); } else { throw new Error('Unsupported kdf'); } diff --git a/packages/caver-klay/caver-klay-accounts/src/scrypt.js b/packages/caver-klay/caver-klay-accounts/src/scrypt.js new file mode 100644 index 00000000..291685b0 --- /dev/null +++ b/packages/caver-klay/caver-klay-accounts/src/scrypt.js @@ -0,0 +1,92 @@ +/* + Modifications copyright 2019 The caver-js Authors + This file is part of web3.js. + + web3.js is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + web3.js is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with web3.js. If not, see . + + This file is derived from web3.js/packages/web3-eth-accounts/src/scrpyt.js (2019/09/03). + Modified and improved for the caver-js development. +*/ + +var scryptsy = require('scryptsy'); + +var scrypt; + +var isNode = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]'; +if (isNode) { + var NODE_MIN_VER_WITH_BUILTIN_SCRYPT = '10.5.0'; + var NODE_MIN_VER_INCOMPAT_SCRYPT_PKG = '12.0.0'; + var semver = require('semver'); + var useNodeBuiltin = isNode && semver.Range('>=' + NODE_MIN_VER_WITH_BUILTIN_SCRYPT).test(process.version); + + var tryScryptPkg = (function() { + var scryptPkg; + return function() { + if (scryptPkg !== undefined) { return scryptPkg; } + try { + scryptPkg = (function(m) { return require(m); })('scrypt'); + } catch (e) { + if (/was compiled against a different/.test(e.message)) { + throw e; + } + scryptPkg = null; + } + return scryptPkg; + }; + })(); + + var canImprove = function(nodeVer) { + return 'can improve web3\'s peformance when running Node.js versions older than ' + nodeVer + ' by installing the (deprecated) scrypt package in your project'; + }; + + if (useNodeBuiltin) { + var crypto = require('crypto'); + var fallbackCount = 0; + scrypt = function(key, salt, N, r, p, dkLen) { + try { + return crypto.scryptSync(key, salt, dkLen, {N: N, r: r, p: p}); + } catch (e) { + if (/scrypt:memory limit exceeded/.test(e.message)) { + var scryptPkg = tryScryptPkg(); + if (scryptPkg) { + return scryptPkg.hashSync(key, {N: N, r: r, p: p}, dkLen, salt); + } + fallbackCount += 1; + console.warn( + '\x1b[33m%s\x1b[0m', + 'Memory limit exceeded for Node\'s built-in crypto.scrypt, falling back to scryptsy (times: ' + fallbackCount + '), if this happens frequently you ' + canImprove(NODE_MIN_VER_INCOMPAT_SCRYPT_PKG) + ); + return scryptsy(key, salt, N, r, p, dkLen); + } + throw e; + } + }; + } else { + var scryptPkg = tryScryptPkg(); + if (scryptPkg) { + scrypt = function(key, salt, N, r, p, dkLen) { + return scryptPkg.hashSync(key, {N: N, r: r, p: p}, dkLen, salt); + }; + } else { + console.warn( + '\x1b[33m%s\x1b[0m', + 'You ' + canImprove(NODE_MIN_VER_WITH_BUILTIN_SCRYPT) + ); + } + } +} + +scrypt = scrypt || scryptsy; + +module.exports = scrypt;