diff options
author | Ian Coleman <coleman.ian@gmail.com> | 2016-11-03 16:34:56 +1100 |
---|---|---|
committer | Ian Coleman <coleman.ian@gmail.com> | 2016-11-04 15:14:13 +1100 |
commit | c6624d51f4e5607202e48903352574c47571baab (patch) | |
tree | ee57075575c8f9b88e13eb7efff083bb9fa2b39c | |
parent | d737abf6809622228faf7d5fe54101e2d87d72a4 (diff) | |
download | BIP39-c6624d51f4e5607202e48903352574c47571baab.tar.gz BIP39-c6624d51f4e5607202e48903352574c47571baab.tar.zst BIP39-c6624d51f4e5607202e48903352574c47571baab.zip |
Entropy can be supplied by user
-rw-r--r-- | bip39-standalone.html | 1936 | ||||
-rw-r--r-- | src/index.html | 56 | ||||
-rw-r--r-- | src/js/entropy.js | 1774 | ||||
-rw-r--r-- | src/js/index.js | 106 | ||||
-rw-r--r-- | tests.js | 607 |
5 files changed, 4465 insertions, 14 deletions
diff --git a/bip39-standalone.html b/bip39-standalone.html index 5993b86..e3af3a6 100644 --- a/bip39-standalone.html +++ b/bip39-standalone.html | |||
@@ -69,12 +69,14 @@ | |||
69 | <div class="col-md-12"> | 69 | <div class="col-md-12"> |
70 | <h2>Mnemonic</h2> | 70 | <h2>Mnemonic</h2> |
71 | <form class="form-horizontal" role="form"> | 71 | <form class="form-horizontal" role="form"> |
72 | <div class="col-sm-2"></div> | ||
73 | <div class="col-sm-10"> | ||
74 | <p>You can enter an existing BIP39 mnemonic, or generate a new random one. Typing your own twelve words will probably not work how you expect, since the words require a particular structure (the last word is a checksum)</p> | ||
75 | <p>For more info see the <a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki" target="_blank">BIP39 spec</a></p> | ||
76 | </div> | ||
77 | <div class="form-group"> | 72 | <div class="form-group"> |
73 | <div class="col-sm-2"></div> | ||
74 | <div class="col-sm-10"> | ||
75 | <p>You can enter an existing BIP39 mnemonic, or generate a new random one. Typing your own twelve words will probably not work how you expect, since the words require a particular structure (the last word is a checksum)</p> | ||
76 | <p>For more info see the <a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki" target="_blank">BIP39 spec</a></p> | ||
77 | </div> | ||
78 | </div> | ||
79 | <div class="form-group generate-container"> | ||
78 | <label class="col-sm-2 control-label"></label> | 80 | <label class="col-sm-2 control-label"></label> |
79 | <div class="col-sm-10"> | 81 | <div class="col-sm-10"> |
80 | <div class="form-inline"> | 82 | <div class="form-inline"> |
@@ -96,7 +98,30 @@ | |||
96 | </div> | 98 | </div> |
97 | </div> | 99 | </div> |
98 | </div> | 100 | </div> |
99 | <div class="form-group"> | 101 | <div class="entropy-container hidden"> |
102 | <label for="entropy" class="col-sm-2 control-label">Entropy</label> | ||
103 | <div class="col-sm-10"> | ||
104 | <input id="entropy" class="entropy form-control" placeholder="Accepts binary, base 6, 6-sided dice, base 10, hexadecimal"> | ||
105 | <span class="help-block"> | ||
106 | <div class="text-danger"> | ||
107 | This is an advanced feature. | ||
108 | Your mnemonic may be insecure if this feature is used incorrectly. | ||
109 | <a href="#entropy-notes">Read more</a> | ||
110 | </div> | ||
111 | <div class="text-danger entropy-error"></div> | ||
112 | </span> | ||
113 | </div> | ||
114 | </div> | ||
115 | <div class="form-group"> | ||
116 | <div class="col-sm-2"></div> | ||
117 | <div class="col-sm-10 checkbox"> | ||
118 | <label> | ||
119 | <input type="checkbox" class="use-entropy"> | ||
120 | Supply my own source of entropy | ||
121 | </label> | ||
122 | </div> | ||
123 | </div> | ||
124 | <div class="form-group"> | ||
100 | <label class="col-sm-2 control-label"></label> | 125 | <label class="col-sm-2 control-label"></label> |
101 | <div class="col-sm-10 languages"> | 126 | <div class="col-sm-10 languages"> |
102 | <a href="#english">English</a> | 127 | <a href="#english">English</a> |
@@ -357,6 +382,24 @@ | |||
357 | but be careful - it can be easy to make mistakes if you | 382 | but be careful - it can be easy to make mistakes if you |
358 | don't know what you're doing | 383 | don't know what you're doing |
359 | </p> | 384 | </p> |
385 | <h3 id="entropy-notes">Entropy</h3> | ||
386 | <p> | ||
387 | Entropy values must be sourced from a | ||
388 | <a href="https://en.wikipedia.org/wiki/Random_number_generation" target="_blank">strong source of randomness</a>. | ||
389 | This means flipping a fair coin, rolling a fair dice, noise measurements etc. Do <strong>NOT</strong> use | ||
390 | phrases from books, lyrics from songs, your birthday or steet address, keyboard mashing, or anything you <i>think</i> | ||
391 | is random, because chances are <em>overwhelming</em> that it isn't random enough for the needs of this tool. | ||
392 | </p> | ||
393 | <p> | ||
394 | The random mnemonic generator on this page uses a | ||
395 | <a href="https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues" target="_blank">cryptographically secure random number generator</a>, | ||
396 | and can generally be trusted more than your own intuition about randomness. | ||
397 | If cryptographic randomness isn't available in your browser, this page will show a warning and <i>will not generate | ||
398 | random mnemonics</i>. | ||
399 | </p> | ||
400 | <p> | ||
401 | <a href="https://bitcointalk.org/index.php?topic=311000.msg3345309#msg3345309" target="_blank">You are not a good source of entropy.</a> | ||
402 | </p> | ||
360 | </div> | 403 | </div> |
361 | </div> | 404 | </div> |
362 | 405 | ||
@@ -16169,6 +16212,1781 @@ var Mnemonic = function(language) { | |||
16169 | 16212 | ||
16170 | } | 16213 | } |
16171 | </script> | 16214 | </script> |
16215 | <script>window.Entropy = new (function() { | ||
16216 | |||
16217 | var matchers = { | ||
16218 | binary: /[0-1]/gi, | ||
16219 | base6: /[0-5]/gi, | ||
16220 | dice: /[1-6]/gi, // ie dice numbers | ||
16221 | base10: /[0-9]/gi, | ||
16222 | hex: /[0-9A-F]/gi, | ||
16223 | } | ||
16224 | |||
16225 | this.fromString = function(rawEntropyStr) { | ||
16226 | // Find type of entropy being used (binary, hex, dice etc) | ||
16227 | var base = getBase(rawEntropyStr); | ||
16228 | // Convert dice to base6 entropy (ie 1-6 to 0-5) | ||
16229 | if (base.str == "dice") { | ||
16230 | var newRawEntropyStr = ""; | ||
16231 | for (var i=0; i<rawEntropyStr.length; i++) { | ||
16232 | var c = rawEntropyStr[i]; | ||
16233 | if ("123456".indexOf(c) > -1) { | ||
16234 | newRawEntropyStr += (parseInt(c) - 1).toString(); | ||
16235 | } | ||
16236 | else { | ||
16237 | newRawEntropyStr += c | ||
16238 | } | ||
16239 | } | ||
16240 | rawEntropyStr = newRawEntropyStr; | ||
16241 | base.str = "base 6 (dice)"; | ||
16242 | base.matcher = matchers.base6; | ||
16243 | } | ||
16244 | var entropyParts = rawEntropyStr.match(base.matcher) || []; | ||
16245 | var entropyStr = entropyParts.join(""); | ||
16246 | // Detect empty entropy | ||
16247 | if (entropyStr.length == 0) { | ||
16248 | return { | ||
16249 | binaryStr: "", | ||
16250 | hexStr: "", | ||
16251 | cleanStr: "", | ||
16252 | base: base, | ||
16253 | }; | ||
16254 | } | ||
16255 | // Pull leading zeros off | ||
16256 | var leadingZeros = ""; | ||
16257 | while (entropyStr[0] == "0") { | ||
16258 | leadingZeros += "0"; | ||
16259 | entropyStr = entropyStr.substring(1); | ||
16260 | } | ||
16261 | // Convert leading zeros to binary equivalent | ||
16262 | var numBinLeadingZeros = Math.ceil(Math.log2(base.asInt) * leadingZeros.length); | ||
16263 | var binLeadingZeros = ""; | ||
16264 | for (var i=0; i<numBinLeadingZeros; i++) { | ||
16265 | binLeadingZeros += "0"; | ||
16266 | } | ||
16267 | // Convert leading zeros to hex equivalent | ||
16268 | var numHexLeadingZeros = Math.floor(numBinLeadingZeros / 4); | ||
16269 | var hexLeadingZeros = ""; | ||
16270 | for (var i=0; i<numHexLeadingZeros; i++) { | ||
16271 | hexLeadingZeros += "0"; | ||
16272 | } | ||
16273 | // Handle entropy of zero | ||
16274 | if (entropyStr == "") { | ||
16275 | return { | ||
16276 | binaryStr: binLeadingZeros, | ||
16277 | hexStr: hexLeadingZeros || "0", | ||
16278 | cleanStr: leadingZeros, | ||
16279 | base: base, | ||
16280 | } | ||
16281 | } | ||
16282 | // If using hex, should always be multiples of 4 bits, which can get | ||
16283 | // out of sync if first number has leading 0 bits, eg 2 in hex is 0010 | ||
16284 | // which would show up as 10, thus missing 2 bits it should have. | ||
16285 | if (base.asInt == 16) { | ||
16286 | var firstDigit = parseInt(entropyStr[0], 16); | ||
16287 | if (firstDigit >= 4 && firstDigit < 8) { | ||
16288 | binLeadingZeros += "0"; | ||
16289 | } | ||
16290 | else if (firstDigit >= 2 && firstDigit < 4) { | ||
16291 | binLeadingZeros += "00"; | ||
16292 | } | ||
16293 | else if (firstDigit >= 1 && firstDigit < 2) { | ||
16294 | binLeadingZeros += "000"; | ||
16295 | } | ||
16296 | } | ||
16297 | // Convert entropy to different foramts | ||
16298 | var entropyInt = BigInteger.parse(entropyStr, base.asInt); | ||
16299 | var entropyBin = binLeadingZeros + entropyInt.toString(2); | ||
16300 | var entropyHex = hexLeadingZeros + entropyInt.toString(16); | ||
16301 | var entropyClean = leadingZeros + entropyStr; | ||
16302 | var e = { | ||
16303 | binaryStr: entropyBin, | ||
16304 | hexStr: entropyHex, | ||
16305 | cleanStr: entropyClean, | ||
16306 | base: base, | ||
16307 | } | ||
16308 | return e; | ||
16309 | } | ||
16310 | |||
16311 | function getBase(str) { | ||
16312 | // Need to get the lowest base for the supplied entropy. | ||
16313 | // This prevents interpreting, say, dice rolls as hexadecimal. | ||
16314 | var binaryMatches = str.match(matchers.binary) || []; | ||
16315 | var base6Matches = str.match(matchers.base6) || []; | ||
16316 | var diceMatches = str.match(matchers.dice) || []; | ||
16317 | var base10Matches = str.match(matchers.base10) || []; | ||
16318 | var hexMatches = str.match(matchers.hex) || []; | ||
16319 | // Find the lowest base that can be used, whilst ignoring any irrelevant chars | ||
16320 | if (binaryMatches.length == hexMatches.length) { | ||
16321 | return { | ||
16322 | matcher: matchers.binary, | ||
16323 | asInt: 2, | ||
16324 | str: "binary", | ||
16325 | } | ||
16326 | } | ||
16327 | if (diceMatches.length == hexMatches.length) { | ||
16328 | return { | ||
16329 | matcher: matchers.dice, | ||
16330 | asInt: 6, | ||
16331 | str: "dice", | ||
16332 | } | ||
16333 | } | ||
16334 | if (base6Matches.length == hexMatches.length) { | ||
16335 | return { | ||
16336 | matcher: matchers.base6, | ||
16337 | asInt: 6, | ||
16338 | str: "base 6", | ||
16339 | } | ||
16340 | } | ||
16341 | if (base10Matches.length == hexMatches.length) { | ||
16342 | return { | ||
16343 | matcher: matchers.base10, | ||
16344 | asInt: 10, | ||
16345 | str: "base 10", | ||
16346 | } | ||
16347 | } | ||
16348 | return { | ||
16349 | matcher: matchers.hex, | ||
16350 | asInt: 16, | ||
16351 | str: "hexadecimal", | ||
16352 | } | ||
16353 | } | ||
16354 | |||
16355 | // Polyfill for Math.log2 | ||
16356 | // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log2#Polyfill | ||
16357 | Math.log2 = Math.log2 || function(x) { | ||
16358 | return Math.log(x) * Math.LOG2E; | ||
16359 | }; | ||
16360 | |||
16361 | })(); | ||
16362 | |||
16363 | |||
16364 | // BigInteger library included here because | ||
16365 | // only the entropy library depends on it | ||
16366 | // so if entropy detection is removed so is the dependency | ||
16367 | |||
16368 | |||
16369 | /* | ||
16370 | JavaScript BigInteger library version 0.9.1 | ||
16371 | http://silentmatt.com/biginteger/ | ||
16372 | |||
16373 | Copyright (c) 2009 Matthew Crumley <email@matthewcrumley.com> | ||
16374 | Copyright (c) 2010,2011 by John Tobey <John.Tobey@gmail.com> | ||
16375 | Licensed under the MIT license. | ||
16376 | |||
16377 | Support for arbitrary internal representation base was added by | ||
16378 | Vitaly Magerya. | ||
16379 | */ | ||
16380 | |||
16381 | /* | ||
16382 | File: biginteger.js | ||
16383 | |||
16384 | Exports: | ||
16385 | |||
16386 | <BigInteger> | ||
16387 | */ | ||
16388 | (function(exports) { | ||
16389 | "use strict"; | ||
16390 | /* | ||
16391 | Class: BigInteger | ||
16392 | An arbitrarily-large integer. | ||
16393 | |||
16394 | <BigInteger> objects should be considered immutable. None of the "built-in" | ||
16395 | methods modify *this* or their arguments. All properties should be | ||
16396 | considered private. | ||
16397 | |||
16398 | All the methods of <BigInteger> instances can be called "statically". The | ||
16399 | static versions are convenient if you don't already have a <BigInteger> | ||
16400 | object. | ||
16401 | |||
16402 | As an example, these calls are equivalent. | ||
16403 | |||
16404 | > BigInteger(4).multiply(5); // returns BigInteger(20); | ||
16405 | > BigInteger.multiply(4, 5); // returns BigInteger(20); | ||
16406 | |||
16407 | > var a = 42; | ||
16408 | > var a = BigInteger.toJSValue("0b101010"); // Not completely useless... | ||
16409 | */ | ||
16410 | |||
16411 | var CONSTRUCT = {}; // Unique token to call "private" version of constructor | ||
16412 | |||
16413 | /* | ||
16414 | Constructor: BigInteger() | ||
16415 | Convert a value to a <BigInteger>. | ||
16416 | |||
16417 | Although <BigInteger()> is the constructor for <BigInteger> objects, it is | ||
16418 | best not to call it as a constructor. If *n* is a <BigInteger> object, it is | ||
16419 | simply returned as-is. Otherwise, <BigInteger()> is equivalent to <parse> | ||
16420 | without a radix argument. | ||
16421 | |||
16422 | > var n0 = BigInteger(); // Same as <BigInteger.ZERO> | ||
16423 | > var n1 = BigInteger("123"); // Create a new <BigInteger> with value 123 | ||
16424 | > var n2 = BigInteger(123); // Create a new <BigInteger> with value 123 | ||
16425 | > var n3 = BigInteger(n2); // Return n2, unchanged | ||
16426 | |||
16427 | The constructor form only takes an array and a sign. *n* must be an | ||
16428 | array of numbers in little-endian order, where each digit is between 0 | ||
16429 | and BigInteger.base. The second parameter sets the sign: -1 for | ||
16430 | negative, +1 for positive, or 0 for zero. The array is *not copied and | ||
16431 | may be modified*. If the array contains only zeros, the sign parameter | ||
16432 | is ignored and is forced to zero. | ||
16433 | |||
16434 | > new BigInteger([5], -1): create a new BigInteger with value -5 | ||
16435 | |||
16436 | Parameters: | ||
16437 | |||
16438 | n - Value to convert to a <BigInteger>. | ||
16439 | |||
16440 | Returns: | ||
16441 | |||
16442 | A <BigInteger> value. | ||
16443 | |||
16444 | See Also: | ||
16445 | |||
16446 | <parse>, <BigInteger> | ||
16447 | */ | ||
16448 | function BigInteger(n, s, token) { | ||
16449 | if (token !== CONSTRUCT) { | ||
16450 | if (n instanceof BigInteger) { | ||
16451 | return n; | ||
16452 | } | ||
16453 | else if (typeof n === "undefined") { | ||
16454 | return ZERO; | ||
16455 | } | ||
16456 | return BigInteger.parse(n); | ||
16457 | } | ||
16458 | |||
16459 | n = n || []; // Provide the nullary constructor for subclasses. | ||
16460 | while (n.length && !n[n.length - 1]) { | ||
16461 | --n.length; | ||
16462 | } | ||
16463 | this._d = n; | ||
16464 | this._s = n.length ? (s || 1) : 0; | ||
16465 | } | ||
16466 | |||
16467 | BigInteger._construct = function(n, s) { | ||
16468 | return new BigInteger(n, s, CONSTRUCT); | ||
16469 | }; | ||
16470 | |||
16471 | // Base-10 speedup hacks in parse, toString, exp10 and log functions | ||
16472 | // require base to be a power of 10. 10^7 is the largest such power | ||
16473 | // that won't cause a precision loss when digits are multiplied. | ||
16474 | var BigInteger_base = 10000000; | ||
16475 | var BigInteger_base_log10 = 7; | ||
16476 | |||
16477 | BigInteger.base = BigInteger_base; | ||
16478 | BigInteger.base_log10 = BigInteger_base_log10; | ||
16479 | |||
16480 | var ZERO = new BigInteger([], 0, CONSTRUCT); | ||
16481 | // Constant: ZERO | ||
16482 | // <BigInteger> 0. | ||
16483 | BigInteger.ZERO = ZERO; | ||
16484 | |||
16485 | var ONE = new BigInteger([1], 1, CONSTRUCT); | ||
16486 | // Constant: ONE | ||
16487 | // <BigInteger> 1. | ||
16488 | BigInteger.ONE = ONE; | ||
16489 | |||
16490 | var M_ONE = new BigInteger(ONE._d, -1, CONSTRUCT); | ||
16491 | // Constant: M_ONE | ||
16492 | // <BigInteger> -1. | ||
16493 | BigInteger.M_ONE = M_ONE; | ||
16494 | |||
16495 | // Constant: _0 | ||
16496 | // Shortcut for <ZERO>. | ||
16497 | BigInteger._0 = ZERO; | ||
16498 | |||
16499 | // Constant: _1 | ||
16500 | // Shortcut for <ONE>. | ||
16501 | BigInteger._1 = ONE; | ||
16502 | |||
16503 | /* | ||
16504 | Constant: small | ||
16505 | Array of <BigIntegers> from 0 to 36. | ||
16506 | |||
16507 | These are used internally for parsing, but useful when you need a "small" | ||
16508 | <BigInteger>. | ||
16509 | |||
16510 | See Also: | ||
16511 | |||
16512 | <ZERO>, <ONE>, <_0>, <_1> | ||
16513 | */ | ||
16514 | BigInteger.small = [ | ||
16515 | ZERO, | ||
16516 | ONE, | ||
16517 | /* Assuming BigInteger_base > 36 */ | ||
16518 | new BigInteger( [2], 1, CONSTRUCT), | ||
16519 | new BigInteger( [3], 1, CONSTRUCT), | ||
16520 | new BigInteger( [4], 1, CONSTRUCT), | ||
16521 | new BigInteger( [5], 1, CONSTRUCT), | ||
16522 | new BigInteger( [6], 1, CONSTRUCT), | ||
16523 | new BigInteger( [7], 1, CONSTRUCT), | ||
16524 | new BigInteger( [8], 1, CONSTRUCT), | ||
16525 | new BigInteger( [9], 1, CONSTRUCT), | ||
16526 | new BigInteger([10], 1, CONSTRUCT), | ||
16527 | new BigInteger([11], 1, CONSTRUCT), | ||
16528 | new BigInteger([12], 1, CONSTRUCT), | ||
16529 | new BigInteger([13], 1, CONSTRUCT), | ||
16530 | new BigInteger([14], 1, CONSTRUCT), | ||
16531 | new BigInteger([15], 1, CONSTRUCT), | ||
16532 | new BigInteger([16], 1, CONSTRUCT), | ||
16533 | new BigInteger([17], 1, CONSTRUCT), | ||
16534 | new BigInteger([18], 1, CONSTRUCT), | ||
16535 | new BigInteger([19], 1, CONSTRUCT), | ||
16536 | new BigInteger([20], 1, CONSTRUCT), | ||
16537 | new BigInteger([21], 1, CONSTRUCT), | ||
16538 | new BigInteger([22], 1, CONSTRUCT), | ||
16539 | new BigInteger([23], 1, CONSTRUCT), | ||
16540 | new BigInteger([24], 1, CONSTRUCT), | ||
16541 | new BigInteger([25], 1, CONSTRUCT), | ||
16542 | new BigInteger([26], 1, CONSTRUCT), | ||
16543 | new BigInteger([27], 1, CONSTRUCT), | ||
16544 | new BigInteger([28], 1, CONSTRUCT), | ||
16545 | new BigInteger([29], 1, CONSTRUCT), | ||
16546 | new BigInteger([30], 1, CONSTRUCT), | ||
16547 | new BigInteger([31], 1, CONSTRUCT), | ||
16548 | new BigInteger([32], 1, CONSTRUCT), | ||
16549 | new BigInteger([33], 1, CONSTRUCT), | ||
16550 | new BigInteger([34], 1, CONSTRUCT), | ||
16551 | new BigInteger([35], 1, CONSTRUCT), | ||
16552 | new BigInteger([36], 1, CONSTRUCT) | ||
16553 | ]; | ||
16554 | |||
16555 | // Used for parsing/radix conversion | ||
16556 | BigInteger.digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); | ||
16557 | |||
16558 | /* | ||
16559 | Method: toString | ||
16560 | Convert a <BigInteger> to a string. | ||
16561 | |||
16562 | When *base* is greater than 10, letters are upper case. | ||
16563 | |||
16564 | Parameters: | ||
16565 | |||
16566 | base - Optional base to represent the number in (default is base 10). | ||
16567 | Must be between 2 and 36 inclusive, or an Error will be thrown. | ||
16568 | |||
16569 | Returns: | ||
16570 | |||
16571 | The string representation of the <BigInteger>. | ||
16572 | */ | ||
16573 | BigInteger.prototype.toString = function(base) { | ||
16574 | base = +base || 10; | ||
16575 | if (base < 2 || base > 36) { | ||
16576 | throw new Error("illegal radix " + base + "."); | ||
16577 | } | ||
16578 | if (this._s === 0) { | ||
16579 | return "0"; | ||
16580 | } | ||
16581 | if (base === 10) { | ||
16582 | var str = this._s < 0 ? "-" : ""; | ||
16583 | str += this._d[this._d.length - 1].toString(); | ||
16584 | for (var i = this._d.length - 2; i >= 0; i--) { | ||
16585 | var group = this._d[i].toString(); | ||
16586 | while (group.length < BigInteger_base_log10) group = '0' + group; | ||
16587 | str += group; | ||
16588 | } | ||
16589 | return str; | ||
16590 | } | ||
16591 | else { | ||
16592 | var numerals = BigInteger.digits; | ||
16593 | base = BigInteger.small[base]; | ||
16594 | var sign = this._s; | ||
16595 | |||
16596 | var n = this.abs(); | ||
16597 | var digits = []; | ||
16598 | var digit; | ||
16599 | |||
16600 | while (n._s !== 0) { | ||
16601 | var divmod = n.divRem(base); | ||
16602 | n = divmod[0]; | ||
16603 | digit = divmod[1]; | ||
16604 | // TODO: This could be changed to unshift instead of reversing at the end. | ||
16605 | // Benchmark both to compare speeds. | ||
16606 | digits.push(numerals[digit.valueOf()]); | ||
16607 | } | ||
16608 | return (sign < 0 ? "-" : "") + digits.reverse().join(""); | ||
16609 | } | ||
16610 | }; | ||
16611 | |||
16612 | // Verify strings for parsing | ||
16613 | BigInteger.radixRegex = [ | ||
16614 | /^$/, | ||
16615 | /^$/, | ||
16616 | /^[01]*$/, | ||
16617 | /^[012]*$/, | ||
16618 | /^[0-3]*$/, | ||
16619 | /^[0-4]*$/, | ||
16620 | /^[0-5]*$/, | ||
16621 | /^[0-6]*$/, | ||
16622 | /^[0-7]*$/, | ||
16623 | /^[0-8]*$/, | ||
16624 | /^[0-9]*$/, | ||
16625 | /^[0-9aA]*$/, | ||
16626 | /^[0-9abAB]*$/, | ||
16627 | /^[0-9abcABC]*$/, | ||
16628 | /^[0-9a-dA-D]*$/, | ||
16629 | /^[0-9a-eA-E]*$/, | ||
16630 | /^[0-9a-fA-F]*$/, | ||
16631 | /^[0-9a-gA-G]*$/, | ||
16632 | /^[0-9a-hA-H]*$/, | ||
16633 | /^[0-9a-iA-I]*$/, | ||
16634 | /^[0-9a-jA-J]*$/, | ||
16635 | /^[0-9a-kA-K]*$/, | ||
16636 | /^[0-9a-lA-L]*$/, | ||
16637 | /^[0-9a-mA-M]*$/, | ||
16638 | /^[0-9a-nA-N]*$/, | ||
16639 | /^[0-9a-oA-O]*$/, | ||
16640 | /^[0-9a-pA-P]*$/, | ||
16641 | /^[0-9a-qA-Q]*$/, | ||
16642 | /^[0-9a-rA-R]*$/, | ||
16643 | /^[0-9a-sA-S]*$/, | ||
16644 | /^[0-9a-tA-T]*$/, | ||
16645 | /^[0-9a-uA-U]*$/, | ||
16646 | /^[0-9a-vA-V]*$/, | ||
16647 | /^[0-9a-wA-W]*$/, | ||
16648 | /^[0-9a-xA-X]*$/, | ||
16649 | /^[0-9a-yA-Y]*$/, | ||
16650 | /^[0-9a-zA-Z]*$/ | ||
16651 | ]; | ||
16652 | |||
16653 | /* | ||
16654 | Function: parse | ||
16655 | Parse a string into a <BigInteger>. | ||
16656 | |||
16657 | *base* is optional but, if provided, must be from 2 to 36 inclusive. If | ||
16658 | *base* is not provided, it will be guessed based on the leading characters | ||
16659 | of *s* as follows: | ||
16660 | |||
16661 | - "0x" or "0X": *base* = 16 | ||
16662 | - "0c" or "0C": *base* = 8 | ||
16663 | - "0b" or "0B": *base* = 2 | ||
16664 | - else: *base* = 10 | ||
16665 | |||
16666 | If no base is provided, or *base* is 10, the number can be in exponential | ||
16667 | form. For example, these are all valid: | ||
16668 | |||
16669 | > BigInteger.parse("1e9"); // Same as "1000000000" | ||
16670 | > BigInteger.parse("1.234*10^3"); // Same as 1234 | ||
16671 | > BigInteger.parse("56789 * 10 ** -2"); // Same as 567 | ||
16672 | |||
16673 | If any characters fall outside the range defined by the radix, an exception | ||
16674 | will be thrown. | ||
16675 | |||
16676 | Parameters: | ||
16677 | |||
16678 | s - The string to parse. | ||
16679 | base - Optional radix (default is to guess based on *s*). | ||
16680 | |||
16681 | Returns: | ||
16682 | |||
16683 | a <BigInteger> instance. | ||
16684 | */ | ||
16685 | BigInteger.parse = function(s, base) { | ||
16686 | // Expands a number in exponential form to decimal form. | ||
16687 | // expandExponential("-13.441*10^5") === "1344100"; | ||
16688 | // expandExponential("1.12300e-1") === "0.112300"; | ||
16689 | // expandExponential(1000000000000000000000000000000) === "1000000000000000000000000000000"; | ||
16690 | function expandExponential(str) { | ||
16691 | str = str.replace(/\s*[*xX]\s*10\s*(\^|\*\*)\s*/, "e"); | ||
16692 | |||
16693 | return str.replace(/^([+\-])?(\d+)\.?(\d*)[eE]([+\-]?\d+)$/, function(x, s, n, f, c) { | ||
16694 | c = +c; | ||
16695 | var l = c < 0; | ||
16696 | var i = n.length + c; | ||
16697 | x = (l ? n : f).length; | ||
16698 | c = ((c = Math.abs(c)) >= x ? c - x + l : 0); | ||
16699 | var z = (new Array(c + 1)).join("0"); | ||
16700 | var r = n + f; | ||
16701 | return (s || "") + (l ? r = z + r : r += z).substr(0, i += l ? z.length : 0) + (i < r.length ? "." + r.substr(i) : ""); | ||
16702 | }); | ||
16703 | } | ||
16704 | |||
16705 | s = s.toString(); | ||
16706 | if (typeof base === "undefined" || +base === 10) { | ||
16707 | s = expandExponential(s); | ||
16708 | } | ||
16709 | |||
16710 | var prefixRE; | ||
16711 | if (typeof base === "undefined") { | ||
16712 | prefixRE = '0[xcb]'; | ||
16713 | } | ||
16714 | else if (base == 16) { | ||
16715 | prefixRE = '0x'; | ||
16716 | } | ||
16717 | else if (base == 8) { | ||
16718 | prefixRE = '0c'; | ||
16719 | } | ||
16720 | else if (base == 2) { | ||
16721 | prefixRE = '0b'; | ||
16722 | } | ||
16723 | else { | ||
16724 | prefixRE = ''; | ||
16725 | } | ||
16726 | var parts = new RegExp('^([+\\-]?)(' + prefixRE + ')?([0-9a-z]*)(?:\\.\\d*)?$', 'i').exec(s); | ||
16727 | if (parts) { | ||
16728 | var sign = parts[1] || "+"; | ||
16729 | var baseSection = parts[2] || ""; | ||
16730 | var digits = parts[3] || ""; | ||
16731 | |||
16732 | if (typeof base === "undefined") { | ||
16733 | // Guess base | ||
16734 | if (baseSection === "0x" || baseSection === "0X") { // Hex | ||
16735 | base = 16; | ||
16736 | } | ||
16737 | else if (baseSection === "0c" || baseSection === "0C") { // Octal | ||
16738 | base = 8; | ||
16739 | } | ||
16740 | else if (baseSection === "0b" || baseSection === "0B") { // Binary | ||
16741 | base = 2; | ||
16742 | } | ||
16743 | else { | ||
16744 | base = 10; | ||
16745 | } | ||
16746 | } | ||
16747 | else if (base < 2 || base > 36) { | ||
16748 | throw new Error("Illegal radix " + base + "."); | ||
16749 | } | ||
16750 | |||
16751 | base = +base; | ||
16752 | |||
16753 | // Check for digits outside the range | ||
16754 | if (!(BigInteger.radixRegex[base].test(digits))) { | ||
16755 | throw new Error("Bad digit for radix " + base); | ||
16756 | } | ||
16757 | |||
16758 | // Strip leading zeros, and convert to array | ||
16759 | digits = digits.replace(/^0+/, "").split(""); | ||
16760 | if (digits.length === 0) { | ||
16761 | return ZERO; | ||
16762 | } | ||
16763 | |||
16764 | // Get the sign (we know it's not zero) | ||
16765 | sign = (sign === "-") ? -1 : 1; | ||
16766 | |||
16767 | // Optimize 10 | ||
16768 | if (base == 10) { | ||
16769 | var d = []; | ||
16770 | while (digits.length >= BigInteger_base_log10) { | ||
16771 | d.push(parseInt(digits.splice(digits.length-BigInteger.base_log10, BigInteger.base_log10).join(''), 10)); | ||
16772 | } | ||
16773 | d.push(parseInt(digits.join(''), 10)); | ||
16774 | return new BigInteger(d, sign, CONSTRUCT); | ||
16775 | } | ||
16776 | |||
16777 | // Do the conversion | ||
16778 | var d = ZERO; | ||
16779 | base = BigInteger.small[base]; | ||
16780 | var small = BigInteger.small; | ||
16781 | for (var i = 0; i < digits.length; i++) { | ||
16782 | d = d.multiply(base).add(small[parseInt(digits[i], 36)]); | ||
16783 | } | ||
16784 | return new BigInteger(d._d, sign, CONSTRUCT); | ||
16785 | } | ||
16786 | else { | ||
16787 | throw new Error("Invalid BigInteger format: " + s); | ||
16788 | } | ||
16789 | }; | ||
16790 | |||
16791 | /* | ||
16792 | Function: add | ||
16793 | Add two <BigIntegers>. | ||
16794 | |||
16795 | Parameters: | ||
16796 | |||
16797 | n - The number to add to *this*. Will be converted to a <BigInteger>. | ||
16798 | |||
16799 | Returns: | ||
16800 | |||
16801 | The numbers added together. | ||
16802 | |||
16803 | See Also: | ||
16804 | |||
16805 | <subtract>, <multiply>, <quotient>, <next> | ||
16806 | */ | ||
16807 | BigInteger.prototype.add = function(n) { | ||
16808 | if (this._s === 0) { | ||
16809 | return BigInteger(n); | ||
16810 | } | ||
16811 | |||
16812 | n = BigInteger(n); | ||
16813 | if (n._s === 0) { | ||
16814 | return this; | ||
16815 | } | ||
16816 | if (this._s !== n._s) { | ||
16817 | n = n.negate(); | ||
16818 | return this.subtract(n); | ||
16819 | } | ||
16820 | |||
16821 | var a = this._d; | ||
16822 | var b = n._d; | ||
16823 | var al = a.length; | ||
16824 | var bl = b.length; | ||
16825 | var sum = new Array(Math.max(al, bl) + 1); | ||
16826 | var size = Math.min(al, bl); | ||
16827 | var carry = 0; | ||
16828 | var digit; | ||
16829 | |||
16830 | for (var i = 0; i < size; i++) { | ||
16831 | digit = a[i] + b[i] + carry; | ||
16832 | sum[i] = digit % BigInteger_base; | ||
16833 | carry = (digit / BigInteger_base) | 0; | ||
16834 | } | ||
16835 | if (bl > al) { | ||
16836 | a = b; | ||
16837 | al = bl; | ||
16838 | } | ||
16839 | for (i = size; carry && i < al; i++) { | ||
16840 | digit = a[i] + carry; | ||
16841 | sum[i] = digit % BigInteger_base; | ||
16842 | carry = (digit / BigInteger_base) | 0; | ||
16843 | } | ||
16844 | if (carry) { | ||
16845 | sum[i] = carry; | ||
16846 | } | ||
16847 | |||
16848 | for ( ; i < al; i++) { | ||
16849 | sum[i] = a[i]; | ||
16850 | } | ||
16851 | |||
16852 | return new BigInteger(sum, this._s, CONSTRUCT); | ||
16853 | }; | ||
16854 | |||
16855 | /* | ||
16856 | Function: negate | ||
16857 | Get the additive inverse of a <BigInteger>. | ||
16858 | |||
16859 | Returns: | ||
16860 | |||
16861 | A <BigInteger> with the same magnatude, but with the opposite sign. | ||
16862 | |||
16863 | See Also: | ||
16864 | |||
16865 | <abs> | ||
16866 | */ | ||
16867 | BigInteger.prototype.negate = function() { | ||
16868 | return new BigInteger(this._d, (-this._s) | 0, CONSTRUCT); | ||
16869 | }; | ||
16870 | |||
16871 | /* | ||
16872 | Function: abs | ||
16873 | Get the absolute value of a <BigInteger>. | ||
16874 | |||
16875 | Returns: | ||
16876 | |||
16877 | A <BigInteger> with the same magnatude, but always positive (or zero). | ||
16878 | |||
16879 | See Also: | ||
16880 | |||
16881 | <negate> | ||
16882 | */ | ||
16883 | BigInteger.prototype.abs = function() { | ||
16884 | return (this._s < 0) ? this.negate() : this; | ||
16885 | }; | ||
16886 | |||
16887 | /* | ||
16888 | Function: subtract | ||
16889 | Subtract two <BigIntegers>. | ||
16890 | |||
16891 | Parameters: | ||
16892 | |||
16893 | n - The number to subtract from *this*. Will be converted to a <BigInteger>. | ||
16894 | |||
16895 | Returns: | ||
16896 | |||
16897 | The *n* subtracted from *this*. | ||
16898 | |||
16899 | See Also: | ||
16900 | |||
16901 | <add>, <multiply>, <quotient>, <prev> | ||
16902 | */ | ||
16903 | BigInteger.prototype.subtract = function(n) { | ||
16904 | if (this._s === 0) { | ||
16905 | return BigInteger(n).negate(); | ||
16906 | } | ||
16907 | |||
16908 | n = BigInteger(n); | ||
16909 | if (n._s === 0) { | ||
16910 | return this; | ||
16911 | } | ||
16912 | if (this._s !== n._s) { | ||
16913 | n = n.negate(); | ||
16914 | return this.add(n); | ||
16915 | } | ||
16916 | |||
16917 | var m = this; | ||
16918 | // negative - negative => -|a| - -|b| => -|a| + |b| => |b| - |a| | ||
16919 | if (this._s < 0) { | ||
16920 | m = new BigInteger(n._d, 1, CONSTRUCT); | ||
16921 | n = new BigInteger(this._d, 1, CONSTRUCT); | ||
16922 | } | ||
16923 | |||
16924 | // Both are positive => a - b | ||
16925 | var sign = m.compareAbs(n); | ||
16926 | if (sign === 0) { | ||
16927 | return ZERO; | ||
16928 | } | ||
16929 | else if (sign < 0) { | ||
16930 | // swap m and n | ||
16931 | var t = n; | ||
16932 | n = m; | ||
16933 | m = t; | ||
16934 | } | ||
16935 | |||
16936 | // a > b | ||
16937 | var a = m._d; | ||
16938 | var b = n._d; | ||
16939 | var al = a.length; | ||
16940 | var bl = b.length; | ||
16941 | var diff = new Array(al); // al >= bl since a > b | ||
16942 | var borrow = 0; | ||
16943 | var i; | ||
16944 | var digit; | ||
16945 | |||
16946 | for (i = 0; i < bl; i++) { | ||
16947 | digit = a[i] - borrow - b[i]; | ||
16948 | if (digit < 0) { | ||
16949 | digit += BigInteger_base; | ||
16950 | borrow = 1; | ||
16951 | } | ||
16952 | else { | ||
16953 | borrow = 0; | ||
16954 | } | ||
16955 | diff[i] = digit; | ||
16956 | } | ||
16957 | for (i = bl; i < al; i++) { | ||
16958 | digit = a[i] - borrow; | ||
16959 | if (digit < 0) { | ||
16960 | digit += BigInteger_base; | ||
16961 | } | ||
16962 | else { | ||
16963 | diff[i++] = digit; | ||
16964 | break; | ||
16965 | } | ||
16966 | diff[i] = digit; | ||
16967 | } | ||
16968 | for ( ; i < al; i++) { | ||
16969 | diff[i] = a[i]; | ||
16970 | } | ||
16971 | |||
16972 | return new BigInteger(diff, sign, CONSTRUCT); | ||
16973 | }; | ||
16974 | |||
16975 | (function() { | ||
16976 | function addOne(n, sign) { | ||
16977 | var a = n._d; | ||
16978 | var sum = a.slice(); | ||
16979 | var carry = true; | ||
16980 | var i = 0; | ||
16981 | |||
16982 | while (true) { | ||
16983 | var digit = (a[i] || 0) + 1; | ||
16984 | sum[i] = digit % BigInteger_base; | ||
16985 | if (digit <= BigInteger_base - 1) { | ||
16986 | break; | ||
16987 | } | ||
16988 | ++i; | ||
16989 | } | ||
16990 | |||
16991 | return new BigInteger(sum, sign, CONSTRUCT); | ||
16992 | } | ||
16993 | |||
16994 | function subtractOne(n, sign) { | ||
16995 | var a = n._d; | ||
16996 | var sum = a.slice(); | ||
16997 | var borrow = true; | ||
16998 | var i = 0; | ||
16999 | |||
17000 | while (true) { | ||
17001 | var digit = (a[i] || 0) - 1; | ||
17002 | if (digit < 0) { | ||
17003 | sum[i] = digit + BigInteger_base; | ||
17004 | } | ||
17005 | else { | ||
17006 | sum[i] = digit; | ||
17007 | break; | ||
17008 | } | ||
17009 | ++i; | ||
17010 | } | ||
17011 | |||
17012 | return new BigInteger(sum, sign, CONSTRUCT); | ||
17013 | } | ||
17014 | |||
17015 | /* | ||
17016 | Function: next | ||
17017 | Get the next <BigInteger> (add one). | ||
17018 | |||
17019 | Returns: | ||
17020 | |||
17021 | *this* + 1. | ||
17022 | |||
17023 | See Also: | ||
17024 | |||
17025 | <add>, <prev> | ||
17026 | */ | ||
17027 | BigInteger.prototype.next = function() { | ||
17028 | switch (this._s) { | ||
17029 | case 0: | ||
17030 | return ONE; | ||
17031 | case -1: | ||
17032 | return subtractOne(this, -1); | ||
17033 | // case 1: | ||
17034 | default: | ||
17035 | return addOne(this, 1); | ||
17036 | } | ||
17037 | }; | ||
17038 | |||
17039 | /* | ||
17040 | Function: prev | ||
17041 | Get the previous <BigInteger> (subtract one). | ||
17042 | |||
17043 | Returns: | ||
17044 | |||
17045 | *this* - 1. | ||
17046 | |||
17047 | See Also: | ||
17048 | |||
17049 | <next>, <subtract> | ||
17050 | */ | ||
17051 | BigInteger.prototype.prev = function() { | ||
17052 | switch (this._s) { | ||
17053 | case 0: | ||
17054 | return M_ONE; | ||
17055 | case -1: | ||
17056 | return addOne(this, -1); | ||
17057 | // case 1: | ||
17058 | default: | ||
17059 | return subtractOne(this, 1); | ||
17060 | } | ||
17061 | }; | ||
17062 | })(); | ||
17063 | |||
17064 | /* | ||
17065 | Function: compareAbs | ||
17066 | Compare the absolute value of two <BigIntegers>. | ||
17067 | |||
17068 | Calling <compareAbs> is faster than calling <abs> twice, then <compare>. | ||
17069 | |||
17070 | Parameters: | ||
17071 | |||
17072 | n - The number to compare to *this*. Will be converted to a <BigInteger>. | ||
17073 | |||
17074 | Returns: | ||
17075 | |||
17076 | -1, 0, or +1 if *|this|* is less than, equal to, or greater than *|n|*. | ||
17077 | |||
17078 | See Also: | ||
17079 | |||
17080 | <compare>, <abs> | ||
17081 | */ | ||
17082 | BigInteger.prototype.compareAbs = function(n) { | ||
17083 | if (this === n) { | ||
17084 | return 0; | ||
17085 | } | ||
17086 | |||
17087 | if (!(n instanceof BigInteger)) { | ||
17088 | if (!isFinite(n)) { | ||
17089 | return(isNaN(n) ? n : -1); | ||
17090 | } | ||
17091 | n = BigInteger(n); | ||
17092 | } | ||
17093 | |||
17094 | if (this._s === 0) { | ||
17095 | return (n._s !== 0) ? -1 : 0; | ||
17096 | } | ||
17097 | if (n._s === 0) { | ||
17098 | return 1; | ||
17099 | } | ||
17100 | |||
17101 | var l = this._d.length; | ||
17102 | var nl = n._d.length; | ||
17103 | if (l < nl) { | ||
17104 | return -1; | ||
17105 | } | ||
17106 | else if (l > nl) { | ||
17107 | return 1; | ||
17108 | } | ||
17109 | |||
17110 | var a = this._d; | ||
17111 | var b = n._d; | ||
17112 | for (var i = l-1; i >= 0; i--) { | ||
17113 | if (a[i] !== b[i]) { | ||
17114 | return a[i] < b[i] ? -1 : 1; | ||
17115 | } | ||
17116 | } | ||
17117 | |||
17118 | return 0; | ||
17119 | }; | ||
17120 | |||
17121 | /* | ||
17122 | Function: compare | ||
17123 | Compare two <BigIntegers>. | ||
17124 | |||
17125 | Parameters: | ||
17126 | |||
17127 | n - The number to compare to *this*. Will be converted to a <BigInteger>. | ||
17128 | |||
17129 | Returns: | ||
17130 | |||
17131 | -1, 0, or +1 if *this* is less than, equal to, or greater than *n*. | ||
17132 | |||
17133 | See Also: | ||
17134 | |||
17135 | <compareAbs>, <isPositive>, <isNegative>, <isUnit> | ||
17136 | */ | ||
17137 | BigInteger.prototype.compare = function(n) { | ||
17138 | if (this === n) { | ||
17139 | return 0; | ||
17140 | } | ||
17141 | |||
17142 | n = BigInteger(n); | ||
17143 | |||
17144 | if (this._s === 0) { | ||
17145 | return -n._s; | ||
17146 | } | ||
17147 | |||
17148 | if (this._s === n._s) { // both positive or both negative | ||
17149 | var cmp = this.compareAbs(n); | ||
17150 | return cmp * this._s; | ||
17151 | } | ||
17152 | else { | ||
17153 | return this._s; | ||
17154 | } | ||
17155 | }; | ||
17156 | |||
17157 | /* | ||
17158 | Function: isUnit | ||
17159 | Return true iff *this* is either 1 or -1. | ||
17160 | |||
17161 | Returns: | ||
17162 | |||
17163 | true if *this* compares equal to <BigInteger.ONE> or <BigInteger.M_ONE>. | ||
17164 | |||
17165 | See Also: | ||
17166 | |||
17167 | <isZero>, <isNegative>, <isPositive>, <compareAbs>, <compare>, | ||
17168 | <BigInteger.ONE>, <BigInteger.M_ONE> | ||
17169 | */ | ||
17170 | BigInteger.prototype.isUnit = function() { | ||
17171 | return this === ONE || | ||
17172 | this === M_ONE || | ||
17173 | (this._d.length === 1 && this._d[0] === 1); | ||
17174 | }; | ||
17175 | |||
17176 | /* | ||
17177 | Function: multiply | ||
17178 | Multiply two <BigIntegers>. | ||
17179 | |||
17180 | Parameters: | ||
17181 | |||
17182 | n - The number to multiply *this* by. Will be converted to a | ||
17183 | <BigInteger>. | ||
17184 | |||
17185 | Returns: | ||
17186 | |||
17187 | The numbers multiplied together. | ||
17188 | |||
17189 | See Also: | ||
17190 | |||
17191 | <add>, <subtract>, <quotient>, <square> | ||
17192 | */ | ||
17193 | BigInteger.prototype.multiply = function(n) { | ||
17194 | // TODO: Consider adding Karatsuba multiplication for large numbers | ||
17195 | if (this._s === 0) { | ||
17196 | return ZERO; | ||
17197 | } | ||
17198 | |||
17199 | n = BigInteger(n); | ||
17200 | if (n._s === 0) { | ||
17201 | return ZERO; | ||
17202 | } | ||
17203 | if (this.isUnit()) { | ||
17204 | if (this._s < 0) { | ||
17205 | return n.negate(); | ||
17206 | } | ||
17207 | return n; | ||
17208 | } | ||
17209 | if (n.isUnit()) { | ||
17210 | if (n._s < 0) { | ||
17211 | return this.negate(); | ||
17212 | } | ||
17213 | return this; | ||
17214 | } | ||
17215 | if (this === n) { | ||
17216 | return this.square(); | ||
17217 | } | ||
17218 | |||
17219 | var r = (this._d.length >= n._d.length); | ||
17220 | var a = (r ? this : n)._d; // a will be longer than b | ||
17221 | var b = (r ? n : this)._d; | ||
17222 | var al = a.length; | ||
17223 | var bl = b.length; | ||
17224 | |||
17225 | var pl = al + bl; | ||
17226 | var partial = new Array(pl); | ||
17227 | var i; | ||
17228 | for (i = 0; i < pl; i++) { | ||
17229 | partial[i] = 0; | ||
17230 | } | ||
17231 | |||
17232 | for (i = 0; i < bl; i++) { | ||
17233 | var carry = 0; | ||
17234 | var bi = b[i]; | ||
17235 | var jlimit = al + i; | ||
17236 | var digit; | ||
17237 | for (var j = i; j < jlimit; j++) { | ||
17238 | digit = partial[j] + bi * a[j - i] + carry; | ||
17239 | carry = (digit / BigInteger_base) | 0; | ||
17240 | partial[j] = (digit % BigInteger_base) | 0; | ||
17241 | } | ||
17242 | if (carry) { | ||
17243 | digit = partial[j] + carry; | ||
17244 | carry = (digit / BigInteger_base) | 0; | ||
17245 | partial[j] = digit % BigInteger_base; | ||
17246 | } | ||
17247 | } | ||
17248 | return new BigInteger(partial, this._s * n._s, CONSTRUCT); | ||
17249 | }; | ||
17250 | |||
17251 | // Multiply a BigInteger by a single-digit native number | ||
17252 | // Assumes that this and n are >= 0 | ||
17253 | // This is not really intended to be used outside the library itself | ||
17254 | BigInteger.prototype.multiplySingleDigit = function(n) { | ||
17255 | if (n === 0 || this._s === 0) { | ||
17256 | return ZERO; | ||
17257 | } | ||
17258 | if (n === 1) { | ||
17259 | return this; | ||
17260 | } | ||
17261 | |||
17262 | var digit; | ||
17263 | if (this._d.length === 1) { | ||
17264 | digit = this._d[0] * n; | ||
17265 | if (digit >= BigInteger_base) { | ||
17266 | return new BigInteger([(digit % BigInteger_base)|0, | ||
17267 | (digit / BigInteger_base)|0], 1, CONSTRUCT); | ||
17268 | } | ||
17269 | return new BigInteger([digit], 1, CONSTRUCT); | ||
17270 | } | ||
17271 | |||
17272 | if (n === 2) { | ||
17273 | return this.add(this); | ||
17274 | } | ||
17275 | if (this.isUnit()) { | ||
17276 | return new BigInteger([n], 1, CONSTRUCT); | ||
17277 | } | ||
17278 | |||
17279 | var a = this._d; | ||
17280 | var al = a.length; | ||
17281 | |||
17282 | var pl = al + 1; | ||
17283 | var partial = new Array(pl); | ||
17284 | for (var i = 0; i < pl; i++) { | ||
17285 | partial[i] = 0; | ||
17286 | } | ||
17287 | |||
17288 | var carry = 0; | ||
17289 | for (var j = 0; j < al; j++) { | ||
17290 | digit = n * a[j] + carry; | ||
17291 | carry = (digit / BigInteger_base) | 0; | ||
17292 | partial[j] = (digit % BigInteger_base) | 0; | ||
17293 | } | ||
17294 | if (carry) { | ||
17295 | partial[j] = carry; | ||
17296 | } | ||
17297 | |||
17298 | return new BigInteger(partial, 1, CONSTRUCT); | ||
17299 | }; | ||
17300 | |||
17301 | /* | ||
17302 | Function: square | ||
17303 | Multiply a <BigInteger> by itself. | ||
17304 | |||
17305 | This is slightly faster than regular multiplication, since it removes the | ||
17306 | duplicated multiplcations. | ||
17307 | |||
17308 | Returns: | ||
17309 | |||
17310 | > this.multiply(this) | ||
17311 | |||
17312 | See Also: | ||
17313 | <multiply> | ||
17314 | */ | ||
17315 | BigInteger.prototype.square = function() { | ||
17316 | // Normally, squaring a 10-digit number would take 100 multiplications. | ||
17317 | // Of these 10 are unique diagonals, of the remaining 90 (100-10), 45 are repeated. | ||
17318 | // This procedure saves (N*(N-1))/2 multiplications, (e.g., 45 of 100 multiplies). | ||
17319 | // Based on code by Gary Darby, Intellitech Systems Inc., www.DelphiForFun.org | ||
17320 | |||
17321 | if (this._s === 0) { | ||
17322 | return ZERO; | ||
17323 | } | ||
17324 | if (this.isUnit()) { | ||
17325 | return ONE; | ||
17326 | } | ||
17327 | |||
17328 | var digits = this._d; | ||
17329 | var length = digits.length; | ||
17330 | var imult1 = new Array(length + length + 1); | ||
17331 | var product, carry, k; | ||
17332 | var i; | ||
17333 | |||
17334 | // Calculate diagonal | ||
17335 | for (i = 0; i < length; i++) { | ||
17336 | k = i * 2; | ||
17337 | product = digits[i] * digits[i]; | ||
17338 | carry = (product / BigInteger_base) | 0; | ||
17339 | imult1[k] = product % BigInteger_base; | ||
17340 | imult1[k + 1] = carry; | ||
17341 | } | ||
17342 | |||
17343 | // Calculate repeating part | ||
17344 | for (i = 0; i < length; i++) { | ||
17345 | carry = 0; | ||
17346 | k = i * 2 + 1; | ||
17347 | for (var j = i + 1; j < length; j++, k++) { | ||
17348 | product = digits[j] * digits[i] * 2 + imult1[k] + carry; | ||
17349 | carry = (product / BigInteger_base) | 0; | ||
17350 | imult1[k] = product % BigInteger_base; | ||
17351 | } | ||
17352 | k = length + i; | ||
17353 | var digit = carry + imult1[k]; | ||
17354 | carry = (digit / BigInteger_base) | 0; | ||
17355 | imult1[k] = digit % BigInteger_base; | ||
17356 | imult1[k + 1] += carry; | ||
17357 | } | ||
17358 | |||
17359 | return new BigInteger(imult1, 1, CONSTRUCT); | ||
17360 | }; | ||
17361 | |||
17362 | /* | ||
17363 | Function: quotient | ||
17364 | Divide two <BigIntegers> and truncate towards zero. | ||
17365 | |||
17366 | <quotient> throws an exception if *n* is zero. | ||
17367 | |||
17368 | Parameters: | ||
17369 | |||
17370 | n - The number to divide *this* by. Will be converted to a <BigInteger>. | ||
17371 | |||
17372 | Returns: | ||
17373 | |||
17374 | The *this* / *n*, truncated to an integer. | ||
17375 | |||
17376 | See Also: | ||
17377 | |||
17378 | <add>, <subtract>, <multiply>, <divRem>, <remainder> | ||
17379 | */ | ||
17380 | BigInteger.prototype.quotient = function(n) { | ||
17381 | return this.divRem(n)[0]; | ||
17382 | }; | ||
17383 | |||
17384 | /* | ||
17385 | Function: divide | ||
17386 | Deprecated synonym for <quotient>. | ||
17387 | */ | ||
17388 | BigInteger.prototype.divide = BigInteger.prototype.quotient; | ||
17389 | |||
17390 | /* | ||
17391 | Function: remainder | ||
17392 | Calculate the remainder of two <BigIntegers>. | ||
17393 | |||
17394 | <remainder> throws an exception if *n* is zero. | ||
17395 | |||
17396 | Parameters: | ||
17397 | |||
17398 | n - The remainder after *this* is divided *this* by *n*. Will be | ||
17399 | converted to a <BigInteger>. | ||
17400 | |||
17401 | Returns: | ||
17402 | |||
17403 | *this* % *n*. | ||
17404 | |||
17405 | See Also: | ||
17406 | |||
17407 | <divRem>, <quotient> | ||
17408 | */ | ||
17409 | BigInteger.prototype.remainder = function(n) { | ||
17410 | return this.divRem(n)[1]; | ||
17411 | }; | ||
17412 | |||
17413 | /* | ||
17414 | Function: divRem | ||
17415 | Calculate the integer quotient and remainder of two <BigIntegers>. | ||
17416 | |||
17417 | <divRem> throws an exception if *n* is zero. | ||
17418 | |||
17419 | Parameters: | ||
17420 | |||
17421 | n - The number to divide *this* by. Will be converted to a <BigInteger>. | ||
17422 | |||
17423 | Returns: | ||
17424 | |||
17425 | A two-element array containing the quotient and the remainder. | ||
17426 | |||
17427 | > a.divRem(b) | ||
17428 | |||
17429 | is exactly equivalent to | ||
17430 | |||
17431 | > [a.quotient(b), a.remainder(b)] | ||
17432 | |||
17433 | except it is faster, because they are calculated at the same time. | ||
17434 | |||
17435 | See Also: | ||
17436 | |||
17437 | <quotient>, <remainder> | ||
17438 | */ | ||
17439 | BigInteger.prototype.divRem = function(n) { | ||
17440 | n = BigInteger(n); | ||
17441 | if (n._s === 0) { | ||
17442 | throw new Error("Divide by zero"); | ||
17443 | } | ||
17444 | if (this._s === 0) { | ||
17445 | return [ZERO, ZERO]; | ||
17446 | } | ||
17447 | if (n._d.length === 1) { | ||
17448 | return this.divRemSmall(n._s * n._d[0]); | ||
17449 | } | ||
17450 | |||
17451 | // Test for easy cases -- |n1| <= |n2| | ||
17452 | switch (this.compareAbs(n)) { | ||
17453 | case 0: // n1 == n2 | ||
17454 | return [this._s === n._s ? ONE : M_ONE, ZERO]; | ||
17455 | case -1: // |n1| < |n2| | ||
17456 | return [ZERO, this]; | ||
17457 | } | ||
17458 | |||
17459 | var sign = this._s * n._s; | ||
17460 | var a = n.abs(); | ||
17461 | var b_digits = this._d; | ||
17462 | var b_index = b_digits.length; | ||
17463 | var digits = n._d.length; | ||
17464 | var quot = []; | ||
17465 | var guess; | ||
17466 | |||
17467 | var part = new BigInteger([], 0, CONSTRUCT); | ||
17468 | |||
17469 | while (b_index) { | ||
17470 | part._d.unshift(b_digits[--b_index]); | ||
17471 | part = new BigInteger(part._d, 1, CONSTRUCT); | ||
17472 | |||
17473 | if (part.compareAbs(n) < 0) { | ||
17474 | quot.push(0); | ||
17475 | continue; | ||
17476 | } | ||
17477 | if (part._s === 0) { | ||
17478 | guess = 0; | ||
17479 | } | ||
17480 | else { | ||
17481 | var xlen = part._d.length, ylen = a._d.length; | ||
17482 | var highx = part._d[xlen-1]*BigInteger_base + part._d[xlen-2]; | ||
17483 | var highy = a._d[ylen-1]*BigInteger_base + a._d[ylen-2]; | ||
17484 | if (part._d.length > a._d.length) { | ||
17485 | // The length of part._d can either match a._d length, | ||
17486 | // or exceed it by one. | ||
17487 | highx = (highx+1)*BigInteger_base; | ||
17488 | } | ||
17489 | guess = Math.ceil(highx/highy); | ||
17490 | } | ||
17491 | do { | ||
17492 | var check = a.multiplySingleDigit(guess); | ||
17493 | if (check.compareAbs(part) <= 0) { | ||
17494 | break; | ||
17495 | } | ||
17496 | guess--; | ||
17497 | } while (guess); | ||
17498 | |||
17499 | quot.push(guess); | ||
17500 | if (!guess) { | ||
17501 | continue; | ||
17502 | } | ||
17503 | var diff = part.subtract(check); | ||
17504 | part._d = diff._d.slice(); | ||
17505 | } | ||
17506 | |||
17507 | return [new BigInteger(quot.reverse(), sign, CONSTRUCT), | ||
17508 | new BigInteger(part._d, this._s, CONSTRUCT)]; | ||
17509 | }; | ||
17510 | |||
17511 | // Throws an exception if n is outside of (-BigInteger.base, -1] or | ||
17512 | // [1, BigInteger.base). It's not necessary to call this, since the | ||
17513 | // other division functions will call it if they are able to. | ||
17514 | BigInteger.prototype.divRemSmall = function(n) { | ||
17515 | var r; | ||
17516 | n = +n; | ||
17517 | if (n === 0) { | ||
17518 | throw new Error("Divide by zero"); | ||
17519 | } | ||
17520 | |||
17521 | var n_s = n < 0 ? -1 : 1; | ||
17522 | var sign = this._s * n_s; | ||
17523 | n = Math.abs(n); | ||
17524 | |||
17525 | if (n < 1 || n >= BigInteger_base) { | ||
17526 | throw new Error("Argument out of range"); | ||
17527 | } | ||
17528 | |||
17529 | if (this._s === 0) { | ||
17530 | return [ZERO, ZERO]; | ||
17531 | } | ||
17532 | |||
17533 | if (n === 1 || n === -1) { | ||
17534 | return [(sign === 1) ? this.abs() : new BigInteger(this._d, sign, CONSTRUCT), ZERO]; | ||
17535 | } | ||
17536 | |||
17537 | // 2 <= n < BigInteger_base | ||
17538 | |||
17539 | // divide a single digit by a single digit | ||
17540 | if (this._d.length === 1) { | ||
17541 | var q = new BigInteger([(this._d[0] / n) | 0], 1, CONSTRUCT); | ||
17542 | r = new BigInteger([(this._d[0] % n) | 0], 1, CONSTRUCT); | ||
17543 | if (sign < 0) { | ||
17544 | q = q.negate(); | ||
17545 | } | ||
17546 | if (this._s < 0) { | ||
17547 | r = r.negate(); | ||
17548 | } | ||
17549 | return [q, r]; | ||
17550 | } | ||
17551 | |||
17552 | var digits = this._d.slice(); | ||
17553 | var quot = new Array(digits.length); | ||
17554 | var part = 0; | ||
17555 | var diff = 0; | ||
17556 | var i = 0; | ||
17557 | var guess; | ||
17558 | |||
17559 | while (digits.length) { | ||
17560 | part = part * BigInteger_base + digits[digits.length - 1]; | ||
17561 | if (part < n) { | ||
17562 | quot[i++] = 0; | ||
17563 | digits.pop(); | ||
17564 | diff = BigInteger_base * diff + part; | ||
17565 | continue; | ||
17566 | } | ||
17567 | if (part === 0) { | ||
17568 | guess = 0; | ||
17569 | } | ||
17570 | else { | ||
17571 | guess = (part / n) | 0; | ||
17572 | } | ||
17573 | |||
17574 | var check = n * guess; | ||
17575 | diff = part - check; | ||
17576 | quot[i++] = guess; | ||
17577 | if (!guess) { | ||
17578 | digits.pop(); | ||
17579 | continue; | ||
17580 | } | ||
17581 | |||
17582 | digits.pop(); | ||
17583 | part = diff; | ||
17584 | } | ||
17585 | |||
17586 | r = new BigInteger([diff], 1, CONSTRUCT); | ||
17587 | if (this._s < 0) { | ||
17588 | r = r.negate(); | ||
17589 | } | ||
17590 | return [new BigInteger(quot.reverse(), sign, CONSTRUCT), r]; | ||
17591 | }; | ||
17592 | |||
17593 | /* | ||
17594 | Function: isEven | ||
17595 | Return true iff *this* is divisible by two. | ||
17596 | |||
17597 | Note that <BigInteger.ZERO> is even. | ||
17598 | |||
17599 | Returns: | ||
17600 | |||
17601 | true if *this* is even, false otherwise. | ||
17602 | |||
17603 | See Also: | ||
17604 | |||
17605 | <isOdd> | ||
17606 | */ | ||
17607 | BigInteger.prototype.isEven = function() { | ||
17608 | var digits = this._d; | ||
17609 | return this._s === 0 || digits.length === 0 || (digits[0] % 2) === 0; | ||
17610 | }; | ||
17611 | |||
17612 | /* | ||
17613 | Function: isOdd | ||
17614 | Return true iff *this* is not divisible by two. | ||
17615 | |||
17616 | Returns: | ||
17617 | |||
17618 | true if *this* is odd, false otherwise. | ||
17619 | |||
17620 | See Also: | ||
17621 | |||
17622 | <isEven> | ||
17623 | */ | ||
17624 | BigInteger.prototype.isOdd = function() { | ||
17625 | return !this.isEven(); | ||
17626 | }; | ||
17627 | |||
17628 | /* | ||
17629 | Function: sign | ||
17630 | Get the sign of a <BigInteger>. | ||
17631 | |||
17632 | Returns: | ||
17633 | |||
17634 | * -1 if *this* < 0 | ||
17635 | * 0 if *this* == 0 | ||
17636 | * +1 if *this* > 0 | ||
17637 | |||
17638 | See Also: | ||
17639 | |||
17640 | <isZero>, <isPositive>, <isNegative>, <compare>, <BigInteger.ZERO> | ||
17641 | */ | ||
17642 | BigInteger.prototype.sign = function() { | ||
17643 | return this._s; | ||
17644 | }; | ||
17645 | |||
17646 | /* | ||
17647 | Function: isPositive | ||
17648 | Return true iff *this* > 0. | ||
17649 | |||
17650 | Returns: | ||
17651 | |||
17652 | true if *this*.compare(<BigInteger.ZERO>) == 1. | ||
17653 | |||
17654 | See Also: | ||
17655 | |||
17656 | <sign>, <isZero>, <isNegative>, <isUnit>, <compare>, <BigInteger.ZERO> | ||
17657 | */ | ||
17658 | BigInteger.prototype.isPositive = function() { | ||
17659 | return this._s > 0; | ||
17660 | }; | ||
17661 | |||
17662 | /* | ||
17663 | Function: isNegative | ||
17664 | Return true iff *this* < 0. | ||
17665 | |||
17666 | Returns: | ||
17667 | |||
17668 | true if *this*.compare(<BigInteger.ZERO>) == -1. | ||
17669 | |||
17670 | See Also: | ||
17671 | |||
17672 | <sign>, <isPositive>, <isZero>, <isUnit>, <compare>, <BigInteger.ZERO> | ||
17673 | */ | ||
17674 | BigInteger.prototype.isNegative = function() { | ||
17675 | return this._s < 0; | ||
17676 | }; | ||
17677 | |||
17678 | /* | ||
17679 | Function: isZero | ||
17680 | Return true iff *this* == 0. | ||
17681 | |||
17682 | Returns: | ||
17683 | |||
17684 | true if *this*.compare(<BigInteger.ZERO>) == 0. | ||
17685 | |||
17686 | See Also: | ||
17687 | |||
17688 | <sign>, <isPositive>, <isNegative>, <isUnit>, <BigInteger.ZERO> | ||
17689 | */ | ||
17690 | BigInteger.prototype.isZero = function() { | ||
17691 | return this._s === 0; | ||
17692 | }; | ||
17693 | |||
17694 | /* | ||
17695 | Function: exp10 | ||
17696 | Multiply a <BigInteger> by a power of 10. | ||
17697 | |||
17698 | This is equivalent to, but faster than | ||
17699 | |||
17700 | > if (n >= 0) { | ||
17701 | > return this.multiply(BigInteger("1e" + n)); | ||
17702 | > } | ||
17703 | > else { // n <= 0 | ||
17704 | > return this.quotient(BigInteger("1e" + -n)); | ||
17705 | > } | ||
17706 | |||
17707 | Parameters: | ||
17708 | |||
17709 | n - The power of 10 to multiply *this* by. *n* is converted to a | ||
17710 | javascipt number and must be no greater than <BigInteger.MAX_EXP> | ||
17711 | (0x7FFFFFFF), or an exception will be thrown. | ||
17712 | |||
17713 | Returns: | ||
17714 | |||
17715 | *this* * (10 ** *n*), truncated to an integer if necessary. | ||
17716 | |||
17717 | See Also: | ||
17718 | |||
17719 | <pow>, <multiply> | ||
17720 | */ | ||
17721 | BigInteger.prototype.exp10 = function(n) { | ||
17722 | n = +n; | ||
17723 | if (n === 0) { | ||
17724 | return this; | ||
17725 | } | ||
17726 | if (Math.abs(n) > Number(MAX_EXP)) { | ||
17727 | throw new Error("exponent too large in BigInteger.exp10"); | ||
17728 | } | ||
17729 | // Optimization for this == 0. This also keeps us from having to trim zeros in the positive n case | ||
17730 | if (this._s === 0) { | ||
17731 | return ZERO; | ||
17732 | } | ||
17733 | if (n > 0) { | ||
17734 | var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); | ||
17735 | |||
17736 | for (; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { | ||
17737 | k._d.unshift(0); | ||
17738 | } | ||
17739 | if (n == 0) | ||
17740 | return k; | ||
17741 | k._s = 1; | ||
17742 | k = k.multiplySingleDigit(Math.pow(10, n)); | ||
17743 | return (this._s < 0 ? k.negate() : k); | ||
17744 | } else if (-n >= this._d.length*BigInteger_base_log10) { | ||
17745 | return ZERO; | ||
17746 | } else { | ||
17747 | var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); | ||
17748 | |||
17749 | for (n = -n; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { | ||
17750 | k._d.shift(); | ||
17751 | } | ||
17752 | return (n == 0) ? k : k.divRemSmall(Math.pow(10, n))[0]; | ||
17753 | } | ||
17754 | }; | ||
17755 | |||
17756 | /* | ||
17757 | Function: pow | ||
17758 | Raise a <BigInteger> to a power. | ||
17759 | |||
17760 | In this implementation, 0**0 is 1. | ||
17761 | |||
17762 | Parameters: | ||
17763 | |||
17764 | n - The exponent to raise *this* by. *n* must be no greater than | ||
17765 | <BigInteger.MAX_EXP> (0x7FFFFFFF), or an exception will be thrown. | ||
17766 | |||
17767 | Returns: | ||
17768 | |||
17769 | *this* raised to the *nth* power. | ||
17770 | |||
17771 | See Also: | ||
17772 | |||
17773 | <modPow> | ||
17774 | */ | ||
17775 | BigInteger.prototype.pow = function(n) { | ||
17776 | if (this.isUnit()) { | ||
17777 | if (this._s > 0) { | ||
17778 | return this; | ||
17779 | } | ||
17780 | else { | ||
17781 | return BigInteger(n).isOdd() ? this : this.negate(); | ||
17782 | } | ||
17783 | } | ||
17784 | |||
17785 | n = BigInteger(n); | ||
17786 | if (n._s === 0) { | ||
17787 | return ONE; | ||
17788 | } | ||
17789 | else if (n._s < 0) { | ||
17790 | if (this._s === 0) { | ||
17791 | throw new Error("Divide by zero"); | ||
17792 | } | ||
17793 | else { | ||
17794 | return ZERO; | ||
17795 | } | ||
17796 | } | ||
17797 | if (this._s === 0) { | ||
17798 | return ZERO; | ||
17799 | } | ||
17800 | if (n.isUnit()) { | ||
17801 | return this; | ||
17802 | } | ||
17803 | |||
17804 | if (n.compareAbs(MAX_EXP) > 0) { | ||
17805 | throw new Error("exponent too large in BigInteger.pow"); | ||
17806 | } | ||
17807 | var x = this; | ||
17808 | var aux = ONE; | ||
17809 | var two = BigInteger.small[2]; | ||
17810 | |||
17811 | while (n.isPositive()) { | ||
17812 | if (n.isOdd()) { | ||
17813 | aux = aux.multiply(x); | ||
17814 | if (n.isUnit()) { | ||
17815 | return aux; | ||
17816 | } | ||
17817 | } | ||
17818 | x = x.square(); | ||
17819 | n = n.quotient(two); | ||
17820 | } | ||
17821 | |||
17822 | return aux; | ||
17823 | }; | ||
17824 | |||
17825 | /* | ||
17826 | Function: modPow | ||
17827 | Raise a <BigInteger> to a power (mod m). | ||
17828 | |||
17829 | Because it is reduced by a modulus, <modPow> is not limited by | ||
17830 | <BigInteger.MAX_EXP> like <pow>. | ||
17831 | |||
17832 | Parameters: | ||
17833 | |||
17834 | exponent - The exponent to raise *this* by. Must be positive. | ||
17835 | modulus - The modulus. | ||
17836 | |||
17837 | Returns: | ||
17838 | |||
17839 | *this* ^ *exponent* (mod *modulus*). | ||
17840 | |||
17841 | See Also: | ||
17842 | |||
17843 | <pow>, <mod> | ||
17844 | */ | ||
17845 | BigInteger.prototype.modPow = function(exponent, modulus) { | ||
17846 | var result = ONE; | ||
17847 | var base = this; | ||
17848 | |||
17849 | while (exponent.isPositive()) { | ||
17850 | if (exponent.isOdd()) { | ||
17851 | result = result.multiply(base).remainder(modulus); | ||
17852 | } | ||
17853 | |||
17854 | exponent = exponent.quotient(BigInteger.small[2]); | ||
17855 | if (exponent.isPositive()) { | ||
17856 | base = base.square().remainder(modulus); | ||
17857 | } | ||
17858 | } | ||
17859 | |||
17860 | return result; | ||
17861 | }; | ||
17862 | |||
17863 | /* | ||
17864 | Function: log | ||
17865 | Get the natural logarithm of a <BigInteger> as a native JavaScript number. | ||
17866 | |||
17867 | This is equivalent to | ||
17868 | |||
17869 | > Math.log(this.toJSValue()) | ||
17870 | |||
17871 | but handles values outside of the native number range. | ||
17872 | |||
17873 | Returns: | ||
17874 | |||
17875 | log( *this* ) | ||
17876 | |||
17877 | See Also: | ||
17878 | |||
17879 | <toJSValue> | ||
17880 | */ | ||
17881 | BigInteger.prototype.log = function() { | ||
17882 | switch (this._s) { | ||
17883 | case 0: return -Infinity; | ||
17884 | case -1: return NaN; | ||
17885 | default: // Fall through. | ||
17886 | } | ||
17887 | |||
17888 | var l = this._d.length; | ||
17889 | |||
17890 | if (l*BigInteger_base_log10 < 30) { | ||
17891 | return Math.log(this.valueOf()); | ||
17892 | } | ||
17893 | |||
17894 | var N = Math.ceil(30/BigInteger_base_log10); | ||
17895 | var firstNdigits = this._d.slice(l - N); | ||
17896 | return Math.log((new BigInteger(firstNdigits, 1, CONSTRUCT)).valueOf()) + (l - N) * Math.log(BigInteger_base); | ||
17897 | }; | ||
17898 | |||
17899 | /* | ||
17900 | Function: valueOf | ||
17901 | Convert a <BigInteger> to a native JavaScript integer. | ||
17902 | |||
17903 | This is called automatically by JavaScipt to convert a <BigInteger> to a | ||
17904 | native value. | ||
17905 | |||
17906 | Returns: | ||
17907 | |||
17908 | > parseInt(this.toString(), 10) | ||
17909 | |||
17910 | See Also: | ||
17911 | |||
17912 | <toString>, <toJSValue> | ||
17913 | */ | ||
17914 | BigInteger.prototype.valueOf = function() { | ||
17915 | return parseInt(this.toString(), 10); | ||
17916 | }; | ||
17917 | |||
17918 | /* | ||
17919 | Function: toJSValue | ||
17920 | Convert a <BigInteger> to a native JavaScript integer. | ||
17921 | |||
17922 | This is the same as valueOf, but more explicitly named. | ||
17923 | |||
17924 | Returns: | ||
17925 | |||
17926 | > parseInt(this.toString(), 10) | ||
17927 | |||
17928 | See Also: | ||
17929 | |||
17930 | <toString>, <valueOf> | ||
17931 | */ | ||
17932 | BigInteger.prototype.toJSValue = function() { | ||
17933 | return parseInt(this.toString(), 10); | ||
17934 | }; | ||
17935 | |||
17936 | var MAX_EXP = BigInteger(0x7FFFFFFF); | ||
17937 | // Constant: MAX_EXP | ||
17938 | // The largest exponent allowed in <pow> and <exp10> (0x7FFFFFFF or 2147483647). | ||
17939 | BigInteger.MAX_EXP = MAX_EXP; | ||
17940 | |||
17941 | (function() { | ||
17942 | function makeUnary(fn) { | ||
17943 | return function(a) { | ||
17944 | return fn.call(BigInteger(a)); | ||
17945 | }; | ||
17946 | } | ||
17947 | |||
17948 | function makeBinary(fn) { | ||
17949 | return function(a, b) { | ||
17950 | return fn.call(BigInteger(a), BigInteger(b)); | ||
17951 | }; | ||
17952 | } | ||
17953 | |||
17954 | function makeTrinary(fn) { | ||
17955 | return function(a, b, c) { | ||
17956 | return fn.call(BigInteger(a), BigInteger(b), BigInteger(c)); | ||
17957 | }; | ||
17958 | } | ||
17959 | |||
17960 | (function() { | ||
17961 | var i, fn; | ||
17962 | var unary = "toJSValue,isEven,isOdd,sign,isZero,isNegative,abs,isUnit,square,negate,isPositive,toString,next,prev,log".split(","); | ||
17963 | var binary = "compare,remainder,divRem,subtract,add,quotient,divide,multiply,pow,compareAbs".split(","); | ||
17964 | var trinary = ["modPow"]; | ||
17965 | |||
17966 | for (i = 0; i < unary.length; i++) { | ||
17967 | fn = unary[i]; | ||
17968 | BigInteger[fn] = makeUnary(BigInteger.prototype[fn]); | ||
17969 | } | ||
17970 | |||
17971 | for (i = 0; i < binary.length; i++) { | ||
17972 | fn = binary[i]; | ||
17973 | BigInteger[fn] = makeBinary(BigInteger.prototype[fn]); | ||
17974 | } | ||
17975 | |||
17976 | for (i = 0; i < trinary.length; i++) { | ||
17977 | fn = trinary[i]; | ||
17978 | BigInteger[fn] = makeTrinary(BigInteger.prototype[fn]); | ||
17979 | } | ||
17980 | |||
17981 | BigInteger.exp10 = function(x, n) { | ||
17982 | return BigInteger(x).exp10(n); | ||
17983 | }; | ||
17984 | })(); | ||
17985 | })(); | ||
17986 | |||
17987 | exports.BigInteger = BigInteger; | ||
17988 | })(typeof exports !== 'undefined' ? exports : this); | ||
17989 | </script> | ||
16172 | <script>(function() { | 17990 | <script>(function() { |
16173 | 17991 | ||
16174 | // mnemonics is populated as required by getLanguage | 17992 | // mnemonics is populated as required by getLanguage |
@@ -16185,14 +18003,20 @@ var Mnemonic = function(language) { | |||
16185 | var showPubKey = true; | 18003 | var showPubKey = true; |
16186 | var showPrivKey = true; | 18004 | var showPrivKey = true; |
16187 | 18005 | ||
18006 | var entropyChangeTimeoutEvent = null; | ||
16188 | var phraseChangeTimeoutEvent = null; | 18007 | var phraseChangeTimeoutEvent = null; |
16189 | var rootKeyChangedTimeoutEvent = null; | 18008 | var rootKeyChangedTimeoutEvent = null; |
16190 | 18009 | ||
16191 | var DOM = {}; | 18010 | var DOM = {}; |
16192 | DOM.network = $(".network"); | 18011 | DOM.network = $(".network"); |
16193 | DOM.phraseNetwork = $("#network-phrase"); | 18012 | DOM.phraseNetwork = $("#network-phrase"); |
18013 | DOM.useEntropy = $(".use-entropy"); | ||
18014 | DOM.entropyContainer = $(".entropy-container"); | ||
18015 | DOM.entropy = $(".entropy"); | ||
18016 | DOM.entropyError = $(".entropy-error"); | ||
16194 | DOM.phrase = $(".phrase"); | 18017 | DOM.phrase = $(".phrase"); |
16195 | DOM.passphrase = $(".passphrase"); | 18018 | DOM.passphrase = $(".passphrase"); |
18019 | DOM.generateContainer = $(".generate-container"); | ||
16196 | DOM.generate = $(".generate"); | 18020 | DOM.generate = $(".generate"); |
16197 | DOM.seed = $(".seed"); | 18021 | DOM.seed = $(".seed"); |
16198 | DOM.rootKey = $(".root-key"); | 18022 | DOM.rootKey = $(".root-key"); |
@@ -16224,6 +18048,8 @@ var Mnemonic = function(language) { | |||
16224 | function init() { | 18048 | function init() { |
16225 | // Events | 18049 | // Events |
16226 | DOM.network.on("change", networkChanged); | 18050 | DOM.network.on("change", networkChanged); |
18051 | DOM.useEntropy.on("change", setEntropyVisibility); | ||
18052 | DOM.entropy.on("input", delayedEntropyChanged); | ||
16227 | DOM.phrase.on("input", delayedPhraseChanged); | 18053 | DOM.phrase.on("input", delayedPhraseChanged); |
16228 | DOM.passphrase.on("input", delayedPhraseChanged); | 18054 | DOM.passphrase.on("input", delayedPhraseChanged); |
16229 | DOM.generate.on("click", generateClicked); | 18055 | DOM.generate.on("click", generateClicked); |
@@ -16260,6 +18086,21 @@ var Mnemonic = function(language) { | |||
16260 | } | 18086 | } |
16261 | } | 18087 | } |
16262 | 18088 | ||
18089 | function setEntropyVisibility() { | ||
18090 | if (isUsingOwnEntropy()) { | ||
18091 | DOM.entropyContainer.removeClass("hidden"); | ||
18092 | DOM.generateContainer.addClass("hidden"); | ||
18093 | DOM.phrase.prop("readonly", true); | ||
18094 | DOM.entropy.focus(); | ||
18095 | entropyChanged(); | ||
18096 | } | ||
18097 | else { | ||
18098 | DOM.entropyContainer.addClass("hidden"); | ||
18099 | DOM.generateContainer.removeClass("hidden"); | ||
18100 | DOM.phrase.prop("readonly", false); | ||
18101 | } | ||
18102 | } | ||
18103 | |||
16263 | function delayedPhraseChanged() { | 18104 | function delayedPhraseChanged() { |
16264 | hideValidationError(); | 18105 | hideValidationError(); |
16265 | showPending(); | 18106 | showPending(); |
@@ -16287,6 +18128,20 @@ var Mnemonic = function(language) { | |||
16287 | hidePending(); | 18128 | hidePending(); |
16288 | } | 18129 | } |
16289 | 18130 | ||
18131 | function delayedEntropyChanged() { | ||
18132 | hideValidationError(); | ||
18133 | showPending(); | ||
18134 | if (entropyChangeTimeoutEvent != null) { | ||
18135 | clearTimeout(entropyChangeTimeoutEvent); | ||
18136 | } | ||
18137 | entropyChangeTimeoutEvent = setTimeout(entropyChanged, 400); | ||
18138 | } | ||
18139 | |||
18140 | function entropyChanged() { | ||
18141 | setMnemonicFromEntropy(); | ||
18142 | phraseChanged(); | ||
18143 | } | ||
18144 | |||
16290 | function delayedRootKeyChanged() { | 18145 | function delayedRootKeyChanged() { |
16291 | // Warn if there is an existing mnemonic or passphrase. | 18146 | // Warn if there is an existing mnemonic or passphrase. |
16292 | if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) { | 18147 | if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) { |
@@ -16339,6 +18194,9 @@ var Mnemonic = function(language) { | |||
16339 | } | 18194 | } |
16340 | 18195 | ||
16341 | function generateClicked() { | 18196 | function generateClicked() { |
18197 | if (isUsingOwnEntropy()) { | ||
18198 | return; | ||
18199 | } | ||
16342 | clearDisplay(); | 18200 | clearDisplay(); |
16343 | showPending(); | 18201 | showPending(); |
16344 | setTimeout(function() { | 18202 | setTimeout(function() { |
@@ -16770,7 +18628,12 @@ var Mnemonic = function(language) { | |||
16770 | } | 18628 | } |
16771 | 18629 | ||
16772 | function getLanguageFromUrl() { | 18630 | function getLanguageFromUrl() { |
16773 | return window.location.hash.substring(1); | 18631 | for (var language in WORDLISTS) { |
18632 | if (window.location.hash.indexOf(language) > -1) { | ||
18633 | return language; | ||
18634 | } | ||
18635 | } | ||
18636 | return ""; | ||
16774 | } | 18637 | } |
16775 | 18638 | ||
16776 | function setMnemonicLanguage() { | 18639 | function setMnemonicLanguage() { |
@@ -16821,6 +18684,65 @@ var Mnemonic = function(language) { | |||
16821 | return phrase; | 18684 | return phrase; |
16822 | } | 18685 | } |
16823 | 18686 | ||
18687 | function isUsingOwnEntropy() { | ||
18688 | return DOM.useEntropy.prop("checked"); | ||
18689 | } | ||
18690 | |||
18691 | function setMnemonicFromEntropy() { | ||
18692 | hideEntropyError(); | ||
18693 | // Work out minimum base for entropy | ||
18694 | var entropyStr = DOM.entropy.val(); | ||
18695 | var entropy = Entropy.fromString(entropyStr); | ||
18696 | if (entropy.hexStr.length == 0) { | ||
18697 | return; | ||
18698 | } | ||
18699 | // Show entropy details | ||
18700 | var extraBits = 32 - (entropy.binaryStr.length % 32); | ||
18701 | var extraChars = Math.ceil(extraBits * Math.log(2) / Math.log(entropy.base.asInt)); | ||
18702 | var strength = "an extremely weak"; | ||
18703 | if (entropy.hexStr.length >= 8) { | ||
18704 | strength = "a very weak"; | ||
18705 | } | ||
18706 | if (entropy.hexStr.length >= 12) { | ||
18707 | strength = "a weak"; | ||
18708 | } | ||
18709 | if (entropy.hexStr.length >= 24) { | ||
18710 | strength = "a strong"; | ||
18711 | } | ||
18712 | if (entropy.hexStr.length >= 32) { | ||
18713 | strength = "a very strong"; | ||
18714 | } | ||
18715 | if (entropy.hexStr.length >= 40) { | ||
18716 | strength = "an extremely strong"; | ||
18717 | } | ||
18718 | if (entropy.hexStr.length >=48) { | ||
18719 | strength = "an even stronger" | ||
18720 | } | ||
18721 | var msg = "Have " + entropy.binaryStr.length + " bits of entropy, " + extraChars + " more " + entropy.base.str + " chars required to generate " + strength + " mnemonic: " + entropy.cleanStr; | ||
18722 | showEntropyError(msg); | ||
18723 | // Discard trailing entropy | ||
18724 | var hexStr = entropy.hexStr.substring(0, Math.floor(entropy.hexStr.length / 8) * 8); | ||
18725 | // Convert entropy string to numeric array | ||
18726 | var entropyArr = []; | ||
18727 | for (var i=0; i<hexStr.length / 2; i++) { | ||
18728 | var entropyByte = parseInt(hexStr[i*2].concat(hexStr[i*2+1]), 16); | ||
18729 | entropyArr.push(entropyByte) | ||
18730 | } | ||
18731 | // Convert entropy array to mnemonic | ||
18732 | var phrase = mnemonic.toMnemonic(entropyArr); | ||
18733 | // Set the mnemonic in the UI | ||
18734 | DOM.phrase.val(phrase); | ||
18735 | } | ||
18736 | |||
18737 | function hideEntropyError() { | ||
18738 | DOM.entropyError.addClass("hidden"); | ||
18739 | } | ||
18740 | |||
18741 | function showEntropyError(msg) { | ||
18742 | DOM.entropyError.text(msg); | ||
18743 | DOM.entropyError.removeClass("hidden"); | ||
18744 | } | ||
18745 | |||
16824 | var networks = [ | 18746 | var networks = [ |
16825 | { | 18747 | { |
16826 | name: "Bitcoin", | 18748 | name: "Bitcoin", |
diff --git a/src/index.html b/src/index.html index 3ec4aa9..cb7a781 100644 --- a/src/index.html +++ b/src/index.html | |||
@@ -65,12 +65,14 @@ | |||
65 | <div class="col-md-12"> | 65 | <div class="col-md-12"> |
66 | <h2>Mnemonic</h2> | 66 | <h2>Mnemonic</h2> |
67 | <form class="form-horizontal" role="form"> | 67 | <form class="form-horizontal" role="form"> |
68 | <div class="col-sm-2"></div> | ||
69 | <div class="col-sm-10"> | ||
70 | <p>You can enter an existing BIP39 mnemonic, or generate a new random one. Typing your own twelve words will probably not work how you expect, since the words require a particular structure (the last word is a checksum)</p> | ||
71 | <p>For more info see the <a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki" target="_blank">BIP39 spec</a></p> | ||
72 | </div> | ||
73 | <div class="form-group"> | 68 | <div class="form-group"> |
69 | <div class="col-sm-2"></div> | ||
70 | <div class="col-sm-10"> | ||
71 | <p>You can enter an existing BIP39 mnemonic, or generate a new random one. Typing your own twelve words will probably not work how you expect, since the words require a particular structure (the last word is a checksum)</p> | ||
72 | <p>For more info see the <a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki" target="_blank">BIP39 spec</a></p> | ||
73 | </div> | ||
74 | </div> | ||
75 | <div class="form-group generate-container"> | ||
74 | <label class="col-sm-2 control-label"></label> | 76 | <label class="col-sm-2 control-label"></label> |
75 | <div class="col-sm-10"> | 77 | <div class="col-sm-10"> |
76 | <div class="form-inline"> | 78 | <div class="form-inline"> |
@@ -92,7 +94,30 @@ | |||
92 | </div> | 94 | </div> |
93 | </div> | 95 | </div> |
94 | </div> | 96 | </div> |
95 | <div class="form-group"> | 97 | <div class="entropy-container hidden"> |
98 | <label for="entropy" class="col-sm-2 control-label">Entropy</label> | ||
99 | <div class="col-sm-10"> | ||
100 | <input id="entropy" class="entropy form-control" placeholder="Accepts binary, base 6, 6-sided dice, base 10, hexadecimal"> | ||
101 | <span class="help-block"> | ||
102 | <div class="text-danger"> | ||
103 | This is an advanced feature. | ||
104 | Your mnemonic may be insecure if this feature is used incorrectly. | ||
105 | <a href="#entropy-notes">Read more</a> | ||
106 | </div> | ||
107 | <div class="text-danger entropy-error"></div> | ||
108 | </span> | ||
109 | </div> | ||
110 | </div> | ||
111 | <div class="form-group"> | ||
112 | <div class="col-sm-2"></div> | ||
113 | <div class="col-sm-10 checkbox"> | ||
114 | <label> | ||
115 | <input type="checkbox" class="use-entropy"> | ||
116 | Supply my own source of entropy | ||
117 | </label> | ||
118 | </div> | ||
119 | </div> | ||
120 | <div class="form-group"> | ||
96 | <label class="col-sm-2 control-label"></label> | 121 | <label class="col-sm-2 control-label"></label> |
97 | <div class="col-sm-10 languages"> | 122 | <div class="col-sm-10 languages"> |
98 | <a href="#english">English</a> | 123 | <a href="#english">English</a> |
@@ -353,6 +378,24 @@ | |||
353 | but be careful - it can be easy to make mistakes if you | 378 | but be careful - it can be easy to make mistakes if you |
354 | don't know what you're doing | 379 | don't know what you're doing |
355 | </p> | 380 | </p> |
381 | <h3 id="entropy-notes">Entropy</h3> | ||
382 | <p> | ||
383 | Entropy values must be sourced from a | ||
384 | <a href="https://en.wikipedia.org/wiki/Random_number_generation" target="_blank">strong source of randomness</a>. | ||
385 | This means flipping a fair coin, rolling a fair dice, noise measurements etc. Do <strong>NOT</strong> use | ||
386 | phrases from books, lyrics from songs, your birthday or steet address, keyboard mashing, or anything you <i>think</i> | ||
387 | is random, because chances are <em>overwhelming</em> that it isn't random enough for the needs of this tool. | ||
388 | </p> | ||
389 | <p> | ||
390 | The random mnemonic generator on this page uses a | ||
391 | <a href="https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues" target="_blank">cryptographically secure random number generator</a>, | ||
392 | and can generally be trusted more than your own intuition about randomness. | ||
393 | If cryptographic randomness isn't available in your browser, this page will show a warning and <i>will not generate | ||
394 | random mnemonics</i>. | ||
395 | </p> | ||
396 | <p> | ||
397 | <a href="https://bitcointalk.org/index.php?topic=311000.msg3345309#msg3345309" target="_blank">You are not a good source of entropy.</a> | ||
398 | </p> | ||
356 | </div> | 399 | </div> |
357 | </div> | 400 | </div> |
358 | 401 | ||
@@ -465,6 +508,7 @@ | |||
465 | <script src="js/wordlist_french.js"></script> | 508 | <script src="js/wordlist_french.js"></script> |
466 | <script src="js/wordlist_italian.js"></script> | 509 | <script src="js/wordlist_italian.js"></script> |
467 | <script src="js/jsbip39.js"></script> | 510 | <script src="js/jsbip39.js"></script> |
511 | <script src="js/entropy.js"></script> | ||
468 | <script src="js/index.js"></script> | 512 | <script src="js/index.js"></script> |
469 | </body> | 513 | </body> |
470 | </html> | 514 | </html> |
diff --git a/src/js/entropy.js b/src/js/entropy.js new file mode 100644 index 0000000..1e556ce --- /dev/null +++ b/src/js/entropy.js | |||
@@ -0,0 +1,1774 @@ | |||
1 | window.Entropy = new (function() { | ||
2 | |||
3 | var matchers = { | ||
4 | binary: /[0-1]/gi, | ||
5 | base6: /[0-5]/gi, | ||
6 | dice: /[1-6]/gi, // ie dice numbers | ||
7 | base10: /[0-9]/gi, | ||
8 | hex: /[0-9A-F]/gi, | ||
9 | } | ||
10 | |||
11 | this.fromString = function(rawEntropyStr) { | ||
12 | // Find type of entropy being used (binary, hex, dice etc) | ||
13 | var base = getBase(rawEntropyStr); | ||
14 | // Convert dice to base6 entropy (ie 1-6 to 0-5) | ||
15 | if (base.str == "dice") { | ||
16 | var newRawEntropyStr = ""; | ||
17 | for (var i=0; i<rawEntropyStr.length; i++) { | ||
18 | var c = rawEntropyStr[i]; | ||
19 | if ("123456".indexOf(c) > -1) { | ||
20 | newRawEntropyStr += (parseInt(c) - 1).toString(); | ||
21 | } | ||
22 | else { | ||
23 | newRawEntropyStr += c | ||
24 | } | ||
25 | } | ||
26 | rawEntropyStr = newRawEntropyStr; | ||
27 | base.str = "base 6 (dice)"; | ||
28 | base.matcher = matchers.base6; | ||
29 | } | ||
30 | var entropyParts = rawEntropyStr.match(base.matcher) || []; | ||
31 | var entropyStr = entropyParts.join(""); | ||
32 | // Detect empty entropy | ||
33 | if (entropyStr.length == 0) { | ||
34 | return { | ||
35 | binaryStr: "", | ||
36 | hexStr: "", | ||
37 | cleanStr: "", | ||
38 | base: base, | ||
39 | }; | ||
40 | } | ||
41 | // Pull leading zeros off | ||
42 | var leadingZeros = ""; | ||
43 | while (entropyStr[0] == "0") { | ||
44 | leadingZeros += "0"; | ||
45 | entropyStr = entropyStr.substring(1); | ||
46 | } | ||
47 | // Convert leading zeros to binary equivalent | ||
48 | var numBinLeadingZeros = Math.ceil(Math.log2(base.asInt) * leadingZeros.length); | ||
49 | var binLeadingZeros = ""; | ||
50 | for (var i=0; i<numBinLeadingZeros; i++) { | ||
51 | binLeadingZeros += "0"; | ||
52 | } | ||
53 | // Convert leading zeros to hex equivalent | ||
54 | var numHexLeadingZeros = Math.floor(numBinLeadingZeros / 4); | ||
55 | var hexLeadingZeros = ""; | ||
56 | for (var i=0; i<numHexLeadingZeros; i++) { | ||
57 | hexLeadingZeros += "0"; | ||
58 | } | ||
59 | // Handle entropy of zero | ||
60 | if (entropyStr == "") { | ||
61 | return { | ||
62 | binaryStr: binLeadingZeros, | ||
63 | hexStr: hexLeadingZeros || "0", | ||
64 | cleanStr: leadingZeros, | ||
65 | base: base, | ||
66 | } | ||
67 | } | ||
68 | // If using hex, should always be multiples of 4 bits, which can get | ||
69 | // out of sync if first number has leading 0 bits, eg 2 in hex is 0010 | ||
70 | // which would show up as 10, thus missing 2 bits it should have. | ||
71 | if (base.asInt == 16) { | ||
72 | var firstDigit = parseInt(entropyStr[0], 16); | ||
73 | if (firstDigit >= 4 && firstDigit < 8) { | ||
74 | binLeadingZeros += "0"; | ||
75 | } | ||
76 | else if (firstDigit >= 2 && firstDigit < 4) { | ||
77 | binLeadingZeros += "00"; | ||
78 | } | ||
79 | else if (firstDigit >= 1 && firstDigit < 2) { | ||
80 | binLeadingZeros += "000"; | ||
81 | } | ||
82 | } | ||
83 | // Convert entropy to different foramts | ||
84 | var entropyInt = BigInteger.parse(entropyStr, base.asInt); | ||
85 | var entropyBin = binLeadingZeros + entropyInt.toString(2); | ||
86 | var entropyHex = hexLeadingZeros + entropyInt.toString(16); | ||
87 | var entropyClean = leadingZeros + entropyStr; | ||
88 | var e = { | ||
89 | binaryStr: entropyBin, | ||
90 | hexStr: entropyHex, | ||
91 | cleanStr: entropyClean, | ||
92 | base: base, | ||
93 | } | ||
94 | return e; | ||
95 | } | ||
96 | |||
97 | function getBase(str) { | ||
98 | // Need to get the lowest base for the supplied entropy. | ||
99 | // This prevents interpreting, say, dice rolls as hexadecimal. | ||
100 | var binaryMatches = str.match(matchers.binary) || []; | ||
101 | var base6Matches = str.match(matchers.base6) || []; | ||
102 | var diceMatches = str.match(matchers.dice) || []; | ||
103 | var base10Matches = str.match(matchers.base10) || []; | ||
104 | var hexMatches = str.match(matchers.hex) || []; | ||
105 | // Find the lowest base that can be used, whilst ignoring any irrelevant chars | ||
106 | if (binaryMatches.length == hexMatches.length) { | ||
107 | return { | ||
108 | matcher: matchers.binary, | ||
109 | asInt: 2, | ||
110 | str: "binary", | ||
111 | } | ||
112 | } | ||
113 | if (diceMatches.length == hexMatches.length) { | ||
114 | return { | ||
115 | matcher: matchers.dice, | ||
116 | asInt: 6, | ||
117 | str: "dice", | ||
118 | } | ||
119 | } | ||
120 | if (base6Matches.length == hexMatches.length) { | ||
121 | return { | ||
122 | matcher: matchers.base6, | ||
123 | asInt: 6, | ||
124 | str: "base 6", | ||
125 | } | ||
126 | } | ||
127 | if (base10Matches.length == hexMatches.length) { | ||
128 | return { | ||
129 | matcher: matchers.base10, | ||
130 | asInt: 10, | ||
131 | str: "base 10", | ||
132 | } | ||
133 | } | ||
134 | return { | ||
135 | matcher: matchers.hex, | ||
136 | asInt: 16, | ||
137 | str: "hexadecimal", | ||
138 | } | ||
139 | } | ||
140 | |||
141 | // Polyfill for Math.log2 | ||
142 | // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/log2#Polyfill | ||
143 | Math.log2 = Math.log2 || function(x) { | ||
144 | return Math.log(x) * Math.LOG2E; | ||
145 | }; | ||
146 | |||
147 | })(); | ||
148 | |||
149 | |||
150 | // BigInteger library included here because | ||
151 | // only the entropy library depends on it | ||
152 | // so if entropy detection is removed so is the dependency | ||
153 | |||
154 | |||
155 | /* | ||
156 | JavaScript BigInteger library version 0.9.1 | ||
157 | http://silentmatt.com/biginteger/ | ||
158 | |||
159 | Copyright (c) 2009 Matthew Crumley <email@matthewcrumley.com> | ||
160 | Copyright (c) 2010,2011 by John Tobey <John.Tobey@gmail.com> | ||
161 | Licensed under the MIT license. | ||
162 | |||
163 | Support for arbitrary internal representation base was added by | ||
164 | Vitaly Magerya. | ||
165 | */ | ||
166 | |||
167 | /* | ||
168 | File: biginteger.js | ||
169 | |||
170 | Exports: | ||
171 | |||
172 | <BigInteger> | ||
173 | */ | ||
174 | (function(exports) { | ||
175 | "use strict"; | ||
176 | /* | ||
177 | Class: BigInteger | ||
178 | An arbitrarily-large integer. | ||
179 | |||
180 | <BigInteger> objects should be considered immutable. None of the "built-in" | ||
181 | methods modify *this* or their arguments. All properties should be | ||
182 | considered private. | ||
183 | |||
184 | All the methods of <BigInteger> instances can be called "statically". The | ||
185 | static versions are convenient if you don't already have a <BigInteger> | ||
186 | object. | ||
187 | |||
188 | As an example, these calls are equivalent. | ||
189 | |||
190 | > BigInteger(4).multiply(5); // returns BigInteger(20); | ||
191 | > BigInteger.multiply(4, 5); // returns BigInteger(20); | ||
192 | |||
193 | > var a = 42; | ||
194 | > var a = BigInteger.toJSValue("0b101010"); // Not completely useless... | ||
195 | */ | ||
196 | |||
197 | var CONSTRUCT = {}; // Unique token to call "private" version of constructor | ||
198 | |||
199 | /* | ||
200 | Constructor: BigInteger() | ||
201 | Convert a value to a <BigInteger>. | ||
202 | |||
203 | Although <BigInteger()> is the constructor for <BigInteger> objects, it is | ||
204 | best not to call it as a constructor. If *n* is a <BigInteger> object, it is | ||
205 | simply returned as-is. Otherwise, <BigInteger()> is equivalent to <parse> | ||
206 | without a radix argument. | ||
207 | |||
208 | > var n0 = BigInteger(); // Same as <BigInteger.ZERO> | ||
209 | > var n1 = BigInteger("123"); // Create a new <BigInteger> with value 123 | ||
210 | > var n2 = BigInteger(123); // Create a new <BigInteger> with value 123 | ||
211 | > var n3 = BigInteger(n2); // Return n2, unchanged | ||
212 | |||
213 | The constructor form only takes an array and a sign. *n* must be an | ||
214 | array of numbers in little-endian order, where each digit is between 0 | ||
215 | and BigInteger.base. The second parameter sets the sign: -1 for | ||
216 | negative, +1 for positive, or 0 for zero. The array is *not copied and | ||
217 | may be modified*. If the array contains only zeros, the sign parameter | ||
218 | is ignored and is forced to zero. | ||
219 | |||
220 | > new BigInteger([5], -1): create a new BigInteger with value -5 | ||
221 | |||
222 | Parameters: | ||
223 | |||
224 | n - Value to convert to a <BigInteger>. | ||
225 | |||
226 | Returns: | ||
227 | |||
228 | A <BigInteger> value. | ||
229 | |||
230 | See Also: | ||
231 | |||
232 | <parse>, <BigInteger> | ||
233 | */ | ||
234 | function BigInteger(n, s, token) { | ||
235 | if (token !== CONSTRUCT) { | ||
236 | if (n instanceof BigInteger) { | ||
237 | return n; | ||
238 | } | ||
239 | else if (typeof n === "undefined") { | ||
240 | return ZERO; | ||
241 | } | ||
242 | return BigInteger.parse(n); | ||
243 | } | ||
244 | |||
245 | n = n || []; // Provide the nullary constructor for subclasses. | ||
246 | while (n.length && !n[n.length - 1]) { | ||
247 | --n.length; | ||
248 | } | ||
249 | this._d = n; | ||
250 | this._s = n.length ? (s || 1) : 0; | ||
251 | } | ||
252 | |||
253 | BigInteger._construct = function(n, s) { | ||
254 | return new BigInteger(n, s, CONSTRUCT); | ||
255 | }; | ||
256 | |||
257 | // Base-10 speedup hacks in parse, toString, exp10 and log functions | ||
258 | // require base to be a power of 10. 10^7 is the largest such power | ||
259 | // that won't cause a precision loss when digits are multiplied. | ||
260 | var BigInteger_base = 10000000; | ||
261 | var BigInteger_base_log10 = 7; | ||
262 | |||
263 | BigInteger.base = BigInteger_base; | ||
264 | BigInteger.base_log10 = BigInteger_base_log10; | ||
265 | |||
266 | var ZERO = new BigInteger([], 0, CONSTRUCT); | ||
267 | // Constant: ZERO | ||
268 | // <BigInteger> 0. | ||
269 | BigInteger.ZERO = ZERO; | ||
270 | |||
271 | var ONE = new BigInteger([1], 1, CONSTRUCT); | ||
272 | // Constant: ONE | ||
273 | // <BigInteger> 1. | ||
274 | BigInteger.ONE = ONE; | ||
275 | |||
276 | var M_ONE = new BigInteger(ONE._d, -1, CONSTRUCT); | ||
277 | // Constant: M_ONE | ||
278 | // <BigInteger> -1. | ||
279 | BigInteger.M_ONE = M_ONE; | ||
280 | |||
281 | // Constant: _0 | ||
282 | // Shortcut for <ZERO>. | ||
283 | BigInteger._0 = ZERO; | ||
284 | |||
285 | // Constant: _1 | ||
286 | // Shortcut for <ONE>. | ||
287 | BigInteger._1 = ONE; | ||
288 | |||
289 | /* | ||
290 | Constant: small | ||
291 | Array of <BigIntegers> from 0 to 36. | ||
292 | |||
293 | These are used internally for parsing, but useful when you need a "small" | ||
294 | <BigInteger>. | ||
295 | |||
296 | See Also: | ||
297 | |||
298 | <ZERO>, <ONE>, <_0>, <_1> | ||
299 | */ | ||
300 | BigInteger.small = [ | ||
301 | ZERO, | ||
302 | ONE, | ||
303 | /* Assuming BigInteger_base > 36 */ | ||
304 | new BigInteger( [2], 1, CONSTRUCT), | ||
305 | new BigInteger( [3], 1, CONSTRUCT), | ||
306 | new BigInteger( [4], 1, CONSTRUCT), | ||
307 | new BigInteger( [5], 1, CONSTRUCT), | ||
308 | new BigInteger( [6], 1, CONSTRUCT), | ||
309 | new BigInteger( [7], 1, CONSTRUCT), | ||
310 | new BigInteger( [8], 1, CONSTRUCT), | ||
311 | new BigInteger( [9], 1, CONSTRUCT), | ||
312 | new BigInteger([10], 1, CONSTRUCT), | ||
313 | new BigInteger([11], 1, CONSTRUCT), | ||
314 | new BigInteger([12], 1, CONSTRUCT), | ||
315 | new BigInteger([13], 1, CONSTRUCT), | ||
316 | new BigInteger([14], 1, CONSTRUCT), | ||
317 | new BigInteger([15], 1, CONSTRUCT), | ||
318 | new BigInteger([16], 1, CONSTRUCT), | ||
319 | new BigInteger([17], 1, CONSTRUCT), | ||
320 | new BigInteger([18], 1, CONSTRUCT), | ||
321 | new BigInteger([19], 1, CONSTRUCT), | ||
322 | new BigInteger([20], 1, CONSTRUCT), | ||
323 | new BigInteger([21], 1, CONSTRUCT), | ||
324 | new BigInteger([22], 1, CONSTRUCT), | ||
325 | new BigInteger([23], 1, CONSTRUCT), | ||
326 | new BigInteger([24], 1, CONSTRUCT), | ||
327 | new BigInteger([25], 1, CONSTRUCT), | ||
328 | new BigInteger([26], 1, CONSTRUCT), | ||
329 | new BigInteger([27], 1, CONSTRUCT), | ||
330 | new BigInteger([28], 1, CONSTRUCT), | ||
331 | new BigInteger([29], 1, CONSTRUCT), | ||
332 | new BigInteger([30], 1, CONSTRUCT), | ||
333 | new BigInteger([31], 1, CONSTRUCT), | ||
334 | new BigInteger([32], 1, CONSTRUCT), | ||
335 | new BigInteger([33], 1, CONSTRUCT), | ||
336 | new BigInteger([34], 1, CONSTRUCT), | ||
337 | new BigInteger([35], 1, CONSTRUCT), | ||
338 | new BigInteger([36], 1, CONSTRUCT) | ||
339 | ]; | ||
340 | |||
341 | // Used for parsing/radix conversion | ||
342 | BigInteger.digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); | ||
343 | |||
344 | /* | ||
345 | Method: toString | ||
346 | Convert a <BigInteger> to a string. | ||
347 | |||
348 | When *base* is greater than 10, letters are upper case. | ||
349 | |||
350 | Parameters: | ||
351 | |||
352 | base - Optional base to represent the number in (default is base 10). | ||
353 | Must be between 2 and 36 inclusive, or an Error will be thrown. | ||
354 | |||
355 | Returns: | ||
356 | |||
357 | The string representation of the <BigInteger>. | ||
358 | */ | ||
359 | BigInteger.prototype.toString = function(base) { | ||
360 | base = +base || 10; | ||
361 | if (base < 2 || base > 36) { | ||
362 | throw new Error("illegal radix " + base + "."); | ||
363 | } | ||
364 | if (this._s === 0) { | ||
365 | return "0"; | ||
366 | } | ||
367 | if (base === 10) { | ||
368 | var str = this._s < 0 ? "-" : ""; | ||
369 | str += this._d[this._d.length - 1].toString(); | ||
370 | for (var i = this._d.length - 2; i >= 0; i--) { | ||
371 | var group = this._d[i].toString(); | ||
372 | while (group.length < BigInteger_base_log10) group = '0' + group; | ||
373 | str += group; | ||
374 | } | ||
375 | return str; | ||
376 | } | ||
377 | else { | ||
378 | var numerals = BigInteger.digits; | ||
379 | base = BigInteger.small[base]; | ||
380 | var sign = this._s; | ||
381 | |||
382 | var n = this.abs(); | ||
383 | var digits = []; | ||
384 | var digit; | ||
385 | |||
386 | while (n._s !== 0) { | ||
387 | var divmod = n.divRem(base); | ||
388 | n = divmod[0]; | ||
389 | digit = divmod[1]; | ||
390 | // TODO: This could be changed to unshift instead of reversing at the end. | ||
391 | // Benchmark both to compare speeds. | ||
392 | digits.push(numerals[digit.valueOf()]); | ||
393 | } | ||
394 | return (sign < 0 ? "-" : "") + digits.reverse().join(""); | ||
395 | } | ||
396 | }; | ||
397 | |||
398 | // Verify strings for parsing | ||
399 | BigInteger.radixRegex = [ | ||
400 | /^$/, | ||
401 | /^$/, | ||
402 | /^[01]*$/, | ||
403 | /^[012]*$/, | ||
404 | /^[0-3]*$/, | ||
405 | /^[0-4]*$/, | ||
406 | /^[0-5]*$/, | ||
407 | /^[0-6]*$/, | ||
408 | /^[0-7]*$/, | ||
409 | /^[0-8]*$/, | ||
410 | /^[0-9]*$/, | ||
411 | /^[0-9aA]*$/, | ||
412 | /^[0-9abAB]*$/, | ||
413 | /^[0-9abcABC]*$/, | ||
414 | /^[0-9a-dA-D]*$/, | ||
415 | /^[0-9a-eA-E]*$/, | ||
416 | /^[0-9a-fA-F]*$/, | ||
417 | /^[0-9a-gA-G]*$/, | ||
418 | /^[0-9a-hA-H]*$/, | ||
419 | /^[0-9a-iA-I]*$/, | ||
420 | /^[0-9a-jA-J]*$/, | ||
421 | /^[0-9a-kA-K]*$/, | ||
422 | /^[0-9a-lA-L]*$/, | ||
423 | /^[0-9a-mA-M]*$/, | ||
424 | /^[0-9a-nA-N]*$/, | ||
425 | /^[0-9a-oA-O]*$/, | ||
426 | /^[0-9a-pA-P]*$/, | ||
427 | /^[0-9a-qA-Q]*$/, | ||
428 | /^[0-9a-rA-R]*$/, | ||
429 | /^[0-9a-sA-S]*$/, | ||
430 | /^[0-9a-tA-T]*$/, | ||
431 | /^[0-9a-uA-U]*$/, | ||
432 | /^[0-9a-vA-V]*$/, | ||
433 | /^[0-9a-wA-W]*$/, | ||
434 | /^[0-9a-xA-X]*$/, | ||
435 | /^[0-9a-yA-Y]*$/, | ||
436 | /^[0-9a-zA-Z]*$/ | ||
437 | ]; | ||
438 | |||
439 | /* | ||
440 | Function: parse | ||
441 | Parse a string into a <BigInteger>. | ||
442 | |||
443 | *base* is optional but, if provided, must be from 2 to 36 inclusive. If | ||
444 | *base* is not provided, it will be guessed based on the leading characters | ||
445 | of *s* as follows: | ||
446 | |||
447 | - "0x" or "0X": *base* = 16 | ||
448 | - "0c" or "0C": *base* = 8 | ||
449 | - "0b" or "0B": *base* = 2 | ||
450 | - else: *base* = 10 | ||
451 | |||
452 | If no base is provided, or *base* is 10, the number can be in exponential | ||
453 | form. For example, these are all valid: | ||
454 | |||
455 | > BigInteger.parse("1e9"); // Same as "1000000000" | ||
456 | > BigInteger.parse("1.234*10^3"); // Same as 1234 | ||
457 | > BigInteger.parse("56789 * 10 ** -2"); // Same as 567 | ||
458 | |||
459 | If any characters fall outside the range defined by the radix, an exception | ||
460 | will be thrown. | ||
461 | |||
462 | Parameters: | ||
463 | |||
464 | s - The string to parse. | ||
465 | base - Optional radix (default is to guess based on *s*). | ||
466 | |||
467 | Returns: | ||
468 | |||
469 | a <BigInteger> instance. | ||
470 | */ | ||
471 | BigInteger.parse = function(s, base) { | ||
472 | // Expands a number in exponential form to decimal form. | ||
473 | // expandExponential("-13.441*10^5") === "1344100"; | ||
474 | // expandExponential("1.12300e-1") === "0.112300"; | ||
475 | // expandExponential(1000000000000000000000000000000) === "1000000000000000000000000000000"; | ||
476 | function expandExponential(str) { | ||
477 | str = str.replace(/\s*[*xX]\s*10\s*(\^|\*\*)\s*/, "e"); | ||
478 | |||
479 | return str.replace(/^([+\-])?(\d+)\.?(\d*)[eE]([+\-]?\d+)$/, function(x, s, n, f, c) { | ||
480 | c = +c; | ||
481 | var l = c < 0; | ||
482 | var i = n.length + c; | ||
483 | x = (l ? n : f).length; | ||
484 | c = ((c = Math.abs(c)) >= x ? c - x + l : 0); | ||
485 | var z = (new Array(c + 1)).join("0"); | ||
486 | var r = n + f; | ||
487 | return (s || "") + (l ? r = z + r : r += z).substr(0, i += l ? z.length : 0) + (i < r.length ? "." + r.substr(i) : ""); | ||
488 | }); | ||
489 | } | ||
490 | |||
491 | s = s.toString(); | ||
492 | if (typeof base === "undefined" || +base === 10) { | ||
493 | s = expandExponential(s); | ||
494 | } | ||
495 | |||
496 | var prefixRE; | ||
497 | if (typeof base === "undefined") { | ||
498 | prefixRE = '0[xcb]'; | ||
499 | } | ||
500 | else if (base == 16) { | ||
501 | prefixRE = '0x'; | ||
502 | } | ||
503 | else if (base == 8) { | ||
504 | prefixRE = '0c'; | ||
505 | } | ||
506 | else if (base == 2) { | ||
507 | prefixRE = '0b'; | ||
508 | } | ||
509 | else { | ||
510 | prefixRE = ''; | ||
511 | } | ||
512 | var parts = new RegExp('^([+\\-]?)(' + prefixRE + ')?([0-9a-z]*)(?:\\.\\d*)?$', 'i').exec(s); | ||
513 | if (parts) { | ||
514 | var sign = parts[1] || "+"; | ||
515 | var baseSection = parts[2] || ""; | ||
516 | var digits = parts[3] || ""; | ||
517 | |||
518 | if (typeof base === "undefined") { | ||
519 | // Guess base | ||
520 | if (baseSection === "0x" || baseSection === "0X") { // Hex | ||
521 | base = 16; | ||
522 | } | ||
523 | else if (baseSection === "0c" || baseSection === "0C") { // Octal | ||
524 | base = 8; | ||
525 | } | ||
526 | else if (baseSection === "0b" || baseSection === "0B") { // Binary | ||
527 | base = 2; | ||
528 | } | ||
529 | else { | ||
530 | base = 10; | ||
531 | } | ||
532 | } | ||
533 | else if (base < 2 || base > 36) { | ||
534 | throw new Error("Illegal radix " + base + "."); | ||
535 | } | ||
536 | |||
537 | base = +base; | ||
538 | |||
539 | // Check for digits outside the range | ||
540 | if (!(BigInteger.radixRegex[base].test(digits))) { | ||
541 | throw new Error("Bad digit for radix " + base); | ||
542 | } | ||
543 | |||
544 | // Strip leading zeros, and convert to array | ||
545 | digits = digits.replace(/^0+/, "").split(""); | ||
546 | if (digits.length === 0) { | ||
547 | return ZERO; | ||
548 | } | ||
549 | |||
550 | // Get the sign (we know it's not zero) | ||
551 | sign = (sign === "-") ? -1 : 1; | ||
552 | |||
553 | // Optimize 10 | ||
554 | if (base == 10) { | ||
555 | var d = []; | ||
556 | while (digits.length >= BigInteger_base_log10) { | ||
557 | d.push(parseInt(digits.splice(digits.length-BigInteger.base_log10, BigInteger.base_log10).join(''), 10)); | ||
558 | } | ||
559 | d.push(parseInt(digits.join(''), 10)); | ||
560 | return new BigInteger(d, sign, CONSTRUCT); | ||
561 | } | ||
562 | |||
563 | // Do the conversion | ||
564 | var d = ZERO; | ||
565 | base = BigInteger.small[base]; | ||
566 | var small = BigInteger.small; | ||
567 | for (var i = 0; i < digits.length; i++) { | ||
568 | d = d.multiply(base).add(small[parseInt(digits[i], 36)]); | ||
569 | } | ||
570 | return new BigInteger(d._d, sign, CONSTRUCT); | ||
571 | } | ||
572 | else { | ||
573 | throw new Error("Invalid BigInteger format: " + s); | ||
574 | } | ||
575 | }; | ||
576 | |||
577 | /* | ||
578 | Function: add | ||
579 | Add two <BigIntegers>. | ||
580 | |||
581 | Parameters: | ||
582 | |||
583 | n - The number to add to *this*. Will be converted to a <BigInteger>. | ||
584 | |||
585 | Returns: | ||
586 | |||
587 | The numbers added together. | ||
588 | |||
589 | See Also: | ||
590 | |||
591 | <subtract>, <multiply>, <quotient>, <next> | ||
592 | */ | ||
593 | BigInteger.prototype.add = function(n) { | ||
594 | if (this._s === 0) { | ||
595 | return BigInteger(n); | ||
596 | } | ||
597 | |||
598 | n = BigInteger(n); | ||
599 | if (n._s === 0) { | ||
600 | return this; | ||
601 | } | ||
602 | if (this._s !== n._s) { | ||
603 | n = n.negate(); | ||
604 | return this.subtract(n); | ||
605 | } | ||
606 | |||
607 | var a = this._d; | ||
608 | var b = n._d; | ||
609 | var al = a.length; | ||
610 | var bl = b.length; | ||
611 | var sum = new Array(Math.max(al, bl) + 1); | ||
612 | var size = Math.min(al, bl); | ||
613 | var carry = 0; | ||
614 | var digit; | ||
615 | |||
616 | for (var i = 0; i < size; i++) { | ||
617 | digit = a[i] + b[i] + carry; | ||
618 | sum[i] = digit % BigInteger_base; | ||
619 | carry = (digit / BigInteger_base) | 0; | ||
620 | } | ||
621 | if (bl > al) { | ||
622 | a = b; | ||
623 | al = bl; | ||
624 | } | ||
625 | for (i = size; carry && i < al; i++) { | ||
626 | digit = a[i] + carry; | ||
627 | sum[i] = digit % BigInteger_base; | ||
628 | carry = (digit / BigInteger_base) | 0; | ||
629 | } | ||
630 | if (carry) { | ||
631 | sum[i] = carry; | ||
632 | } | ||
633 | |||
634 | for ( ; i < al; i++) { | ||
635 | sum[i] = a[i]; | ||
636 | } | ||
637 | |||
638 | return new BigInteger(sum, this._s, CONSTRUCT); | ||
639 | }; | ||
640 | |||
641 | /* | ||
642 | Function: negate | ||
643 | Get the additive inverse of a <BigInteger>. | ||
644 | |||
645 | Returns: | ||
646 | |||
647 | A <BigInteger> with the same magnatude, but with the opposite sign. | ||
648 | |||
649 | See Also: | ||
650 | |||
651 | <abs> | ||
652 | */ | ||
653 | BigInteger.prototype.negate = function() { | ||
654 | return new BigInteger(this._d, (-this._s) | 0, CONSTRUCT); | ||
655 | }; | ||
656 | |||
657 | /* | ||
658 | Function: abs | ||
659 | Get the absolute value of a <BigInteger>. | ||
660 | |||
661 | Returns: | ||
662 | |||
663 | A <BigInteger> with the same magnatude, but always positive (or zero). | ||
664 | |||
665 | See Also: | ||
666 | |||
667 | <negate> | ||
668 | */ | ||
669 | BigInteger.prototype.abs = function() { | ||
670 | return (this._s < 0) ? this.negate() : this; | ||
671 | }; | ||
672 | |||
673 | /* | ||
674 | Function: subtract | ||
675 | Subtract two <BigIntegers>. | ||
676 | |||
677 | Parameters: | ||
678 | |||
679 | n - The number to subtract from *this*. Will be converted to a <BigInteger>. | ||
680 | |||
681 | Returns: | ||
682 | |||
683 | The *n* subtracted from *this*. | ||
684 | |||
685 | See Also: | ||
686 | |||
687 | <add>, <multiply>, <quotient>, <prev> | ||
688 | */ | ||
689 | BigInteger.prototype.subtract = function(n) { | ||
690 | if (this._s === 0) { | ||
691 | return BigInteger(n).negate(); | ||
692 | } | ||
693 | |||
694 | n = BigInteger(n); | ||
695 | if (n._s === 0) { | ||
696 | return this; | ||
697 | } | ||
698 | if (this._s !== n._s) { | ||
699 | n = n.negate(); | ||
700 | return this.add(n); | ||
701 | } | ||
702 | |||
703 | var m = this; | ||
704 | // negative - negative => -|a| - -|b| => -|a| + |b| => |b| - |a| | ||
705 | if (this._s < 0) { | ||
706 | m = new BigInteger(n._d, 1, CONSTRUCT); | ||
707 | n = new BigInteger(this._d, 1, CONSTRUCT); | ||
708 | } | ||
709 | |||
710 | // Both are positive => a - b | ||
711 | var sign = m.compareAbs(n); | ||
712 | if (sign === 0) { | ||
713 | return ZERO; | ||
714 | } | ||
715 | else if (sign < 0) { | ||
716 | // swap m and n | ||
717 | var t = n; | ||
718 | n = m; | ||
719 | m = t; | ||
720 | } | ||
721 | |||
722 | // a > b | ||
723 | var a = m._d; | ||
724 | var b = n._d; | ||
725 | var al = a.length; | ||
726 | var bl = b.length; | ||
727 | var diff = new Array(al); // al >= bl since a > b | ||
728 | var borrow = 0; | ||
729 | var i; | ||
730 | var digit; | ||
731 | |||
732 | for (i = 0; i < bl; i++) { | ||
733 | digit = a[i] - borrow - b[i]; | ||
734 | if (digit < 0) { | ||
735 | digit += BigInteger_base; | ||
736 | borrow = 1; | ||
737 | } | ||
738 | else { | ||
739 | borrow = 0; | ||
740 | } | ||
741 | diff[i] = digit; | ||
742 | } | ||
743 | for (i = bl; i < al; i++) { | ||
744 | digit = a[i] - borrow; | ||
745 | if (digit < 0) { | ||
746 | digit += BigInteger_base; | ||
747 | } | ||
748 | else { | ||
749 | diff[i++] = digit; | ||
750 | break; | ||
751 | } | ||
752 | diff[i] = digit; | ||
753 | } | ||
754 | for ( ; i < al; i++) { | ||
755 | diff[i] = a[i]; | ||
756 | } | ||
757 | |||
758 | return new BigInteger(diff, sign, CONSTRUCT); | ||
759 | }; | ||
760 | |||
761 | (function() { | ||
762 | function addOne(n, sign) { | ||
763 | var a = n._d; | ||
764 | var sum = a.slice(); | ||
765 | var carry = true; | ||
766 | var i = 0; | ||
767 | |||
768 | while (true) { | ||
769 | var digit = (a[i] || 0) + 1; | ||
770 | sum[i] = digit % BigInteger_base; | ||
771 | if (digit <= BigInteger_base - 1) { | ||
772 | break; | ||
773 | } | ||
774 | ++i; | ||
775 | } | ||
776 | |||
777 | return new BigInteger(sum, sign, CONSTRUCT); | ||
778 | } | ||
779 | |||
780 | function subtractOne(n, sign) { | ||
781 | var a = n._d; | ||
782 | var sum = a.slice(); | ||
783 | var borrow = true; | ||
784 | var i = 0; | ||
785 | |||
786 | while (true) { | ||
787 | var digit = (a[i] || 0) - 1; | ||
788 | if (digit < 0) { | ||
789 | sum[i] = digit + BigInteger_base; | ||
790 | } | ||
791 | else { | ||
792 | sum[i] = digit; | ||
793 | break; | ||
794 | } | ||
795 | ++i; | ||
796 | } | ||
797 | |||
798 | return new BigInteger(sum, sign, CONSTRUCT); | ||
799 | } | ||
800 | |||
801 | /* | ||
802 | Function: next | ||
803 | Get the next <BigInteger> (add one). | ||
804 | |||
805 | Returns: | ||
806 | |||
807 | *this* + 1. | ||
808 | |||
809 | See Also: | ||
810 | |||
811 | <add>, <prev> | ||
812 | */ | ||
813 | BigInteger.prototype.next = function() { | ||
814 | switch (this._s) { | ||
815 | case 0: | ||
816 | return ONE; | ||
817 | case -1: | ||
818 | return subtractOne(this, -1); | ||
819 | // case 1: | ||
820 | default: | ||
821 | return addOne(this, 1); | ||
822 | } | ||
823 | }; | ||
824 | |||
825 | /* | ||
826 | Function: prev | ||
827 | Get the previous <BigInteger> (subtract one). | ||
828 | |||
829 | Returns: | ||
830 | |||
831 | *this* - 1. | ||
832 | |||
833 | See Also: | ||
834 | |||
835 | <next>, <subtract> | ||
836 | */ | ||
837 | BigInteger.prototype.prev = function() { | ||
838 | switch (this._s) { | ||
839 | case 0: | ||
840 | return M_ONE; | ||
841 | case -1: | ||
842 | return addOne(this, -1); | ||
843 | // case 1: | ||
844 | default: | ||
845 | return subtractOne(this, 1); | ||
846 | } | ||
847 | }; | ||
848 | })(); | ||
849 | |||
850 | /* | ||
851 | Function: compareAbs | ||
852 | Compare the absolute value of two <BigIntegers>. | ||
853 | |||
854 | Calling <compareAbs> is faster than calling <abs> twice, then <compare>. | ||
855 | |||
856 | Parameters: | ||
857 | |||
858 | n - The number to compare to *this*. Will be converted to a <BigInteger>. | ||
859 | |||
860 | Returns: | ||
861 | |||
862 | -1, 0, or +1 if *|this|* is less than, equal to, or greater than *|n|*. | ||
863 | |||
864 | See Also: | ||
865 | |||
866 | <compare>, <abs> | ||
867 | */ | ||
868 | BigInteger.prototype.compareAbs = function(n) { | ||
869 | if (this === n) { | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | if (!(n instanceof BigInteger)) { | ||
874 | if (!isFinite(n)) { | ||
875 | return(isNaN(n) ? n : -1); | ||
876 | } | ||
877 | n = BigInteger(n); | ||
878 | } | ||
879 | |||
880 | if (this._s === 0) { | ||
881 | return (n._s !== 0) ? -1 : 0; | ||
882 | } | ||
883 | if (n._s === 0) { | ||
884 | return 1; | ||
885 | } | ||
886 | |||
887 | var l = this._d.length; | ||
888 | var nl = n._d.length; | ||
889 | if (l < nl) { | ||
890 | return -1; | ||
891 | } | ||
892 | else if (l > nl) { | ||
893 | return 1; | ||
894 | } | ||
895 | |||
896 | var a = this._d; | ||
897 | var b = n._d; | ||
898 | for (var i = l-1; i >= 0; i--) { | ||
899 | if (a[i] !== b[i]) { | ||
900 | return a[i] < b[i] ? -1 : 1; | ||
901 | } | ||
902 | } | ||
903 | |||
904 | return 0; | ||
905 | }; | ||
906 | |||
907 | /* | ||
908 | Function: compare | ||
909 | Compare two <BigIntegers>. | ||
910 | |||
911 | Parameters: | ||
912 | |||
913 | n - The number to compare to *this*. Will be converted to a <BigInteger>. | ||
914 | |||
915 | Returns: | ||
916 | |||
917 | -1, 0, or +1 if *this* is less than, equal to, or greater than *n*. | ||
918 | |||
919 | See Also: | ||
920 | |||
921 | <compareAbs>, <isPositive>, <isNegative>, <isUnit> | ||
922 | */ | ||
923 | BigInteger.prototype.compare = function(n) { | ||
924 | if (this === n) { | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | n = BigInteger(n); | ||
929 | |||
930 | if (this._s === 0) { | ||
931 | return -n._s; | ||
932 | } | ||
933 | |||
934 | if (this._s === n._s) { // both positive or both negative | ||
935 | var cmp = this.compareAbs(n); | ||
936 | return cmp * this._s; | ||
937 | } | ||
938 | else { | ||
939 | return this._s; | ||
940 | } | ||
941 | }; | ||
942 | |||
943 | /* | ||
944 | Function: isUnit | ||
945 | Return true iff *this* is either 1 or -1. | ||
946 | |||
947 | Returns: | ||
948 | |||
949 | true if *this* compares equal to <BigInteger.ONE> or <BigInteger.M_ONE>. | ||
950 | |||
951 | See Also: | ||
952 | |||
953 | <isZero>, <isNegative>, <isPositive>, <compareAbs>, <compare>, | ||
954 | <BigInteger.ONE>, <BigInteger.M_ONE> | ||
955 | */ | ||
956 | BigInteger.prototype.isUnit = function() { | ||
957 | return this === ONE || | ||
958 | this === M_ONE || | ||
959 | (this._d.length === 1 && this._d[0] === 1); | ||
960 | }; | ||
961 | |||
962 | /* | ||
963 | Function: multiply | ||
964 | Multiply two <BigIntegers>. | ||
965 | |||
966 | Parameters: | ||
967 | |||
968 | n - The number to multiply *this* by. Will be converted to a | ||
969 | <BigInteger>. | ||
970 | |||
971 | Returns: | ||
972 | |||
973 | The numbers multiplied together. | ||
974 | |||
975 | See Also: | ||
976 | |||
977 | <add>, <subtract>, <quotient>, <square> | ||
978 | */ | ||
979 | BigInteger.prototype.multiply = function(n) { | ||
980 | // TODO: Consider adding Karatsuba multiplication for large numbers | ||
981 | if (this._s === 0) { | ||
982 | return ZERO; | ||
983 | } | ||
984 | |||
985 | n = BigInteger(n); | ||
986 | if (n._s === 0) { | ||
987 | return ZERO; | ||
988 | } | ||
989 | if (this.isUnit()) { | ||
990 | if (this._s < 0) { | ||
991 | return n.negate(); | ||
992 | } | ||
993 | return n; | ||
994 | } | ||
995 | if (n.isUnit()) { | ||
996 | if (n._s < 0) { | ||
997 | return this.negate(); | ||
998 | } | ||
999 | return this; | ||
1000 | } | ||
1001 | if (this === n) { | ||
1002 | return this.square(); | ||
1003 | } | ||
1004 | |||
1005 | var r = (this._d.length >= n._d.length); | ||
1006 | var a = (r ? this : n)._d; // a will be longer than b | ||
1007 | var b = (r ? n : this)._d; | ||
1008 | var al = a.length; | ||
1009 | var bl = b.length; | ||
1010 | |||
1011 | var pl = al + bl; | ||
1012 | var partial = new Array(pl); | ||
1013 | var i; | ||
1014 | for (i = 0; i < pl; i++) { | ||
1015 | partial[i] = 0; | ||
1016 | } | ||
1017 | |||
1018 | for (i = 0; i < bl; i++) { | ||
1019 | var carry = 0; | ||
1020 | var bi = b[i]; | ||
1021 | var jlimit = al + i; | ||
1022 | var digit; | ||
1023 | for (var j = i; j < jlimit; j++) { | ||
1024 | digit = partial[j] + bi * a[j - i] + carry; | ||
1025 | carry = (digit / BigInteger_base) | 0; | ||
1026 | partial[j] = (digit % BigInteger_base) | 0; | ||
1027 | } | ||
1028 | if (carry) { | ||
1029 | digit = partial[j] + carry; | ||
1030 | carry = (digit / BigInteger_base) | 0; | ||
1031 | partial[j] = digit % BigInteger_base; | ||
1032 | } | ||
1033 | } | ||
1034 | return new BigInteger(partial, this._s * n._s, CONSTRUCT); | ||
1035 | }; | ||
1036 | |||
1037 | // Multiply a BigInteger by a single-digit native number | ||
1038 | // Assumes that this and n are >= 0 | ||
1039 | // This is not really intended to be used outside the library itself | ||
1040 | BigInteger.prototype.multiplySingleDigit = function(n) { | ||
1041 | if (n === 0 || this._s === 0) { | ||
1042 | return ZERO; | ||
1043 | } | ||
1044 | if (n === 1) { | ||
1045 | return this; | ||
1046 | } | ||
1047 | |||
1048 | var digit; | ||
1049 | if (this._d.length === 1) { | ||
1050 | digit = this._d[0] * n; | ||
1051 | if (digit >= BigInteger_base) { | ||
1052 | return new BigInteger([(digit % BigInteger_base)|0, | ||
1053 | (digit / BigInteger_base)|0], 1, CONSTRUCT); | ||
1054 | } | ||
1055 | return new BigInteger([digit], 1, CONSTRUCT); | ||
1056 | } | ||
1057 | |||
1058 | if (n === 2) { | ||
1059 | return this.add(this); | ||
1060 | } | ||
1061 | if (this.isUnit()) { | ||
1062 | return new BigInteger([n], 1, CONSTRUCT); | ||
1063 | } | ||
1064 | |||
1065 | var a = this._d; | ||
1066 | var al = a.length; | ||
1067 | |||
1068 | var pl = al + 1; | ||
1069 | var partial = new Array(pl); | ||
1070 | for (var i = 0; i < pl; i++) { | ||
1071 | partial[i] = 0; | ||
1072 | } | ||
1073 | |||
1074 | var carry = 0; | ||
1075 | for (var j = 0; j < al; j++) { | ||
1076 | digit = n * a[j] + carry; | ||
1077 | carry = (digit / BigInteger_base) | 0; | ||
1078 | partial[j] = (digit % BigInteger_base) | 0; | ||
1079 | } | ||
1080 | if (carry) { | ||
1081 | partial[j] = carry; | ||
1082 | } | ||
1083 | |||
1084 | return new BigInteger(partial, 1, CONSTRUCT); | ||
1085 | }; | ||
1086 | |||
1087 | /* | ||
1088 | Function: square | ||
1089 | Multiply a <BigInteger> by itself. | ||
1090 | |||
1091 | This is slightly faster than regular multiplication, since it removes the | ||
1092 | duplicated multiplcations. | ||
1093 | |||
1094 | Returns: | ||
1095 | |||
1096 | > this.multiply(this) | ||
1097 | |||
1098 | See Also: | ||
1099 | <multiply> | ||
1100 | */ | ||
1101 | BigInteger.prototype.square = function() { | ||
1102 | // Normally, squaring a 10-digit number would take 100 multiplications. | ||
1103 | // Of these 10 are unique diagonals, of the remaining 90 (100-10), 45 are repeated. | ||
1104 | // This procedure saves (N*(N-1))/2 multiplications, (e.g., 45 of 100 multiplies). | ||
1105 | // Based on code by Gary Darby, Intellitech Systems Inc., www.DelphiForFun.org | ||
1106 | |||
1107 | if (this._s === 0) { | ||
1108 | return ZERO; | ||
1109 | } | ||
1110 | if (this.isUnit()) { | ||
1111 | return ONE; | ||
1112 | } | ||
1113 | |||
1114 | var digits = this._d; | ||
1115 | var length = digits.length; | ||
1116 | var imult1 = new Array(length + length + 1); | ||
1117 | var product, carry, k; | ||
1118 | var i; | ||
1119 | |||
1120 | // Calculate diagonal | ||
1121 | for (i = 0; i < length; i++) { | ||
1122 | k = i * 2; | ||
1123 | product = digits[i] * digits[i]; | ||
1124 | carry = (product / BigInteger_base) | 0; | ||
1125 | imult1[k] = product % BigInteger_base; | ||
1126 | imult1[k + 1] = carry; | ||
1127 | } | ||
1128 | |||
1129 | // Calculate repeating part | ||
1130 | for (i = 0; i < length; i++) { | ||
1131 | carry = 0; | ||
1132 | k = i * 2 + 1; | ||
1133 | for (var j = i + 1; j < length; j++, k++) { | ||
1134 | product = digits[j] * digits[i] * 2 + imult1[k] + carry; | ||
1135 | carry = (product / BigInteger_base) | 0; | ||
1136 | imult1[k] = product % BigInteger_base; | ||
1137 | } | ||
1138 | k = length + i; | ||
1139 | var digit = carry + imult1[k]; | ||
1140 | carry = (digit / BigInteger_base) | 0; | ||
1141 | imult1[k] = digit % BigInteger_base; | ||
1142 | imult1[k + 1] += carry; | ||
1143 | } | ||
1144 | |||
1145 | return new BigInteger(imult1, 1, CONSTRUCT); | ||
1146 | }; | ||
1147 | |||
1148 | /* | ||
1149 | Function: quotient | ||
1150 | Divide two <BigIntegers> and truncate towards zero. | ||
1151 | |||
1152 | <quotient> throws an exception if *n* is zero. | ||
1153 | |||
1154 | Parameters: | ||
1155 | |||
1156 | n - The number to divide *this* by. Will be converted to a <BigInteger>. | ||
1157 | |||
1158 | Returns: | ||
1159 | |||
1160 | The *this* / *n*, truncated to an integer. | ||
1161 | |||
1162 | See Also: | ||
1163 | |||
1164 | <add>, <subtract>, <multiply>, <divRem>, <remainder> | ||
1165 | */ | ||
1166 | BigInteger.prototype.quotient = function(n) { | ||
1167 | return this.divRem(n)[0]; | ||
1168 | }; | ||
1169 | |||
1170 | /* | ||
1171 | Function: divide | ||
1172 | Deprecated synonym for <quotient>. | ||
1173 | */ | ||
1174 | BigInteger.prototype.divide = BigInteger.prototype.quotient; | ||
1175 | |||
1176 | /* | ||
1177 | Function: remainder | ||
1178 | Calculate the remainder of two <BigIntegers>. | ||
1179 | |||
1180 | <remainder> throws an exception if *n* is zero. | ||
1181 | |||
1182 | Parameters: | ||
1183 | |||
1184 | n - The remainder after *this* is divided *this* by *n*. Will be | ||
1185 | converted to a <BigInteger>. | ||
1186 | |||
1187 | Returns: | ||
1188 | |||
1189 | *this* % *n*. | ||
1190 | |||
1191 | See Also: | ||
1192 | |||
1193 | <divRem>, <quotient> | ||
1194 | */ | ||
1195 | BigInteger.prototype.remainder = function(n) { | ||
1196 | return this.divRem(n)[1]; | ||
1197 | }; | ||
1198 | |||
1199 | /* | ||
1200 | Function: divRem | ||
1201 | Calculate the integer quotient and remainder of two <BigIntegers>. | ||
1202 | |||
1203 | <divRem> throws an exception if *n* is zero. | ||
1204 | |||
1205 | Parameters: | ||
1206 | |||
1207 | n - The number to divide *this* by. Will be converted to a <BigInteger>. | ||
1208 | |||
1209 | Returns: | ||
1210 | |||
1211 | A two-element array containing the quotient and the remainder. | ||
1212 | |||
1213 | > a.divRem(b) | ||
1214 | |||
1215 | is exactly equivalent to | ||
1216 | |||
1217 | > [a.quotient(b), a.remainder(b)] | ||
1218 | |||
1219 | except it is faster, because they are calculated at the same time. | ||
1220 | |||
1221 | See Also: | ||
1222 | |||
1223 | <quotient>, <remainder> | ||
1224 | */ | ||
1225 | BigInteger.prototype.divRem = function(n) { | ||
1226 | n = BigInteger(n); | ||
1227 | if (n._s === 0) { | ||
1228 | throw new Error("Divide by zero"); | ||
1229 | } | ||
1230 | if (this._s === 0) { | ||
1231 | return [ZERO, ZERO]; | ||
1232 | } | ||
1233 | if (n._d.length === 1) { | ||
1234 | return this.divRemSmall(n._s * n._d[0]); | ||
1235 | } | ||
1236 | |||
1237 | // Test for easy cases -- |n1| <= |n2| | ||
1238 | switch (this.compareAbs(n)) { | ||
1239 | case 0: // n1 == n2 | ||
1240 | return [this._s === n._s ? ONE : M_ONE, ZERO]; | ||
1241 | case -1: // |n1| < |n2| | ||
1242 | return [ZERO, this]; | ||
1243 | } | ||
1244 | |||
1245 | var sign = this._s * n._s; | ||
1246 | var a = n.abs(); | ||
1247 | var b_digits = this._d; | ||
1248 | var b_index = b_digits.length; | ||
1249 | var digits = n._d.length; | ||
1250 | var quot = []; | ||
1251 | var guess; | ||
1252 | |||
1253 | var part = new BigInteger([], 0, CONSTRUCT); | ||
1254 | |||
1255 | while (b_index) { | ||
1256 | part._d.unshift(b_digits[--b_index]); | ||
1257 | part = new BigInteger(part._d, 1, CONSTRUCT); | ||
1258 | |||
1259 | if (part.compareAbs(n) < 0) { | ||
1260 | quot.push(0); | ||
1261 | continue; | ||
1262 | } | ||
1263 | if (part._s === 0) { | ||
1264 | guess = 0; | ||
1265 | } | ||
1266 | else { | ||
1267 | var xlen = part._d.length, ylen = a._d.length; | ||
1268 | var highx = part._d[xlen-1]*BigInteger_base + part._d[xlen-2]; | ||
1269 | var highy = a._d[ylen-1]*BigInteger_base + a._d[ylen-2]; | ||
1270 | if (part._d.length > a._d.length) { | ||
1271 | // The length of part._d can either match a._d length, | ||
1272 | // or exceed it by one. | ||
1273 | highx = (highx+1)*BigInteger_base; | ||
1274 | } | ||
1275 | guess = Math.ceil(highx/highy); | ||
1276 | } | ||
1277 | do { | ||
1278 | var check = a.multiplySingleDigit(guess); | ||
1279 | if (check.compareAbs(part) <= 0) { | ||
1280 | break; | ||
1281 | } | ||
1282 | guess--; | ||
1283 | } while (guess); | ||
1284 | |||
1285 | quot.push(guess); | ||
1286 | if (!guess) { | ||
1287 | continue; | ||
1288 | } | ||
1289 | var diff = part.subtract(check); | ||
1290 | part._d = diff._d.slice(); | ||
1291 | } | ||
1292 | |||
1293 | return [new BigInteger(quot.reverse(), sign, CONSTRUCT), | ||
1294 | new BigInteger(part._d, this._s, CONSTRUCT)]; | ||
1295 | }; | ||
1296 | |||
1297 | // Throws an exception if n is outside of (-BigInteger.base, -1] or | ||
1298 | // [1, BigInteger.base). It's not necessary to call this, since the | ||
1299 | // other division functions will call it if they are able to. | ||
1300 | BigInteger.prototype.divRemSmall = function(n) { | ||
1301 | var r; | ||
1302 | n = +n; | ||
1303 | if (n === 0) { | ||
1304 | throw new Error("Divide by zero"); | ||
1305 | } | ||
1306 | |||
1307 | var n_s = n < 0 ? -1 : 1; | ||
1308 | var sign = this._s * n_s; | ||
1309 | n = Math.abs(n); | ||
1310 | |||
1311 | if (n < 1 || n >= BigInteger_base) { | ||
1312 | throw new Error("Argument out of range"); | ||
1313 | } | ||
1314 | |||
1315 | if (this._s === 0) { | ||
1316 | return [ZERO, ZERO]; | ||
1317 | } | ||
1318 | |||
1319 | if (n === 1 || n === -1) { | ||
1320 | return [(sign === 1) ? this.abs() : new BigInteger(this._d, sign, CONSTRUCT), ZERO]; | ||
1321 | } | ||
1322 | |||
1323 | // 2 <= n < BigInteger_base | ||
1324 | |||
1325 | // divide a single digit by a single digit | ||
1326 | if (this._d.length === 1) { | ||
1327 | var q = new BigInteger([(this._d[0] / n) | 0], 1, CONSTRUCT); | ||
1328 | r = new BigInteger([(this._d[0] % n) | 0], 1, CONSTRUCT); | ||
1329 | if (sign < 0) { | ||
1330 | q = q.negate(); | ||
1331 | } | ||
1332 | if (this._s < 0) { | ||
1333 | r = r.negate(); | ||
1334 | } | ||
1335 | return [q, r]; | ||
1336 | } | ||
1337 | |||
1338 | var digits = this._d.slice(); | ||
1339 | var quot = new Array(digits.length); | ||
1340 | var part = 0; | ||
1341 | var diff = 0; | ||
1342 | var i = 0; | ||
1343 | var guess; | ||
1344 | |||
1345 | while (digits.length) { | ||
1346 | part = part * BigInteger_base + digits[digits.length - 1]; | ||
1347 | if (part < n) { | ||
1348 | quot[i++] = 0; | ||
1349 | digits.pop(); | ||
1350 | diff = BigInteger_base * diff + part; | ||
1351 | continue; | ||
1352 | } | ||
1353 | if (part === 0) { | ||
1354 | guess = 0; | ||
1355 | } | ||
1356 | else { | ||
1357 | guess = (part / n) | 0; | ||
1358 | } | ||
1359 | |||
1360 | var check = n * guess; | ||
1361 | diff = part - check; | ||
1362 | quot[i++] = guess; | ||
1363 | if (!guess) { | ||
1364 | digits.pop(); | ||
1365 | continue; | ||
1366 | } | ||
1367 | |||
1368 | digits.pop(); | ||
1369 | part = diff; | ||
1370 | } | ||
1371 | |||
1372 | r = new BigInteger([diff], 1, CONSTRUCT); | ||
1373 | if (this._s < 0) { | ||
1374 | r = r.negate(); | ||
1375 | } | ||
1376 | return [new BigInteger(quot.reverse(), sign, CONSTRUCT), r]; | ||
1377 | }; | ||
1378 | |||
1379 | /* | ||
1380 | Function: isEven | ||
1381 | Return true iff *this* is divisible by two. | ||
1382 | |||
1383 | Note that <BigInteger.ZERO> is even. | ||
1384 | |||
1385 | Returns: | ||
1386 | |||
1387 | true if *this* is even, false otherwise. | ||
1388 | |||
1389 | See Also: | ||
1390 | |||
1391 | <isOdd> | ||
1392 | */ | ||
1393 | BigInteger.prototype.isEven = function() { | ||
1394 | var digits = this._d; | ||
1395 | return this._s === 0 || digits.length === 0 || (digits[0] % 2) === 0; | ||
1396 | }; | ||
1397 | |||
1398 | /* | ||
1399 | Function: isOdd | ||
1400 | Return true iff *this* is not divisible by two. | ||
1401 | |||
1402 | Returns: | ||
1403 | |||
1404 | true if *this* is odd, false otherwise. | ||
1405 | |||
1406 | See Also: | ||
1407 | |||
1408 | <isEven> | ||
1409 | */ | ||
1410 | BigInteger.prototype.isOdd = function() { | ||
1411 | return !this.isEven(); | ||
1412 | }; | ||
1413 | |||
1414 | /* | ||
1415 | Function: sign | ||
1416 | Get the sign of a <BigInteger>. | ||
1417 | |||
1418 | Returns: | ||
1419 | |||
1420 | * -1 if *this* < 0 | ||
1421 | * 0 if *this* == 0 | ||
1422 | * +1 if *this* > 0 | ||
1423 | |||
1424 | See Also: | ||
1425 | |||
1426 | <isZero>, <isPositive>, <isNegative>, <compare>, <BigInteger.ZERO> | ||
1427 | */ | ||
1428 | BigInteger.prototype.sign = function() { | ||
1429 | return this._s; | ||
1430 | }; | ||
1431 | |||
1432 | /* | ||
1433 | Function: isPositive | ||
1434 | Return true iff *this* > 0. | ||
1435 | |||
1436 | Returns: | ||
1437 | |||
1438 | true if *this*.compare(<BigInteger.ZERO>) == 1. | ||
1439 | |||
1440 | See Also: | ||
1441 | |||
1442 | <sign>, <isZero>, <isNegative>, <isUnit>, <compare>, <BigInteger.ZERO> | ||
1443 | */ | ||
1444 | BigInteger.prototype.isPositive = function() { | ||
1445 | return this._s > 0; | ||
1446 | }; | ||
1447 | |||
1448 | /* | ||
1449 | Function: isNegative | ||
1450 | Return true iff *this* < 0. | ||
1451 | |||
1452 | Returns: | ||
1453 | |||
1454 | true if *this*.compare(<BigInteger.ZERO>) == -1. | ||
1455 | |||
1456 | See Also: | ||
1457 | |||
1458 | <sign>, <isPositive>, <isZero>, <isUnit>, <compare>, <BigInteger.ZERO> | ||
1459 | */ | ||
1460 | BigInteger.prototype.isNegative = function() { | ||
1461 | return this._s < 0; | ||
1462 | }; | ||
1463 | |||
1464 | /* | ||
1465 | Function: isZero | ||
1466 | Return true iff *this* == 0. | ||
1467 | |||
1468 | Returns: | ||
1469 | |||
1470 | true if *this*.compare(<BigInteger.ZERO>) == 0. | ||
1471 | |||
1472 | See Also: | ||
1473 | |||
1474 | <sign>, <isPositive>, <isNegative>, <isUnit>, <BigInteger.ZERO> | ||
1475 | */ | ||
1476 | BigInteger.prototype.isZero = function() { | ||
1477 | return this._s === 0; | ||
1478 | }; | ||
1479 | |||
1480 | /* | ||
1481 | Function: exp10 | ||
1482 | Multiply a <BigInteger> by a power of 10. | ||
1483 | |||
1484 | This is equivalent to, but faster than | ||
1485 | |||
1486 | > if (n >= 0) { | ||
1487 | > return this.multiply(BigInteger("1e" + n)); | ||
1488 | > } | ||
1489 | > else { // n <= 0 | ||
1490 | > return this.quotient(BigInteger("1e" + -n)); | ||
1491 | > } | ||
1492 | |||
1493 | Parameters: | ||
1494 | |||
1495 | n - The power of 10 to multiply *this* by. *n* is converted to a | ||
1496 | javascipt number and must be no greater than <BigInteger.MAX_EXP> | ||
1497 | (0x7FFFFFFF), or an exception will be thrown. | ||
1498 | |||
1499 | Returns: | ||
1500 | |||
1501 | *this* * (10 ** *n*), truncated to an integer if necessary. | ||
1502 | |||
1503 | See Also: | ||
1504 | |||
1505 | <pow>, <multiply> | ||
1506 | */ | ||
1507 | BigInteger.prototype.exp10 = function(n) { | ||
1508 | n = +n; | ||
1509 | if (n === 0) { | ||
1510 | return this; | ||
1511 | } | ||
1512 | if (Math.abs(n) > Number(MAX_EXP)) { | ||
1513 | throw new Error("exponent too large in BigInteger.exp10"); | ||
1514 | } | ||
1515 | // Optimization for this == 0. This also keeps us from having to trim zeros in the positive n case | ||
1516 | if (this._s === 0) { | ||
1517 | return ZERO; | ||
1518 | } | ||
1519 | if (n > 0) { | ||
1520 | var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); | ||
1521 | |||
1522 | for (; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { | ||
1523 | k._d.unshift(0); | ||
1524 | } | ||
1525 | if (n == 0) | ||
1526 | return k; | ||
1527 | k._s = 1; | ||
1528 | k = k.multiplySingleDigit(Math.pow(10, n)); | ||
1529 | return (this._s < 0 ? k.negate() : k); | ||
1530 | } else if (-n >= this._d.length*BigInteger_base_log10) { | ||
1531 | return ZERO; | ||
1532 | } else { | ||
1533 | var k = new BigInteger(this._d.slice(), this._s, CONSTRUCT); | ||
1534 | |||
1535 | for (n = -n; n >= BigInteger_base_log10; n -= BigInteger_base_log10) { | ||
1536 | k._d.shift(); | ||
1537 | } | ||
1538 | return (n == 0) ? k : k.divRemSmall(Math.pow(10, n))[0]; | ||
1539 | } | ||
1540 | }; | ||
1541 | |||
1542 | /* | ||
1543 | Function: pow | ||
1544 | Raise a <BigInteger> to a power. | ||
1545 | |||
1546 | In this implementation, 0**0 is 1. | ||
1547 | |||
1548 | Parameters: | ||
1549 | |||
1550 | n - The exponent to raise *this* by. *n* must be no greater than | ||
1551 | <BigInteger.MAX_EXP> (0x7FFFFFFF), or an exception will be thrown. | ||
1552 | |||
1553 | Returns: | ||
1554 | |||
1555 | *this* raised to the *nth* power. | ||
1556 | |||
1557 | See Also: | ||
1558 | |||
1559 | <modPow> | ||
1560 | */ | ||
1561 | BigInteger.prototype.pow = function(n) { | ||
1562 | if (this.isUnit()) { | ||
1563 | if (this._s > 0) { | ||
1564 | return this; | ||
1565 | } | ||
1566 | else { | ||
1567 | return BigInteger(n).isOdd() ? this : this.negate(); | ||
1568 | } | ||
1569 | } | ||
1570 | |||
1571 | n = BigInteger(n); | ||
1572 | if (n._s === 0) { | ||
1573 | return ONE; | ||
1574 | } | ||
1575 | else if (n._s < 0) { | ||
1576 | if (this._s === 0) { | ||
1577 | throw new Error("Divide by zero"); | ||
1578 | } | ||
1579 | else { | ||
1580 | return ZERO; | ||
1581 | } | ||
1582 | } | ||
1583 | if (this._s === 0) { | ||
1584 | return ZERO; | ||
1585 | } | ||
1586 | if (n.isUnit()) { | ||
1587 | return this; | ||
1588 | } | ||
1589 | |||
1590 | if (n.compareAbs(MAX_EXP) > 0) { | ||
1591 | throw new Error("exponent too large in BigInteger.pow"); | ||
1592 | } | ||
1593 | var x = this; | ||
1594 | var aux = ONE; | ||
1595 | var two = BigInteger.small[2]; | ||
1596 | |||
1597 | while (n.isPositive()) { | ||
1598 | if (n.isOdd()) { | ||
1599 | aux = aux.multiply(x); | ||
1600 | if (n.isUnit()) { | ||
1601 | return aux; | ||
1602 | } | ||
1603 | } | ||
1604 | x = x.square(); | ||
1605 | n = n.quotient(two); | ||
1606 | } | ||
1607 | |||
1608 | return aux; | ||
1609 | }; | ||
1610 | |||
1611 | /* | ||
1612 | Function: modPow | ||
1613 | Raise a <BigInteger> to a power (mod m). | ||
1614 | |||
1615 | Because it is reduced by a modulus, <modPow> is not limited by | ||
1616 | <BigInteger.MAX_EXP> like <pow>. | ||
1617 | |||
1618 | Parameters: | ||
1619 | |||
1620 | exponent - The exponent to raise *this* by. Must be positive. | ||
1621 | modulus - The modulus. | ||
1622 | |||
1623 | Returns: | ||
1624 | |||
1625 | *this* ^ *exponent* (mod *modulus*). | ||
1626 | |||
1627 | See Also: | ||
1628 | |||
1629 | <pow>, <mod> | ||
1630 | */ | ||
1631 | BigInteger.prototype.modPow = function(exponent, modulus) { | ||
1632 | var result = ONE; | ||
1633 | var base = this; | ||
1634 | |||
1635 | while (exponent.isPositive()) { | ||
1636 | if (exponent.isOdd()) { | ||
1637 | result = result.multiply(base).remainder(modulus); | ||
1638 | } | ||
1639 | |||
1640 | exponent = exponent.quotient(BigInteger.small[2]); | ||
1641 | if (exponent.isPositive()) { | ||
1642 | base = base.square().remainder(modulus); | ||
1643 | } | ||
1644 | } | ||
1645 | |||
1646 | return result; | ||
1647 | }; | ||
1648 | |||
1649 | /* | ||
1650 | Function: log | ||
1651 | Get the natural logarithm of a <BigInteger> as a native JavaScript number. | ||
1652 | |||
1653 | This is equivalent to | ||
1654 | |||
1655 | > Math.log(this.toJSValue()) | ||
1656 | |||
1657 | but handles values outside of the native number range. | ||
1658 | |||
1659 | Returns: | ||
1660 | |||
1661 | log( *this* ) | ||
1662 | |||
1663 | See Also: | ||
1664 | |||
1665 | <toJSValue> | ||
1666 | */ | ||
1667 | BigInteger.prototype.log = function() { | ||
1668 | switch (this._s) { | ||
1669 | case 0: return -Infinity; | ||
1670 | case -1: return NaN; | ||
1671 | default: // Fall through. | ||
1672 | } | ||
1673 | |||
1674 | var l = this._d.length; | ||
1675 | |||
1676 | if (l*BigInteger_base_log10 < 30) { | ||
1677 | return Math.log(this.valueOf()); | ||
1678 | } | ||
1679 | |||
1680 | var N = Math.ceil(30/BigInteger_base_log10); | ||
1681 | var firstNdigits = this._d.slice(l - N); | ||
1682 | return Math.log((new BigInteger(firstNdigits, 1, CONSTRUCT)).valueOf()) + (l - N) * Math.log(BigInteger_base); | ||
1683 | }; | ||
1684 | |||
1685 | /* | ||
1686 | Function: valueOf | ||
1687 | Convert a <BigInteger> to a native JavaScript integer. | ||
1688 | |||
1689 | This is called automatically by JavaScipt to convert a <BigInteger> to a | ||
1690 | native value. | ||
1691 | |||
1692 | Returns: | ||
1693 | |||
1694 | > parseInt(this.toString(), 10) | ||
1695 | |||
1696 | See Also: | ||
1697 | |||
1698 | <toString>, <toJSValue> | ||
1699 | */ | ||
1700 | BigInteger.prototype.valueOf = function() { | ||
1701 | return parseInt(this.toString(), 10); | ||
1702 | }; | ||
1703 | |||
1704 | /* | ||
1705 | Function: toJSValue | ||
1706 | Convert a <BigInteger> to a native JavaScript integer. | ||
1707 | |||
1708 | This is the same as valueOf, but more explicitly named. | ||
1709 | |||
1710 | Returns: | ||
1711 | |||
1712 | > parseInt(this.toString(), 10) | ||
1713 | |||
1714 | See Also: | ||
1715 | |||
1716 | <toString>, <valueOf> | ||
1717 | */ | ||
1718 | BigInteger.prototype.toJSValue = function() { | ||
1719 | return parseInt(this.toString(), 10); | ||
1720 | }; | ||
1721 | |||
1722 | var MAX_EXP = BigInteger(0x7FFFFFFF); | ||
1723 | // Constant: MAX_EXP | ||
1724 | // The largest exponent allowed in <pow> and <exp10> (0x7FFFFFFF or 2147483647). | ||
1725 | BigInteger.MAX_EXP = MAX_EXP; | ||
1726 | |||
1727 | (function() { | ||
1728 | function makeUnary(fn) { | ||
1729 | return function(a) { | ||
1730 | return fn.call(BigInteger(a)); | ||
1731 | }; | ||
1732 | } | ||
1733 | |||
1734 | function makeBinary(fn) { | ||
1735 | return function(a, b) { | ||
1736 | return fn.call(BigInteger(a), BigInteger(b)); | ||
1737 | }; | ||
1738 | } | ||
1739 | |||
1740 | function makeTrinary(fn) { | ||
1741 | return function(a, b, c) { | ||
1742 | return fn.call(BigInteger(a), BigInteger(b), BigInteger(c)); | ||
1743 | }; | ||
1744 | } | ||
1745 | |||
1746 | (function() { | ||
1747 | var i, fn; | ||
1748 | var unary = "toJSValue,isEven,isOdd,sign,isZero,isNegative,abs,isUnit,square,negate,isPositive,toString,next,prev,log".split(","); | ||
1749 | var binary = "compare,remainder,divRem,subtract,add,quotient,divide,multiply,pow,compareAbs".split(","); | ||
1750 | var trinary = ["modPow"]; | ||
1751 | |||
1752 | for (i = 0; i < unary.length; i++) { | ||
1753 | fn = unary[i]; | ||
1754 | BigInteger[fn] = makeUnary(BigInteger.prototype[fn]); | ||
1755 | } | ||
1756 | |||
1757 | for (i = 0; i < binary.length; i++) { | ||
1758 | fn = binary[i]; | ||
1759 | BigInteger[fn] = makeBinary(BigInteger.prototype[fn]); | ||
1760 | } | ||
1761 | |||
1762 | for (i = 0; i < trinary.length; i++) { | ||
1763 | fn = trinary[i]; | ||
1764 | BigInteger[fn] = makeTrinary(BigInteger.prototype[fn]); | ||
1765 | } | ||
1766 | |||
1767 | BigInteger.exp10 = function(x, n) { | ||
1768 | return BigInteger(x).exp10(n); | ||
1769 | }; | ||
1770 | })(); | ||
1771 | })(); | ||
1772 | |||
1773 | exports.BigInteger = BigInteger; | ||
1774 | })(typeof exports !== 'undefined' ? exports : this); | ||
diff --git a/src/js/index.js b/src/js/index.js index 0e4cc05..cd7f281 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -14,14 +14,20 @@ | |||
14 | var showPubKey = true; | 14 | var showPubKey = true; |
15 | var showPrivKey = true; | 15 | var showPrivKey = true; |
16 | 16 | ||
17 | var entropyChangeTimeoutEvent = null; | ||
17 | var phraseChangeTimeoutEvent = null; | 18 | var phraseChangeTimeoutEvent = null; |
18 | var rootKeyChangedTimeoutEvent = null; | 19 | var rootKeyChangedTimeoutEvent = null; |
19 | 20 | ||
20 | var DOM = {}; | 21 | var DOM = {}; |
21 | DOM.network = $(".network"); | 22 | DOM.network = $(".network"); |
22 | DOM.phraseNetwork = $("#network-phrase"); | 23 | DOM.phraseNetwork = $("#network-phrase"); |
24 | DOM.useEntropy = $(".use-entropy"); | ||
25 | DOM.entropyContainer = $(".entropy-container"); | ||
26 | DOM.entropy = $(".entropy"); | ||
27 | DOM.entropyError = $(".entropy-error"); | ||
23 | DOM.phrase = $(".phrase"); | 28 | DOM.phrase = $(".phrase"); |
24 | DOM.passphrase = $(".passphrase"); | 29 | DOM.passphrase = $(".passphrase"); |
30 | DOM.generateContainer = $(".generate-container"); | ||
25 | DOM.generate = $(".generate"); | 31 | DOM.generate = $(".generate"); |
26 | DOM.seed = $(".seed"); | 32 | DOM.seed = $(".seed"); |
27 | DOM.rootKey = $(".root-key"); | 33 | DOM.rootKey = $(".root-key"); |
@@ -53,6 +59,8 @@ | |||
53 | function init() { | 59 | function init() { |
54 | // Events | 60 | // Events |
55 | DOM.network.on("change", networkChanged); | 61 | DOM.network.on("change", networkChanged); |
62 | DOM.useEntropy.on("change", setEntropyVisibility); | ||
63 | DOM.entropy.on("input", delayedEntropyChanged); | ||
56 | DOM.phrase.on("input", delayedPhraseChanged); | 64 | DOM.phrase.on("input", delayedPhraseChanged); |
57 | DOM.passphrase.on("input", delayedPhraseChanged); | 65 | DOM.passphrase.on("input", delayedPhraseChanged); |
58 | DOM.generate.on("click", generateClicked); | 66 | DOM.generate.on("click", generateClicked); |
@@ -89,6 +97,21 @@ | |||
89 | } | 97 | } |
90 | } | 98 | } |
91 | 99 | ||
100 | function setEntropyVisibility() { | ||
101 | if (isUsingOwnEntropy()) { | ||
102 | DOM.entropyContainer.removeClass("hidden"); | ||
103 | DOM.generateContainer.addClass("hidden"); | ||
104 | DOM.phrase.prop("readonly", true); | ||
105 | DOM.entropy.focus(); | ||
106 | entropyChanged(); | ||
107 | } | ||
108 | else { | ||
109 | DOM.entropyContainer.addClass("hidden"); | ||
110 | DOM.generateContainer.removeClass("hidden"); | ||
111 | DOM.phrase.prop("readonly", false); | ||
112 | } | ||
113 | } | ||
114 | |||
92 | function delayedPhraseChanged() { | 115 | function delayedPhraseChanged() { |
93 | hideValidationError(); | 116 | hideValidationError(); |
94 | showPending(); | 117 | showPending(); |
@@ -116,6 +139,20 @@ | |||
116 | hidePending(); | 139 | hidePending(); |
117 | } | 140 | } |
118 | 141 | ||
142 | function delayedEntropyChanged() { | ||
143 | hideValidationError(); | ||
144 | showPending(); | ||
145 | if (entropyChangeTimeoutEvent != null) { | ||
146 | clearTimeout(entropyChangeTimeoutEvent); | ||
147 | } | ||
148 | entropyChangeTimeoutEvent = setTimeout(entropyChanged, 400); | ||
149 | } | ||
150 | |||
151 | function entropyChanged() { | ||
152 | setMnemonicFromEntropy(); | ||
153 | phraseChanged(); | ||
154 | } | ||
155 | |||
119 | function delayedRootKeyChanged() { | 156 | function delayedRootKeyChanged() { |
120 | // Warn if there is an existing mnemonic or passphrase. | 157 | // Warn if there is an existing mnemonic or passphrase. |
121 | if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) { | 158 | if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) { |
@@ -168,6 +205,9 @@ | |||
168 | } | 205 | } |
169 | 206 | ||
170 | function generateClicked() { | 207 | function generateClicked() { |
208 | if (isUsingOwnEntropy()) { | ||
209 | return; | ||
210 | } | ||
171 | clearDisplay(); | 211 | clearDisplay(); |
172 | showPending(); | 212 | showPending(); |
173 | setTimeout(function() { | 213 | setTimeout(function() { |
@@ -599,7 +639,12 @@ | |||
599 | } | 639 | } |
600 | 640 | ||
601 | function getLanguageFromUrl() { | 641 | function getLanguageFromUrl() { |
602 | return window.location.hash.substring(1); | 642 | for (var language in WORDLISTS) { |
643 | if (window.location.hash.indexOf(language) > -1) { | ||
644 | return language; | ||
645 | } | ||
646 | } | ||
647 | return ""; | ||
603 | } | 648 | } |
604 | 649 | ||
605 | function setMnemonicLanguage() { | 650 | function setMnemonicLanguage() { |
@@ -650,6 +695,65 @@ | |||
650 | return phrase; | 695 | return phrase; |
651 | } | 696 | } |
652 | 697 | ||
698 | function isUsingOwnEntropy() { | ||
699 | return DOM.useEntropy.prop("checked"); | ||
700 | } | ||
701 | |||
702 | function setMnemonicFromEntropy() { | ||
703 | hideEntropyError(); | ||
704 | // Work out minimum base for entropy | ||
705 | var entropyStr = DOM.entropy.val(); | ||
706 | var entropy = Entropy.fromString(entropyStr); | ||
707 | if (entropy.hexStr.length == 0) { | ||
708 | return; | ||
709 | } | ||
710 | // Show entropy details | ||
711 | var extraBits = 32 - (entropy.binaryStr.length % 32); | ||
712 | var extraChars = Math.ceil(extraBits * Math.log(2) / Math.log(entropy.base.asInt)); | ||
713 | var strength = "an extremely weak"; | ||
714 | if (entropy.hexStr.length >= 8) { | ||
715 | strength = "a very weak"; | ||
716 | } | ||
717 | if (entropy.hexStr.length >= 12) { | ||
718 | strength = "a weak"; | ||
719 | } | ||
720 | if (entropy.hexStr.length >= 24) { | ||
721 | strength = "a strong"; | ||
722 | } | ||
723 | if (entropy.hexStr.length >= 32) { | ||
724 | strength = "a very strong"; | ||
725 | } | ||
726 | if (entropy.hexStr.length >= 40) { | ||
727 | strength = "an extremely strong"; | ||
728 | } | ||
729 | if (entropy.hexStr.length >=48) { | ||
730 | strength = "an even stronger" | ||
731 | } | ||
732 | var msg = "Have " + entropy.binaryStr.length + " bits of entropy, " + extraChars + " more " + entropy.base.str + " chars required to generate " + strength + " mnemonic: " + entropy.cleanStr; | ||
733 | showEntropyError(msg); | ||
734 | // Discard trailing entropy | ||
735 | var hexStr = entropy.hexStr.substring(0, Math.floor(entropy.hexStr.length / 8) * 8); | ||
736 | // Convert entropy string to numeric array | ||
737 | var entropyArr = []; | ||
738 | for (var i=0; i<hexStr.length / 2; i++) { | ||
739 | var entropyByte = parseInt(hexStr[i*2].concat(hexStr[i*2+1]), 16); | ||
740 | entropyArr.push(entropyByte) | ||
741 | } | ||
742 | // Convert entropy array to mnemonic | ||
743 | var phrase = mnemonic.toMnemonic(entropyArr); | ||
744 | // Set the mnemonic in the UI | ||
745 | DOM.phrase.val(phrase); | ||
746 | } | ||
747 | |||
748 | function hideEntropyError() { | ||
749 | DOM.entropyError.addClass("hidden"); | ||
750 | } | ||
751 | |||
752 | function showEntropyError(msg) { | ||
753 | DOM.entropyError.text(msg); | ||
754 | DOM.entropyError.removeClass("hidden"); | ||
755 | } | ||
756 | |||
653 | var networks = [ | 757 | var networks = [ |
654 | { | 758 | { |
655 | name: "Bitcoin", | 759 | name: "Bitcoin", |
@@ -1960,6 +1960,613 @@ page.open(url, function(status) { | |||
1960 | }); | 1960 | }); |
1961 | }, | 1961 | }, |
1962 | 1962 | ||
1963 | // Entropy unit tests | ||
1964 | function() { | ||
1965 | page.open(url, function(status) { | ||
1966 | var error = page.evaluate(function() { | ||
1967 | var e; | ||
1968 | // binary entropy is detected | ||
1969 | e = Entropy.fromString("01010101"); | ||
1970 | if (e.base.str != "binary") { | ||
1971 | return "Binary entropy not detected correctly"; | ||
1972 | } | ||
1973 | // base6 entropy is detected | ||
1974 | e = Entropy.fromString("012345012345"); | ||
1975 | if (e.base.str != "base 6") { | ||
1976 | return "base6 entropy not detected correctly"; | ||
1977 | } | ||
1978 | // dice entropy is detected | ||
1979 | e = Entropy.fromString("123456123456"); | ||
1980 | if (e.base.str != "base 6 (dice)") { | ||
1981 | return "dice entropy not detected correctly"; | ||
1982 | } | ||
1983 | // base10 entropy is detected | ||
1984 | e = Entropy.fromString("0123456789"); | ||
1985 | if (e.base.str != "base 10") { | ||
1986 | return "base10 entropy not detected correctly"; | ||
1987 | } | ||
1988 | // hex entropy is detected | ||
1989 | e = Entropy.fromString("0123456789ABCDEF"); | ||
1990 | if (e.base.str != "hexadecimal") { | ||
1991 | return "hexadecimal entropy not detected correctly"; | ||
1992 | } | ||
1993 | // entropy is case insensitive | ||
1994 | e = Entropy.fromString("aBcDeF"); | ||
1995 | if (e.cleanStr != "aBcDeF") { | ||
1996 | return "Entropy should not be case sensitive"; | ||
1997 | } | ||
1998 | // dice entropy is converted to base6 | ||
1999 | e = Entropy.fromString("123456"); | ||
2000 | if (e.cleanStr != "012345") { | ||
2001 | return "Dice entropy is not automatically converted to base6"; | ||
2002 | } | ||
2003 | // dice entropy is preferred to base6 if ambiguous | ||
2004 | e = Entropy.fromString("12345"); | ||
2005 | if (e.base.str != "base 6 (dice)") { | ||
2006 | return "dice not used as default over base 6"; | ||
2007 | } | ||
2008 | // unused characters are ignored | ||
2009 | e = Entropy.fromString("fghijkl"); | ||
2010 | if (e.cleanStr != "f") { | ||
2011 | return "additional characters are not ignored"; | ||
2012 | } | ||
2013 | // the lowest base is used by default | ||
2014 | // 7 could be decimal or hexadecimal, but should be detected as decimal | ||
2015 | e = Entropy.fromString("7"); | ||
2016 | if (e.base.str != "base 10") { | ||
2017 | return "lowest base is not used"; | ||
2018 | } | ||
2019 | // Hexadecimal representation is returned | ||
2020 | e = Entropy.fromString("1010"); | ||
2021 | if (e.hexStr != "A") { | ||
2022 | return "Hexadecimal representation not returned"; | ||
2023 | } | ||
2024 | // Leading zeros are retained | ||
2025 | e = Entropy.fromString("000A"); | ||
2026 | if (e.cleanStr != "000A") { | ||
2027 | return "Leading zeros are not retained"; | ||
2028 | } | ||
2029 | // Leading zeros are correctly preserved for hex in binary string | ||
2030 | e = Entropy.fromString("2A"); | ||
2031 | if (e.binaryStr != "00101010") { | ||
2032 | return "Hex leading zeros are not correct in binary"; | ||
2033 | } | ||
2034 | // Keyboard mashing results in weak entropy | ||
2035 | // Despite being a long string, it's less than 30 bits of entropy | ||
2036 | e = Entropy.fromString("aj;se ifj; ask,dfv js;ifj"); | ||
2037 | if (e.binaryStr.length >= 30) { | ||
2038 | return "Keyboard mashing should produce weak entropy"; | ||
2039 | } | ||
2040 | return false; | ||
2041 | }); | ||
2042 | if (error) { | ||
2043 | console.log("Entropy unit tests"); | ||
2044 | console.log(error); | ||
2045 | fail(); | ||
2046 | }; | ||
2047 | next(); | ||
2048 | }); | ||
2049 | }, | ||
2050 | |||
2051 | // Entropy can be entered by the user | ||
2052 | function() { | ||
2053 | page.open(url, function(status) { | ||
2054 | expected = { | ||
2055 | mnemonic: "abandon abandon ability", | ||
2056 | address: "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug", | ||
2057 | } | ||
2058 | // use entropy | ||
2059 | page.evaluate(function() { | ||
2060 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2061 | $(".entropy").val("00000000 00000000 00000000 00000000").trigger("input"); | ||
2062 | }); | ||
2063 | // check the mnemonic is set and address is correct | ||
2064 | waitForGenerate(function() { | ||
2065 | var actual = page.evaluate(function() { | ||
2066 | return { | ||
2067 | address: $(".address:first").text(), | ||
2068 | mnemonic: $(".phrase").val(), | ||
2069 | } | ||
2070 | }); | ||
2071 | if (actual.mnemonic != expected.mnemonic) { | ||
2072 | console.log("Entropy does not generate correct mnemonic"); | ||
2073 | console.log("Expected: " + expected.mnemonic); | ||
2074 | console.log("Got: " + actual.mnemonic); | ||
2075 | fail(); | ||
2076 | } | ||
2077 | if (actual.address != expected.address) { | ||
2078 | console.log("Entropy does not generate correct address"); | ||
2079 | console.log("Expected: " + expected.address); | ||
2080 | console.log("Got: " + actual.address); | ||
2081 | fail(); | ||
2082 | } | ||
2083 | next(); | ||
2084 | }); | ||
2085 | }); | ||
2086 | }, | ||
2087 | |||
2088 | // A warning about entropy is shown to the user, with additional information | ||
2089 | function() { | ||
2090 | page.open(url, function(status) { | ||
2091 | // get text content from entropy sections of page | ||
2092 | var hasWarning = page.evaluate(function() { | ||
2093 | var entropyText = $(".entropy-container").text(); | ||
2094 | var warning = "mnemonic may be insecure"; | ||
2095 | if (entropyText.indexOf(warning) == -1) { | ||
2096 | return false; | ||
2097 | } | ||
2098 | var readMoreText = $("#entropy-notes").parent().text(); | ||
2099 | var goodSources = "flipping a fair coin, rolling a fair dice, noise measurements etc"; | ||
2100 | if (readMoreText.indexOf(goodSources) == -1) { | ||
2101 | return false; | ||
2102 | } | ||
2103 | return true; | ||
2104 | }); | ||
2105 | // check the warnings and information are shown | ||
2106 | if (!hasWarning) { | ||
2107 | console.log("Page does not contain warning about using own entropy"); | ||
2108 | fail(); | ||
2109 | } | ||
2110 | next(); | ||
2111 | }); | ||
2112 | }, | ||
2113 | |||
2114 | // The types of entropy available are described to the user | ||
2115 | function() { | ||
2116 | page.open(url, function(status) { | ||
2117 | // get placeholder text for entropy field | ||
2118 | var placeholder = page.evaluate(function() { | ||
2119 | return $(".entropy").attr("placeholder"); | ||
2120 | }); | ||
2121 | var options = [ | ||
2122 | "binary", | ||
2123 | "base 6", | ||
2124 | "dice", | ||
2125 | "base 10", | ||
2126 | "hexadecimal", | ||
2127 | ]; | ||
2128 | for (var i=0; i<options.length; i++) { | ||
2129 | var option = options[i]; | ||
2130 | if (placeholder.indexOf(option) == -1) { | ||
2131 | console.log("Available entropy type is not shown to user: " + option); | ||
2132 | fail(); | ||
2133 | } | ||
2134 | } | ||
2135 | next(); | ||
2136 | }); | ||
2137 | }, | ||
2138 | |||
2139 | // The actual entropy used is shown to the user | ||
2140 | function() { | ||
2141 | page.open(url, function(status) { | ||
2142 | // use entropy | ||
2143 | var badEntropySource = page.evaluate(function() { | ||
2144 | var entropy = "Not A Very Good Entropy Source At All"; | ||
2145 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2146 | $(".entropy").val(entropy).trigger("input"); | ||
2147 | }); | ||
2148 | // check the actual entropy being used is shown | ||
2149 | waitForGenerate(function() { | ||
2150 | var expectedText = "AedEceAA"; | ||
2151 | var entropyText = page.evaluate(function() { | ||
2152 | return $(".entropy-container").text(); | ||
2153 | }); | ||
2154 | if (entropyText.indexOf(expectedText) == -1) { | ||
2155 | console.log("Actual entropy used is not shown"); | ||
2156 | fail(); | ||
2157 | } | ||
2158 | next(); | ||
2159 | }); | ||
2160 | }); | ||
2161 | }, | ||
2162 | |||
2163 | // Binary entropy can be entered | ||
2164 | function() { | ||
2165 | page.open(url, function(status) { | ||
2166 | // use entropy | ||
2167 | page.evaluate(function() { | ||
2168 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2169 | $(".entropy").val("01").trigger("input"); | ||
2170 | }); | ||
2171 | // check the entropy is shown to be the correct type | ||
2172 | waitForGenerate(function() { | ||
2173 | var entropyText = page.evaluate(function() { | ||
2174 | return $(".entropy-container").text(); | ||
2175 | }); | ||
2176 | if (entropyText.indexOf("binary") == -1) { | ||
2177 | console.log("Binary entropy is not detected and presented to user"); | ||
2178 | fail(); | ||
2179 | } | ||
2180 | next(); | ||
2181 | }); | ||
2182 | }); | ||
2183 | }, | ||
2184 | |||
2185 | // Base 6 entropy can be entered | ||
2186 | function() { | ||
2187 | page.open(url, function(status) { | ||
2188 | // use entropy | ||
2189 | page.evaluate(function() { | ||
2190 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2191 | $(".entropy").val("012345").trigger("input"); | ||
2192 | }); | ||
2193 | // check the entropy is shown to be the correct type | ||
2194 | waitForGenerate(function() { | ||
2195 | var entropyText = page.evaluate(function() { | ||
2196 | return $(".entropy-container").text(); | ||
2197 | }); | ||
2198 | if (entropyText.indexOf("base 6") == -1) { | ||
2199 | console.log("Base 6 entropy is not detected and presented to user"); | ||
2200 | fail(); | ||
2201 | } | ||
2202 | next(); | ||
2203 | }); | ||
2204 | }); | ||
2205 | }, | ||
2206 | |||
2207 | // Base 6 dice entropy can be entered | ||
2208 | function() { | ||
2209 | page.open(url, function(status) { | ||
2210 | // use entropy | ||
2211 | page.evaluate(function() { | ||
2212 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2213 | $(".entropy").val("123456").trigger("input"); | ||
2214 | }); | ||
2215 | // check the entropy is shown to be the correct type | ||
2216 | waitForGenerate(function() { | ||
2217 | var entropyText = page.evaluate(function() { | ||
2218 | return $(".entropy-container").text(); | ||
2219 | }); | ||
2220 | if (entropyText.indexOf("dice") == -1) { | ||
2221 | console.log("Dice entropy is not detected and presented to user"); | ||
2222 | fail(); | ||
2223 | } | ||
2224 | next(); | ||
2225 | }); | ||
2226 | }); | ||
2227 | }, | ||
2228 | |||
2229 | // Base 10 entropy can be entered | ||
2230 | function() { | ||
2231 | page.open(url, function(status) { | ||
2232 | // use entropy | ||
2233 | page.evaluate(function() { | ||
2234 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2235 | $(".entropy").val("789").trigger("input"); | ||
2236 | }); | ||
2237 | // check the entropy is shown to be the correct type | ||
2238 | waitForGenerate(function() { | ||
2239 | var entropyText = page.evaluate(function() { | ||
2240 | return $(".entropy-container").text(); | ||
2241 | }); | ||
2242 | if (entropyText.indexOf("base 10") == -1) { | ||
2243 | console.log("Base 10 entropy is not detected and presented to user"); | ||
2244 | fail(); | ||
2245 | } | ||
2246 | next(); | ||
2247 | }); | ||
2248 | }); | ||
2249 | }, | ||
2250 | |||
2251 | // Hexadecimal entropy can be entered | ||
2252 | function() { | ||
2253 | page.open(url, function(status) { | ||
2254 | // use entropy | ||
2255 | page.evaluate(function() { | ||
2256 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2257 | $(".entropy").val("abcdef").trigger("input"); | ||
2258 | }); | ||
2259 | // check the entropy is shown to be the correct type | ||
2260 | waitForGenerate(function() { | ||
2261 | var entropyText = page.evaluate(function() { | ||
2262 | return $(".entropy-container").text(); | ||
2263 | }); | ||
2264 | if (entropyText.indexOf("hexadecimal") == -1) { | ||
2265 | console.log("Hexadecimal entropy is not detected and presented to user"); | ||
2266 | fail(); | ||
2267 | } | ||
2268 | next(); | ||
2269 | }); | ||
2270 | }); | ||
2271 | }, | ||
2272 | |||
2273 | // Dice entropy value is shown as the converted base 6 value | ||
2274 | function() { | ||
2275 | page.open(url, function(status) { | ||
2276 | // use entropy | ||
2277 | page.evaluate(function() { | ||
2278 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2279 | $(".entropy").val("123456").trigger("input"); | ||
2280 | }); | ||
2281 | // check the entropy is shown as base 6, not as the original dice value | ||
2282 | waitForGenerate(function() { | ||
2283 | var entropyText = page.evaluate(function() { | ||
2284 | return $(".entropy-container").text(); | ||
2285 | }); | ||
2286 | if (entropyText.indexOf("012345") == -1) { | ||
2287 | console.log("Dice entropy is not shown to user as base 6 value"); | ||
2288 | fail(); | ||
2289 | } | ||
2290 | if (entropyText.indexOf("123456") > -1) { | ||
2291 | console.log("Dice entropy value is shown instead of true base 6 value"); | ||
2292 | fail(); | ||
2293 | } | ||
2294 | next(); | ||
2295 | }); | ||
2296 | }); | ||
2297 | }, | ||
2298 | |||
2299 | // The number of bits of entropy accumulated is shown | ||
2300 | function() { | ||
2301 | page.open(url, function(status) { | ||
2302 | var tests = { | ||
2303 | "0000 0000 0000 0000 0000": "20", | ||
2304 | "0": "1", | ||
2305 | "0000": "4", | ||
2306 | "6": "3", | ||
2307 | "7": "3", | ||
2308 | "8": "4", | ||
2309 | "F": "4", | ||
2310 | "29": "5", | ||
2311 | "0A": "8", | ||
2312 | "1A": "8", // hex is always multiple of 4 bits of entropy | ||
2313 | "2A": "8", | ||
2314 | "4A": "8", | ||
2315 | "8A": "8", | ||
2316 | "FA": "8", | ||
2317 | "000A": "16", | ||
2318 | "2220": "10", | ||
2319 | "2221": "9", // uses dice, so entropy is actually 1110 | ||
2320 | "2227": "12", | ||
2321 | "222F": "16", | ||
2322 | "FFFF": "16", | ||
2323 | } | ||
2324 | // Arrange tests in array so last one can be easily detected | ||
2325 | var entropys = []; | ||
2326 | var results = []; | ||
2327 | for (var entropy in tests) { | ||
2328 | entropys.push(entropy); | ||
2329 | results.push(tests[entropy]); | ||
2330 | } | ||
2331 | // use entropy | ||
2332 | page.evaluate(function(e) { | ||
2333 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2334 | }); | ||
2335 | // Run each test | ||
2336 | var nextTest = function runNextTest(i) { | ||
2337 | var entropy = entropys[i]; | ||
2338 | var expected = results[i]; | ||
2339 | // set entropy | ||
2340 | page.evaluate(function(e) { | ||
2341 | $(".addresses").empty(); // bit of a hack, but needed for waitForGenerate | ||
2342 | $(".entropy").val(e).trigger("input"); | ||
2343 | }, entropy); | ||
2344 | // check the number of bits of entropy is shown | ||
2345 | waitForGenerate(function() { | ||
2346 | var entropyText = page.evaluate(function() { | ||
2347 | return $(".entropy-container").text(); | ||
2348 | }); | ||
2349 | if (entropyText.indexOf("Have " + expected + " bits of entropy") == -1) { | ||
2350 | console.log("Accumulated entropy is not shown correctly for " + entropy); | ||
2351 | fail(); | ||
2352 | } | ||
2353 | var isLastTest = i == results.length - 1; | ||
2354 | if (isLastTest) { | ||
2355 | next(); | ||
2356 | } | ||
2357 | else { | ||
2358 | runNextTest(i+1); | ||
2359 | } | ||
2360 | }); | ||
2361 | } | ||
2362 | nextTest(0); | ||
2363 | }); | ||
2364 | }, | ||
2365 | |||
2366 | // The number of bits of entropy to reach the next mnemonic strength is shown | ||
2367 | function() { | ||
2368 | page.open(url, function(status) { | ||
2369 | // use entropy | ||
2370 | page.evaluate(function() { | ||
2371 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2372 | $(".entropy").val("7654321").trigger("input"); | ||
2373 | }); | ||
2374 | // check the amount of additional entropy required is shown | ||
2375 | waitForGenerate(function() { | ||
2376 | var entropyText = page.evaluate(function() { | ||
2377 | return $(".entropy-container").text(); | ||
2378 | }); | ||
2379 | if (entropyText.indexOf("3 more base 10 chars required") == -1) { | ||
2380 | console.log("Additional entropy requirement is not shown"); | ||
2381 | fail(); | ||
2382 | } | ||
2383 | next(); | ||
2384 | }); | ||
2385 | }); | ||
2386 | }, | ||
2387 | |||
2388 | // The next strength above 0-word mnemonics is considered extremely weak | ||
2389 | // The next strength above 3-word mnemonics is considered very weak | ||
2390 | // The next strength above 6-word mnemonics is considered weak | ||
2391 | // The next strength above 9-word mnemonics is considered strong | ||
2392 | // The next strength above 12-word mnemonics is considered very strong | ||
2393 | // The next strength above 15-word mnemonics is considered extremely strong | ||
2394 | function() { | ||
2395 | page.open(url, function(status) { | ||
2396 | var tests = [ | ||
2397 | { | ||
2398 | entropy: "A", | ||
2399 | words: 0, | ||
2400 | nextStrength: "an extremely weak", | ||
2401 | }, | ||
2402 | { | ||
2403 | entropy: "AAAAAAAA", | ||
2404 | words: 3, | ||
2405 | nextStrength: "a very weak", | ||
2406 | }, | ||
2407 | { | ||
2408 | entropy: "AAAAAAAA B", | ||
2409 | words: 3, | ||
2410 | nextStrength: "a very weak", | ||
2411 | }, | ||
2412 | { | ||
2413 | entropy: "AAAAAAAA BBBBBBBB", | ||
2414 | words: 6, | ||
2415 | nextStrength: "a weak", | ||
2416 | }, | ||
2417 | { | ||
2418 | entropy: "AAAAAAAA BBBBBBBB CCCCCCCC", | ||
2419 | words: 9, | ||
2420 | nextStrength: "a strong", | ||
2421 | }, | ||
2422 | { | ||
2423 | entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD", | ||
2424 | words: 12, | ||
2425 | nextStrength: "a very strong", | ||
2426 | }, | ||
2427 | { | ||
2428 | entropy: "AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD EEEEEEEE", | ||
2429 | words: 15, | ||
2430 | nextStrength: "an extremely strong", | ||
2431 | } | ||
2432 | ]; | ||
2433 | // use entropy | ||
2434 | page.evaluate(function() { | ||
2435 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2436 | }); | ||
2437 | var nextTest = function runNextTest(i) { | ||
2438 | test = tests[i]; | ||
2439 | page.evaluate(function(e) { | ||
2440 | $(".addresses").empty(); | ||
2441 | $(".entropy").val(e).trigger("input"); | ||
2442 | }, test.entropy); | ||
2443 | waitForGenerate(function() { | ||
2444 | // check the strength of the current mnemonic | ||
2445 | var mnemonic = page.evaluate(function() { | ||
2446 | return $(".phrase").val(); | ||
2447 | }); | ||
2448 | if (test.words == 0) { | ||
2449 | if (mnemonic.length > 0) { | ||
2450 | console.log("Mnemonic length for " + test.nextStrength + " strength is not " + test.words); | ||
2451 | console.log("Mnemonic: " + mnemonic); | ||
2452 | fail(); | ||
2453 | } | ||
2454 | } | ||
2455 | else { | ||
2456 | if (mnemonic.split(" ").length != test.words) { | ||
2457 | console.log("Mnemonic length for " + test.nextStrength + " strength is not " + test.words); | ||
2458 | console.log("Mnemonic: " + mnemonic); | ||
2459 | fail(); | ||
2460 | } | ||
2461 | } | ||
2462 | // check the strength of the next mnemonic is shown | ||
2463 | var entropyText = page.evaluate(function() { | ||
2464 | return $(".entropy-container").text(); | ||
2465 | }); | ||
2466 | if (entropyText.indexOf("required to generate " + test.nextStrength + " mnemonic") == -1) { | ||
2467 | console.log("Strength indicator for " + test.nextStrength + " mnemonic is incorrect"); | ||
2468 | fail(); | ||
2469 | } | ||
2470 | var isLastTest = i == tests.length - 1; | ||
2471 | if (isLastTest) { | ||
2472 | next(); | ||
2473 | } | ||
2474 | else { | ||
2475 | runNextTest(i+1); | ||
2476 | } | ||
2477 | }); | ||
2478 | } | ||
2479 | nextTest(0); | ||
2480 | }); | ||
2481 | }, | ||
2482 | |||
2483 | // Entropy is truncated from the right | ||
2484 | function() { | ||
2485 | page.open(url, function(status) { | ||
2486 | var expected = "abandon abandon ability"; | ||
2487 | // use entropy | ||
2488 | page.evaluate(function() { | ||
2489 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2490 | var entropy = "00000000 00000000 00000000 00000000"; | ||
2491 | entropy += "11111111 11111111 11111111 1111"; // Missing last byte, only first 8 bytes are used | ||
2492 | $(".entropy").val(entropy).trigger("input"); | ||
2493 | }); | ||
2494 | // check the entropy is truncated from the right | ||
2495 | waitForGenerate(function() { | ||
2496 | var actual = page.evaluate(function() { | ||
2497 | return $(".phrase").val(); | ||
2498 | }); | ||
2499 | if (actual != expected) { | ||
2500 | console.log("Entropy is not truncated from the right"); | ||
2501 | console.log("Expected: " + expected); | ||
2502 | console.log("Got: " + actual); | ||
2503 | fail(); | ||
2504 | } | ||
2505 | next(); | ||
2506 | }); | ||
2507 | }); | ||
2508 | }, | ||
2509 | |||
2510 | // Very large entropy results in very long mnemonics | ||
2511 | function() { | ||
2512 | page.open(url, function(status) { | ||
2513 | // use entropy | ||
2514 | page.evaluate(function() { | ||
2515 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2516 | var entropy = ""; | ||
2517 | // Generate a very long entropy string | ||
2518 | for (var i=0; i<33; i++) { | ||
2519 | entropy += "AAAAAAAA"; // 3 words * 33 iterations = 99 words | ||
2520 | } | ||
2521 | $(".entropy").val(entropy).trigger("input"); | ||
2522 | }); | ||
2523 | // check the mnemonic is very long | ||
2524 | waitForGenerate(function() { | ||
2525 | var wordCount = page.evaluate(function() { | ||
2526 | return $(".phrase").val().split(" ").length; | ||
2527 | }); | ||
2528 | if (wordCount != 99) { | ||
2529 | console.log("Large entropy does not generate long mnemonic"); | ||
2530 | console.log("Expected 99 words, got " + wordCount); | ||
2531 | fail(); | ||
2532 | } | ||
2533 | next(); | ||
2534 | }); | ||
2535 | }); | ||
2536 | }, | ||
2537 | |||
2538 | // Is compatible with bip32jp entropy | ||
2539 | // https://bip32jp.github.io/english/index.html | ||
2540 | // NOTES: | ||
2541 | // Is incompatible with: | ||
2542 | // base 6 with leading zeros | ||
2543 | // base 6 wth 12 words / 53 chars | ||
2544 | // base 20 | ||
2545 | function() { | ||
2546 | page.open(url, function(status) { | ||
2547 | var expected = "defy trip fatal jaguar mean rack rifle survey satisfy drift twist champion steel wife state furnace night consider glove olympic oblige donor novel left"; | ||
2548 | // use entropy | ||
2549 | page.evaluate(function() { | ||
2550 | $(".use-entropy").prop("checked", true).trigger("change"); | ||
2551 | var entropy = "123450123450123450123450123450123450123450123450123450123450123450123450123450123450123450123450123"; | ||
2552 | $(".entropy").val(entropy).trigger("input"); | ||
2553 | }); | ||
2554 | // check the mnemonic matches the expected value from bip32jp | ||
2555 | waitForGenerate(function() { | ||
2556 | var actual = page.evaluate(function() { | ||
2557 | return $(".phrase").val(); | ||
2558 | }); | ||
2559 | if (actual != expected) { | ||
2560 | console.log("Mnemonic does not match bip32jp for base 6 entropy"); | ||
2561 | console.log("Expected: " + expected); | ||
2562 | console.log("Got: " + actual); | ||
2563 | fail(); | ||
2564 | } | ||
2565 | next(); | ||
2566 | }); | ||
2567 | }); | ||
2568 | }, | ||
2569 | |||
1963 | // If you wish to add more tests, do so here... | 2570 | // If you wish to add more tests, do so here... |
1964 | 2571 | ||
1965 | // Here is a blank test template | 2572 | // Here is a blank test template |