eth-lightwallet
Version:
A lightweight ethereum javascript wallet.
1,467 lines (1,155 loc) • 2.57 MB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.lightwallet = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
module.exports = {
txutils: require('./lib/txutils.js'),
encryption: require('./lib/encryption.js'),
signing: require('./lib/signing.js'),
keystore: require('./lib/keystore.js'),
upgrade: require('./lib/upgrade.js')
};
},{"./lib/encryption.js":3,"./lib/keystore.js":4,"./lib/signing.js":5,"./lib/txutils.js":6,"./lib/upgrade.js":7}],2:[function(require,module,exports){
"use strict";
function derivedKey(keystore, pwDerivedKey) {
if (!keystore.isDerivedKeyCorrect(pwDerivedKey)) {
throw new Error('Incorrect derived key!');
}
}
module.exports = {
derivedKey: derivedKey
};
},{}],3:[function(require,module,exports){
(function (Buffer){
"use strict";
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
var Nacl = require('tweetnacl');
var NaclUtil = require('tweetnacl-util');
var Assert = require('./assert');
function encodeHex(msgUInt8Arr) {
var msgBase64 = NaclUtil.encodeBase64(msgUInt8Arr);
return new Buffer(msgBase64, 'base64').toString('hex');
}
function decodeHex(msgHex) {
var msgBase64 = new Buffer(msgHex, 'hex').toString('base64');
return NaclUtil.decodeBase64(msgBase64);
}
function asymEncryptRaw(keystore, pwDerivedKey, msgUint8Array, myAddress, theirPubKey) {
Assert.derivedKey(keystore, pwDerivedKey);
var privateKey = keystore.exportPrivateKey(myAddress, pwDerivedKey);
var privateKeyUInt8Array = decodeHex(privateKey);
var pubKeyUInt8Array = decodeHex(theirPubKey);
var nonce = Nacl.randomBytes(Nacl.box.nonceLength);
var encryptedMessage = Nacl.box(msgUint8Array, nonce, pubKeyUInt8Array, privateKeyUInt8Array);
return {
alg: 'curve25519-xsalsa20-poly1305',
nonce: NaclUtil.encodeBase64(nonce),
ciphertext: NaclUtil.encodeBase64(encryptedMessage)
};
}
function asymDecryptRaw(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress) {
Assert.derivedKey(keystore, pwDerivedKey);
var privateKey = keystore.exportPrivateKey(myAddress, pwDerivedKey);
var privateKeyUInt8Array = decodeHex(privateKey);
var pubKeyUInt8Array = decodeHex(theirPubKey);
var nonce = NaclUtil.decodeBase64(encMsg.nonce);
var cipherText = NaclUtil.decodeBase64(encMsg.ciphertext);
var clearText = Nacl.box.open(cipherText, nonce, pubKeyUInt8Array, privateKeyUInt8Array);
return clearText;
}
function asymEncryptString(keystore, pwDerivedKey, msg, myAddress, theirPubKey) {
Assert.derivedKey(keystore, pwDerivedKey);
var messageUInt8Array = NaclUtil.decodeUTF8(msg);
return asymEncryptRaw(keystore, pwDerivedKey, messageUInt8Array, myAddress, theirPubKey);
}
function asymDecryptString(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress) {
Assert.derivedKey(keystore, pwDerivedKey);
var clearText = asymDecryptRaw(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress);
if (clearText === null) {
return false;
}
return NaclUtil.encodeUTF8(clearText);
}
function multiEncryptString(keystore, pwDerivedKey, msg, myAddress, theirPubKeyArray) {
Assert.derivedKey(keystore, pwDerivedKey);
var messageUInt8Array = NaclUtil.decodeUTF8(msg);
var symEncryptionKey = Nacl.randomBytes(Nacl.secretbox.keyLength);
var symNonce = Nacl.randomBytes(Nacl.secretbox.nonceLength);
var symEncMessage = Nacl.secretbox(messageUInt8Array, symNonce, symEncryptionKey);
if (theirPubKeyArray.length < 1) {
throw new Error('Found no pubkeys to encrypt to.');
}
var encryptedSymKey = theirPubKeyArray.map(function (theirPubKey) {
var _asymEncryptRaw = asymEncryptRaw(keystore, pwDerivedKey, symEncryptionKey, myAddress, theirPubKey),
alg = _asymEncryptRaw.alg,
props = _objectWithoutProperties(_asymEncryptRaw, ["alg"]);
return _objectSpread({}, props);
});
return {
version: 1,
asymAlg: 'curve25519-xsalsa20-poly1305',
symAlg: 'xsalsa20-poly1305',
symNonce: NaclUtil.encodeBase64(symNonce),
symEncMessage: NaclUtil.encodeBase64(symEncMessage),
encryptedSymKey: encryptedSymKey
};
}
function multiDecryptString(keystore, pwDerivedKey, encMsg, theirPubKey, myAddress) {
Assert.derivedKey(keystore, pwDerivedKey);
var symKey = null;
for (var i = 0; i < encMsg.encryptedSymKey.length; i++) {
var result = asymDecryptRaw(keystore, pwDerivedKey, encMsg.encryptedSymKey[i], theirPubKey, myAddress);
if (result !== null) {
symKey = result;
break;
}
}
if (symKey === null) {
return false;
}
var symNonce = NaclUtil.decodeBase64(encMsg.symNonce);
var symEncMessage = NaclUtil.decodeBase64(encMsg.symEncMessage);
var msg = Nacl.secretbox.open(symEncMessage, symNonce, symKey);
if (msg === null) {
return false;
}
return NaclUtil.encodeUTF8(msg);
}
function addressToPublicEncKey(keystore, pwDerivedKey, address) {
Assert.derivedKey(keystore, pwDerivedKey);
var privateKey = keystore.exportPrivateKey(address, pwDerivedKey);
var privateKeyUInt8Array = decodeHex(privateKey);
var pubKeyUInt8Array = Nacl.box.keyPair.fromSecretKey(privateKeyUInt8Array).publicKey;
return encodeHex(pubKeyUInt8Array);
}
module.exports = {
encodeHex: encodeHex,
decodeHex: decodeHex,
asymEncryptString: asymEncryptString,
asymDecryptString: asymDecryptString,
multiEncryptString: multiEncryptString,
multiDecryptString: multiDecryptString,
addressToPublicEncKey: addressToPublicEncKey
};
}).call(this,require("buffer").Buffer)
},{"./assert":2,"buffer":138,"tweetnacl":311,"tweetnacl-util":310}],4:[function(require,module,exports){
(function (Buffer){
"use strict";
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
var CryptoJS = require('crypto-js');
var Util = require('ethereumjs-util');
var EC = require('elliptic').ec;
var BitCore = require('bitcore-lib');
var Random = BitCore.crypto.Random;
var Hash = BitCore.crypto.Hash;
var Mnemonic = require('bitcore-mnemonic');
var Nacl = require('tweetnacl');
var NaclUtil = require('tweetnacl-util');
var ScryptAsync = require('scrypt-async');
var Assert = require('./assert');
var Encryption = require('./encryption');
var Signing = require('./signing');
var TxUtils = require('./txutils');
var ec = new EC('secp256k1');
function leftPadString(stringToPad, padChar, length) {
var repeatedPadChar = '';
for (var i = 0; i < length; i++) {
repeatedPadChar += padChar;
}
return (repeatedPadChar + stringToPad).slice(-length);
}
var KeyStore = function KeyStore() {};
KeyStore.prototype.init = function (mnemonic, pwDerivedKey, hdPathString, salt) {
this.salt = salt;
this.hdPathString = hdPathString;
this.encSeed = undefined;
this.encHdRootPriv = undefined;
this.version = 3;
this.hdIndex = 0;
this.encPrivKeys = {};
this.addresses = [];
if (typeof pwDerivedKey !== 'undefined' && typeof mnemonic !== 'undefined') {
var words = mnemonic.split(' ');
if (!KeyStore.isSeedValid(mnemonic) || words.length !== 12) {
throw new Error('KeyStore: Invalid mnemonic');
} // Pad the seed to length 120 before encrypting
var paddedSeed = leftPadString(mnemonic, ' ', 120);
this.encSeed = KeyStore._encryptString(paddedSeed, pwDerivedKey); // hdRoot is the relative root from which we derive the keys using generateNewAddress().
// The derived keys are then `hdRoot/hdIndex`.
var hdRoot = new Mnemonic(mnemonic).toHDPrivateKey().xprivkey;
var hdRootKey = new BitCore.HDPrivateKey(hdRoot);
var hdPathKey = hdRootKey.derive(hdPathString).xprivkey;
this.encHdRootPriv = KeyStore._encryptString(hdPathKey, pwDerivedKey);
}
};
KeyStore.prototype.isDerivedKeyCorrect = function (pwDerivedKey) {
var paddedSeed = KeyStore._decryptString(this.encSeed, pwDerivedKey);
return paddedSeed && paddedSeed.length > 0;
};
KeyStore.prototype.serialize = function () {
return JSON.stringify({
encSeed: this.encSeed,
encHdRootPriv: this.encHdRootPriv,
addresses: this.addresses,
encPrivKeys: this.encPrivKeys,
hdPathString: this.hdPathString,
salt: this.salt,
hdIndex: this.hdIndex,
version: this.version
});
};
KeyStore.prototype.getAddresses = function () {
return this.addresses.map(function (addr) {
return Util.addHexPrefix(addr);
});
};
KeyStore.prototype.getSeed = function (pwDerivedKey) {
Assert.derivedKey(this, pwDerivedKey);
var paddedSeed = KeyStore._decryptString(this.encSeed, pwDerivedKey);
if (!paddedSeed || paddedSeed.length === 0) {
throw new Error('Provided password derived key is wrong');
}
return paddedSeed.trim();
};
KeyStore.prototype.exportPrivateKey = function (address, pwDerivedKey) {
Assert.derivedKey(this, pwDerivedKey);
var addr = Util.stripHexPrefix(address).toLowerCase();
if (this.encPrivKeys[addr] === undefined) {
throw new Error('KeyStore.exportPrivateKey: Address not found in KeyStore');
}
var encPrivateKey = this.encPrivKeys[addr];
return KeyStore._decryptKey(encPrivateKey, pwDerivedKey);
};
KeyStore.prototype.generateNewAddress = function (pwDerivedKey, n) {
Assert.derivedKey(this, pwDerivedKey);
if (!this.encSeed) {
throw new Error('KeyStore.generateNewAddress: No seed set');
}
n = n || 1;
var keys = this._generatePrivKeys(pwDerivedKey, n);
for (var i = 0; i < n; i++) {
var keyObj = keys[i];
var address = KeyStore._computeAddressFromPrivKey(keyObj.privKey);
this.encPrivKeys[address] = keyObj.encPrivKey;
this.addresses.push(address);
}
};
KeyStore.prototype.keyFromPassword = function (password, callback) {
KeyStore.deriveKeyFromPasswordAndSalt(password, this.salt, callback);
};
KeyStore.prototype.passwordProvider = function (callback) {
var password = prompt('Enter password to continue', 'Enter password');
callback(null, password);
};
KeyStore.prototype.hasAddress = function (address, callback) {
var addrToCheck = Util.stripHexPrefix(address);
if (this.encPrivKeys[addrToCheck] === undefined) {
var err = new Error('Address not found!');
callback(err, false);
return;
}
callback(null, true);
};
KeyStore.prototype.signTransaction = function (txParams, callback) {
var _this = this;
var gas = txParams.gas,
params = _objectWithoutProperties(txParams, ["gas"]);
var txObj = _objectSpread({}, params, {
gasLimit: gas
});
var tx = TxUtils.createTx(txObj);
var rawTx = TxUtils.txToHexString(tx);
var signingAddress = Util.stripHexPrefix(txParams.from);
this.passwordProvider(function (err, password) {
if (err) {
callback(err);
return;
}
_this.keyFromPassword(password, function (err, pwDerivedKey) {
if (err) {
callback(err);
return;
}
var signedTx = Signing.signTx(_this, pwDerivedKey, rawTx, signingAddress);
callback(null, Util.addHexPrefix(signedTx));
});
});
};
KeyStore.prototype._generatePrivKeys = function (pwDerivedKey, n) {
Assert.derivedKey(this, pwDerivedKey);
var hdRoot = KeyStore._decryptString(this.encHdRootPriv, pwDerivedKey);
if (!hdRoot || hdRoot.length === 0) {
throw new Error('Provided password derived key is wrong');
}
var keys = [];
for (var i = 0; i < n; i++) {
var hdPrivateKey = new BitCore.HDPrivateKey(hdRoot).derive(this.hdIndex++);
var privateKeyBuf = hdPrivateKey.privateKey.toBuffer();
var privateKeyHex = privateKeyBuf.toString('hex');
if (privateKeyBuf.length < 16) {
// Way too small key, something must have gone wrong
// Halt and catch fire
throw new Error('Private key suspiciously small: < 16 bytes. Aborting!');
} else if (privateKeyBuf.length > 32) {
throw new Error('Private key larger than 32 bytes. Aborting!');
} else if (privateKeyBuf.length < 32) {
// Pad private key if too short
// bitcore has a bug where it sometimes returns
// truncated keys
privateKeyHex = leftPadString(privateKeyBuf.toString('hex'), '0', 64);
}
var encPrivateKey = KeyStore._encryptKey(privateKeyHex, pwDerivedKey);
keys[i] = {
privKey: privateKeyHex,
encPrivKey: encPrivateKey
};
}
return keys;
};
KeyStore.createVault = function (opts, cb) {
var hdPathString = opts.hdPathString,
seedPhrase = opts.seedPhrase,
password = opts.password;
var salt = opts.salt; // Default hdPathString
if (!hdPathString) {
var err = new Error('Keystore: Must include hdPathString in createVault inputs. Suggested alternatives are m/0\'/0\'/0\' for previous lightwallet default, or m/44\'/60\'/0\'/0 for BIP44 (used by Jaxx & MetaMask)');
return cb(err);
}
if (!seedPhrase) {
var _err = new Error('Keystore: Must include seedPhrase in createVault inputs.');
return cb(_err);
}
if (!salt) {
salt = KeyStore.generateSalt(32);
}
KeyStore.deriveKeyFromPasswordAndSalt(password, salt, function (err, pwDerivedKey) {
if (err) {
cb(err);
return;
}
var ks = new KeyStore();
ks.init(seedPhrase, pwDerivedKey, hdPathString, salt);
cb(null, ks);
});
};
KeyStore.generateSalt = function (byteCount) {
return BitCore.crypto.Random.getRandomBuffer(byteCount || 32).toString('base64');
}; // Generates a random seed. If the optional string extraEntropy is set,
// a random set of entropy is created, then concatenated with extraEntropy
// and hashed to produce the entropy that gives the seed.
// Thus if extraEntropy comes from a high-entropy source (like dice)
// it can give some protection from a bad RNG.
// If extraEntropy is not set, the random number generator is used directly.
KeyStore.generateRandomSeed = function (extraEntropy) {
var seed = '';
if (extraEntropy === undefined) {
seed = new Mnemonic(Mnemonic.Words.ENGLISH);
} else if (typeof extraEntropy === 'string') {
var entBuf = new Buffer(extraEntropy);
var randBuf = Random.getRandomBuffer(256 / 8);
var hashedEnt = this._concatAndSha256(randBuf, entBuf).slice(0, 128 / 8);
seed = new Mnemonic(hashedEnt, Mnemonic.Words.ENGLISH);
} else {
throw new Error('generateRandomSeed: extraEntropy is set but not a string.');
}
return seed.toString();
};
KeyStore.isSeedValid = function (seed) {
return Mnemonic.isValid(seed, Mnemonic.Words.ENGLISH);
};
KeyStore.deserialize = function (keystore) {
var dataKS = JSON.parse(keystore);
var version = dataKS.version,
salt = dataKS.salt,
encSeed = dataKS.encSeed,
encHdRootPriv = dataKS.encHdRootPriv,
encPrivKeys = dataKS.encPrivKeys,
hdIndex = dataKS.hdIndex,
hdPathString = dataKS.hdPathString,
addresses = dataKS.addresses;
if (version === undefined || version < 3) {
throw new Error('Old version of serialized keystore. Please use KeyStore.upgradeOldSerialized() to convert it to the latest version.');
}
var ks = new KeyStore();
ks.salt = salt;
ks.hdPathString = hdPathString;
ks.encSeed = encSeed;
ks.encHdRootPriv = encHdRootPriv;
ks.version = version;
ks.hdIndex = hdIndex;
ks.encPrivKeys = encPrivKeys;
ks.addresses = addresses;
return ks;
};
KeyStore.deriveKeyFromPasswordAndSalt = function (password, salt, callback) {
// Do not require salt, and default it to 'lightwalletSalt'
// (for backwards compatibility)
if (!callback && typeof salt === 'function') {
callback = salt;
salt = KeyStore.DEFAULT_SALT;
} else if (!salt && typeof callback === 'function') {
salt = KeyStore.DEFAULT_SALT;
}
var logN = 14;
var r = 8;
var dkLen = 32;
var interruptStep = 200;
var cb = function cb(derKey) {
var err = null;
var ui8arr = null;
try {
ui8arr = new Uint8Array(derKey);
} catch (e) {
err = e;
}
callback(err, ui8arr);
};
ScryptAsync(password, salt, logN, r, dkLen, interruptStep, cb, null);
};
KeyStore._encryptString = function (string, pwDerivedKey) {
var nonce = Nacl.randomBytes(Nacl.secretbox.nonceLength);
var encStr = Nacl.secretbox(NaclUtil.decodeUTF8(string), nonce, pwDerivedKey);
return {
encStr: NaclUtil.encodeBase64(encStr),
nonce: NaclUtil.encodeBase64(nonce)
};
};
KeyStore._decryptString = function (encryptedStr, pwDerivedKey) {
var decStr = NaclUtil.decodeBase64(encryptedStr.encStr);
var nonce = NaclUtil.decodeBase64(encryptedStr.nonce);
var decryptedStr = Nacl.secretbox.open(decStr, nonce, pwDerivedKey);
if (decryptedStr === null) {
return false;
}
return NaclUtil.encodeUTF8(decryptedStr);
};
KeyStore._encryptKey = function (privateKey, pwDerivedKey) {
var nonce = Nacl.randomBytes(Nacl.secretbox.nonceLength);
var privateKeyArray = Encryption.decodeHex(privateKey);
var encKey = Nacl.secretbox(privateKeyArray, nonce, pwDerivedKey);
return {
key: NaclUtil.encodeBase64(encKey),
nonce: NaclUtil.encodeBase64(nonce)
};
};
KeyStore._decryptKey = function (encryptedKey, pwDerivedKey) {
var decKey = NaclUtil.decodeBase64(encryptedKey.key);
var nonce = NaclUtil.decodeBase64(encryptedKey.nonce);
var decryptedKey = Nacl.secretbox.open(decKey, nonce, pwDerivedKey);
if (decryptedKey === null) {
throw new Error('Decryption failed!');
}
return Encryption.encodeHex(decryptedKey);
};
KeyStore._computeAddressFromPrivKey = function (privateKey) {
var keyPair = ec.genKeyPair();
keyPair._importPrivate(privateKey, 'hex');
var pubKey = keyPair.getPublic(false, 'hex').slice(2);
var pubKeyWordArray = CryptoJS.enc.Hex.parse(pubKey);
var hash = CryptoJS.SHA3(pubKeyWordArray, {
outputLength: 256
});
var address = hash.toString(CryptoJS.enc.Hex).slice(24);
return address;
};
KeyStore._computePubkeyFromPrivKey = function (privKey, curve) {
if (curve !== 'curve25519') {
throw new Error('KeyStore._computePubkeyFromPrivKey: Only "curve25519" supported.');
}
var privateKeyBase64 = new Buffer(privKey, 'hex').toString('base64');
var privateKeyUInt8Array = NaclUtil.decodeBase64(privateKeyBase64);
var pubKey = Nacl.box.keyPair.fromSecretKey(privateKeyUInt8Array).publicKey;
var pubKeyBase64 = NaclUtil.encodeBase64(pubKey);
var pubKeyHex = new Buffer(pubKeyBase64, 'base64').toString('hex');
return pubKeyHex;
}; // This function is tested using the test vectors here:
// http://www.di-mgt.com.au/sha_testvectors.html
KeyStore._concatAndSha256 = function (entropyBuf0, entropyBuf1) {
var totalEnt = Buffer.concat([entropyBuf0, entropyBuf1]);
if (totalEnt.length !== entropyBuf0.length + entropyBuf1.length) {
throw new Error('generateRandomSeed: Logic error! Concatenation of entropy sources failed.');
}
return Hash.sha256(totalEnt);
};
KeyStore.DEFAULT_SALT = 'lightwalletSalt';
module.exports = KeyStore;
}).call(this,require("buffer").Buffer)
},{"./assert":2,"./encryption":3,"./signing":5,"./txutils":6,"bitcore-lib":29,"bitcore-mnemonic":93,"buffer":138,"crypto-js":155,"elliptic":191,"ethereumjs-util":210,"scrypt-async":290,"tweetnacl":311,"tweetnacl-util":310}],5:[function(require,module,exports){
(function (Buffer){
"use strict";
var Transaction = require('ethereumjs-tx');
var Util = require('ethereumjs-util');
var Assert = require('./assert');
function getPrivateKeyBuff(keystore, pwDerivedKey, address) {
var privateKey = keystore.exportPrivateKey(Util.stripHexPrefix(address), pwDerivedKey);
return new Buffer(privateKey, 'hex');
}
function signTx(keystore, pwDerivedKey, rawTx, signingAddress) {
Assert.derivedKey(keystore, pwDerivedKey);
var tx = new Transaction(new Buffer(Util.stripHexPrefix(rawTx), 'hex'));
var privateKeyBuff = getPrivateKeyBuff(keystore, pwDerivedKey, signingAddress);
tx.sign(privateKeyBuff);
return tx.serialize().toString('hex');
}
function signMsg(keystore, pwDerivedKey, rawMsg, signingAddress) {
Assert.derivedKey(keystore, pwDerivedKey);
var msgHash = Util.addHexPrefix(Util.keccak(rawMsg).toString('hex'));
return this.signMsgHash(keystore, pwDerivedKey, msgHash, signingAddress);
}
function signMsgHash(keystore, pwDerivedKey, msgHash, signingAddress) {
Assert.derivedKey(keystore, pwDerivedKey);
var msgBuff = new Buffer(Util.stripHexPrefix(msgHash), 'hex');
var privateKeyBuff = getPrivateKeyBuff(keystore, pwDerivedKey, signingAddress);
return Util.ecsign(msgBuff, privateKeyBuff);
}
function concatSig(signature) {
var v = signature.v;
var r = signature.r;
var s = signature.s;
r = Util.fromSigned(r);
s = Util.fromSigned(s);
v = Util.bufferToInt(v);
r = Util.setLengthLeft(Util.toUnsigned(r), 32).toString('hex');
s = Util.setLengthLeft(Util.toUnsigned(s), 32).toString('hex');
v = Util.stripHexPrefix(Util.intToHex(v));
return Util.addHexPrefix(r.concat(s, v).toString('hex'));
}
function recoverAddress(rawMsg, v, r, s) {
var msgHash = Util.keccak(rawMsg);
return Util.pubToAddress(Util.ecrecover(msgHash, v, r, s));
}
module.exports = {
signTx: signTx,
signMsg: signMsg,
signMsgHash: signMsgHash,
concatSig: concatSig,
recoverAddress: recoverAddress
};
}).call(this,require("buffer").Buffer)
},{"./assert":2,"buffer":138,"ethereumjs-tx":208,"ethereumjs-util":210}],6:[function(require,module,exports){
(function (Buffer){
"use strict";
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { keys.push.apply(keys, Object.getOwnPropertySymbols(object)); } if (enumerableOnly) keys = keys.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var Transaction = require('ethereumjs-tx');
var Util = require('ethereumjs-util');
var Coder = require('web3/lib/solidity/coder');
var Rlp = require('rlp');
var CryptoJS = require('crypto-js');
function createTx(txObject) {
return new Transaction(_objectSpread({}, txObject.from && {
from: Util.addHexPrefix(txObject.from)
}, {}, txObject.to && {
to: Util.addHexPrefix(txObject.to)
}, {}, txObject.gasPrice && {
gasPrice: Util.addHexPrefix(txObject.gasPrice)
}, {}, txObject.gasLimit && {
gasLimit: Util.addHexPrefix(txObject.gasLimit)
}, {}, txObject.nonce && {
nonce: Util.addHexPrefix(txObject.nonce)
}, {}, txObject.value && {
value: Util.addHexPrefix(txObject.value)
}, {}, txObject.data && {
data: Util.addHexPrefix(txObject.data)
}));
}
function txToHexString(tx) {
return Util.addHexPrefix(tx.serialize().toString('hex'));
}
function _getTypesFromAbi(abi, functionName) {
var funcJson = abi.filter(function (json) {
return json.type === 'function' && json.name === functionName;
})[0];
return funcJson.inputs.map(function (json) {
return json.type;
});
}
function _encodeFunctionTxData(functionName, types, args) {
var fullName = "".concat(functionName, "(").concat(types.join(), ")");
var signature = CryptoJS.SHA3(fullName, {
outputLength: 256
}).toString(CryptoJS.enc.Hex).slice(0, 8);
var encodeParams = Coder.encodeParams(types, args);
var dataHex = Util.addHexPrefix("".concat(signature).concat(encodeParams));
return dataHex;
}
function functionTx(abi, functionName, args, txObject) {
var types = _getTypesFromAbi(abi, functionName);
var txData = _encodeFunctionTxData(functionName, types, args);
var tx = createTx(_objectSpread({}, txObject, {
data: txData
}));
return txToHexString(tx);
}
function valueTx(txObject) {
var tx = createTx(txObject);
return txToHexString(tx);
}
function createdContractAddress(fromAddress, nonce) {
var addressBuf = new Buffer(Util.stripHexPrefix(fromAddress), 'hex');
var rlpEncodedHex = Rlp.encode([addressBuf, nonce]).toString('hex');
var rlpEncodedWordArray = CryptoJS.enc.Hex.parse(rlpEncodedHex);
var hash = CryptoJS.SHA3(rlpEncodedWordArray, {
outputLength: 256
}).toString(CryptoJS.enc.Hex);
return Util.addHexPrefix(hash.slice(24));
}
function createContractTx(fromAddress, txObject) {
var tx = createTx(txObject);
var contractAddress = createdContractAddress(fromAddress, txObject.nonce);
return {
tx: txToHexString(tx),
addr: contractAddress
};
}
module.exports = {
_encodeFunctionTxData: _encodeFunctionTxData,
_getTypesFromAbi: _getTypesFromAbi,
createTx: createTx,
txToHexString: txToHexString,
functionTx: functionTx,
createdContractAddress: createdContractAddress,
createContractTx: createContractTx,
valueTx: valueTx
};
}).call(this,require("buffer").Buffer)
},{"buffer":138,"crypto-js":155,"ethereumjs-tx":208,"ethereumjs-util":210,"rlp":288,"web3/lib/solidity/coder":321}],7:[function(require,module,exports){
"use strict";
var CryptoJS = require('crypto-js');
var Keystore = require('./keystore');
var HD_PATH_STRING = 'm/0\'/0\'/0\'';
function legacyGenerateEncKey(password, salt) {
return CryptoJS.PBKDF2(password, salt, {
keySize: 512 / 32,
iterations: 150
}).toString();
}
function legacyDecryptString(encryptedStr, password) {
var encStr = encryptedStr.encStr,
iv = encryptedStr.iv,
salt = encryptedStr.salt;
var decryptedStr = CryptoJS.AES.decrypt(encStr, password, {
iv: iv,
salt: salt
});
return decryptedStr.toString(CryptoJS.enc.Latin1);
}
function upgradeVersion1(oldKS, password, callback) {
var salt = oldKS.salt,
keyHash = oldKS.keyHash,
encSeed = oldKS.encSeed,
hdIndex = oldKS.hdIndex;
var derivedKey = legacyGenerateEncKey(password, salt);
var hash = CryptoJS.SHA3(derivedKey).toString();
if (keyHash !== hash) {
callback(new Error('Keystore Upgrade: Invalid Password!'));
return;
}
var seedPhrase = legacyDecryptString(encSeed, derivedKey);
Keystore.createVault({
password: password,
seedPhrase: seedPhrase,
salt: Keystore.DEFAULT_SALT,
hdPathString: HD_PATH_STRING
}, function (err, newKeyStore) {
if (err) {
callback(err);
return;
}
newKeyStore.keyFromPassword(password, function (err, pwDerivedKey) {
if (err) {
callback(err);
return;
}
newKeyStore.generateNewAddress(pwDerivedKey, hdIndex);
callback(null, newKeyStore.serialize());
});
});
}
function upgradeVersion2(oldKS, password, callback) {
var _oldKS$salt = oldKS.salt,
salt = _oldKS$salt === void 0 ? Keystore.DEFAULT_SALT : _oldKS$salt,
encSeed = oldKS.encSeed,
ksData = oldKS.ksData;
Keystore.deriveKeyFromPasswordAndSalt(password, salt, function (err, pwKey) {
if (err) {
callback(err);
return;
}
var seedPhrase = Keystore._decryptString(encSeed, pwKey);
if (seedPhrase) {
seedPhrase = seedPhrase.trim();
}
if (!seedPhrase || !Keystore.isSeedValid(seedPhrase)) {
callback(new Error('Keystore Upgrade: Invalid provided password.'));
return;
}
var hdPaths = Object.keys(ksData);
var hdPathString = HD_PATH_STRING;
if (hdPaths.length > 0) {
hdPathString = hdPaths[0];
}
Keystore.createVault({
password: password,
seedPhrase: seedPhrase,
salt: salt,
hdPathString: hdPathString
}, function (err, newKeyStore) {
if (err) {
callback(err);
return;
}
newKeyStore.keyFromPassword(password, function (err, pwDerivedKey) {
if (err) {
callback(err);
return;
}
var hdIndex = ksData[hdPathString].hdIndex;
newKeyStore.generateNewAddress(pwDerivedKey, hdIndex);
callback(null, newKeyStore.serialize());
});
});
});
}
function upgradeOldSerialized(oldSerialized, password, callback) {
var oldKS = JSON.parse(oldSerialized);
var version = oldKS.version;
if (version === undefined || version === 1) {
upgradeVersion1(oldKS, password, callback);
} else if (version === 2) {
upgradeVersion2(oldKS, password, callback);
} else if (version === 3) {
callback(null, oldSerialized);
} else {
throw new Error('Keystore is not of correct version.');
}
}
module.exports = {
upgradeOldSerialized: upgradeOldSerialized
};
},{"./keystore":4,"crypto-js":155}],8:[function(require,module,exports){
"use strict";
var asn1 = exports;
asn1.bignum = require('bn.js');
asn1.define = require('./asn1/api').define;
asn1.base = require('./asn1/base');
asn1.constants = require('./asn1/constants');
asn1.decoders = require('./asn1/decoders');
asn1.encoders = require('./asn1/encoders');
},{"./asn1/api":9,"./asn1/base":11,"./asn1/constants":15,"./asn1/decoders":17,"./asn1/encoders":20,"bn.js":105}],9:[function(require,module,exports){
"use strict";
var asn1 = require('../asn1');
var inherits = require('inherits');
var api = exports;
api.define = function define(name, body) {
return new Entity(name, body);
};
function Entity(name, body) {
this.name = name;
this.body = body;
this.decoders = {};
this.encoders = {};
}
;
Entity.prototype._createNamed = function createNamed(base) {
var named;
try {
named = require('vm').runInThisContext('(function ' + this.name + '(entity) {\n' + ' this._initNamed(entity);\n' + '})');
} catch (e) {
named = function named(entity) {
this._initNamed(entity);
};
}
inherits(named, base);
named.prototype._initNamed = function initnamed(entity) {
base.call(this, entity);
};
return new named(this);
};
Entity.prototype._getDecoder = function _getDecoder(enc) {
enc = enc || 'der'; // Lazily create decoder
if (!this.decoders.hasOwnProperty(enc)) this.decoders[enc] = this._createNamed(asn1.decoders[enc]);
return this.decoders[enc];
};
Entity.prototype.decode = function decode(data, enc, options) {
return this._getDecoder(enc).decode(data, options);
};
Entity.prototype._getEncoder = function _getEncoder(enc) {
enc = enc || 'der'; // Lazily create encoder
if (!this.encoders.hasOwnProperty(enc)) this.encoders[enc] = this._createNamed(asn1.encoders[enc]);
return this.encoders[enc];
};
Entity.prototype.encode = function encode(data, enc,
/* internal */
reporter) {
return this._getEncoder(enc).encode(data, reporter);
};
},{"../asn1":8,"inherits":230,"vm":317}],10:[function(require,module,exports){
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
var inherits = require('inherits');
var Reporter = require('../base').Reporter;
var Buffer = require('buffer').Buffer;
function DecoderBuffer(base, options) {
Reporter.call(this, options);
if (!Buffer.isBuffer(base)) {
this.error('Input not Buffer');
return;
}
this.base = base;
this.offset = 0;
this.length = base.length;
}
inherits(DecoderBuffer, Reporter);
exports.DecoderBuffer = DecoderBuffer;
DecoderBuffer.prototype.save = function save() {
return {
offset: this.offset,
reporter: Reporter.prototype.save.call(this)
};
};
DecoderBuffer.prototype.restore = function restore(save) {
// Return skipped data
var res = new DecoderBuffer(this.base);
res.offset = save.offset;
res.length = this.offset;
this.offset = save.offset;
Reporter.prototype.restore.call(this, save.reporter);
return res;
};
DecoderBuffer.prototype.isEmpty = function isEmpty() {
return this.offset === this.length;
};
DecoderBuffer.prototype.readUInt8 = function readUInt8(fail) {
if (this.offset + 1 <= this.length) return this.base.readUInt8(this.offset++, true);else return this.error(fail || 'DecoderBuffer overrun');
};
DecoderBuffer.prototype.skip = function skip(bytes, fail) {
if (!(this.offset + bytes <= this.length)) return this.error(fail || 'DecoderBuffer overrun');
var res = new DecoderBuffer(this.base); // Share reporter state
res._reporterState = this._reporterState;
res.offset = this.offset;
res.length = this.offset + bytes;
this.offset += bytes;
return res;
};
DecoderBuffer.prototype.raw = function raw(save) {
return this.base.slice(save ? save.offset : this.offset, this.length);
};
function EncoderBuffer(value, reporter) {
if (Array.isArray(value)) {
this.length = 0;
this.value = value.map(function (item) {
if (!(item instanceof EncoderBuffer)) item = new EncoderBuffer(item, reporter);
this.length += item.length;
return item;
}, this);
} else if (typeof value === 'number') {
if (!(0 <= value && value <= 0xff)) return reporter.error('non-byte EncoderBuffer value');
this.value = value;
this.length = 1;
} else if (typeof value === 'string') {
this.value = value;
this.length = Buffer.byteLength(value);
} else if (Buffer.isBuffer(value)) {
this.value = value;
this.length = value.length;
} else {
return reporter.error('Unsupported type: ' + _typeof(value));
}
}
exports.EncoderBuffer = EncoderBuffer;
EncoderBuffer.prototype.join = function join(out, offset) {
if (!out) out = new Buffer(this.length);
if (!offset) offset = 0;
if (this.length === 0) return out;
if (Array.isArray(this.value)) {
this.value.forEach(function (item) {
item.join(out, offset);
offset += item.length;
});
} else {
if (typeof this.value === 'number') out[offset] = this.value;else if (typeof this.value === 'string') out.write(this.value, offset);else if (Buffer.isBuffer(this.value)) this.value.copy(out, offset);
offset += this.length;
}
return out;
};
},{"../base":11,"buffer":138,"inherits":230}],11:[function(require,module,exports){
"use strict";
var base = exports;
base.Reporter = require('./reporter').Reporter;
base.DecoderBuffer = require('./buffer').DecoderBuffer;
base.EncoderBuffer = require('./buffer').EncoderBuffer;
base.Node = require('./node');
},{"./buffer":10,"./node":12,"./reporter":13}],12:[function(require,module,exports){
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
var Reporter = require('../base').Reporter;
var EncoderBuffer = require('../base').EncoderBuffer;
var DecoderBuffer = require('../base').DecoderBuffer;
var assert = require('minimalistic-assert'); // Supported tags
var tags = ['seq', 'seqof', 'set', 'setof', 'objid', 'bool', 'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc', 'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str', 'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr']; // Public methods list
var methods = ['key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice', 'any', 'contains'].concat(tags); // Overrided methods list
var overrided = ['_peekTag', '_decodeTag', '_use', '_decodeStr', '_decodeObjid', '_decodeTime', '_decodeNull', '_decodeInt', '_decodeBool', '_decodeList', '_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime', '_encodeNull', '_encodeInt', '_encodeBool'];
function Node(enc, parent) {
var state = {};
this._baseState = state;
state.enc = enc;
state.parent = parent || null;
state.children = null; // State
state.tag = null;
state.args = null;
state.reverseArgs = null;
state.choice = null;
state.optional = false;
state.any = false;
state.obj = false;
state.use = null;
state.useDecoder = null;
state.key = null;
state['default'] = null;
state.explicit = null;
state.implicit = null;
state.contains = null; // Should create new instance on each method
if (!state.parent) {
state.children = [];
this._wrap();
}
}
module.exports = Node;
var stateProps = ['enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice', 'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit', 'implicit', 'contains'];
Node.prototype.clone = function clone() {
var state = this._baseState;
var cstate = {};
stateProps.forEach(function (prop) {
cstate[prop] = state[prop];
});
var res = new this.constructor(cstate.parent);
res._baseState = cstate;
return res;
};
Node.prototype._wrap = function wrap() {
var state = this._baseState;
methods.forEach(function (method) {
this[method] = function _wrappedMethod() {
var clone = new this.constructor(this);
state.children.push(clone);
return clone[method].apply(clone, arguments);
};
}, this);
};
Node.prototype._init = function init(body) {
var state = this._baseState;
assert(state.parent === null);
body.call(this); // Filter children
state.children = state.children.filter(function (child) {
return child._baseState.parent === this;
}, this);
assert.equal(state.children.length, 1, 'Root node can have only one child');
};
Node.prototype._useArgs = function useArgs(args) {
var state = this._baseState; // Filter children and args
var children = args.filter(function (arg) {
return arg instanceof this.constructor;
}, this);
args = args.filter(function (arg) {
return !(arg instanceof this.constructor);
}, this);
if (children.length !== 0) {
assert(state.children === null);
state.children = children; // Replace parent to maintain backward link
children.forEach(function (child) {
child._baseState.parent = this;
}, this);
}
if (args.length !== 0) {
assert(state.args === null);
state.args = args;
state.reverseArgs = args.map(function (arg) {
if (_typeof(arg) !== 'object' || arg.constructor !== Object) return arg;
var res = {};
Object.keys(arg).forEach(function (key) {
if (key == (key | 0)) key |= 0;
var value = arg[key];
res[value] = key;
});
return res;
});
}
}; //
// Overrided methods
//
overrided.forEach(function (method) {
Node.prototype[method] = function _overrided() {
var state = this._baseState;
throw new Error(method + ' not implemented for encoding: ' + state.enc);
};
}); //
// Public methods
//
tags.forEach(function (tag) {
Node.prototype[tag] = function _tagMethod() {
var state = this._baseState;
var args = Array.prototype.slice.call(arguments);
assert(state.tag === null);
state.tag = tag;
this._useArgs(args);
return this;
};
});
Node.prototype.use = function use(item) {
assert(item);
var state = this._baseState;
assert(state.use === null);
state.use = item;
return this;
};
Node.prototype.optional = function optional() {
var state = this._baseState;
state.optional = true;
return this;
};
Node.prototype.def = function def(val) {
var state = this._baseState;
assert(state['default'] === null);
state['default'] = val;
state.optional = true;
return this;
};
Node.prototype.explicit = function explicit(num) {
var state = this._baseState;
assert(state.explicit === null && state.implicit === null);
state.explicit = num;
return this;
};
Node.prototype.implicit = function implicit(num) {
var state = this._baseState;
assert(state.explicit === null && state.implicit === null);
state.implicit = num;
return this;
};
Node.prototype.obj = function obj() {
var state = this._baseState;
var args = Array.prototype.slice.call(arguments);
state.obj = true;
if (args.length !== 0) this._useArgs(args);
return this;
};
Node.prototype.key = function key(newKey) {
var state = this._baseState;
assert(state.key === null);
state.key = newKey;
return this;
};
Node.prototype.any = function any() {
var state = this._baseState;
state.any = true;
return this;
};
Node.prototype.choice = function choice(obj) {
var state = this._baseState;
assert(state.choice === null);
state.choice = obj;
this._useArgs(Object.keys(obj).map(function (key) {
return obj[key];
}));
return this;
};
Node.prototype.contains = function contains(item) {
var state = this._baseState;
assert(state.use === null);
state.contains = item;
return this;
}; //
// Decoding
//
Node.prototype._decode = function decode(input, options) {
var state = this._baseState; // Decode root node
if (state.parent === null) return input.wrapResult(state.children[0]._decode(input, options));
var result = state['default'];
var present = true;
var prevKey = null;
if (state.key !== null) prevKey = input.enterKey(state.key); // Check if tag is there
if (state.optional) {
var tag = null;
if (state.explicit !== null) tag = state.explicit;else if (state.implicit !== null) tag = state.implicit;else if (state.tag !== null) tag = state.tag;
if (tag === null && !state.any) {
// Trial and Error
var save = input.save();
try {
if (state.choice === null) this._decodeGeneric(state.tag, input, options);else this._decodeChoice(input, options);
present = true;
} catch (e) {
present = false;
}
input.restore(save);
} else {
present = this._peekTag(input, tag, state.any);
if (input.isError(present)) return present;
}
} // Push object on stack
var prevObj;
if (state.obj && present) prevObj = input.enterObject();
if (present) {
// Unwrap explicit values
if (state.explicit !== null) {
var explicit = this._decodeTag(input, state.explicit);
if (input.isError(explicit)) return explicit;
input = explicit;
}
var start = input.offset; // Unwrap implicit and normal values
if (state.use === null && state.choice === null) {
if (state.any) var save = input.save();
var body = this._decodeTag(input, state.implicit !== null ? state.implicit : state.tag, state.any);
if (input.isError(body)) return body;
if (state.any) result = input.raw(save);else input = body;
}
if (options && options.track && state.tag !== null) options.track(input.path(), start, input.length, 'tagged');
if (options && options.track && state.tag !== null) options.track(input.path(), input.offset, input.length, 'content'); // Select proper method for tag
if (state.any) result = result;else if (state.choice === null) result = this._decodeGeneric(state.tag, input, options);else result = this._decodeChoice(input, options);
if (input.isError(result)) return result; // Decode children
if (!state.any && state.choice === null && state.children !== null) {
state.children.forEach(function decodeChildren(child) {
// NOTE: We are ignoring errors here, to let parser continue with other
// parts of encoded data
child._decode(input, options);
});
} // Decode contained/encoded by schema, only in bit or octet strings
if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) {
var data = new DecoderBuffer(result);
result = this._getUse(state.contains, input._reporterState.obj)._decode(data, options);
}
} // Pop object
if (state.obj && present) result = input.leaveObject(prevObj); // Set key
if (state.key !== null && (result !== null || present === true)) input.leaveKey(prevKey, state.key, result);else if (prevKey !== null) input.exitKey(prevKey);
return result;
};
Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) {
var state = this._baseState;
if (tag === 'seq' || tag === 'set') return null;
if (tag === 'seqof' || tag === 'setof') return this._decodeList(input, tag, state.args[0], options);else if (/str$/.test(tag)) return this._decodeStr(input, tag, options);else if (tag === 'objid' && state.args) return this._decodeObjid(input, state.args[0], state.args[1], options);else if (tag === 'objid') return this._decodeObjid(input, null, null, options);else if (tag === 'gentime' || tag === 'utctime') return this._decodeTime(input, tag, options);else if (tag === 'null_') return this._decodeNull(input, options);else if (tag === 'bool') return this._decodeBool(input, options);else if (tag === 'objDesc') return this._decodeStr(input, tag, options);else if (tag === 'int' || tag === 'enum') return this._decodeInt(input, state.args && state.args[0], options);
if (state.use !== null) {
return this._getUse(state.use, input._reporterState.obj)._decode(input, options);
} else {
return input.error('unknown tag: ' + tag);
}
};
Node.prototype._getUse = function _getUse(entity, obj) {
var state = this._baseState; // Create altered use decoder if implicit is set
state.useDecoder = this._use(entity, obj);
assert(state.useDecoder._baseState.parent === null);
state.useDecoder = state.useDecoder._baseState.children[0];
if (state.implicit !== state.useDecoder._baseState.implicit) {
state.useDecoder = state.useDecoder.clone();
state.useDecoder._baseState.implicit = state.implicit;
}
return state.useDecoder;
};
Node.prototype._decodeChoice = function decodeChoice(input, options) {
var state = this._baseSt