int-cli
Version:
INT is the new generation of bottom-up created system of IoT and blockchain
148 lines (121 loc) • 5.25 kB
JavaScript
var _ = require('underscore');
var Hash = require("./hash");
var uuid = require('uuid');
var cryp = (typeof global === 'undefined') ? require('crypto-browserify') : require('crypto');
var scryptsy = require('scrypt.js');
var Address = require('../address');
let isHexStrict = function(hex) {
return ((_.isString(hex) || _.isNumber(hex)) && /^(-)?0x[0-9a-f]*$/i.test(hex));
};
let hexToBytes = function(hex) {
hex = hex.toString(16);
if (!isHexStrict(hex)) {
throw new Error('Given value "' + hex + '" is not a valid hex string.');
}
hex = hex.replace(/^0x/i, '');
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
};
let sha3 = function(value) {
if (isHexStrict(value) && /^0x/i.test((value).toString())) {
value = hexToBytes(value);
}
var returnValue = Hash.keccak256(value); // jshint ignore:line
//if(returnValue === SHA3_NULL_S) {
// return null;
//} else {
return returnValue;
//}
};
let encrypt = function(privateKey, password, options) {
/* jshint maxcomplexity: 20 */
//var account = this.privateKeyToAccount(privateKey);
options = options || {};
var salt = options.salt || cryp.randomBytes(32);
var iv = options.iv || cryp.randomBytes(16);
var derivedKey;
var kdf = options.kdf || 'scrypt';
var kdfparams = {
dklen: options.dklen || 32,
salt: salt.toString('hex')
};
if (kdf === 'pbkdf2') {
kdfparams.c = options.c || 262144;
kdfparams.prf = 'hmac-sha256';
derivedKey = cryp.pbkdf2Sync(new Buffer(password), salt, kdfparams.c, kdfparams.dklen, 'sha256');
} else if (kdf === 'scrypt') {
// FIXME: support progress reporting callback
kdfparams.n = options.n || 8192; // 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);
} else {
throw new Error('Unsupported kdf');
}
var cipher = cryp.createCipheriv(options.cipher || 'aes-128-ctr', derivedKey.slice(0, 16), iv);
if (!cipher) {
throw new Error('Unsupported cipher');
}
//var ciphertext = Buffer.concat([ cipher.update(new Buffer(account.privateKey.replace('0x',''), 'hex')),
// cipher.final() ]);
var ciphertext = Buffer.concat([cipher.update(new Buffer(privateKey, 'hex')), cipher.final()]);
//var mac = utils.sha3(Buffer.concat([ derivedKey.slice(16, 32), new Buffer(ciphertext, 'hex') ])).replace('0x','');
var mac = sha3(Buffer.concat([derivedKey.slice(16, 32), new Buffer(ciphertext, 'hex')])).replace('0x', '');
return {
version: 3,
id: uuid.v4({ random: options.uuid || cryp.randomBytes(16) }),
address: '',
crypto: {
ciphertext: ciphertext.toString('hex'),
cipherparams: {
iv: iv.toString('hex')
},
cipher: options.cipher || 'aes-128-ctr',
kdf: kdf,
kdfparams: kdfparams,
mac: mac.toString('hex')
}
};
};
let decrypt = function(v3Keystore, password, nonStrict) {
/* jshint maxcomplexity: 10 */
if (!_.isString(password)) {
throw new Error('No password given.');
}
var json = (_.isObject(v3Keystore)) ? v3Keystore : JSON.parse(nonStrict ? v3Keystore.toLowerCase() : v3Keystore);
if (json.version !== 3) {
throw new Error('Not a valid V3 wallet');
}
var derivedKey;
var kdfparams;
if (json.crypto.kdf === 'scrypt') {
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);
} else if (json.crypto.kdf === 'pbkdf2') {
kdfparams = json.crypto.kdfparams;
if (kdfparams.prf !== 'hmac-sha256') {
throw new Error('Unsupported parameters to PBKDF2');
}
derivedKey = cryp.pbkdf2Sync(new Buffer(password), new Buffer(kdfparams.salt, 'hex'), kdfparams.c, kdfparams.dklen, 'sha256');
} else {
throw new Error('Unsupported key derivation scheme');
}
var ciphertext = new Buffer(json.crypto.ciphertext, 'hex');
//var mac = utils.sha3(Buffer.concat([ derivedKey.slice(16, 32), ciphertext ])).replace('0x','');
var mac = sha3(Buffer.concat([derivedKey.slice(16, 32), ciphertext])).replace('0x', '');
if (mac !== json.crypto.mac) {
throw new Error('Key derivation failed - possibly wrong password');
}
var decipher = cryp.createDecipheriv(json.crypto.cipher, derivedKey.slice(0, 16), new Buffer(json.crypto.cipherparams.iv, 'hex'));
// var seed = '0x'+ Buffer.concat([ decipher.update(ciphertext), decipher.final() ]).toString('hex');
var seed = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString('hex');
//return this.privateKeyToAccount(seed);
var address = Address.addressFromSecretKey(seed);
return {address: address, privateKey: seed};
};
module.exports = {
encrypt,
decrypt
}