Bitcoin.KeyPool = (function () { var KeyPool = function () { this.keyArray = []; this.push = function (item) { if (item == null || item.priv == null) return; var doAdd = true; // prevent duplicates from being added to the array for (var index in this.keyArray) { var currentItem = this.keyArray[index]; if (currentItem != null && currentItem.priv != null && item.getBitcoinAddress() == currentItem.getBitcoinAddress()) { doAdd = false; break; } } if (doAdd) this.keyArray.push(item); }; this.reset = function () { this.keyArray = []; }; this.getArray = function () { // copy array return this.keyArray.slice(0); }; this.setArray = function (ka) { this.keyArray = ka; }; this.length = function () { return this.keyArray.length; }; this.toString = function () { var keyPoolString = "# = " + this.length() + "\n"; var pool = this.getArray(); for (var index in pool) { var item = pool[index]; if (Bitcoin.Util.hasMethods(item, 'getBitcoinAddress', 'toString')) { if (item != null) { keyPoolString += "\"" + item.getBitcoinAddress() + "\"" + ", \"" + item.toString("wif") + "\"\n"; } } } return keyPoolString; }; return this; }; return new KeyPool(); })(); Bitcoin.Bip38Key = (function () { var Bip38 = function (address, encryptedKey) { this.address = address; this.priv = encryptedKey; }; Bip38.prototype.getBitcoinAddress = function () { return this.address; }; Bip38.prototype.toString = function () { return this.priv; }; return Bip38; })(); //https://raw.github.com/pointbiz/bitcoinjs-lib/9b2f94a028a7bc9bed94e0722563e9ff1d8e8db8/src/eckey.js Bitcoin.ECKey = (function () { var ECDSA = Bitcoin.ECDSA; var KeyPool = Bitcoin.KeyPool; var ecparams = EllipticCurve.getSECCurveByName("secp256k1"); var ECKey = function (input) { if (!input) { // Generate new key var n = ecparams.getN(); this.priv = ECDSA.getBigRandom(n); } else if (input instanceof BigInteger) { // Input is a private key value this.priv = input; } else if (Bitcoin.Util.isArray(input)) { // Prepend zero byte to prevent interpretation as negative integer this.priv = BigInteger.fromByteArrayUnsigned(input); } else if ("string" == typeof input) { var bytes = null; if (ECKey.isWalletImportFormat(input)) { bytes = ECKey.decodeWalletImportFormat(input); } else if (ECKey.isCompressedWalletImportFormat(input)) { bytes = ECKey.decodeCompressedWalletImportFormat(input); this.compressed = true; } else if (ECKey.isMiniFormat(input)) { bytes = Crypto.SHA256(input, { asBytes: true }); } else if (ECKey.isHexFormat(input)) { bytes = Crypto.util.hexToBytes(input); } else if (ECKey.isBase64Format(input)) { bytes = Crypto.util.base64ToBytes(input); } if (ECKey.isBase6Format(input)) { this.priv = new BigInteger(input, 6); } else if (bytes == null || bytes.length != 32) { this.priv = null; } else { // Prepend zero byte to prevent interpretation as negative integer this.priv = BigInteger.fromByteArrayUnsigned(bytes); } } this.compressed = (this.compressed == undefined) ? !!ECKey.compressByDefault : this.compressed; KeyPool.push(this); }; ECKey.privateKeyPrefix = 0x80; // mainnet 0x80 testnet 0xEF /** * Whether public keys should be returned compressed by default. */ ECKey.compressByDefault = false; /** * Set whether the public key should be returned compressed or not. */ ECKey.prototype.setCompressed = function (v) { this.compressed = !!v; if (this.pubPoint) this.pubPoint.compressed = this.compressed; return this; }; /* * Return public key as a byte array in DER encoding */ ECKey.prototype.getPub = function () { if (this.compressed) { if (this.pubComp) return this.pubComp; return this.pubComp = this.getPubPoint().getEncoded(1); } else { if (this.pubUncomp) return this.pubUncomp; return this.pubUncomp = this.getPubPoint().getEncoded(0); } }; /** * Return public point as ECPoint object. */ ECKey.prototype.getPubPoint = function () { if (!this.pubPoint) { this.pubPoint = ecparams.getG().multiply(this.priv); this.pubPoint.compressed = this.compressed; } return this.pubPoint; }; ECKey.prototype.getPubKeyHex = function () { if (this.compressed) { if (this.pubKeyHexComp) return this.pubKeyHexComp; return this.pubKeyHexComp = Crypto.util.bytesToHex(this.getPub()).toString().toUpperCase(); } else { if (this.pubKeyHexUncomp) return this.pubKeyHexUncomp; return this.pubKeyHexUncomp = Crypto.util.bytesToHex(this.getPub()).toString().toUpperCase(); } }; /** * Get the pubKeyHash for this key. * * This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as * a byte array. */ ECKey.prototype.getPubKeyHash = function () { if (this.compressed) { if (this.pubKeyHashComp) return this.pubKeyHashComp; return this.pubKeyHashComp = Bitcoin.Util.sha256ripe160(this.getPub()); } else { if (this.pubKeyHashUncomp) return this.pubKeyHashUncomp; return this.pubKeyHashUncomp = Bitcoin.Util.sha256ripe160(this.getPub()); } }; ECKey.prototype.getBitcoinAddress = function () { var hash = this.getPubKeyHash(); var addr = new Bitcoin.Address(hash); return addr.toString(); }; /* * Takes a public point as a hex string or byte array */ ECKey.prototype.setPub = function (pub) { // byte array if (Bitcoin.Util.isArray(pub)) { pub = Crypto.util.bytesToHex(pub).toString().toUpperCase(); } var ecPoint = ecparams.getCurve().decodePointHex(pub); this.setCompressed(ecPoint.compressed); this.pubPoint = ecPoint; return this; }; // Sipa Private Key Wallet Import Format ECKey.prototype.getBitcoinWalletImportFormat = function () { var bytes = this.getBitcoinPrivateKeyByteArray(); if (bytes == null) return ""; bytes.unshift(ECKey.privateKeyPrefix); // prepend 0x80 byte if (this.compressed) bytes.push(0x01); // append 0x01 byte for compressed format var checksum = Crypto.SHA256(Crypto.SHA256(bytes, { asBytes: true }), { asBytes: true }); bytes = bytes.concat(checksum.slice(0, 4)); var privWif = Bitcoin.Base58.encode(bytes); return privWif; }; // Private Key Hex Format ECKey.prototype.getBitcoinHexFormat = function () { return Crypto.util.bytesToHex(this.getBitcoinPrivateKeyByteArray()).toString().toUpperCase(); }; // Private Key Base64 Format ECKey.prototype.getBitcoinBase64Format = function () { return Crypto.util.bytesToBase64(this.getBitcoinPrivateKeyByteArray()); }; ECKey.prototype.getBitcoinPrivateKeyByteArray = function () { if (this.priv == null) return null; // Get a copy of private key as a byte array var bytes = this.priv.toByteArrayUnsigned(); // zero pad if private key is less than 32 bytes while (bytes.length < 32) bytes.unshift(0x00); return bytes; }; ECKey.prototype.toString = function (format) { format = format || ""; if (format.toString().toLowerCase() == "base64" || format.toString().toLowerCase() == "b64") { return this.getBitcoinBase64Format(); } // Wallet Import Format else if (format.toString().toLowerCase() == "wif") { return this.getBitcoinWalletImportFormat(); } else { return this.getBitcoinHexFormat(); } }; ECKey.prototype.sign = function (hash) { return ECDSA.sign(hash, this.priv); }; ECKey.prototype.verify = function (hash, sig) { return ECDSA.verify(hash, sig, this.getPub()); }; /** * Parse a wallet import format private key contained in a string. */ ECKey.decodeWalletImportFormat = function (privStr) { var bytes = Bitcoin.Base58.decode(privStr); var hash = bytes.slice(0, 33); var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true }); if (checksum[0] != bytes[33] || checksum[1] != bytes[34] || checksum[2] != bytes[35] || checksum[3] != bytes[36]) { throw "Checksum validation failed!"; } var version = hash.shift(); if (version != ECKey.privateKeyPrefix) { throw "Version " + version + " not supported!"; } return hash; }; /** * Parse a compressed wallet import format private key contained in a string. */ ECKey.decodeCompressedWalletImportFormat = function (privStr) { var bytes = Bitcoin.Base58.decode(privStr); var hash = bytes.slice(0, 34); var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true }); if (checksum[0] != bytes[34] || checksum[1] != bytes[35] || checksum[2] != bytes[36] || checksum[3] != bytes[37]) { throw "Checksum validation failed!"; } var version = hash.shift(); if (version != ECKey.privateKeyPrefix) { throw "Version " + version + " not supported!"; } hash.pop(); return hash; }; // 64 characters [0-9A-F] ECKey.isHexFormat = function (key) { key = key.toString(); return /^[A-Fa-f0-9]{64}$/.test(key); }; // 51 characters base58, always starts with a '5' ECKey.isWalletImportFormat = function (key) { key = key.toString(); return (ECKey.privateKeyPrefix == 0x80) ? (/^5[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{50}$/.test(key)) : (/^9[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{50}$/.test(key)); }; // 52 characters base58 ECKey.isCompressedWalletImportFormat = function (key) { key = key.toString(); return (ECKey.privateKeyPrefix == 0x80) ? (/^[LK][123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{51}$/.test(key)) : (/^c[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{51}$/.test(key)); }; // 44 characters ECKey.isBase64Format = function (key) { key = key.toString(); return (/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=+\/]{44}$/.test(key)); }; // 99 characters, 1=1, if using dice convert 6 to 0 ECKey.isBase6Format = function (key) { key = key.toString(); return (/^[012345]{99}$/.test(key)); }; // 22, 26 or 30 characters, always starts with an 'S' ECKey.isMiniFormat = function (key) { key = key.toString(); var validChars22 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21}$/.test(key); var validChars26 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{25}$/.test(key); var validChars30 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{29}$/.test(key); var testBytes = Crypto.SHA256(key + "?", { asBytes: true }); return ((testBytes[0] === 0x00 || testBytes[0] === 0x01) && (validChars22 || validChars26 || validChars30)); }; return ECKey; })();