v3.0.0 add session log of keypairs
This commit is contained in:
parent
3cd0ae0e8b
commit
c26f106f81
17 changed files with 686 additions and 238 deletions
|
@ -28,6 +28,10 @@ END USER NOTES:
|
|||
|
||||
Here is a signed list of file names and version history.
|
||||
|
||||
2015-10-25: status ACTIVE
|
||||
bitaddress.org-v3.0.0-SHA256-4781574ca09c07f65d1966619f37a762aac6decd8732cacc85b2f2f972f82751.html
|
||||
- add session log icon that shows all the key pairs generated during the current session.
|
||||
|
||||
2015-08-16: status ACTIVE
|
||||
bitaddress.org-v2.9.11-SHA256-40376eddc790a63d9afcfb72c0a45002827da965f3bfe6ba8c330e697bf188b2.html
|
||||
- add status icons for checking the URI protocol used, support for window.crypto.getRandomValues
|
||||
|
|
|
@ -31,6 +31,10 @@ END USER NOTES:
|
|||
|
||||
Here is a signed list of file names and version history.
|
||||
|
||||
2015-10-25: status ACTIVE
|
||||
bitaddress.org-v3.0.0-SHA256-4781574ca09c07f65d1966619f37a762aac6decd8732cacc85b2f2f972f82751.html
|
||||
- add session log icon that shows all the key pairs generated during the current session.
|
||||
|
||||
2015-08-16: status ACTIVE
|
||||
bitaddress.org-v2.9.11-SHA256-40376eddc790a63d9afcfb72c0a45002827da965f3bfe6ba8c330e697bf188b2.html
|
||||
- add status icons for checking the URI protocol used, support for window.crypto.getRandomValues
|
||||
|
@ -298,11 +302,11 @@ bitaddress.org-v0.1-SHA1-f40e706490f3eb2be56c31ddbf4c8646cd51ef40.html
|
|||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.13 (MingW32)
|
||||
|
||||
iQEcBAEBAgAGBQJV0Pu2AAoJEIdJe5Fjl09avHcH/31ABkos0xmXJ6E1PC2P7SUN
|
||||
SiX6ehnKVTnMzbu1APhyJ2hlUrpSOBS0bbRhlHc9M6X2z8aqBT5izRba6V3LnxJ7
|
||||
dxtPPv++ieJR/5s6EIrbn1I1f+eoCxKCtuFabmqq/Pmc+ChMbjsWbTz/Nx1lwjSq
|
||||
F/a1k5RqEL3qMPHTc2eCwT4UdlcNr5YKm/8bJTbRKFygWGfj7U0ryX87h+xI3D2s
|
||||
jO69dtU6hiQ490574Hl1w9cDMbAdNkhXP5TXZ9Tl7Lqs1SMgHZ9Shi+8xjiOyUSM
|
||||
7hnRbGyK+r2DbpyLzFnayvez1Zu3oELa5qKNgIq1rS3XLZzxPXId+0li/MRSn1c=
|
||||
=5DkH
|
||||
iQEcBAEBAgAGBQJWLSSBAAoJEIdJe5Fjl09ajBMIAJobpBphyjpCmkt8CIzILevd
|
||||
YZ4M9wCXq0rDj8oRmHzwHDU/UEqTQtmw0NK4juogBiBdfQ6SKon2woISYw1jg6g7
|
||||
EaL3n14dykaXxCvRCo8uTqLr3zsK0w9bxBa0GQ9uh+xG61vM9B14bFkVn90zXLsw
|
||||
njn+wyibt4b4NmymKdklU4Ds1jTfquAB/9+dbi7DT5p6hcCGTcvWqekLyVYzVmzO
|
||||
fiAmbQyWgGC1GvvRsIhi5vgzhLttXaC/K6s4Ypb74Qd5Uw7DO3qje3pmdZF1V/gQ
|
||||
HOsL43jhqFSeGz2SbdJZLQOi1l9GA04cODJsa18tyiZ5ItbXfp9XKL/EcIG1mV4=
|
||||
=8hP9
|
||||
-----END PGP SIGNATURE-----
|
||||
|
|
|
@ -5620,11 +5620,83 @@ Bitcoin.ECDSA = (function () {
|
|||
})();
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
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 () {
|
||||
return this.keyArray;
|
||||
};
|
||||
|
||||
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 rng = new SecureRandom();
|
||||
|
||||
var ECKey = function (input) {
|
||||
if (!input) {
|
||||
|
@ -5663,6 +5735,7 @@ Bitcoin.ECKey = (function () {
|
|||
}
|
||||
|
||||
this.compressed = (this.compressed == undefined) ? !!ECKey.compressByDefault : this.compressed;
|
||||
KeyPool.push(this);
|
||||
};
|
||||
|
||||
ECKey.privateKeyPrefix = 0x80; // mainnet 0x80 testnet 0xEF
|
||||
|
@ -5754,6 +5827,7 @@ Bitcoin.ECKey = (function () {
|
|||
// 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 });
|
||||
|
@ -5773,6 +5847,7 @@ Bitcoin.ECKey = (function () {
|
|||
};
|
||||
|
||||
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
|
||||
|
@ -5995,6 +6070,16 @@ Bitcoin.Util = {
|
|||
// double sha256
|
||||
dsha256: function (data) {
|
||||
return Crypto.SHA256(Crypto.SHA256(data, { asBytes: true }), { asBytes: true });
|
||||
},
|
||||
// duck typing method
|
||||
hasMethods: function(obj /*, method list as strings */){
|
||||
var i = 1, methodName;
|
||||
while((methodName = arguments[i++])){
|
||||
if(typeof obj[methodName] != 'function') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -6321,7 +6406,7 @@ body, html { height: 99%; }
|
|||
.question:hover, .expandable:hover { color: #77777A; }
|
||||
.answer { padding: 0 15px 10px 25px; text-align: left; display: none; font-size: 80%; }
|
||||
.faq { border: 0; border-top: 2px solid #009900; }
|
||||
.button {}
|
||||
.button { margin-left: 5px; margin-right: 5px; }
|
||||
|
||||
#wallets { clear: both; }
|
||||
#btcaddress, #btcprivwif, #detailaddress, #detailaddresscomp, #detailprivwif, #detailprivwifcomp { font-family: monospace; font-size: 1.25em; }
|
||||
|
@ -6502,7 +6587,7 @@ body, html { height: 99%; }
|
|||
#bulkstartindex, #paperlimit, #paperlimitperpage { width: 35px; }
|
||||
#bulklimit { width: 45px; }
|
||||
|
||||
.footer { font-size: 90%; clear: both; width: 750px; padding: 10px 0 10px 0; margin: 50px auto auto auto; }
|
||||
.footer { font-size: 90%; clear: both; width: 770px; padding: 10px 0 10px 0; margin: 50px auto auto auto; }
|
||||
.footer div span.item { padding: 10px; }
|
||||
.footer .authorbtc { float: left; width: 470px; }
|
||||
.footer .authorbtc span.item { text-align: left; display: block; padding: 0 20px; }
|
||||
|
@ -6589,6 +6674,7 @@ body, html { height: 99%; }
|
|||
<span class="print"><input type="button" name="print" value="Print" id="singleprint" onclick="window.print();" /></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div id="keyarea" class="keyarea">
|
||||
<div class="public">
|
||||
<div class="pubaddress">
|
||||
|
@ -6620,6 +6706,7 @@ body, html { height: 99%; }
|
|||
<p id="singletip5"><b>Spend your bitcoins</b> by going to blockchain.info and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="paperarea">
|
||||
<div class="commands">
|
||||
|
@ -6919,10 +7006,18 @@ body, html { height: 99%; }
|
|||
<div class="tooltip" id="statusprotocolbad">
|
||||
<span class="statuswarn" id="statuslabelprotocolbad">⚠ Think twice!</span>
|
||||
<span id="statuslabelprotocolbad1">You appear to be running this generator online from a live website. For valuable wallets it is recommended to</span>
|
||||
<a id="statuslabelprotocolbad2" href="https://github.com/pointbiz/bitaddress.org/archive/v2.9.11.zip">download</a>
|
||||
<a id="statuslabelprotocolbad2" href="https://github.com/pointbiz/bitaddress.org/archive/v3.0.0.zip">download</a>
|
||||
<span id="statuslabelprotocolbad3">the zip file from GitHub and run this generator offline as a local html file.</span>
|
||||
<br /><br /><input type="button" value="OK" class="button" id="statusokprotocolbad" onclick="document.getElementById('statusprotocolbad').style.display = 'none';" />
|
||||
</div>
|
||||
<div class="tooltip" id="statuskeypoolgood">
|
||||
<span id="statuslabelkeypool1">This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.</span>
|
||||
<textarea rows="20" cols="102" id="keypooltextarea"></textarea>
|
||||
|
||||
<br /><br />
|
||||
<input type="button" value="Refresh" class="button" id="statuskeypoolrefresh" onclick="ninja.status.showKeyPool();" />
|
||||
<input type="button" value="OK" class="button" id="statusokkeypool" onclick="document.getElementById('statuskeypoolgood').style.display = 'none';" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="authorbtc">
|
||||
|
@ -6931,22 +7026,24 @@ body, html { height: 99%; }
|
|||
<span class="statusicon" id="statusprotocol" onclick="ninja.status.showProtocol();">...</span>
|
||||
<span class="statusicon" id="statuscrypto" onclick="ninja.status.showCrypto();">...</span>
|
||||
<span class="statusicon" id="statusunittests" onclick="ninja.status.showUnitTests();">...</span>
|
||||
<span class="statusicon" id="statuskeypool" onclick="ninja.status.showKeyPool();"></span>
|
||||
</span>
|
||||
<span class="item"><span id="footerlabeldonations">Donations:</span> <b>1NiNja</b>1bUmhSoTXozBRBEtR8LeF9TGbZBN</span>
|
||||
<span class="item" id="footerlabeltranslatedby"></span>
|
||||
<span class="item"><a href="https://github.com/pointbiz/bitaddress.org" target="_blank" id="footerlabelgithub">GitHub Repository</a>
|
||||
(<a href="https://github.com/pointbiz/bitaddress.org/archive/v2.9.11.zip" target="_blank" id="footerlabelgithubzip">zip</a>)</span>
|
||||
(<a href="https://github.com/pointbiz/bitaddress.org/archive/v3.0.0.zip" target="_blank" id="footerlabelgithubzip">zip</a>)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="authorpgp">
|
||||
<span class="item">
|
||||
<a href="CHANGELOG.txt.asc" target="_blank"><span id="footerlabelversion">Version History</span> (2.9.11)</a>
|
||||
<a href="CHANGELOG.txt.asc" target="_blank"><span id="footerlabelversion">Version History</span> (3.0.0)</a>
|
||||
|
||||
</span>
|
||||
<span class="item">527B 5C82 B1F6 B2DB 72A0<br />ECBF 8749 7B91 6397 4F5A</span>
|
||||
<span class="item">
|
||||
(<a href="ninja_bitaddress.org.txt" target="_blank" id="footerlabelpgp">PGP</a>)
|
||||
(<a href="pointbiz_bitaddress.org.asc" target="_blank" id="footerlabelpgp">PGP</a>)
|
||||
(<a href="javascript:window.location=window.location.pathname+'.sig';" target="_blank" id="footerlabelsig">sig</a>)
|
||||
</span>
|
||||
</div>
|
||||
<div class="copyright">
|
||||
<span id="footerlabelcopyright1">Copyright bitaddress.org.</span>
|
||||
|
@ -7091,9 +7188,12 @@ ninja.privateKey = {
|
|||
var prefactorB = prefactorA.concat(ownerentropy); // ownerentropy using closure
|
||||
passfactor = Bitcoin.Util.dsha256(prefactorB);
|
||||
}
|
||||
// remove this ECKey from the pool (because user does not see it)
|
||||
var userKeyPool = Bitcoin.KeyPool.getArray();
|
||||
Bitcoin.KeyPool.reset();
|
||||
var kp = new Bitcoin.ECKey(passfactor);
|
||||
var passpoint = kp.setCompressed(true).getPub();
|
||||
|
||||
Bitcoin.KeyPool.setArray(userKeyPool);
|
||||
var encryptedpart2 = hex.slice(23, 23 + 16);
|
||||
|
||||
var addresshashplusownerentropy = hex.slice(3, 3 + 12);
|
||||
|
@ -7557,6 +7657,8 @@ ninja.publicKey = {
|
|||
document.getElementById("statusunittests").innerHTML = "×"; //×
|
||||
unitTestsCase = "bad";
|
||||
}
|
||||
// show session log icon
|
||||
document.getElementById("statuskeypool").innerHTML = "≣"; //≣
|
||||
};
|
||||
|
||||
var showCrypto = function () {
|
||||
|
@ -7571,7 +7673,15 @@ ninja.publicKey = {
|
|||
if(unitTestsCase != "") document.getElementById('statusunittests' + unitTestsCase).style.display = 'block';
|
||||
};
|
||||
|
||||
return { unitTests: unitTests, showCrypto: showCrypto, showProtocol: showProtocol, showUnitTests: showUnitTests };
|
||||
var showKeyPool = function () {
|
||||
document.getElementById('statuskeypoolgood').style.display = 'block';
|
||||
document.getElementById("keypooltextarea").value = Bitcoin.KeyPool.toString();
|
||||
};
|
||||
|
||||
return {
|
||||
unitTests: unitTests, showCrypto: showCrypto, showProtocol: showProtocol,
|
||||
showUnitTests: showUnitTests, showKeyPool: showKeyPool
|
||||
};
|
||||
}();
|
||||
})(ninja);
|
||||
|
||||
|
@ -7806,6 +7916,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Generar dirección",
|
||||
|
@ -7967,6 +8080,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Générer Une Nouvelle Adresse",
|
||||
|
@ -8128,6 +8244,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Δημιουργία μιας νέας Διεύθυνσης",
|
||||
|
@ -8289,6 +8408,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Genera un Nuovo Indirizzo",
|
||||
|
@ -8450,6 +8572,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Neues Wallet erstellen",
|
||||
|
@ -8611,6 +8736,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Vytvořit novou adresu",
|
||||
|
@ -8772,6 +8900,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Új cím előállítása",
|
||||
|
@ -8939,6 +9070,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "新アドレス生成",
|
||||
|
@ -9107,6 +9241,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Gerar endereço",
|
||||
|
@ -9268,6 +9405,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "生成新地址",
|
||||
|
@ -9435,6 +9575,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Сгенерировать новый адрес",
|
||||
|
@ -9573,14 +9716,15 @@ ninja.translator.showEnglishJson = function () {
|
|||
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
ninja.wallets.singlewallet = {
|
||||
(function (wallets) {
|
||||
var single = wallets.singlewallet = {
|
||||
isOpen: function () {
|
||||
return (document.getElementById("singlewallet").className.indexOf("selected") != -1);
|
||||
},
|
||||
|
||||
open: function () {
|
||||
if (document.getElementById("btcaddress").innerHTML == "") {
|
||||
ninja.wallets.singlewallet.generateNewAddressAndKey();
|
||||
single.generateNewAddressAndKey();
|
||||
}
|
||||
document.getElementById("singlearea").style.display = "block";
|
||||
},
|
||||
|
@ -9612,7 +9756,8 @@ ninja.wallets.singlewallet = {
|
|||
document.getElementById("qrcode_private").innerHTML = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})(ninja.wallets);
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
ninja.wallets.paperwallet = {
|
||||
|
@ -9718,6 +9863,7 @@ ninja.wallets.paperwallet = {
|
|||
generateNewWallet: function (idPostFix) {
|
||||
if (ninja.wallets.paperwallet.encrypt) {
|
||||
ninja.privateKey.BIP38GenerateECAddressAsync(ninja.wallets.paperwallet.intermediatePoint, false, function (address, encryptedKey) {
|
||||
Bitcoin.KeyPool.push(new Bitcoin.Bip38Key(address, encryptedKey));
|
||||
if (ninja.wallets.paperwallet.useArtisticWallet) {
|
||||
ninja.wallets.paperwallet.showArtisticWallet(idPostFix, address, encryptedKey);
|
||||
}
|
||||
|
@ -10229,7 +10375,10 @@ ninja.wallets.detailwallet = {
|
|||
},
|
||||
|
||||
populateKeyDetails: function (btcKey) {
|
||||
|
||||
if (btcKey.priv != null) {
|
||||
// get the original compression value and set it back later in this function
|
||||
var originalCompression = btcKey.compressed;
|
||||
btcKey.setCompressed(false);
|
||||
document.getElementById("detailprivhex").innerHTML = btcKey.toString().toUpperCase();
|
||||
document.getElementById("detailprivb64").innerHTML = btcKey.toString("base64");
|
||||
|
@ -10244,6 +10393,9 @@ ninja.wallets.detailwallet = {
|
|||
document.getElementById("detailpubkeycomp").innerHTML = btcKey.getPubKeyHex();
|
||||
document.getElementById("detailaddresscomp").innerHTML = bitcoinAddressComp;
|
||||
document.getElementById("detailprivwifcomp").innerHTML = wifComp;
|
||||
btcKey.setCompressed(originalCompression); // to satisfy the key pool
|
||||
var pool1 = new Bitcoin.ECKey(wif); // to satisfy the key pool
|
||||
var pool2 = new Bitcoin.ECKey(wifComp); // to satisfy the key pool
|
||||
|
||||
ninja.qrCode.showQrCode({
|
||||
"detailqrcodepublic": bitcoinAddress,
|
||||
|
@ -10438,22 +10590,31 @@ ninja.wallets.splitwallet = {
|
|||
document.body.appendChild(div);
|
||||
document.getElementById("busyblock").className = "";
|
||||
}
|
||||
Bitcoin.KeyPool.reset(); // reset the key pool so users don't see the test keys
|
||||
return { passCount: passCount, testCount: testCount };
|
||||
},
|
||||
|
||||
runAsynchronousTests: function () {
|
||||
runAsynchronousTests: function (showOutput) {
|
||||
if (showOutput) {
|
||||
var div = document.createElement("div");
|
||||
div.setAttribute("class", "unittests");
|
||||
div.setAttribute("id", "asyncunittests");
|
||||
div.innerHTML = "<h3>Async Unit Tests</h3><div id=\"asyncunittestresults\"></div><br/><br/><br/><br/>";
|
||||
document.body.appendChild(div);
|
||||
}
|
||||
|
||||
var userKeyPool = Bitcoin.KeyPool.getArray();
|
||||
// run the asynchronous tests one after another so we don't crash the browser
|
||||
ninja.foreachSerialized(ninja.unitTests.asynchronousTests, function (name, cb) {
|
||||
Bitcoin.KeyPool.reset();
|
||||
document.getElementById("busyblock").className = "busy";
|
||||
ninja.unitTests.asynchronousTests[name](cb);
|
||||
}, function () {
|
||||
if (showOutput) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running of asynchronous unit tests complete!<br/>";
|
||||
}
|
||||
console.log("running of asynchronous unit tests complete!");
|
||||
Bitcoin.KeyPool.setArray(userKeyPool);
|
||||
document.getElementById("busyblock").className = "";
|
||||
});
|
||||
},
|
||||
|
@ -10697,7 +10858,8 @@ ninja.wallets.splitwallet = {
|
|||
var key = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||||
var btcKey = new Bitcoin.ECKey(key);
|
||||
if (btcKey.getBitcoinWalletImportFormat() != "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S"
|
||||
|| btcKey.getPubPoint().compressed != true) {
|
||||
|| btcKey.getPubPoint().compressed != true
|
||||
|| btcKey.compressed != true) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -10705,7 +10867,8 @@ ninja.wallets.splitwallet = {
|
|||
testWifToECKey: function () {
|
||||
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||||
var btcKey = new Bitcoin.ECKey(key);
|
||||
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb") {
|
||||
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb"
|
||||
|| btcKey.compressed == true) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -10969,6 +11132,46 @@ ninja.wallets.splitwallet = {
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
//Bitcoin.KeyPool tests
|
||||
testKeyPoolStoresCompressedAndUncompressedKey: function () {
|
||||
var keyUncompressed = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||||
var keyCompressed = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||||
Bitcoin.KeyPool.reset();
|
||||
|
||||
var btcKeyUncompressed = new Bitcoin.ECKey(keyUncompressed);
|
||||
var btcKeyCompressed = new Bitcoin.ECKey(keyCompressed);
|
||||
var pool = Bitcoin.KeyPool.getArray();
|
||||
|
||||
if (pool.length != 2
|
||||
|| pool[0].getBitcoinWalletImportFormat() != keyUncompressed
|
||||
|| pool[1].getBitcoinWalletImportFormat() != keyCompressed
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
testKeyPoolPreventDuplicatesWhenAdding: function () {
|
||||
var keyUncompressed = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||||
var keyCompressed = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||||
var keyHex = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B";
|
||||
|
||||
Bitcoin.KeyPool.reset();
|
||||
var btcKeyUncompressed = new Bitcoin.ECKey(keyUncompressed);
|
||||
var btcKeyCompressed = new Bitcoin.ECKey(keyCompressed);
|
||||
var btcKeyCompressed2 = new Bitcoin.ECKey(keyCompressed);
|
||||
var btcKeyUncompressed2 = new Bitcoin.ECKey(keyUncompressed);
|
||||
var btcKeyHex = new Bitcoin.ECKey(keyHex);
|
||||
var pool = Bitcoin.KeyPool.getArray();
|
||||
|
||||
if (pool.length != 2
|
||||
|| pool[0].getBitcoinWalletImportFormat() != keyUncompressed
|
||||
|| pool[1].getBitcoinWalletImportFormat() != keyCompressed
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -10989,43 +11192,50 @@ ninja.wallets.splitwallet = {
|
|||
["6PgNBNNzDkKdhkT6uJntUXwwzQV8Rr2tZcbkDcuC9DZRsS6AtHts4Ypo1j", "MOLON LABE", "5JLdxTtcTHcfYcmJsNVy1v2PMDx432JPoYcBTVVRHpPaxUrdtf8"],
|
||||
["6PgGWtx25kUg8QWvwuJAgorN6k9FbE25rv5dMRwu5SKMnfpfVe5mar2ngH", Crypto.charenc.UTF8.bytesToString([206, 156, 206, 159, 206, 155, 206, 169, 206, 157, 32, 206, 155, 206, 145, 206, 146, 206, 149])/*UTF-8 characters, encoded in source so they don't get corrupted*/, "5KMKKuUmAkiNbA3DazMQiLfDq47qs8MAEThm4yL8R2PhV1ov33D"]];
|
||||
|
||||
var waitTimeMs = 60000;
|
||||
|
||||
// running each test uses a lot of memory, which isn't freed
|
||||
// immediately, so give the VM a little time to reclaim memory
|
||||
function waitThenCall(callback) {
|
||||
return function () { setTimeout(callback, 10000); }
|
||||
return function () { setTimeout(callback, waitTimeMs); }
|
||||
}
|
||||
|
||||
var decryptTest = function (test, i, onComplete) {
|
||||
function log(str) {
|
||||
if (document.getElementById("asyncunittestresults")) document.getElementById("asyncunittestresults").innerHTML += str + "<br/>";
|
||||
console.log(str);
|
||||
}
|
||||
|
||||
var decryptBip38Test = function (test, i, onComplete) {
|
||||
ninja.privateKey.BIP38EncryptedKeyToByteArrayAsync(test[0], test[1], function (privBytes) {
|
||||
if (privBytes.constructor == Error) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testDecryptBip38 #" + i + ", error: " + privBytes.message + "<br/>";
|
||||
log("fail decryptBip38Test #" + i + ", error: " + privBytes.message);
|
||||
} else {
|
||||
var btcKey = new Bitcoin.ECKey(privBytes);
|
||||
var wif = !test[2].substr(0, 1).match(/[LK]/) ? btcKey.setCompressed(false).getBitcoinWalletImportFormat() : btcKey.setCompressed(true).getBitcoinWalletImportFormat();
|
||||
if (wif != test[2]) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testDecryptBip38 #" + i + "<br/>";
|
||||
log("fail decryptBip38Test #" + i);
|
||||
} else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass testDecryptBip38 #" + i + "<br/>";
|
||||
log("pass decryptBip38Test #" + i);
|
||||
}
|
||||
}
|
||||
onComplete();
|
||||
});
|
||||
};
|
||||
|
||||
var encryptTest = function (test, compressed, i, onComplete) {
|
||||
var encryptBip38Test = function (test, compressed, i, onComplete) {
|
||||
ninja.privateKey.BIP38PrivateKeyToEncryptedKeyAsync(test[2], test[1], compressed, function (encryptedKey) {
|
||||
if (encryptedKey === test[0]) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass testBip38Encrypt #" + i + "<br/>";
|
||||
log("pass encryptBip38Test #" + i);
|
||||
} else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testBip38Encrypt #" + i + "<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "expected " + test[0] + "<br/>received " + encryptedKey + "<br/>";
|
||||
log("fail encryptBip38Test #" + i);
|
||||
log("expected " + test[0] + "<br/>received " + encryptedKey);
|
||||
}
|
||||
onComplete();
|
||||
});
|
||||
};
|
||||
|
||||
// test randomly generated encryption-decryption cycle
|
||||
var cycleTest = function (i, compress, onComplete) {
|
||||
var cycleBip38Test = function (i, compress, onComplete) {
|
||||
// create new private key
|
||||
var privKey = (new Bitcoin.ECKey(false)).getBitcoinWalletImportFormat();
|
||||
|
||||
|
@ -11036,11 +11246,11 @@ ninja.wallets.splitwallet = {
|
|||
var decryptedKey = (new Bitcoin.ECKey(decryptedBytes)).getBitcoinWalletImportFormat();
|
||||
|
||||
if (decryptedKey === privKey) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass cycleBip38 test #" + i + "<br/>";
|
||||
log("pass cycleBip38Test #" + i);
|
||||
}
|
||||
else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail cycleBip38 test #" + i + " " + privKey + "<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "encrypted key: " + encryptedKey + "<br/>decrypted key: " + decryptedKey;
|
||||
log("fail cycleBip38Test #" + i + " " + privKey);
|
||||
log("encrypted key: " + encryptedKey + "<br/>decrypted key: " + decryptedKey);
|
||||
}
|
||||
onComplete();
|
||||
});
|
||||
|
@ -11049,20 +11259,20 @@ ninja.wallets.splitwallet = {
|
|||
|
||||
// intermediate test - create some encrypted keys from an intermediate
|
||||
// then decrypt them to check that the private keys are recoverable
|
||||
var intermediateTest = function (i, onComplete) {
|
||||
var intermediateBip38Test = function (i, onComplete) {
|
||||
var pass = Math.random().toString(36).substr(2);
|
||||
ninja.privateKey.BIP38GenerateIntermediatePointAsync(pass, null, null, function (intermediatePoint) {
|
||||
ninja.privateKey.BIP38GenerateECAddressAsync(intermediatePoint, false, function (address, encryptedKey) {
|
||||
ninja.privateKey.BIP38EncryptedKeyToByteArrayAsync(encryptedKey, pass, function (privBytes) {
|
||||
if (privBytes.constructor == Error) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testBip38Intermediate #" + i + ", error: " + privBytes.message + "<br/>";
|
||||
log("fail intermediateBip38Test #" + i + ", error: " + privBytes.message);
|
||||
} else {
|
||||
var btcKey = new Bitcoin.ECKey(privBytes);
|
||||
var btcAddress = btcKey.getBitcoinAddress();
|
||||
if (address !== btcKey.getBitcoinAddress()) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testBip38Intermediate #" + i + "<br/>";
|
||||
log("fail intermediateBip38Test #" + i);
|
||||
} else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass testBip38Intermediate #" + i + "<br/>";
|
||||
log("pass intermediateBip38Test #" + i);
|
||||
}
|
||||
}
|
||||
onComplete();
|
||||
|
@ -11071,34 +11281,44 @@ ninja.wallets.splitwallet = {
|
|||
});
|
||||
}
|
||||
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running " + tests.length + " tests named testDecryptBip38<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running 4 tests named testBip38Encrypt<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running 2 tests named cycleBip38<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running 5 tests named testBip38Intermediate<br/>";
|
||||
ninja.runSerialized([
|
||||
var testArray = [
|
||||
function (cb) {
|
||||
log("running " + tests.length + " tests named decryptBip38Test");
|
||||
ninja.forSerialized(0, tests.length, function (i, callback) {
|
||||
decryptTest(tests[i], i, waitThenCall(callback));
|
||||
console.log("running decryptBip38Test #" + i + " " + tests[i]);
|
||||
decryptBip38Test(tests[i], i, waitThenCall(callback));
|
||||
}, waitThenCall(cb));
|
||||
},
|
||||
}
|
||||
,
|
||||
function (cb) {
|
||||
log("running 4 tests named encryptBip38Test");
|
||||
ninja.forSerialized(0, 4, function (i, callback) {
|
||||
console.log("running encryptBip38Test #" + i + " " + tests[i]);
|
||||
// only first 4 test vectors are not EC-multiply,
|
||||
// compression param false for i = 1,2 and true for i = 3,4
|
||||
encryptTest(tests[i], i >= 2, i, waitThenCall(callback));
|
||||
encryptBip38Test(tests[i], i >= 2, i, waitThenCall(callback));
|
||||
}, waitThenCall(cb));
|
||||
},
|
||||
}
|
||||
,
|
||||
function (cb) {
|
||||
log("running 2 tests named cycleBip38Test");
|
||||
ninja.forSerialized(0, 2, function (i, callback) {
|
||||
cycleTest(i, i % 2 ? true : false, waitThenCall(callback));
|
||||
console.log("running cycleBip38Test #" + i);
|
||||
cycleBip38Test(i, i % 2 ? true : false, waitThenCall(callback));
|
||||
}, waitThenCall(cb));
|
||||
},
|
||||
}
|
||||
,
|
||||
function (cb) {
|
||||
log("running 5 tests named intermediateBip38Test");
|
||||
ninja.forSerialized(0, 5, function (i, callback) {
|
||||
intermediateTest(i, waitThenCall(callback));
|
||||
console.log("running intermediateBip38Test #" + i);
|
||||
intermediateBip38Test(i, waitThenCall(callback));
|
||||
}, cb);
|
||||
}
|
||||
], done);
|
||||
];
|
||||
|
||||
ninja.runSerialized(testArray, done);
|
||||
//TODO: ninja.runSerialized([ testArray[0],testArray[1] ], done);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -11112,7 +11332,7 @@ if (ninja.getQueryString()["unittests"] == "true" || ninja.getQueryString()["uni
|
|||
}
|
||||
// run async unit tests
|
||||
if (ninja.getQueryString()["asyncunittests"] == "true" || ninja.getQueryString()["asyncunittests"] == "1") {
|
||||
ninja.unitTests.runAsynchronousTests();
|
||||
ninja.unitTests.runAsynchronousTests(true);
|
||||
}
|
||||
// change language
|
||||
if (ninja.getQueryString()["culture"] != undefined) {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.13 (MingW32)
|
||||
|
||||
iQEcBAABAgAGBQJV0PvPAAoJEIdJe5Fjl09aUz8IAIen68xsU8MnU56fHx+/KDbx
|
||||
fiYz88OU7I6PnB+0hlVc5TW5VH4RD8Tzfpc1+31+RyPJ+Va/PUdh68FptcthBsuL
|
||||
byv3+rrwxRDy/00stIQh1HBd0JJ+mX0DBCqnJ79NdGJJqEHW8D5VgfSnxaqvconi
|
||||
U5Q1RvzdArb/HcbQ5BvNTXRgHP+TzQBJ3hHyoCxtwOpa3Qd/w5FzkB2TN52mvEiw
|
||||
U1X0KrT4ntyLYAy4eJb+ecLYHi1dn92BTq8fqkj0mN+inBWb5J0zuZd/aBcqqvRM
|
||||
qBBPMHBjbXETOunM0PmQ/ENiOugIuN/3JqL0yqVHP1cZxqtLPK5Iw7AVUchPe+E=
|
||||
=O+Y0
|
||||
iQEcBAABAgAGBQJWLSSUAAoJEIdJe5Fjl09aOCEIAI4GIeb3WpHoEFzGs0hEaJ/k
|
||||
UHBlr716hqOyl0bmeTIABYMncJBxXsVtSphtGJChAAw4tdklRmCpXnauSrEnBqMO
|
||||
bTkjrLXcif5Xot4bJ1+mKJZtDtDj57bpICA/Am7tSchlK/tJNlW5WhV8egd6IF1M
|
||||
nkcWRz5Jx5VV+sDP0O/WgEYwL3dHZ+M4Q2Be+UCjj8G3GYbFOjocpowtab/2QXRF
|
||||
Q+3e7XHflMdY04wYc/V/0ZYPx7kUZ456OjNbEIOTkKb0Rb968ERTVGkm0XuDWUuk
|
||||
4Bay+IaRN6fSsHRtM1Qj6Z6ATSX4ofVh/qBTwjFJESrDz+4tBpbTTNfhvD7av1I=
|
||||
=HQw+
|
||||
-----END PGP SIGNATURE-----
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"name": "bitaddress.org",
|
||||
"version": "2.9.11",
|
||||
"sha1sum": "7232900c98e3af634a46374cd7178ce5e33cb96f",
|
||||
"sha256sum": "40376eddc790a63d9afcfb72c0a45002827da965f3bfe6ba8c330e697bf188b2",
|
||||
"version": "3.0.0",
|
||||
"sha1sum": "c3838fd668edd5e51aa262916ac7c286db0ddc51",
|
||||
"sha256sum": "4781574ca09c07f65d1966619f37a762aac6decd8732cacc85b2f2f972f82751",
|
||||
"description": "Open Source JavaScript Client-Side Bitcoin Wallet Generator",
|
||||
"main": "Gruntfile.js",
|
||||
"dependencies": {
|
||||
|
|
|
@ -163,6 +163,7 @@
|
|||
<span class="print"><input type="button" name="print" value="Print" id="singleprint" onclick="window.print();" /></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="body">
|
||||
<div id="keyarea" class="keyarea">
|
||||
<div class="public">
|
||||
<div class="pubaddress">
|
||||
|
@ -194,6 +195,7 @@
|
|||
<p id="singletip5"><b>Spend your bitcoins</b> by going to blockchain.info and sweep the full balance of your private key into your account at their website. You can also spend your funds by downloading one of the popular bitcoin p2p clients and importing your private key to the p2p client wallet. Keep in mind when you import your single key to a bitcoin p2p client and spend funds your key will be bundled with other private keys in the p2p client wallet. When you perform a transaction your change will be sent to another bitcoin address within the p2p client wallet. You must then backup the p2p client wallet and keep it safe as your remaining bitcoins will be stored there. Satoshi advised that one should never delete a wallet.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="paperarea">
|
||||
<div class="commands">
|
||||
|
@ -497,6 +499,14 @@
|
|||
<span id="statuslabelprotocolbad3">the zip file from GitHub and run this generator offline as a local html file.</span>
|
||||
<br /><br /><input type="button" value="OK" class="button" id="statusokprotocolbad" onclick="document.getElementById('statusprotocolbad').style.display = 'none';" />
|
||||
</div>
|
||||
<div class="tooltip" id="statuskeypoolgood">
|
||||
<span id="statuslabelkeypool1">This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.</span>
|
||||
<textarea rows="20" cols="102" id="keypooltextarea"></textarea>
|
||||
|
||||
<br /><br />
|
||||
<input type="button" value="Refresh" class="button" id="statuskeypoolrefresh" onclick="ninja.status.showKeyPool();" />
|
||||
<input type="button" value="OK" class="button" id="statusokkeypool" onclick="document.getElementById('statuskeypoolgood').style.display = 'none';" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="authorbtc">
|
||||
|
@ -505,6 +515,7 @@
|
|||
<span class="statusicon" id="statusprotocol" onclick="ninja.status.showProtocol();">...</span>
|
||||
<span class="statusicon" id="statuscrypto" onclick="ninja.status.showCrypto();">...</span>
|
||||
<span class="statusicon" id="statusunittests" onclick="ninja.status.showUnitTests();">...</span>
|
||||
<span class="statusicon" id="statuskeypool" onclick="ninja.status.showKeyPool();"></span>
|
||||
</span>
|
||||
<span class="item"><span id="footerlabeldonations">Donations:</span> <b>1NiNja</b>1bUmhSoTXozBRBEtR8LeF9TGbZBN</span>
|
||||
<span class="item" id="footerlabeltranslatedby"></span>
|
||||
|
@ -519,8 +530,9 @@
|
|||
</span>
|
||||
<span class="item">527B 5C82 B1F6 B2DB 72A0<br />ECBF 8749 7B91 6397 4F5A</span>
|
||||
<span class="item">
|
||||
(<a href="ninja_bitaddress.org.txt" target="_blank" id="footerlabelpgp">PGP</a>)
|
||||
(<a href="pointbiz_bitaddress.org.asc" target="_blank" id="footerlabelpgp">PGP</a>)
|
||||
(<a href="javascript:window.location=window.location.pathname+'.sig';" target="_blank" id="footerlabelsig">sig</a>)
|
||||
</span>
|
||||
</div>
|
||||
<div class="copyright">
|
||||
<span id="footerlabelcopyright1">Copyright bitaddress.org.</span>
|
||||
|
|
|
@ -1,8 +1,80 @@
|
|||
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 () {
|
||||
return this.keyArray;
|
||||
};
|
||||
|
||||
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 rng = new SecureRandom();
|
||||
|
||||
var ECKey = function (input) {
|
||||
if (!input) {
|
||||
|
@ -41,6 +113,7 @@ Bitcoin.ECKey = (function () {
|
|||
}
|
||||
|
||||
this.compressed = (this.compressed == undefined) ? !!ECKey.compressByDefault : this.compressed;
|
||||
KeyPool.push(this);
|
||||
};
|
||||
|
||||
ECKey.privateKeyPrefix = 0x80; // mainnet 0x80 testnet 0xEF
|
||||
|
@ -132,6 +205,7 @@ Bitcoin.ECKey = (function () {
|
|||
// 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 });
|
||||
|
@ -151,6 +225,7 @@ Bitcoin.ECKey = (function () {
|
|||
};
|
||||
|
||||
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
|
||||
|
|
|
@ -101,5 +101,15 @@ Bitcoin.Util = {
|
|||
// double sha256
|
||||
dsha256: function (data) {
|
||||
return Crypto.SHA256(Crypto.SHA256(data, { asBytes: true }), { asBytes: true });
|
||||
},
|
||||
// duck typing method
|
||||
hasMethods: function(obj /*, method list as strings */){
|
||||
var i = 1, methodName;
|
||||
while((methodName = arguments[i++])){
|
||||
if(typeof obj[methodName] != 'function') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
|
@ -23,7 +23,7 @@ body, html { height: 99%; }
|
|||
.question:hover, .expandable:hover { color: #77777A; }
|
||||
.answer { padding: 0 15px 10px 25px; text-align: left; display: none; font-size: 80%; }
|
||||
.faq { border: 0; border-top: 2px solid #009900; }
|
||||
.button {}
|
||||
.button { margin-left: 5px; margin-right: 5px; }
|
||||
|
||||
#wallets { clear: both; }
|
||||
#btcaddress, #btcprivwif, #detailaddress, #detailaddresscomp, #detailprivwif, #detailprivwifcomp { font-family: monospace; font-size: 1.25em; }
|
||||
|
@ -204,7 +204,7 @@ body, html { height: 99%; }
|
|||
#bulkstartindex, #paperlimit, #paperlimitperpage { width: 35px; }
|
||||
#bulklimit { width: 45px; }
|
||||
|
||||
.footer { font-size: 90%; clear: both; width: 750px; padding: 10px 0 10px 0; margin: 50px auto auto auto; }
|
||||
.footer { font-size: 90%; clear: both; width: 770px; padding: 10px 0 10px 0; margin: 50px auto auto auto; }
|
||||
.footer div span.item { padding: 10px; }
|
||||
.footer .authorbtc { float: left; width: 470px; }
|
||||
.footer .authorbtc span.item { text-align: left; display: block; padding: 0 20px; }
|
||||
|
|
|
@ -95,7 +95,10 @@ ninja.wallets.detailwallet = {
|
|||
},
|
||||
|
||||
populateKeyDetails: function (btcKey) {
|
||||
|
||||
if (btcKey.priv != null) {
|
||||
// get the original compression value and set it back later in this function
|
||||
var originalCompression = btcKey.compressed;
|
||||
btcKey.setCompressed(false);
|
||||
document.getElementById("detailprivhex").innerHTML = btcKey.toString().toUpperCase();
|
||||
document.getElementById("detailprivb64").innerHTML = btcKey.toString("base64");
|
||||
|
@ -110,6 +113,9 @@ ninja.wallets.detailwallet = {
|
|||
document.getElementById("detailpubkeycomp").innerHTML = btcKey.getPubKeyHex();
|
||||
document.getElementById("detailaddresscomp").innerHTML = bitcoinAddressComp;
|
||||
document.getElementById("detailprivwifcomp").innerHTML = wifComp;
|
||||
btcKey.setCompressed(originalCompression); // to satisfy the key pool
|
||||
var pool1 = new Bitcoin.ECKey(wif); // to satisfy the key pool
|
||||
var pool2 = new Bitcoin.ECKey(wifComp); // to satisfy the key pool
|
||||
|
||||
ninja.qrCode.showQrCode({
|
||||
"detailqrcodepublic": bitcoinAddress,
|
||||
|
|
|
@ -132,9 +132,12 @@ ninja.privateKey = {
|
|||
var prefactorB = prefactorA.concat(ownerentropy); // ownerentropy using closure
|
||||
passfactor = Bitcoin.Util.dsha256(prefactorB);
|
||||
}
|
||||
// remove this ECKey from the pool (because user does not see it)
|
||||
var userKeyPool = Bitcoin.KeyPool.getArray();
|
||||
Bitcoin.KeyPool.reset();
|
||||
var kp = new Bitcoin.ECKey(passfactor);
|
||||
var passpoint = kp.setCompressed(true).getPub();
|
||||
|
||||
Bitcoin.KeyPool.setArray(userKeyPool);
|
||||
var encryptedpart2 = hex.slice(23, 23 + 16);
|
||||
|
||||
var addresshashplusownerentropy = hex.slice(3, 3 + 12);
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
document.getElementById("statusunittests").innerHTML = "×"; //×
|
||||
unitTestsCase = "bad";
|
||||
}
|
||||
// show session log icon
|
||||
document.getElementById("statuskeypool").innerHTML = "≣"; //≣
|
||||
};
|
||||
|
||||
var showCrypto = function () {
|
||||
|
@ -49,7 +51,15 @@
|
|||
if(unitTestsCase != "") document.getElementById('statusunittests' + unitTestsCase).style.display = 'block';
|
||||
};
|
||||
|
||||
return { unitTests: unitTests, showCrypto: showCrypto, showProtocol: showProtocol, showUnitTests: showUnitTests };
|
||||
var showKeyPool = function () {
|
||||
document.getElementById('statuskeypoolgood').style.display = 'block';
|
||||
document.getElementById("keypooltextarea").value = Bitcoin.KeyPool.toString();
|
||||
};
|
||||
|
||||
return {
|
||||
unitTests: unitTests, showCrypto: showCrypto, showProtocol: showProtocol,
|
||||
showUnitTests: showUnitTests, showKeyPool: showKeyPool
|
||||
};
|
||||
}();
|
||||
})(ninja);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ if (ninja.getQueryString()["unittests"] == "true" || ninja.getQueryString()["uni
|
|||
}
|
||||
// run async unit tests
|
||||
if (ninja.getQueryString()["asyncunittests"] == "true" || ninja.getQueryString()["asyncunittests"] == "1") {
|
||||
ninja.unitTests.runAsynchronousTests();
|
||||
ninja.unitTests.runAsynchronousTests(true);
|
||||
}
|
||||
// change language
|
||||
if (ninja.getQueryString()["culture"] != undefined) {
|
||||
|
|
|
@ -101,6 +101,7 @@ ninja.wallets.paperwallet = {
|
|||
generateNewWallet: function (idPostFix) {
|
||||
if (ninja.wallets.paperwallet.encrypt) {
|
||||
ninja.privateKey.BIP38GenerateECAddressAsync(ninja.wallets.paperwallet.intermediatePoint, false, function (address, encryptedKey) {
|
||||
Bitcoin.KeyPool.push(new Bitcoin.Bip38Key(address, encryptedKey));
|
||||
if (ninja.wallets.paperwallet.useArtisticWallet) {
|
||||
ninja.wallets.paperwallet.showArtisticWallet(idPostFix, address, encryptedKey);
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
ninja.wallets.singlewallet = {
|
||||
(function (wallets) {
|
||||
var single = wallets.singlewallet = {
|
||||
isOpen: function () {
|
||||
return (document.getElementById("singlewallet").className.indexOf("selected") != -1);
|
||||
},
|
||||
|
||||
open: function () {
|
||||
if (document.getElementById("btcaddress").innerHTML == "") {
|
||||
ninja.wallets.singlewallet.generateNewAddressAndKey();
|
||||
single.generateNewAddressAndKey();
|
||||
}
|
||||
document.getElementById("singlearea").style.display = "block";
|
||||
},
|
||||
|
@ -37,4 +38,5 @@ ninja.wallets.singlewallet = {
|
|||
document.getElementById("qrcode_private").innerHTML = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})(ninja.wallets);
|
|
@ -145,6 +145,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Generar dirección",
|
||||
|
@ -306,6 +309,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Générer Une Nouvelle Adresse",
|
||||
|
@ -467,6 +473,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Δημιουργία μιας νέας Διεύθυνσης",
|
||||
|
@ -628,6 +637,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Genera un Nuovo Indirizzo",
|
||||
|
@ -789,6 +801,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Neues Wallet erstellen",
|
||||
|
@ -950,6 +965,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Vytvořit novou adresu",
|
||||
|
@ -1111,6 +1129,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Új cím előállítása",
|
||||
|
@ -1278,6 +1299,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "新アドレス生成",
|
||||
|
@ -1446,6 +1470,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Gerar endereço",
|
||||
|
@ -1607,6 +1634,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "生成新地址",
|
||||
|
@ -1774,6 +1804,9 @@ ninja.translator = {
|
|||
"statuslabelprotocolbad2": "download", //TODO: please translate
|
||||
"statuslabelprotocolbad3": "the zip file from GitHub and run this generator offline as a local html file.", //TODO: please translate
|
||||
"statusokprotocolbad": "OK", //TODO: please translate
|
||||
"statuslabelkeypool1": "This is a log of all the Bitcoin Addresses and Private Keys you generated during your current session. Reloading the page will create a new session.", //TODO: please translate
|
||||
"statuskeypoolrefresh": "Refresh", //TODO: please translate
|
||||
"statusokkeypool": "OK", //TODO: please translate
|
||||
|
||||
// single wallet html
|
||||
"newaddress": "Сгенерировать новый адрес",
|
||||
|
|
|
@ -38,22 +38,31 @@
|
|||
document.body.appendChild(div);
|
||||
document.getElementById("busyblock").className = "";
|
||||
}
|
||||
Bitcoin.KeyPool.reset(); // reset the key pool so users don't see the test keys
|
||||
return { passCount: passCount, testCount: testCount };
|
||||
},
|
||||
|
||||
runAsynchronousTests: function () {
|
||||
runAsynchronousTests: function (showOutput) {
|
||||
if (showOutput) {
|
||||
var div = document.createElement("div");
|
||||
div.setAttribute("class", "unittests");
|
||||
div.setAttribute("id", "asyncunittests");
|
||||
div.innerHTML = "<h3>Async Unit Tests</h3><div id=\"asyncunittestresults\"></div><br/><br/><br/><br/>";
|
||||
document.body.appendChild(div);
|
||||
}
|
||||
|
||||
var userKeyPool = Bitcoin.KeyPool.getArray();
|
||||
// run the asynchronous tests one after another so we don't crash the browser
|
||||
ninja.foreachSerialized(ninja.unitTests.asynchronousTests, function (name, cb) {
|
||||
Bitcoin.KeyPool.reset();
|
||||
document.getElementById("busyblock").className = "busy";
|
||||
ninja.unitTests.asynchronousTests[name](cb);
|
||||
}, function () {
|
||||
if (showOutput) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running of asynchronous unit tests complete!<br/>";
|
||||
}
|
||||
console.log("running of asynchronous unit tests complete!");
|
||||
Bitcoin.KeyPool.setArray(userKeyPool);
|
||||
document.getElementById("busyblock").className = "";
|
||||
});
|
||||
},
|
||||
|
@ -297,7 +306,8 @@
|
|||
var key = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||||
var btcKey = new Bitcoin.ECKey(key);
|
||||
if (btcKey.getBitcoinWalletImportFormat() != "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S"
|
||||
|| btcKey.getPubPoint().compressed != true) {
|
||||
|| btcKey.getPubPoint().compressed != true
|
||||
|| btcKey.compressed != true) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -305,7 +315,8 @@
|
|||
testWifToECKey: function () {
|
||||
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||||
var btcKey = new Bitcoin.ECKey(key);
|
||||
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb") {
|
||||
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb"
|
||||
|| btcKey.compressed == true) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -569,6 +580,46 @@
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
//Bitcoin.KeyPool tests
|
||||
testKeyPoolStoresCompressedAndUncompressedKey: function () {
|
||||
var keyUncompressed = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||||
var keyCompressed = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||||
Bitcoin.KeyPool.reset();
|
||||
|
||||
var btcKeyUncompressed = new Bitcoin.ECKey(keyUncompressed);
|
||||
var btcKeyCompressed = new Bitcoin.ECKey(keyCompressed);
|
||||
var pool = Bitcoin.KeyPool.getArray();
|
||||
|
||||
if (pool.length != 2
|
||||
|| pool[0].getBitcoinWalletImportFormat() != keyUncompressed
|
||||
|| pool[1].getBitcoinWalletImportFormat() != keyCompressed
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
testKeyPoolPreventDuplicatesWhenAdding: function () {
|
||||
var keyUncompressed = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||||
var keyCompressed = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||||
var keyHex = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B";
|
||||
|
||||
Bitcoin.KeyPool.reset();
|
||||
var btcKeyUncompressed = new Bitcoin.ECKey(keyUncompressed);
|
||||
var btcKeyCompressed = new Bitcoin.ECKey(keyCompressed);
|
||||
var btcKeyCompressed2 = new Bitcoin.ECKey(keyCompressed);
|
||||
var btcKeyUncompressed2 = new Bitcoin.ECKey(keyUncompressed);
|
||||
var btcKeyHex = new Bitcoin.ECKey(keyHex);
|
||||
var pool = Bitcoin.KeyPool.getArray();
|
||||
|
||||
if (pool.length != 2
|
||||
|| pool[0].getBitcoinWalletImportFormat() != keyUncompressed
|
||||
|| pool[1].getBitcoinWalletImportFormat() != keyCompressed
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -589,43 +640,50 @@
|
|||
["6PgNBNNzDkKdhkT6uJntUXwwzQV8Rr2tZcbkDcuC9DZRsS6AtHts4Ypo1j", "MOLON LABE", "5JLdxTtcTHcfYcmJsNVy1v2PMDx432JPoYcBTVVRHpPaxUrdtf8"],
|
||||
["6PgGWtx25kUg8QWvwuJAgorN6k9FbE25rv5dMRwu5SKMnfpfVe5mar2ngH", Crypto.charenc.UTF8.bytesToString([206, 156, 206, 159, 206, 155, 206, 169, 206, 157, 32, 206, 155, 206, 145, 206, 146, 206, 149])/*UTF-8 characters, encoded in source so they don't get corrupted*/, "5KMKKuUmAkiNbA3DazMQiLfDq47qs8MAEThm4yL8R2PhV1ov33D"]];
|
||||
|
||||
var waitTimeMs = 60000;
|
||||
|
||||
// running each test uses a lot of memory, which isn't freed
|
||||
// immediately, so give the VM a little time to reclaim memory
|
||||
function waitThenCall(callback) {
|
||||
return function () { setTimeout(callback, 10000); }
|
||||
return function () { setTimeout(callback, waitTimeMs); }
|
||||
}
|
||||
|
||||
var decryptTest = function (test, i, onComplete) {
|
||||
function log(str) {
|
||||
if (document.getElementById("asyncunittestresults")) document.getElementById("asyncunittestresults").innerHTML += str + "<br/>";
|
||||
console.log(str);
|
||||
}
|
||||
|
||||
var decryptBip38Test = function (test, i, onComplete) {
|
||||
ninja.privateKey.BIP38EncryptedKeyToByteArrayAsync(test[0], test[1], function (privBytes) {
|
||||
if (privBytes.constructor == Error) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testDecryptBip38 #" + i + ", error: " + privBytes.message + "<br/>";
|
||||
log("fail decryptBip38Test #" + i + ", error: " + privBytes.message);
|
||||
} else {
|
||||
var btcKey = new Bitcoin.ECKey(privBytes);
|
||||
var wif = !test[2].substr(0, 1).match(/[LK]/) ? btcKey.setCompressed(false).getBitcoinWalletImportFormat() : btcKey.setCompressed(true).getBitcoinWalletImportFormat();
|
||||
if (wif != test[2]) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testDecryptBip38 #" + i + "<br/>";
|
||||
log("fail decryptBip38Test #" + i);
|
||||
} else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass testDecryptBip38 #" + i + "<br/>";
|
||||
log("pass decryptBip38Test #" + i);
|
||||
}
|
||||
}
|
||||
onComplete();
|
||||
});
|
||||
};
|
||||
|
||||
var encryptTest = function (test, compressed, i, onComplete) {
|
||||
var encryptBip38Test = function (test, compressed, i, onComplete) {
|
||||
ninja.privateKey.BIP38PrivateKeyToEncryptedKeyAsync(test[2], test[1], compressed, function (encryptedKey) {
|
||||
if (encryptedKey === test[0]) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass testBip38Encrypt #" + i + "<br/>";
|
||||
log("pass encryptBip38Test #" + i);
|
||||
} else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testBip38Encrypt #" + i + "<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "expected " + test[0] + "<br/>received " + encryptedKey + "<br/>";
|
||||
log("fail encryptBip38Test #" + i);
|
||||
log("expected " + test[0] + "<br/>received " + encryptedKey);
|
||||
}
|
||||
onComplete();
|
||||
});
|
||||
};
|
||||
|
||||
// test randomly generated encryption-decryption cycle
|
||||
var cycleTest = function (i, compress, onComplete) {
|
||||
var cycleBip38Test = function (i, compress, onComplete) {
|
||||
// create new private key
|
||||
var privKey = (new Bitcoin.ECKey(false)).getBitcoinWalletImportFormat();
|
||||
|
||||
|
@ -636,11 +694,11 @@
|
|||
var decryptedKey = (new Bitcoin.ECKey(decryptedBytes)).getBitcoinWalletImportFormat();
|
||||
|
||||
if (decryptedKey === privKey) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass cycleBip38 test #" + i + "<br/>";
|
||||
log("pass cycleBip38Test #" + i);
|
||||
}
|
||||
else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail cycleBip38 test #" + i + " " + privKey + "<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "encrypted key: " + encryptedKey + "<br/>decrypted key: " + decryptedKey;
|
||||
log("fail cycleBip38Test #" + i + " " + privKey);
|
||||
log("encrypted key: " + encryptedKey + "<br/>decrypted key: " + decryptedKey);
|
||||
}
|
||||
onComplete();
|
||||
});
|
||||
|
@ -649,20 +707,20 @@
|
|||
|
||||
// intermediate test - create some encrypted keys from an intermediate
|
||||
// then decrypt them to check that the private keys are recoverable
|
||||
var intermediateTest = function (i, onComplete) {
|
||||
var intermediateBip38Test = function (i, onComplete) {
|
||||
var pass = Math.random().toString(36).substr(2);
|
||||
ninja.privateKey.BIP38GenerateIntermediatePointAsync(pass, null, null, function (intermediatePoint) {
|
||||
ninja.privateKey.BIP38GenerateECAddressAsync(intermediatePoint, false, function (address, encryptedKey) {
|
||||
ninja.privateKey.BIP38EncryptedKeyToByteArrayAsync(encryptedKey, pass, function (privBytes) {
|
||||
if (privBytes.constructor == Error) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testBip38Intermediate #" + i + ", error: " + privBytes.message + "<br/>";
|
||||
log("fail intermediateBip38Test #" + i + ", error: " + privBytes.message);
|
||||
} else {
|
||||
var btcKey = new Bitcoin.ECKey(privBytes);
|
||||
var btcAddress = btcKey.getBitcoinAddress();
|
||||
if (address !== btcKey.getBitcoinAddress()) {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "fail testBip38Intermediate #" + i + "<br/>";
|
||||
log("fail intermediateBip38Test #" + i);
|
||||
} else {
|
||||
document.getElementById("asyncunittestresults").innerHTML += "pass testBip38Intermediate #" + i + "<br/>";
|
||||
log("pass intermediateBip38Test #" + i);
|
||||
}
|
||||
}
|
||||
onComplete();
|
||||
|
@ -671,34 +729,44 @@
|
|||
});
|
||||
}
|
||||
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running " + tests.length + " tests named testDecryptBip38<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running 4 tests named testBip38Encrypt<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running 2 tests named cycleBip38<br/>";
|
||||
document.getElementById("asyncunittestresults").innerHTML += "running 5 tests named testBip38Intermediate<br/>";
|
||||
ninja.runSerialized([
|
||||
var testArray = [
|
||||
function (cb) {
|
||||
log("running " + tests.length + " tests named decryptBip38Test");
|
||||
ninja.forSerialized(0, tests.length, function (i, callback) {
|
||||
decryptTest(tests[i], i, waitThenCall(callback));
|
||||
console.log("running decryptBip38Test #" + i + " " + tests[i]);
|
||||
decryptBip38Test(tests[i], i, waitThenCall(callback));
|
||||
}, waitThenCall(cb));
|
||||
},
|
||||
}
|
||||
,
|
||||
function (cb) {
|
||||
log("running 4 tests named encryptBip38Test");
|
||||
ninja.forSerialized(0, 4, function (i, callback) {
|
||||
console.log("running encryptBip38Test #" + i + " " + tests[i]);
|
||||
// only first 4 test vectors are not EC-multiply,
|
||||
// compression param false for i = 1,2 and true for i = 3,4
|
||||
encryptTest(tests[i], i >= 2, i, waitThenCall(callback));
|
||||
encryptBip38Test(tests[i], i >= 2, i, waitThenCall(callback));
|
||||
}, waitThenCall(cb));
|
||||
},
|
||||
}
|
||||
,
|
||||
function (cb) {
|
||||
log("running 2 tests named cycleBip38Test");
|
||||
ninja.forSerialized(0, 2, function (i, callback) {
|
||||
cycleTest(i, i % 2 ? true : false, waitThenCall(callback));
|
||||
console.log("running cycleBip38Test #" + i);
|
||||
cycleBip38Test(i, i % 2 ? true : false, waitThenCall(callback));
|
||||
}, waitThenCall(cb));
|
||||
},
|
||||
}
|
||||
,
|
||||
function (cb) {
|
||||
log("running 5 tests named intermediateBip38Test");
|
||||
ninja.forSerialized(0, 5, function (i, callback) {
|
||||
intermediateTest(i, waitThenCall(callback));
|
||||
console.log("running intermediateBip38Test #" + i);
|
||||
intermediateBip38Test(i, waitThenCall(callback));
|
||||
}, cb);
|
||||
}
|
||||
], done);
|
||||
];
|
||||
|
||||
ninja.runSerialized(testArray, done);
|
||||
//TODO: ninja.runSerialized([ testArray[0],testArray[1] ], done);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue