Merge pull request #136 from pointbiz/biginteger-fixes

BigInteger modInverse should be positive
This commit is contained in:
pointbiz 2016-08-21 15:33:49 -04:00 committed by GitHub
commit 834aad72d2
5 changed files with 476 additions and 20 deletions

View file

@ -28,6 +28,14 @@ END USER NOTES:
Here is a signed list of file names and version history.
2016-07-31: status ACTIVE
bitaddress.org-v3.2.1-SHA256-.html
- BigInteger modInverse should be positive
- throw if modInverse 0
- improve BigInteger constructor so that it works if caller forgets 'new'
- add unit tests for BigInteger
- thanks to dooglus, jprichardson, dcousens
2016-02-19: status ACTIVE
bitaddress.org-v3.2.0-SHA256-ad4fd171c647772aa76d0ce828731b01ca586596275d43a94008766b758e8736.html
- switch languages without full page load

View file

@ -2878,8 +2878,12 @@ exports.init();
})(typeof module !== 'undefined' && module['exports'] ? module['exports'] : (window['secrets'] = {}), typeof GLOBAL !== 'undefined' ? GLOBAL : window );
</script>
<script type="text/javascript">
// Upstream 'BigInteger' here:
// Original Author: http://www-cs-students.stanford.edu/~tjw/jsbn/
// Follows 'jsbn' on Github: https://github.com/jasondavies/jsbn
// Review and Testing: https://github.com/cryptocoinjs/bigi/
/*!
* Basic JavaScript BN library - subset useful for RSA encryption. v1.3
* Basic JavaScript BN library - subset useful for RSA encryption. v1.4
*
* Copyright (c) 2005 Tom Wu
* All Rights Reserved.
@ -2887,13 +2891,16 @@ exports.init();
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
*
* Copyright Stephan Thomas
* Copyright bitaddress.org
* Copyright pointbiz
*/
(function () {
// (public) Constructor function of Global BigInteger object
var BigInteger = window.BigInteger = function BigInteger(a, b, c) {
if (!(this instanceof BigInteger))
return new BigInteger(a, b, c);
if (a != null)
if ("number" == typeof a) this.fromNumber(a, b, c);
else if (b == null && "string" != typeof a) this.fromString(a, 256);
@ -3824,6 +3831,7 @@ exports.init();
// (public) 1/this % m (HAC 14.61)
BigInteger.prototype.modInverse = function (m) {
var ac = m.isEven();
if (this.signum() === 0) throw new Error('division by zero');
if ((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
var u = m.clone(), v = this.clone();
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
@ -3858,9 +3866,9 @@ exports.init();
}
}
if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
if (d.compareTo(m) >= 0) return d.subtract(m);
if (d.signum() < 0) d.addTo(m, d); else return d;
if (d.signum() < 0) return d.add(m); else return d;
while (d.compareTo(m) >= 0) d.subTo(m, d);
while (d.signum() < 0) d.addTo(m, d);
return d;
};
@ -7025,7 +7033,7 @@ input[type=checkbox] { position: relative; z-index: 20; }
<div class="tooltip" id="statusprotocolbad">
<span class="statuswarn" id="statuslabelprotocolbad">&#9888; 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/v3.2.0.zip">download</a>
<a id="statuslabelprotocolbad2" href="https://github.com/pointbiz/bitaddress.org/archive/v3.2.1.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>
@ -7050,12 +7058,12 @@ input[type=checkbox] { position: relative; z-index: 20; }
<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/v3.2.0.zip" target="_blank" id="footerlabelgithubzip">zip</a>)</span>
(<a href="https://github.com/pointbiz/bitaddress.org/archive/v3.2.1.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> (3.2.0)</a>
<a href="CHANGELOG.txt.asc" target="_blank"><span id="footerlabelversion">Version History</span> (3.2.1)</a>
</span>
<span class="item">527B 5C82 B1F6 B2DB 72A0<br />ECBF 8749 7B91 6397 4F5A</span>
@ -10817,7 +10825,7 @@ ninja.wallets.splitwallet = {
}
testResults += passCount + " of " + testCount + " synchronous tests passed";
if (passCount < testCount) {
testResults += "<b>" + (testCount - passCount) + " unit test(s) failed</b>";
testResults += "<br/><b>" + (testCount - passCount) + " unit test(s) failed</b>";
}
if (showOutput) {
div.innerHTML = "<h3>Unit Tests</h3><div id=\"unittestresults\">" + testResults + "<br/><br/></div>";
@ -11406,7 +11414,223 @@ ninja.wallets.splitwallet = {
return false;
}
return true;
}
},
//BigInteger tests
testBigIntegerShouldWorkWithoutNew: function () {
var bi = BigInteger('12345')
if (bi.toString(10) != '12345') {
return false;
}
return true;
},
testBigIntegerShouldWorkWithStringInput: function () {
if (new BigInteger('12345').toString(16) != '3039') return false;
if (new BigInteger('29048849665247').toString(16) != '1a6b765d8cdf') return false;
if (new BigInteger('-29048849665247').toString(16) != '-1a6b765d8cdf') return false;
if (new BigInteger('1A6B765D8CDF', 16).toString(16) != '1a6b765d8cdf') return false;
if (new BigInteger('FF', 16).toString() != '255') return false;
if (new BigInteger('1A6B765D8CDF', 16).toString() != '29048849665247') return false;
if (new BigInteger('a89c e5af8724 c0a23e0e 0ff77500', 16).toString(16) != 'a89ce5af8724c0a23e0e0ff77500') return false;
if (new BigInteger('123456789abcdef123456789abcdef123456789abcdef', 16).toString(16) != '123456789abcdef123456789abcdef123456789abcdef') return false;
if (new BigInteger('10654321').toString() != '10654321') return false;
if (new BigInteger('10000000000000000').toString(10) != '10000000000000000') return false;
return true;
},
testBigIntegerShouldImportExportTwosComplementBigEndian: function () {
if (new BigInteger([1, 2, 3], 256).toString(16) != '10203') return false;
if (new BigInteger([1, 2, 3, 4], 256).toString(16) != '1020304') return false;
if (new BigInteger([1, 2, 3, 4, 5], 256).toString(16) != '102030405') return false;
if (new BigInteger([1, 2, 3, 4, 5, 6, 7, 8], 256).toString(16) != '102030405060708') return false;
if (new BigInteger([1, 2, 3, 4], 256).toByteArray().join(',') != '1,2,3,4') return false;
if (new BigInteger([1, 2, 3, 4, 5, 6, 7, 8], 256).toByteArray().join(',') != '1,2,3,4,5,6,7,8') return false;
return true;
},
testBigIntegerShouldReturnProperBitLength: function () {
if (new BigInteger('0').bitLength() != 0) return false;
if (new BigInteger('1', 16).bitLength() != 1) return false;
if (new BigInteger('2', 16).bitLength() != 2) return false;
if (new BigInteger('3', 16).bitLength() != 2) return false;
if (new BigInteger('4', 16).bitLength() != 3) return false;
if (new BigInteger('8', 16).bitLength() != 4) return false;
if (new BigInteger('10', 16).bitLength() != 5) return false;
if (new BigInteger('100', 16).bitLength() != 9) return false;
if (new BigInteger('123456', 16).bitLength() != 21) return false;
if (new BigInteger('123456789', 16).bitLength() != 33) return false;
if (new BigInteger('8023456789', 16).bitLength() != 40) return false;
return true;
},
testBigIntegerShouldAddNumbers: function () {
// test 1
if (new BigInteger('14').add(new BigInteger('26')).toString(16) != '28') return false;
// test 2
var k = new BigInteger('1234', 16);
var r = k;
for (var i = 0; i < 257; i++) r = r.add(k);
if (r.toString(16) != '125868') return false;
// test 3
var k = new BigInteger('abcdefabcdefabcdef', 16);
var r = new BigInteger('deadbeef', 16);
for (var i = 0; i < 257; i++) {
r = r.add(k);
}
if (r.toString(16) != 'ac79bd9b79be7a277bde') return false;
return true;
},
testBigIntegerShouldSubtractNumbers: function () {
// test 1
if (new BigInteger('14').subtract(new BigInteger('26')).toString(16) != '-c') return false;
// test 2
if (new BigInteger('26').subtract(new BigInteger('14')).toString(16) != 'c') return false;
// test 3
if (new BigInteger('26').subtract(new BigInteger('26')).toString(16) != '0') return false;
// test 4
if (new BigInteger('-26').subtract(new BigInteger('26')).toString(16) != '-34') return false;
// test 5
var a = new BigInteger('31ff3c61db2db84b9823d320907a573f6ad37c437abe458b1802cda041d6384a7d8daef41395491e2', 16);
var b = new BigInteger('6f0e4d9f1d6071c183677f601af9305721c91d31b0bbbae8fb790000', 16);
var r = new BigInteger('31ff3c61db2db84b9823d3208989726578fd75276287cd9516533a9acfb9a6776281f34583ddb91e2', 16);
if (a.subtract(b).compareTo(r) != 0) return false;
// test 6
var r = b.subtract(new BigInteger('14'));
if (b.clone().subtract(new BigInteger('14')).compareTo(r) != 0) return false;
// test 7
var r = new BigInteger('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b', 16);
if (r.subtract(new BigInteger('-1')).toString(16) != '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681c') return false;
// test 8
// Carry and copy
var a = new BigInteger('12345', 16);
var b = new BigInteger('1000000000000', 16);
if (a.subtract(b).toString(16) != '-fffffffedcbb') return false;
// test 9
var a = new BigInteger('12345', 16);
var b = new BigInteger('1000000000000', 16);
if (b.subtract(a).toString(16) != 'fffffffedcbb') return false;
return true;
},
testBigIntegerShouldMultiplyNumbers: function () {
if (new BigInteger('1001', 16).multiply(new BigInteger('1234', 16)).toString(16) != '1235234') return false;
if (new BigInteger('-1001', 16).multiply(new BigInteger('1234', 16)).toString(16) != '-1235234') return false;
if (new BigInteger('-1001', 16).multiply(new BigInteger('-1234', 16)).toString(16) != '1235234') return false;
// test 4
var n = new BigInteger('1001', 16);
var r = n;
for (var i = 0; i < 4; i++) {
r = r.multiply(n);
}
if (r.toString(16) != '100500a00a005001') return false;
var n = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
if (n.multiply(n).toString(16) != '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9978a8bd8acaa40') return false;
if (n.multiply(n).multiply(n).toString(16) != '1b888e01a06e974017a28a5b4da436169761c9730b7aeedf75fc60f687b46e0cf2cb11667f795d5569482640fe5f628939467a01a612b023500d0161e9730279a7561043af6197798e41b7432458463e64fa81158907322dc330562697d0d600') return false;
if (new BigInteger('-100000000000').multiply(new BigInteger('3').divide(new BigInteger('4'))).toString(16) != '0') return false;
return true;
},
testBigIntegerShouldDivideNumbers: function () {
if (new BigInteger('10').divide(new BigInteger('256')).toString(16) != '0') return false;
if (new BigInteger('69527932928').divide(new BigInteger('16974594')).toString(16) != 'fff') return false;
if (new BigInteger('-69527932928').divide(new BigInteger('16974594')).toString(16) != '-fff') return false;
var b = new BigInteger('39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9978a8bd8acaa40', 16);
var n = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
if (b.divide(n).toString(16) != n.toString(16)) return false;
if (new BigInteger('1').divide(new BigInteger('-5')).toString(10) != '0') return false;
// // Regression after moving to word div
var p = new BigInteger('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16);
var a = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
var as = a.square();
if (as.divide(p).toString(16) != '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729e58090b9') return false;
var p = new BigInteger('ffffffff00000001000000000000000000000000ffffffffffffffffffffffff', 16);
var a = new BigInteger('fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16);
if (a.divide(p).toString(16) != 'ffffffff00000002000000000000000000000001000000000000000000000001') return false;
return true;
},
testBigIntegerShouldModNumbers: function () {
if (new BigInteger('10').mod(new BigInteger('256')).toString(16) != 'a') return false;
if (new BigInteger('69527932928').mod(new BigInteger('16974594')).toString(16) != '102f302') return false;
if (new BigInteger('-69527932928').mod(new BigInteger('16974594')).toString(16) != '1000') return false;
if (new BigInteger('10', 16).mod(new BigInteger('256')).toString(16) != '10') return false;
if (new BigInteger('100', 16).mod(new BigInteger('256')).toString(16) != '0') return false;
if (new BigInteger('1001', 16).mod(new BigInteger('256')).toString(16) != '1') return false;
if (new BigInteger('100000000001', 16).mod(new BigInteger('256')).toString(16) != '1') return false;
if (new BigInteger('100000000001', 16).mod(new BigInteger('257')).toString(16) != new BigInteger('100000000001', 16).mod(new BigInteger('257')).toString(16)) return false;
if (new BigInteger('123456789012', 16).mod(new BigInteger('3')).toString(16) != new BigInteger('123456789012', 16).mod(new BigInteger('3')).toString(16)) return false;
var p = new BigInteger('ffffffff00000001000000000000000000000000ffffffffffffffffffffffff', 16);
var a = new BigInteger('fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16);
if (a.mod(p).toString(16) != '0') return false;
return true;
},
testBigIntegerShouldShiftLeftNumbers: function () {
if (new BigInteger('69527932928').shiftLeft(13).toString(16) != '2060602000000') return false;
if (new BigInteger('69527932928').shiftLeft(45).toString(16) != '206060200000000000000') return false;
return true;
},
testBigIntegerShouldShiftRightNumbers: function () {
if (new BigInteger('69527932928').shiftRight(13).toString(16) != '818180') return false;
if (new BigInteger('69527932928').shiftRight(17).toString(16) != '81818') return false;
if (new BigInteger('69527932928').shiftRight(256).toString(16) != '0') return false;
return true;
},
testBigIntegerShouldModInverseNumbers: function () {
var p = new BigInteger('257');
var a = new BigInteger('3');
var b = a.modInverse(p);
if (a.multiply(b).mod(p).toString(16) != '1') return false;
var p192 = new BigInteger('fffffffffffffffffffffffffffffffeffffffffffffffff', 16);
var a = new BigInteger('deadbeef', 16);
var b = a.modInverse(p192);
if (a.multiply(b).mod(p192).toString(16) != '1') return false;
return true;
},
testBigIntegerShouldThrowOnModInverseOfZero: function () {
var p = new BigInteger('257');
var a = new BigInteger('0');
//division by zero
try {
a.modInverse(p);
}
catch (e) {
return true;
}
return false;
},
testBigIntegerShouldAlwaysReturnPositiveNumber: function () {
var z = new BigInteger('cc61934972bba029382f0bef146b228ca15d54f7e38b6cd5f6b382398b7a97a8', 16);
var p = new BigInteger('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16);
var zInv = z.modInverse(p);
if (zInv.signum() !== 1) return false; //zInv should be positive
return true;
},
testECKeyDoesntHangWithSpecificKey: function () {
var key = "848b39bbe4c9ddf978d3d8f786315bdc3ba71237d5f780399e0026e1269313ef";
var btcKey = new Bitcoin.ECKey(key);
if (btcKey.getPubKeyHex() != "0478BC8F7CB4485E7A0314A698AA1600639FF2922D09C26DED5F730CAC4784477D2B325922459F017AC1E8775436D11D7F84BD84E11CB64FC9BE110931D0C990CE"
) {
return false;
}
return true;
}
},
asynchronousTests: {

View file

@ -1,8 +1,8 @@
{
"name": "bitaddress.org",
"version": "3.2.0",
"sha1sum": "057f3192b603d42c980ea23d5ae332a65f7a327c",
"sha256sum": "ad4fd171c647772aa76d0ce828731b01ca586596275d43a94008766b758e8736",
"version": "3.2.1",
"sha1sum": "",
"sha256sum": "",
"description": "Open Source JavaScript Client-Side Bitcoin Wallet Generator",
"main": "Gruntfile.js",
"dependencies": {

View file

@ -1,5 +1,9 @@
// Upstream 'BigInteger' here:
// Original Author: http://www-cs-students.stanford.edu/~tjw/jsbn/
// Follows 'jsbn' on Github: https://github.com/jasondavies/jsbn
// Review and Testing: https://github.com/cryptocoinjs/bigi/
/*!
* Basic JavaScript BN library - subset useful for RSA encryption. v1.3
* Basic JavaScript BN library - subset useful for RSA encryption. v1.4
*
* Copyright (c) 2005 Tom Wu
* All Rights Reserved.
@ -7,13 +11,16 @@
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
*
* Copyright Stephan Thomas
* Copyright bitaddress.org
* Copyright pointbiz
*/
(function () {
// (public) Constructor function of Global BigInteger object
var BigInteger = window.BigInteger = function BigInteger(a, b, c) {
if (!(this instanceof BigInteger))
return new BigInteger(a, b, c);
if (a != null)
if ("number" == typeof a) this.fromNumber(a, b, c);
else if (b == null && "string" != typeof a) this.fromString(a, 256);
@ -944,6 +951,7 @@
// (public) 1/this % m (HAC 14.61)
BigInteger.prototype.modInverse = function (m) {
var ac = m.isEven();
if (this.signum() === 0) throw new Error('division by zero');
if ((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
var u = m.clone(), v = this.clone();
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
@ -978,9 +986,9 @@
}
}
if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
if (d.compareTo(m) >= 0) return d.subtract(m);
if (d.signum() < 0) d.addTo(m, d); else return d;
if (d.signum() < 0) return d.add(m); else return d;
while (d.compareTo(m) >= 0) d.subTo(m, d);
while (d.signum() < 0) d.addTo(m, d);
return d;
};

View file

@ -32,7 +32,7 @@
}
testResults += passCount + " of " + testCount + " synchronous tests passed";
if (passCount < testCount) {
testResults += "<b>" + (testCount - passCount) + " unit test(s) failed</b>";
testResults += "<br/><b>" + (testCount - passCount) + " unit test(s) failed</b>";
}
if (showOutput) {
div.innerHTML = "<h3>Unit Tests</h3><div id=\"unittestresults\">" + testResults + "<br/><br/></div>";
@ -621,7 +621,223 @@
return false;
}
return true;
}
},
//BigInteger tests
testBigIntegerShouldWorkWithoutNew: function () {
var bi = BigInteger('12345')
if (bi.toString(10) != '12345') {
return false;
}
return true;
},
testBigIntegerShouldWorkWithStringInput: function () {
if (new BigInteger('12345').toString(16) != '3039') return false;
if (new BigInteger('29048849665247').toString(16) != '1a6b765d8cdf') return false;
if (new BigInteger('-29048849665247').toString(16) != '-1a6b765d8cdf') return false;
if (new BigInteger('1A6B765D8CDF', 16).toString(16) != '1a6b765d8cdf') return false;
if (new BigInteger('FF', 16).toString() != '255') return false;
if (new BigInteger('1A6B765D8CDF', 16).toString() != '29048849665247') return false;
if (new BigInteger('a89c e5af8724 c0a23e0e 0ff77500', 16).toString(16) != 'a89ce5af8724c0a23e0e0ff77500') return false;
if (new BigInteger('123456789abcdef123456789abcdef123456789abcdef', 16).toString(16) != '123456789abcdef123456789abcdef123456789abcdef') return false;
if (new BigInteger('10654321').toString() != '10654321') return false;
if (new BigInteger('10000000000000000').toString(10) != '10000000000000000') return false;
return true;
},
testBigIntegerShouldImportExportTwosComplementBigEndian: function () {
if (new BigInteger([1, 2, 3], 256).toString(16) != '10203') return false;
if (new BigInteger([1, 2, 3, 4], 256).toString(16) != '1020304') return false;
if (new BigInteger([1, 2, 3, 4, 5], 256).toString(16) != '102030405') return false;
if (new BigInteger([1, 2, 3, 4, 5, 6, 7, 8], 256).toString(16) != '102030405060708') return false;
if (new BigInteger([1, 2, 3, 4], 256).toByteArray().join(',') != '1,2,3,4') return false;
if (new BigInteger([1, 2, 3, 4, 5, 6, 7, 8], 256).toByteArray().join(',') != '1,2,3,4,5,6,7,8') return false;
return true;
},
testBigIntegerShouldReturnProperBitLength: function () {
if (new BigInteger('0').bitLength() != 0) return false;
if (new BigInteger('1', 16).bitLength() != 1) return false;
if (new BigInteger('2', 16).bitLength() != 2) return false;
if (new BigInteger('3', 16).bitLength() != 2) return false;
if (new BigInteger('4', 16).bitLength() != 3) return false;
if (new BigInteger('8', 16).bitLength() != 4) return false;
if (new BigInteger('10', 16).bitLength() != 5) return false;
if (new BigInteger('100', 16).bitLength() != 9) return false;
if (new BigInteger('123456', 16).bitLength() != 21) return false;
if (new BigInteger('123456789', 16).bitLength() != 33) return false;
if (new BigInteger('8023456789', 16).bitLength() != 40) return false;
return true;
},
testBigIntegerShouldAddNumbers: function () {
// test 1
if (new BigInteger('14').add(new BigInteger('26')).toString(16) != '28') return false;
// test 2
var k = new BigInteger('1234', 16);
var r = k;
for (var i = 0; i < 257; i++) r = r.add(k);
if (r.toString(16) != '125868') return false;
// test 3
var k = new BigInteger('abcdefabcdefabcdef', 16);
var r = new BigInteger('deadbeef', 16);
for (var i = 0; i < 257; i++) {
r = r.add(k);
}
if (r.toString(16) != 'ac79bd9b79be7a277bde') return false;
return true;
},
testBigIntegerShouldSubtractNumbers: function () {
// test 1
if (new BigInteger('14').subtract(new BigInteger('26')).toString(16) != '-c') return false;
// test 2
if (new BigInteger('26').subtract(new BigInteger('14')).toString(16) != 'c') return false;
// test 3
if (new BigInteger('26').subtract(new BigInteger('26')).toString(16) != '0') return false;
// test 4
if (new BigInteger('-26').subtract(new BigInteger('26')).toString(16) != '-34') return false;
// test 5
var a = new BigInteger('31ff3c61db2db84b9823d320907a573f6ad37c437abe458b1802cda041d6384a7d8daef41395491e2', 16);
var b = new BigInteger('6f0e4d9f1d6071c183677f601af9305721c91d31b0bbbae8fb790000', 16);
var r = new BigInteger('31ff3c61db2db84b9823d3208989726578fd75276287cd9516533a9acfb9a6776281f34583ddb91e2', 16);
if (a.subtract(b).compareTo(r) != 0) return false;
// test 6
var r = b.subtract(new BigInteger('14'));
if (b.clone().subtract(new BigInteger('14')).compareTo(r) != 0) return false;
// test 7
var r = new BigInteger('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b', 16);
if (r.subtract(new BigInteger('-1')).toString(16) != '7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681c') return false;
// test 8
// Carry and copy
var a = new BigInteger('12345', 16);
var b = new BigInteger('1000000000000', 16);
if (a.subtract(b).toString(16) != '-fffffffedcbb') return false;
// test 9
var a = new BigInteger('12345', 16);
var b = new BigInteger('1000000000000', 16);
if (b.subtract(a).toString(16) != 'fffffffedcbb') return false;
return true;
},
testBigIntegerShouldMultiplyNumbers: function () {
if (new BigInteger('1001', 16).multiply(new BigInteger('1234', 16)).toString(16) != '1235234') return false;
if (new BigInteger('-1001', 16).multiply(new BigInteger('1234', 16)).toString(16) != '-1235234') return false;
if (new BigInteger('-1001', 16).multiply(new BigInteger('-1234', 16)).toString(16) != '1235234') return false;
// test 4
var n = new BigInteger('1001', 16);
var r = n;
for (var i = 0; i < 4; i++) {
r = r.multiply(n);
}
if (r.toString(16) != '100500a00a005001') return false;
var n = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
if (n.multiply(n).toString(16) != '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9978a8bd8acaa40') return false;
if (n.multiply(n).multiply(n).toString(16) != '1b888e01a06e974017a28a5b4da436169761c9730b7aeedf75fc60f687b46e0cf2cb11667f795d5569482640fe5f628939467a01a612b023500d0161e9730279a7561043af6197798e41b7432458463e64fa81158907322dc330562697d0d600') return false;
if (new BigInteger('-100000000000').multiply(new BigInteger('3').divide(new BigInteger('4'))).toString(16) != '0') return false;
return true;
},
testBigIntegerShouldDivideNumbers: function () {
if (new BigInteger('10').divide(new BigInteger('256')).toString(16) != '0') return false;
if (new BigInteger('69527932928').divide(new BigInteger('16974594')).toString(16) != 'fff') return false;
if (new BigInteger('-69527932928').divide(new BigInteger('16974594')).toString(16) != '-fff') return false;
var b = new BigInteger('39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729ab9b055c3a9458e4ce3289560a38e08ba8175a9446ce14e608245ab3a9978a8bd8acaa40', 16);
var n = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
if (b.divide(n).toString(16) != n.toString(16)) return false;
if (new BigInteger('1').divide(new BigInteger('-5')).toString(10) != '0') return false;
// // Regression after moving to word div
var p = new BigInteger('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16);
var a = new BigInteger('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16);
var as = a.square();
if (as.divide(p).toString(16) != '39e58a8055b6fb264b75ec8c646509784204ac15a8c24e05babc9729e58090b9') return false;
var p = new BigInteger('ffffffff00000001000000000000000000000000ffffffffffffffffffffffff', 16);
var a = new BigInteger('fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16);
if (a.divide(p).toString(16) != 'ffffffff00000002000000000000000000000001000000000000000000000001') return false;
return true;
},
testBigIntegerShouldModNumbers: function () {
if (new BigInteger('10').mod(new BigInteger('256')).toString(16) != 'a') return false;
if (new BigInteger('69527932928').mod(new BigInteger('16974594')).toString(16) != '102f302') return false;
if (new BigInteger('-69527932928').mod(new BigInteger('16974594')).toString(16) != '1000') return false;
if (new BigInteger('10', 16).mod(new BigInteger('256')).toString(16) != '10') return false;
if (new BigInteger('100', 16).mod(new BigInteger('256')).toString(16) != '0') return false;
if (new BigInteger('1001', 16).mod(new BigInteger('256')).toString(16) != '1') return false;
if (new BigInteger('100000000001', 16).mod(new BigInteger('256')).toString(16) != '1') return false;
if (new BigInteger('100000000001', 16).mod(new BigInteger('257')).toString(16) != new BigInteger('100000000001', 16).mod(new BigInteger('257')).toString(16)) return false;
if (new BigInteger('123456789012', 16).mod(new BigInteger('3')).toString(16) != new BigInteger('123456789012', 16).mod(new BigInteger('3')).toString(16)) return false;
var p = new BigInteger('ffffffff00000001000000000000000000000000ffffffffffffffffffffffff', 16);
var a = new BigInteger('fffffffe00000003fffffffd0000000200000001fffffffe00000002ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16);
if (a.mod(p).toString(16) != '0') return false;
return true;
},
testBigIntegerShouldShiftLeftNumbers: function () {
if (new BigInteger('69527932928').shiftLeft(13).toString(16) != '2060602000000') return false;
if (new BigInteger('69527932928').shiftLeft(45).toString(16) != '206060200000000000000') return false;
return true;
},
testBigIntegerShouldShiftRightNumbers: function () {
if (new BigInteger('69527932928').shiftRight(13).toString(16) != '818180') return false;
if (new BigInteger('69527932928').shiftRight(17).toString(16) != '81818') return false;
if (new BigInteger('69527932928').shiftRight(256).toString(16) != '0') return false;
return true;
},
testBigIntegerShouldModInverseNumbers: function () {
var p = new BigInteger('257');
var a = new BigInteger('3');
var b = a.modInverse(p);
if (a.multiply(b).mod(p).toString(16) != '1') return false;
var p192 = new BigInteger('fffffffffffffffffffffffffffffffeffffffffffffffff', 16);
var a = new BigInteger('deadbeef', 16);
var b = a.modInverse(p192);
if (a.multiply(b).mod(p192).toString(16) != '1') return false;
return true;
},
testBigIntegerShouldThrowOnModInverseOfZero: function () {
var p = new BigInteger('257');
var a = new BigInteger('0');
//division by zero
try {
a.modInverse(p);
}
catch (e) {
return true;
}
return false;
},
testBigIntegerShouldAlwaysReturnPositiveNumber: function () {
var z = new BigInteger('cc61934972bba029382f0bef146b228ca15d54f7e38b6cd5f6b382398b7a97a8', 16);
var p = new BigInteger('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 16);
var zInv = z.modInverse(p);
if (zInv.signum() !== 1) return false; //zInv should be positive
return true;
},
testECKeyDoesntHangWithSpecificKey: function () {
var key = "848b39bbe4c9ddf978d3d8f786315bdc3ba71237d5f780399e0026e1269313ef";
var btcKey = new Bitcoin.ECKey(key);
if (btcKey.getPubKeyHex() != "0478BC8F7CB4485E7A0314A698AA1600639FF2922D09C26DED5F730CAC4784477D2B325922459F017AC1E8775436D11D7F84BD84E11CB64FC9BE110931D0C990CE"
) {
return false;
}
return true;
}
},
asynchronousTests: {