6400 lines
No EOL
459 KiB
HTML
6400 lines
No EOL
459 KiB
HTML
<!doctype html>
|
||
<html>
|
||
<head>
|
||
<!--
|
||
This is a fork of bitaddress.org for Litecoin.
|
||
GitHub Repository: https://github.com/litecoin-project/bitaddress.org
|
||
Here's the bitaddress.org info:
|
||
|
||
Donation Address: 1NiNja1bUmhSoTXozBRBEtR8LeF9TGbZBN
|
||
|
||
Notice of Copyrights and Licenses:
|
||
***********************************
|
||
The bitaddress.org project, software and embedded resources are copyright bitaddress.org.
|
||
The bitaddress.org name and logo are not part of the open source license.
|
||
|
||
Portions of the all-in-one HTML document contain JavaScript codes that are the copyrights of others.
|
||
The individual copyrights are included throughout the document along with their licenses.
|
||
Included JavaScript libraries are separated with HTML script tags.
|
||
|
||
Summary of JavaScript functions with a redistributable license:
|
||
JavaScript function License
|
||
******************* ***************
|
||
Array.prototype.map Public Domain
|
||
window.Crypto BSD License
|
||
window.SecureRandom BSD License
|
||
window.EllipticCurve BSD License
|
||
window.BigInteger BSD License
|
||
window.QRCode MIT License
|
||
window.Bitcoin MIT License
|
||
|
||
The bitaddress.org software is available under The MIT License (MIT)
|
||
Copyright (c) 2011-2012 bitaddress.org
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||
sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject
|
||
to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||
portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
GitHub Repository: https://github.com/pointbiz/bitaddress.org
|
||
-->
|
||
|
||
<title>liteaddress.org</title>
|
||
|
||
<script type="text/javascript">
|
||
// Array.prototype.map function is in the public domain.
|
||
// Production steps of ECMA-262, Edition 5, 15.4.4.19
|
||
// Reference: http://es5.github.com/#x15.4.4.19
|
||
if (!Array.prototype.map) {
|
||
Array.prototype.map = function (callback, thisArg) {
|
||
var T, A, k;
|
||
if (this == null) {
|
||
throw new TypeError(" this is null or not defined");
|
||
}
|
||
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
|
||
var O = Object(this);
|
||
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
|
||
// 3. Let len be ToUint32(lenValue).
|
||
var len = O.length >>> 0;
|
||
// 4. If IsCallable(callback) is false, throw a TypeError exception.
|
||
// See: http://es5.github.com/#x9.11
|
||
if ({}.toString.call(callback) != "[object Function]") {
|
||
throw new TypeError(callback + " is not a function");
|
||
}
|
||
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
||
if (thisArg) {
|
||
T = thisArg;
|
||
}
|
||
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
|
||
// the standard built-in constructor with that name and len is the value of len.
|
||
A = new Array(len);
|
||
// 7. Let k be 0
|
||
k = 0;
|
||
// 8. Repeat, while k < len
|
||
while (k < len) {
|
||
var kValue, mappedValue;
|
||
// a. Let Pk be ToString(k).
|
||
// This is implicit for LHS operands of the in operator
|
||
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
|
||
// This step can be combined with c
|
||
// c. If kPresent is true, then
|
||
if (k in O) {
|
||
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
|
||
kValue = O[k];
|
||
// ii. Let mappedValue be the result of calling the Call internal method of callback
|
||
// with T as the this value and argument list containing kValue, k, and O.
|
||
mappedValue = callback.call(T, kValue, k, O);
|
||
// iii. Call the DefineOwnProperty internal method of A with arguments
|
||
// Pk, Property Descriptor {Value: mappedValue, Writable: true, Enumerable: true, Configurable: true},
|
||
// and false.
|
||
// In browsers that support Object.defineProperty, use the following:
|
||
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
|
||
// For best browser support, use the following:
|
||
A[k] = mappedValue;
|
||
}
|
||
// d. Increase k by 1.
|
||
k++;
|
||
}
|
||
// 9. return A
|
||
return A;
|
||
};
|
||
}
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
/*!
|
||
* Crypto-JS v2.0.0
|
||
* http://code.google.com/p/crypto-js/
|
||
* Copyright (c) 2009, Jeff Mott. All rights reserved.
|
||
* http://code.google.com/p/crypto-js/wiki/License
|
||
*/
|
||
(function () {
|
||
|
||
var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||
|
||
// Global Crypto object
|
||
var Crypto = window.Crypto = {};
|
||
|
||
// Crypto utilities
|
||
var util = Crypto.util = {
|
||
|
||
// Bit-wise rotate left
|
||
rotl: function (n, b) {
|
||
return (n << b) | (n >>> (32 - b));
|
||
},
|
||
|
||
// Bit-wise rotate right
|
||
rotr: function (n, b) {
|
||
return (n << (32 - b)) | (n >>> b);
|
||
},
|
||
|
||
// Swap big-endian to little-endian and vice versa
|
||
endian: function (n) {
|
||
|
||
// If number given, swap endian
|
||
if (n.constructor == Number) {
|
||
return util.rotl(n, 8) & 0x00FF00FF |
|
||
util.rotl(n, 24) & 0xFF00FF00;
|
||
}
|
||
|
||
// Else, assume array and swap all items
|
||
for (var i = 0; i < n.length; i++)
|
||
n[i] = util.endian(n[i]);
|
||
return n;
|
||
|
||
},
|
||
|
||
// Generate an array of any length of random bytes
|
||
randomBytes: function (n) {
|
||
for (var bytes = []; n > 0; n--)
|
||
bytes.push(Math.floor(Math.random() * 256));
|
||
return bytes;
|
||
},
|
||
|
||
// Convert a byte array to big-endian 32-bit words
|
||
bytesToWords: function (bytes) {
|
||
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
|
||
words[b >>> 5] |= bytes[i] << (24 - b % 32);
|
||
return words;
|
||
},
|
||
|
||
// Convert big-endian 32-bit words to a byte array
|
||
wordsToBytes: function (words) {
|
||
for (var bytes = [], b = 0; b < words.length * 32; b += 8)
|
||
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
|
||
return bytes;
|
||
},
|
||
|
||
// Convert a byte array to a hex string
|
||
bytesToHex: function (bytes) {
|
||
for (var hex = [], i = 0; i < bytes.length; i++) {
|
||
hex.push((bytes[i] >>> 4).toString(16));
|
||
hex.push((bytes[i] & 0xF).toString(16));
|
||
}
|
||
return hex.join("");
|
||
},
|
||
|
||
// Convert a hex string to a byte array
|
||
hexToBytes: function (hex) {
|
||
for (var bytes = [], c = 0; c < hex.length; c += 2)
|
||
bytes.push(parseInt(hex.substr(c, 2), 16));
|
||
return bytes;
|
||
},
|
||
|
||
// Convert a byte array to a base-64 string
|
||
bytesToBase64: function (bytes) {
|
||
|
||
// Use browser-native function if it exists
|
||
if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes));
|
||
|
||
for (var base64 = [], i = 0; i < bytes.length; i += 3) {
|
||
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
||
for (var j = 0; j < 4; j++) {
|
||
if (i * 8 + j * 6 <= bytes.length * 8)
|
||
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
|
||
else base64.push("=");
|
||
}
|
||
}
|
||
|
||
return base64.join("");
|
||
|
||
},
|
||
|
||
// Convert a base-64 string to a byte array
|
||
base64ToBytes: function (base64) {
|
||
|
||
// Use browser-native function if it exists
|
||
if (typeof atob == "function") return Binary.stringToBytes(atob(base64));
|
||
|
||
// Remove non-base-64 characters
|
||
base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
|
||
|
||
for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) {
|
||
if (imod4 == 0) continue;
|
||
bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) |
|
||
(base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
|
||
}
|
||
|
||
return bytes;
|
||
|
||
}
|
||
|
||
};
|
||
|
||
// Crypto mode namespace
|
||
Crypto.mode = {};
|
||
|
||
// Crypto character encodings
|
||
var charenc = Crypto.charenc = {};
|
||
|
||
// UTF-8 encoding
|
||
var UTF8 = charenc.UTF8 = {
|
||
|
||
// Convert a string to a byte array
|
||
stringToBytes: function (str) {
|
||
return Binary.stringToBytes(unescape(encodeURIComponent(str)));
|
||
},
|
||
|
||
// Convert a byte array to a string
|
||
bytesToString: function (bytes) {
|
||
return decodeURIComponent(escape(Binary.bytesToString(bytes)));
|
||
}
|
||
|
||
};
|
||
|
||
// Binary encoding
|
||
var Binary = charenc.Binary = {
|
||
|
||
// Convert a string to a byte array
|
||
stringToBytes: function (str) {
|
||
for (var bytes = [], i = 0; i < str.length; i++)
|
||
bytes.push(str.charCodeAt(i));
|
||
return bytes;
|
||
},
|
||
|
||
// Convert a byte array to a string
|
||
bytesToString: function (bytes) {
|
||
for (var str = [], i = 0; i < bytes.length; i++)
|
||
str.push(String.fromCharCode(bytes[i]));
|
||
return str.join("");
|
||
}
|
||
|
||
};
|
||
|
||
})();
|
||
|
||
|
||
|
||
/*!
|
||
* Crypto-JS v2.0.0
|
||
* http://code.google.com/p/crypto-js/
|
||
* Copyright (c) 2009, Jeff Mott. All rights reserved.
|
||
* http://code.google.com/p/crypto-js/wiki/License
|
||
*/
|
||
(function () {
|
||
|
||
// Shortcuts
|
||
var C = Crypto,
|
||
util = C.util,
|
||
charenc = C.charenc,
|
||
UTF8 = charenc.UTF8,
|
||
Binary = charenc.Binary;
|
||
|
||
// Constants
|
||
var K = [0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
|
||
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
|
||
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
|
||
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
|
||
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
|
||
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
|
||
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
|
||
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
|
||
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
|
||
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
|
||
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
|
||
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
|
||
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
|
||
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
|
||
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
|
||
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2];
|
||
|
||
// Public API
|
||
var SHA256 = C.SHA256 = function (message, options) {
|
||
var digestbytes = util.wordsToBytes(SHA256._sha256(message));
|
||
return options && options.asBytes ? digestbytes :
|
||
options && options.asString ? Binary.bytesToString(digestbytes) :
|
||
util.bytesToHex(digestbytes);
|
||
};
|
||
|
||
// The core
|
||
SHA256._sha256 = function (message) {
|
||
|
||
// Convert to byte array
|
||
if (message.constructor == String) message = UTF8.stringToBytes(message);
|
||
/* else, assume byte array already */
|
||
|
||
var m = util.bytesToWords(message),
|
||
l = message.length * 8,
|
||
H = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19],
|
||
w = [],
|
||
a, b, c, d, e, f, g, h, i, j,
|
||
t1, t2;
|
||
|
||
// Padding
|
||
m[l >> 5] |= 0x80 << (24 - l % 32);
|
||
m[((l + 64 >> 9) << 4) + 15] = l;
|
||
|
||
for (var i = 0; i < m.length; i += 16) {
|
||
|
||
a = H[0];
|
||
b = H[1];
|
||
c = H[2];
|
||
d = H[3];
|
||
e = H[4];
|
||
f = H[5];
|
||
g = H[6];
|
||
h = H[7];
|
||
|
||
for (var j = 0; j < 64; j++) {
|
||
|
||
if (j < 16) w[j] = m[j + i];
|
||
else {
|
||
|
||
var gamma0x = w[j - 15],
|
||
gamma1x = w[j - 2],
|
||
gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^
|
||
((gamma0x << 14) | (gamma0x >>> 18)) ^
|
||
(gamma0x >>> 3),
|
||
gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^
|
||
((gamma1x << 13) | (gamma1x >>> 19)) ^
|
||
(gamma1x >>> 10);
|
||
|
||
w[j] = gamma0 + (w[j - 7] >>> 0) +
|
||
gamma1 + (w[j - 16] >>> 0);
|
||
|
||
}
|
||
|
||
var ch = e & f ^ ~e & g,
|
||
maj = a & b ^ a & c ^ b & c,
|
||
sigma0 = ((a << 30) | (a >>> 2)) ^
|
||
((a << 19) | (a >>> 13)) ^
|
||
((a << 10) | (a >>> 22)),
|
||
sigma1 = ((e << 26) | (e >>> 6)) ^
|
||
((e << 21) | (e >>> 11)) ^
|
||
((e << 7) | (e >>> 25));
|
||
|
||
|
||
t1 = (h >>> 0) + sigma1 + ch + (K[j]) + (w[j] >>> 0);
|
||
t2 = sigma0 + maj;
|
||
|
||
h = g;
|
||
g = f;
|
||
f = e;
|
||
e = d + t1;
|
||
d = c;
|
||
c = b;
|
||
b = a;
|
||
a = t1 + t2;
|
||
|
||
}
|
||
|
||
H[0] += a;
|
||
H[1] += b;
|
||
H[2] += c;
|
||
H[3] += d;
|
||
H[4] += e;
|
||
H[5] += f;
|
||
H[6] += g;
|
||
H[7] += h;
|
||
|
||
}
|
||
|
||
return H;
|
||
|
||
};
|
||
|
||
// Package private blocksize
|
||
SHA256._blocksize = 16;
|
||
|
||
})();
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/*!
|
||
* Crypto-JS v2.0.0
|
||
* http://code.google.com/p/crypto-js/
|
||
* Copyright (c) 2009, Jeff Mott. All rights reserved.
|
||
* http://code.google.com/p/crypto-js/wiki/License
|
||
*
|
||
* A JavaScript implementation of the RIPEMD-160 Algorithm
|
||
* Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
|
||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||
* Distributed under the BSD License
|
||
* See http://pajhome.org.uk/crypt/md5 for details.
|
||
* Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
|
||
* Ported to Crypto-JS by Stefan Thomas.
|
||
*/
|
||
|
||
(function () {
|
||
// Shortcuts
|
||
var C = Crypto,
|
||
util = C.util,
|
||
charenc = C.charenc,
|
||
UTF8 = charenc.UTF8,
|
||
Binary = charenc.Binary;
|
||
|
||
// Convert a byte array to little-endian 32-bit words
|
||
util.bytesToLWords = function (bytes) {
|
||
|
||
var output = Array(bytes.length >> 2);
|
||
for (var i = 0; i < output.length; i++)
|
||
output[i] = 0;
|
||
for (var i = 0; i < bytes.length * 8; i += 8)
|
||
output[i >> 5] |= (bytes[i / 8] & 0xFF) << (i % 32);
|
||
return output;
|
||
};
|
||
|
||
// Convert little-endian 32-bit words to a byte array
|
||
util.lWordsToBytes = function (words) {
|
||
var output = [];
|
||
for (var i = 0; i < words.length * 32; i += 8)
|
||
output.push((words[i >> 5] >>> (i % 32)) & 0xff);
|
||
return output;
|
||
};
|
||
|
||
// Public API
|
||
var RIPEMD160 = C.RIPEMD160 = function (message, options) {
|
||
var digestbytes = util.lWordsToBytes(RIPEMD160._rmd160(message));
|
||
return options && options.asBytes ? digestbytes :
|
||
options && options.asString ? Binary.bytesToString(digestbytes) :
|
||
util.bytesToHex(digestbytes);
|
||
};
|
||
|
||
// The core
|
||
RIPEMD160._rmd160 = function (message) {
|
||
// Convert to byte array
|
||
if (message.constructor == String) message = UTF8.stringToBytes(message);
|
||
|
||
var x = util.bytesToLWords(message),
|
||
len = message.length * 8;
|
||
|
||
/* append padding */
|
||
x[len >> 5] |= 0x80 << (len % 32);
|
||
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
||
|
||
var h0 = 0x67452301;
|
||
var h1 = 0xefcdab89;
|
||
var h2 = 0x98badcfe;
|
||
var h3 = 0x10325476;
|
||
var h4 = 0xc3d2e1f0;
|
||
|
||
for (var i = 0; i < x.length; i += 16) {
|
||
var T;
|
||
var A1 = h0, B1 = h1, C1 = h2, D1 = h3, E1 = h4;
|
||
var A2 = h0, B2 = h1, C2 = h2, D2 = h3, E2 = h4;
|
||
for (var j = 0; j <= 79; ++j) {
|
||
T = safe_add(A1, rmd160_f(j, B1, C1, D1));
|
||
T = safe_add(T, x[i + rmd160_r1[j]]);
|
||
T = safe_add(T, rmd160_K1(j));
|
||
T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
|
||
A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;
|
||
T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
|
||
T = safe_add(T, x[i + rmd160_r2[j]]);
|
||
T = safe_add(T, rmd160_K2(j));
|
||
T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
|
||
A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;
|
||
}
|
||
T = safe_add(h1, safe_add(C1, D2));
|
||
h1 = safe_add(h2, safe_add(D1, E2));
|
||
h2 = safe_add(h3, safe_add(E1, A2));
|
||
h3 = safe_add(h4, safe_add(A1, B2));
|
||
h4 = safe_add(h0, safe_add(B1, C2));
|
||
h0 = T;
|
||
}
|
||
return [h0, h1, h2, h3, h4];
|
||
}
|
||
|
||
function rmd160_f(j, x, y, z) {
|
||
return (0 <= j && j <= 15) ? (x ^ y ^ z) :
|
||
(16 <= j && j <= 31) ? (x & y) | (~x & z) :
|
||
(32 <= j && j <= 47) ? (x | ~y) ^ z :
|
||
(48 <= j && j <= 63) ? (x & z) | (y & ~z) :
|
||
(64 <= j && j <= 79) ? x ^ (y | ~z) :
|
||
"rmd160_f: j out of range";
|
||
}
|
||
function rmd160_K1(j) {
|
||
return (0 <= j && j <= 15) ? 0x00000000 :
|
||
(16 <= j && j <= 31) ? 0x5a827999 :
|
||
(32 <= j && j <= 47) ? 0x6ed9eba1 :
|
||
(48 <= j && j <= 63) ? 0x8f1bbcdc :
|
||
(64 <= j && j <= 79) ? 0xa953fd4e :
|
||
"rmd160_K1: j out of range";
|
||
}
|
||
function rmd160_K2(j) {
|
||
return (0 <= j && j <= 15) ? 0x50a28be6 :
|
||
(16 <= j && j <= 31) ? 0x5c4dd124 :
|
||
(32 <= j && j <= 47) ? 0x6d703ef3 :
|
||
(48 <= j && j <= 63) ? 0x7a6d76e9 :
|
||
(64 <= j && j <= 79) ? 0x00000000 :
|
||
"rmd160_K2: j out of range";
|
||
}
|
||
var rmd160_r1 = [
|
||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
||
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
|
||
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
|
||
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
|
||
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
|
||
];
|
||
var rmd160_r2 = [
|
||
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
|
||
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
|
||
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
|
||
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
|
||
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
|
||
];
|
||
var rmd160_s1 = [
|
||
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
|
||
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
|
||
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
|
||
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
|
||
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
|
||
];
|
||
var rmd160_s2 = [
|
||
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
|
||
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
|
||
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
|
||
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
|
||
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
|
||
];
|
||
|
||
/*
|
||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||
* to work around bugs in some JS interpreters.
|
||
*/
|
||
function safe_add(x, y) {
|
||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||
return (msw << 16) | (lsw & 0xFFFF);
|
||
}
|
||
|
||
/*
|
||
* Bitwise rotate a 32-bit number to the left.
|
||
*/
|
||
function bit_rol(num, cnt) {
|
||
return (num << cnt) | (num >>> (32 - cnt));
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
/*!
|
||
* Random number generator with ArcFour PRNG
|
||
*
|
||
* NOTE: For best results, put code like
|
||
* <body onclick='SecureRandom.seedTime();' onkeypress='SecureRandom.seedTime();'>
|
||
* in your main HTML document.
|
||
*
|
||
* Copyright Tom Wu, bitaddress.org BSD License.
|
||
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
|
||
*/
|
||
(function () {
|
||
|
||
// Constructor function of Global SecureRandom object
|
||
var sr = window.SecureRandom = function () { };
|
||
|
||
// Properties
|
||
sr.state;
|
||
sr.pool;
|
||
sr.pptr;
|
||
|
||
// Pool size must be a multiple of 4 and greater than 32.
|
||
// An array of bytes the size of the pool will be passed to init()
|
||
sr.poolSize = 256;
|
||
|
||
|
||
// --- object methods ---
|
||
|
||
// public method
|
||
// ba: byte array
|
||
sr.prototype.nextBytes = function (ba) {
|
||
var i;
|
||
for (i = 0; i < ba.length; ++i) ba[i] = sr.getByte();
|
||
};
|
||
|
||
|
||
// --- static methods ---
|
||
|
||
// Mix in the current time (w/milliseconds) into the pool
|
||
// NOTE: this method should be called from body click/keypress event handlers to increase entropy
|
||
sr.seedTime = function () {
|
||
sr.seedInt(new Date().getTime());
|
||
}
|
||
|
||
sr.getByte = function () {
|
||
if (sr.state == null) {
|
||
sr.seedTime();
|
||
sr.state = sr.ArcFour(); // Plug in your RNG constructor here
|
||
sr.state.init(sr.pool);
|
||
for (sr.pptr = 0; sr.pptr < sr.pool.length; ++sr.pptr)
|
||
sr.pool[sr.pptr] = 0;
|
||
sr.pptr = 0;
|
||
}
|
||
// TODO: allow reseeding after first request
|
||
return sr.state.next();
|
||
}
|
||
|
||
// Mix in a 32-bit integer into the pool
|
||
sr.seedInt = function (x) {
|
||
sr.pool[sr.pptr++] ^= x & 255;
|
||
sr.pool[sr.pptr++] ^= (x >> 8) & 255;
|
||
sr.pool[sr.pptr++] ^= (x >> 16) & 255;
|
||
sr.pool[sr.pptr++] ^= (x >> 24) & 255;
|
||
if (sr.pptr >= sr.poolSize) sr.pptr -= sr.poolSize;
|
||
}
|
||
|
||
|
||
// Arcfour is a PRNG
|
||
sr.ArcFour = function () {
|
||
function Arcfour() {
|
||
this.i = 0;
|
||
this.j = 0;
|
||
this.S = new Array();
|
||
}
|
||
|
||
// Initialize arcfour context from key, an array of ints, each from [0..255]
|
||
function ARC4init(key) {
|
||
var i, j, t;
|
||
for (i = 0; i < 256; ++i)
|
||
this.S[i] = i;
|
||
j = 0;
|
||
for (i = 0; i < 256; ++i) {
|
||
j = (j + this.S[i] + key[i % key.length]) & 255;
|
||
t = this.S[i];
|
||
this.S[i] = this.S[j];
|
||
this.S[j] = t;
|
||
}
|
||
this.i = 0;
|
||
this.j = 0;
|
||
}
|
||
|
||
function ARC4next() {
|
||
var t;
|
||
this.i = (this.i + 1) & 255;
|
||
this.j = (this.j + this.S[this.i]) & 255;
|
||
t = this.S[this.i];
|
||
this.S[this.i] = this.S[this.j];
|
||
this.S[this.j] = t;
|
||
return this.S[(t + this.S[this.i]) & 255];
|
||
}
|
||
|
||
Arcfour.prototype.init = ARC4init;
|
||
Arcfour.prototype.next = ARC4next;
|
||
|
||
return new Arcfour();
|
||
};
|
||
|
||
|
||
// Initialize the pool with junk if needed.
|
||
if (sr.pool == null) {
|
||
sr.pool = new Array();
|
||
sr.pptr = 0;
|
||
var t;
|
||
if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
|
||
// Extract entropy (256 bits) from NS4 RNG if available
|
||
var z = window.crypto.random(32);
|
||
for (t = 0; t < z.length; ++t)
|
||
sr.pool[sr.pptr++] = z.charCodeAt(t) & 255;
|
||
}
|
||
while (sr.pptr < sr.poolSize) { // extract some randomness from Math.random()
|
||
t = Math.floor(65536 * Math.random());
|
||
sr.pool[sr.pptr++] = t >>> 8;
|
||
sr.pool[sr.pptr++] = t & 255;
|
||
}
|
||
sr.pptr = 0;
|
||
sr.seedTime();
|
||
// entropy
|
||
sr.seedInt(window.screenX);
|
||
sr.seedInt(window.screenY);
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/faa10f0f6a1fff0b9a99fffb9bc30cee33b17212/src/ecdsa.js
|
||
/*!
|
||
* Basic Javascript Elliptic Curve implementation
|
||
* Ported loosely from BouncyCastle's Java EC code
|
||
* Only Fp curves implemented for now
|
||
*
|
||
* Copyright Tom Wu, bitaddress.org BSD License.
|
||
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
|
||
*/
|
||
(function () {
|
||
|
||
// Constructor function of Global EllipticCurve object
|
||
var ec = window.EllipticCurve = function () { };
|
||
|
||
|
||
// ----------------
|
||
// ECFieldElementFp constructor
|
||
// q instanceof BigInteger
|
||
// x instanceof BigInteger
|
||
ec.FieldElementFp = function (q, x) {
|
||
this.x = x;
|
||
// TODO if(x.compareTo(q) >= 0) error
|
||
this.q = q;
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.equals = function (other) {
|
||
if (other == this) return true;
|
||
return (this.q.equals(other.q) && this.x.equals(other.x));
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.toBigInteger = function () {
|
||
return this.x;
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.negate = function () {
|
||
return new ec.FieldElementFp(this.q, this.x.negate().mod(this.q));
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.add = function (b) {
|
||
return new ec.FieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q));
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.subtract = function (b) {
|
||
return new ec.FieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q));
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.multiply = function (b) {
|
||
return new ec.FieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q));
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.square = function () {
|
||
return new ec.FieldElementFp(this.q, this.x.square().mod(this.q));
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.divide = function (b) {
|
||
return new ec.FieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q));
|
||
};
|
||
|
||
ec.FieldElementFp.prototype.getByteLength = function () {
|
||
return Math.floor((this.toBigInteger().bitLength() + 7) / 8);
|
||
};
|
||
|
||
// D.1.4 91
|
||
/**
|
||
* return a sqrt root - the routine verifies that the calculation
|
||
* returns the right value - if none exists it returns null.
|
||
*
|
||
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
||
* Ported to JavaScript by bitaddress.org
|
||
*/
|
||
ec.FieldElementFp.prototype.sqrt = function () {
|
||
if (!this.q.testBit(0)) throw new Error("even value of q");
|
||
|
||
// p mod 4 == 3
|
||
if (this.q.testBit(1)) {
|
||
// z = g^(u+1) + p, p = 4u + 3
|
||
var z = new ec.FieldElementFp(this.q, this.x.modPow(this.q.shiftRight(2).add(BigInteger.ONE), this.q));
|
||
return z.square().equals(this) ? z : null;
|
||
}
|
||
|
||
// p mod 4 == 1
|
||
var qMinusOne = this.q.subtract(BigInteger.ONE);
|
||
var legendreExponent = qMinusOne.shiftRight(1);
|
||
if (!(this.x.modPow(legendreExponent, this.q).equals(BigInteger.ONE))) return null;
|
||
var u = qMinusOne.shiftRight(2);
|
||
var k = u.shiftLeft(1).add(BigInteger.ONE);
|
||
var Q = this.x;
|
||
var fourQ = Q.shiftLeft(2).mod(this.q);
|
||
var U, V;
|
||
|
||
do {
|
||
var rand = new SecureRandom();
|
||
var P;
|
||
do {
|
||
P = new BigInteger(this.q.bitLength(), rand);
|
||
}
|
||
while (P.compareTo(this.q) >= 0 || !(P.multiply(P).subtract(fourQ).modPow(legendreExponent, this.q).equals(qMinusOne)));
|
||
|
||
var result = ec.FieldElementFp.fastLucasSequence(this.q, P, Q, k);
|
||
|
||
U = result[0];
|
||
V = result[1];
|
||
if (V.multiply(V).mod(this.q).equals(fourQ)) {
|
||
// Integer division by 2, mod q
|
||
if (V.testBit(0)) {
|
||
V = V.add(this.q);
|
||
}
|
||
V = V.shiftRight(1);
|
||
return new ec.FieldElementFp(this.q, V);
|
||
}
|
||
}
|
||
while (U.equals(BigInteger.ONE) || U.equals(qMinusOne));
|
||
|
||
return null;
|
||
};
|
||
|
||
/*
|
||
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
||
* Ported to JavaScript by bitaddress.org
|
||
*/
|
||
ec.FieldElementFp.fastLucasSequence = function (p, P, Q, k) {
|
||
// TODO Research and apply "common-multiplicand multiplication here"
|
||
|
||
var n = k.bitLength();
|
||
var s = k.getLowestSetBit();
|
||
var Uh = BigInteger.ONE;
|
||
var Vl = BigInteger.TWO;
|
||
var Vh = P;
|
||
var Ql = BigInteger.ONE;
|
||
var Qh = BigInteger.ONE;
|
||
|
||
for (var j = n - 1; j >= s + 1; --j) {
|
||
Ql = Ql.multiply(Qh).mod(p);
|
||
if (k.testBit(j)) {
|
||
Qh = Ql.multiply(Q).mod(p);
|
||
Uh = Uh.multiply(Vh).mod(p);
|
||
Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
|
||
Vh = Vh.multiply(Vh).subtract(Qh.shiftLeft(1)).mod(p);
|
||
}
|
||
else {
|
||
Qh = Ql;
|
||
Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
|
||
Vh = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
|
||
Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
|
||
}
|
||
}
|
||
|
||
Ql = Ql.multiply(Qh).mod(p);
|
||
Qh = Ql.multiply(Q).mod(p);
|
||
Uh = Uh.multiply(Vl).subtract(Ql).mod(p);
|
||
Vl = Vh.multiply(Vl).subtract(P.multiply(Ql)).mod(p);
|
||
Ql = Ql.multiply(Qh).mod(p);
|
||
|
||
for (var j = 1; j <= s; ++j) {
|
||
Uh = Uh.multiply(Vl).mod(p);
|
||
Vl = Vl.multiply(Vl).subtract(Ql.shiftLeft(1)).mod(p);
|
||
Ql = Ql.multiply(Ql).mod(p);
|
||
}
|
||
|
||
return [Uh, Vl];
|
||
};
|
||
|
||
// ----------------
|
||
// ECPointFp constructor
|
||
ec.PointFp = function (curve, x, y, z, compressed) {
|
||
this.curve = curve;
|
||
this.x = x;
|
||
this.y = y;
|
||
// Projective coordinates: either zinv == null or z * zinv == 1
|
||
// z and zinv are just BigIntegers, not fieldElements
|
||
if (z == null) {
|
||
this.z = BigInteger.ONE;
|
||
}
|
||
else {
|
||
this.z = z;
|
||
}
|
||
this.zinv = null;
|
||
// compression flag
|
||
this.compressed = !!compressed;
|
||
};
|
||
|
||
ec.PointFp.prototype.getX = function () {
|
||
if (this.zinv == null) {
|
||
this.zinv = this.z.modInverse(this.curve.q);
|
||
}
|
||
return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q));
|
||
};
|
||
|
||
ec.PointFp.prototype.getY = function () {
|
||
if (this.zinv == null) {
|
||
this.zinv = this.z.modInverse(this.curve.q);
|
||
}
|
||
return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q));
|
||
};
|
||
|
||
ec.PointFp.prototype.equals = function (other) {
|
||
if (other == this) return true;
|
||
if (this.isInfinity()) return other.isInfinity();
|
||
if (other.isInfinity()) return this.isInfinity();
|
||
var u, v;
|
||
// u = Y2 * Z1 - Y1 * Z2
|
||
u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q);
|
||
if (!u.equals(BigInteger.ZERO)) return false;
|
||
// v = X2 * Z1 - X1 * Z2
|
||
v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q);
|
||
return v.equals(BigInteger.ZERO);
|
||
};
|
||
|
||
ec.PointFp.prototype.isInfinity = function () {
|
||
if ((this.x == null) && (this.y == null)) return true;
|
||
return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO);
|
||
};
|
||
|
||
ec.PointFp.prototype.negate = function () {
|
||
return new ec.PointFp(this.curve, this.x, this.y.negate(), this.z);
|
||
};
|
||
|
||
ec.PointFp.prototype.add = function (b) {
|
||
if (this.isInfinity()) return b;
|
||
if (b.isInfinity()) return this;
|
||
|
||
// u = Y2 * Z1 - Y1 * Z2
|
||
var u = b.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(b.z)).mod(this.curve.q);
|
||
// v = X2 * Z1 - X1 * Z2
|
||
var v = b.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(b.z)).mod(this.curve.q);
|
||
|
||
|
||
if (BigInteger.ZERO.equals(v)) {
|
||
if (BigInteger.ZERO.equals(u)) {
|
||
return this.twice(); // this == b, so double
|
||
}
|
||
return this.curve.getInfinity(); // this = -b, so infinity
|
||
}
|
||
|
||
var THREE = new BigInteger("3");
|
||
var x1 = this.x.toBigInteger();
|
||
var y1 = this.y.toBigInteger();
|
||
var x2 = b.x.toBigInteger();
|
||
var y2 = b.y.toBigInteger();
|
||
|
||
var v2 = v.square();
|
||
var v3 = v2.multiply(v);
|
||
var x1v2 = x1.multiply(v2);
|
||
var zu2 = u.square().multiply(this.z);
|
||
|
||
// x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3)
|
||
var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.q);
|
||
// y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3
|
||
var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.q);
|
||
// z3 = v^3 * z1 * z2
|
||
var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.q);
|
||
|
||
return new ec.PointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
|
||
};
|
||
|
||
ec.PointFp.prototype.twice = function () {
|
||
if (this.isInfinity()) return this;
|
||
if (this.y.toBigInteger().signum() == 0) return this.curve.getInfinity();
|
||
|
||
// TODO: optimized handling of constants
|
||
var THREE = new BigInteger("3");
|
||
var x1 = this.x.toBigInteger();
|
||
var y1 = this.y.toBigInteger();
|
||
|
||
var y1z1 = y1.multiply(this.z);
|
||
var y1sqz1 = y1z1.multiply(y1).mod(this.curve.q);
|
||
var a = this.curve.a.toBigInteger();
|
||
|
||
// w = 3 * x1^2 + a * z1^2
|
||
var w = x1.square().multiply(THREE);
|
||
if (!BigInteger.ZERO.equals(a)) {
|
||
w = w.add(this.z.square().multiply(a));
|
||
}
|
||
w = w.mod(this.curve.q);
|
||
// x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1)
|
||
var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.q);
|
||
// y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3
|
||
var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.square().multiply(w)).mod(this.curve.q);
|
||
// z3 = 8 * (y1 * z1)^3
|
||
var z3 = y1z1.square().multiply(y1z1).shiftLeft(3).mod(this.curve.q);
|
||
|
||
return new ec.PointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3);
|
||
};
|
||
|
||
// Simple NAF (Non-Adjacent Form) multiplication algorithm
|
||
// TODO: modularize the multiplication algorithm
|
||
ec.PointFp.prototype.multiply = function (k) {
|
||
if (this.isInfinity()) return this;
|
||
if (k.signum() == 0) return this.curve.getInfinity();
|
||
|
||
var e = k;
|
||
var h = e.multiply(new BigInteger("3"));
|
||
|
||
var neg = this.negate();
|
||
var R = this;
|
||
|
||
var i;
|
||
for (i = h.bitLength() - 2; i > 0; --i) {
|
||
R = R.twice();
|
||
|
||
var hBit = h.testBit(i);
|
||
var eBit = e.testBit(i);
|
||
|
||
if (hBit != eBit) {
|
||
R = R.add(hBit ? this : neg);
|
||
}
|
||
}
|
||
|
||
return R;
|
||
};
|
||
|
||
// Compute this*j + x*k (simultaneous multiplication)
|
||
ec.PointFp.prototype.multiplyTwo = function (j, x, k) {
|
||
var i;
|
||
if (j.bitLength() > k.bitLength())
|
||
i = j.bitLength() - 1;
|
||
else
|
||
i = k.bitLength() - 1;
|
||
|
||
var R = this.curve.getInfinity();
|
||
var both = this.add(x);
|
||
while (i >= 0) {
|
||
R = R.twice();
|
||
if (j.testBit(i)) {
|
||
if (k.testBit(i)) {
|
||
R = R.add(both);
|
||
}
|
||
else {
|
||
R = R.add(this);
|
||
}
|
||
}
|
||
else {
|
||
if (k.testBit(i)) {
|
||
R = R.add(x);
|
||
}
|
||
}
|
||
--i;
|
||
}
|
||
|
||
return R;
|
||
};
|
||
|
||
// patched by bitaddress.org and Casascius for use with Bitcoin.ECKey
|
||
// patched by coretechs to support compressed public keys
|
||
ec.PointFp.prototype.getEncoded = function (compressed) {
|
||
var x = this.getX().toBigInteger();
|
||
var y = this.getY().toBigInteger();
|
||
var len = 32; // integerToBytes will zero pad if integer is less than 32 bytes. 32 bytes length is required by the Bitcoin protocol.
|
||
var enc = ec.integerToBytes(x, len);
|
||
|
||
// when compressed prepend byte depending if y point is even or odd
|
||
if (compressed) {
|
||
if (y.isEven()) {
|
||
enc.unshift(0x02);
|
||
}
|
||
else {
|
||
enc.unshift(0x03);
|
||
}
|
||
}
|
||
else {
|
||
enc.unshift(0x04);
|
||
enc = enc.concat(ec.integerToBytes(y, len)); // uncompressed public key appends the bytes of the y point
|
||
}
|
||
return enc;
|
||
};
|
||
|
||
ec.PointFp.decodeFrom = function (curve, enc) {
|
||
var type = enc[0];
|
||
var dataLen = enc.length - 1;
|
||
|
||
// Extract x and y as byte arrays
|
||
var xBa = enc.slice(1, 1 + dataLen / 2);
|
||
var yBa = enc.slice(1 + dataLen / 2, 1 + dataLen);
|
||
|
||
// Prepend zero byte to prevent interpretation as negative integer
|
||
xBa.unshift(0);
|
||
yBa.unshift(0);
|
||
|
||
// Convert to BigIntegers
|
||
var x = new BigInteger(xBa);
|
||
var y = new BigInteger(yBa);
|
||
|
||
// Return point
|
||
return new ec.PointFp(curve, curve.fromBigInteger(x), curve.fromBigInteger(y));
|
||
};
|
||
|
||
ec.PointFp.prototype.add2D = function (b) {
|
||
if (this.isInfinity()) return b;
|
||
if (b.isInfinity()) return this;
|
||
|
||
if (this.x.equals(b.x)) {
|
||
if (this.y.equals(b.y)) {
|
||
// this = b, i.e. this must be doubled
|
||
return this.twice();
|
||
}
|
||
// this = -b, i.e. the result is the point at infinity
|
||
return this.curve.getInfinity();
|
||
}
|
||
|
||
var x_x = b.x.subtract(this.x);
|
||
var y_y = b.y.subtract(this.y);
|
||
var gamma = y_y.divide(x_x);
|
||
|
||
var x3 = gamma.square().subtract(this.x).subtract(b.x);
|
||
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
|
||
|
||
return new ec.PointFp(this.curve, x3, y3);
|
||
};
|
||
|
||
ec.PointFp.prototype.twice2D = function () {
|
||
if (this.isInfinity()) return this;
|
||
if (this.y.toBigInteger().signum() == 0) {
|
||
// if y1 == 0, then (x1, y1) == (x1, -y1)
|
||
// and hence this = -this and thus 2(x1, y1) == infinity
|
||
return this.curve.getInfinity();
|
||
}
|
||
|
||
var TWO = this.curve.fromBigInteger(BigInteger.valueOf(2));
|
||
var THREE = this.curve.fromBigInteger(BigInteger.valueOf(3));
|
||
var gamma = this.x.square().multiply(THREE).add(this.curve.a).divide(this.y.multiply(TWO));
|
||
|
||
var x3 = gamma.square().subtract(this.x.multiply(TWO));
|
||
var y3 = gamma.multiply(this.x.subtract(x3)).subtract(this.y);
|
||
|
||
return new ec.PointFp(this.curve, x3, y3);
|
||
};
|
||
|
||
ec.PointFp.prototype.multiply2D = function (k) {
|
||
if (this.isInfinity()) return this;
|
||
if (k.signum() == 0) return this.curve.getInfinity();
|
||
|
||
var e = k;
|
||
var h = e.multiply(new BigInteger("3"));
|
||
|
||
var neg = this.negate();
|
||
var R = this;
|
||
|
||
var i;
|
||
for (i = h.bitLength() - 2; i > 0; --i) {
|
||
R = R.twice();
|
||
|
||
var hBit = h.testBit(i);
|
||
var eBit = e.testBit(i);
|
||
|
||
if (hBit != eBit) {
|
||
R = R.add2D(hBit ? this : neg);
|
||
}
|
||
}
|
||
|
||
return R;
|
||
};
|
||
|
||
ec.PointFp.prototype.isOnCurve = function () {
|
||
var x = this.getX().toBigInteger();
|
||
var y = this.getY().toBigInteger();
|
||
var a = this.curve.getA().toBigInteger();
|
||
var b = this.curve.getB().toBigInteger();
|
||
var n = this.curve.getQ();
|
||
var lhs = y.multiply(y).mod(n);
|
||
var rhs = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(n);
|
||
return lhs.equals(rhs);
|
||
};
|
||
|
||
ec.PointFp.prototype.toString = function () {
|
||
return '(' + this.getX().toBigInteger().toString() + ',' + this.getY().toBigInteger().toString() + ')';
|
||
};
|
||
|
||
/**
|
||
* Validate an elliptic curve point.
|
||
*
|
||
* See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive
|
||
*/
|
||
ec.PointFp.prototype.validate = function () {
|
||
var n = this.curve.getQ();
|
||
|
||
// Check Q != O
|
||
if (this.isInfinity()) {
|
||
throw new Error("Point is at infinity.");
|
||
}
|
||
|
||
// Check coordinate bounds
|
||
var x = this.getX().toBigInteger();
|
||
var y = this.getY().toBigInteger();
|
||
if (x.compareTo(BigInteger.ONE) < 0 || x.compareTo(n.subtract(BigInteger.ONE)) > 0) {
|
||
throw new Error('x coordinate out of bounds');
|
||
}
|
||
if (y.compareTo(BigInteger.ONE) < 0 || y.compareTo(n.subtract(BigInteger.ONE)) > 0) {
|
||
throw new Error('y coordinate out of bounds');
|
||
}
|
||
|
||
// Check y^2 = x^3 + ax + b (mod n)
|
||
if (!this.isOnCurve()) {
|
||
throw new Error("Point is not on the curve.");
|
||
}
|
||
|
||
// Check nQ = 0 (Q is a scalar multiple of G)
|
||
if (this.multiply(n).isInfinity()) {
|
||
// TODO: This check doesn't work - fix.
|
||
throw new Error("Point is not a scalar multiple of G.");
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
|
||
|
||
|
||
// ----------------
|
||
// ECCurveFp constructor
|
||
ec.CurveFp = function (q, a, b) {
|
||
this.q = q;
|
||
this.a = this.fromBigInteger(a);
|
||
this.b = this.fromBigInteger(b);
|
||
this.infinity = new ec.PointFp(this, null, null);
|
||
}
|
||
|
||
ec.CurveFp.prototype.getQ = function () {
|
||
return this.q;
|
||
};
|
||
|
||
ec.CurveFp.prototype.getA = function () {
|
||
return this.a;
|
||
};
|
||
|
||
ec.CurveFp.prototype.getB = function () {
|
||
return this.b;
|
||
};
|
||
|
||
ec.CurveFp.prototype.equals = function (other) {
|
||
if (other == this) return true;
|
||
return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b));
|
||
};
|
||
|
||
ec.CurveFp.prototype.getInfinity = function () {
|
||
return this.infinity;
|
||
};
|
||
|
||
ec.CurveFp.prototype.fromBigInteger = function (x) {
|
||
return new ec.FieldElementFp(this.q, x);
|
||
};
|
||
|
||
// for now, work with hex strings because they're easier in JS
|
||
// compressed support added by bitaddress.org
|
||
ec.CurveFp.prototype.decodePointHex = function (s) {
|
||
var firstByte = parseInt(s.substr(0, 2), 16);
|
||
switch (firstByte) { // first byte
|
||
case 0:
|
||
return this.infinity;
|
||
case 2: // compressed
|
||
case 3: // compressed
|
||
var yTilde = firstByte & 1;
|
||
var xHex = s.substr(2, s.length - 2);
|
||
var X1 = new BigInteger(xHex, 16);
|
||
return this.decompressPoint(yTilde, X1);
|
||
case 4: // uncompressed
|
||
case 6: // hybrid
|
||
case 7: // hybrid
|
||
var len = (s.length - 2) / 2;
|
||
var xHex = s.substr(2, len);
|
||
var yHex = s.substr(len + 2, len);
|
||
|
||
return new ec.PointFp(this,
|
||
this.fromBigInteger(new BigInteger(xHex, 16)),
|
||
this.fromBigInteger(new BigInteger(yHex, 16)));
|
||
|
||
default: // unsupported
|
||
return null;
|
||
}
|
||
};
|
||
|
||
/*
|
||
* Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
|
||
* Ported to JavaScript by bitaddress.org
|
||
*
|
||
* Number yTilde
|
||
* BigInteger X1
|
||
*/
|
||
ec.CurveFp.prototype.decompressPoint = function (yTilde, X1) {
|
||
var x = this.fromBigInteger(X1);
|
||
var alpha = x.multiply(x.square().add(this.getA())).add(this.getB());
|
||
var beta = alpha.sqrt();
|
||
// if we can't find a sqrt we haven't got a point on the curve - run!
|
||
if (beta == null) throw new Error("Invalid point compression");
|
||
var betaValue = beta.toBigInteger();
|
||
var bit0 = betaValue.testBit(0) ? 1 : 0;
|
||
if (bit0 != yTilde) {
|
||
// Use the other root
|
||
beta = this.fromBigInteger(this.getQ().subtract(betaValue));
|
||
}
|
||
return new ec.PointFp(this, x, beta, null, true);
|
||
};
|
||
|
||
|
||
ec.fromHex = function (s) { return new BigInteger(s, 16); };
|
||
|
||
ec.integerToBytes = function (i, len) {
|
||
var bytes = i.toByteArrayUnsigned();
|
||
if (len < bytes.length) {
|
||
bytes = bytes.slice(bytes.length - len);
|
||
} else while (len > bytes.length) {
|
||
bytes.unshift(0);
|
||
}
|
||
return bytes;
|
||
};
|
||
|
||
|
||
// Named EC curves
|
||
// ----------------
|
||
// X9ECParameters constructor
|
||
ec.X9Parameters = function (curve, g, n, h) {
|
||
this.curve = curve;
|
||
this.g = g;
|
||
this.n = n;
|
||
this.h = h;
|
||
}
|
||
ec.X9Parameters.prototype.getCurve = function () { return this.curve; };
|
||
ec.X9Parameters.prototype.getG = function () { return this.g; };
|
||
ec.X9Parameters.prototype.getN = function () { return this.n; };
|
||
ec.X9Parameters.prototype.getH = function () { return this.h; };
|
||
|
||
// secp256k1 is the Curve used by Bitcoin
|
||
ec.secNamedCurves = {
|
||
// used by Bitcoin
|
||
"secp256k1": function () {
|
||
// p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
|
||
var p = ec.fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
|
||
var a = BigInteger.ZERO;
|
||
var b = ec.fromHex("7");
|
||
var n = ec.fromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
|
||
var h = BigInteger.ONE;
|
||
var curve = new ec.CurveFp(p, a, b);
|
||
var G = curve.decodePointHex("04"
|
||
+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
|
||
+ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8");
|
||
return new ec.X9Parameters(curve, G, n, h);
|
||
}
|
||
};
|
||
|
||
// secp256k1 called by Bitcoin's ECKEY
|
||
ec.getSECCurveByName = function (name) {
|
||
if (ec.secNamedCurves[name] == undefined) return null;
|
||
return ec.secNamedCurves[name]();
|
||
}
|
||
})();
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
/*!
|
||
* Basic JavaScript BN library - subset useful for RSA encryption. v1.3
|
||
*
|
||
* Copyright (c) 2005 Tom Wu
|
||
* All Rights Reserved.
|
||
* BSD License
|
||
* http://www-cs-students.stanford.edu/~tjw/jsbn/LICENSE
|
||
*
|
||
* Copyright Stephan Thomas
|
||
* Copyright bitaddress.org
|
||
*/
|
||
|
||
(function () {
|
||
|
||
// (public) Constructor function of Global BigInteger object
|
||
var BigInteger = window.BigInteger = function BigInteger(a, b, c) {
|
||
if (a != null)
|
||
if ("number" == typeof a) this.fromNumber(a, b, c);
|
||
else if (b == null && "string" != typeof a) this.fromString(a, 256);
|
||
else this.fromString(a, b);
|
||
};
|
||
|
||
// Bits per digit
|
||
var dbits;
|
||
|
||
// JavaScript engine analysis
|
||
var canary = 0xdeadbeefcafe;
|
||
var j_lm = ((canary & 0xffffff) == 0xefcafe);
|
||
|
||
// return new, unset BigInteger
|
||
function nbi() { return new BigInteger(null); }
|
||
|
||
// am: Compute w_j += (x*this_i), propagate carries,
|
||
// c is initial carry, returns final carry.
|
||
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
|
||
// We need to select the fastest one that works in this environment.
|
||
|
||
// am1: use a single mult and divide to get the high bits,
|
||
// max digit bits should be 26 because
|
||
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
|
||
function am1(i, x, w, j, c, n) {
|
||
while (--n >= 0) {
|
||
var v = x * this[i++] + w[j] + c;
|
||
c = Math.floor(v / 0x4000000);
|
||
w[j++] = v & 0x3ffffff;
|
||
}
|
||
return c;
|
||
}
|
||
// am2 avoids a big mult-and-extract completely.
|
||
// Max digit bits should be <= 30 because we do bitwise ops
|
||
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
|
||
function am2(i, x, w, j, c, n) {
|
||
var xl = x & 0x7fff, xh = x >> 15;
|
||
while (--n >= 0) {
|
||
var l = this[i] & 0x7fff;
|
||
var h = this[i++] >> 15;
|
||
var m = xh * l + h * xl;
|
||
l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff);
|
||
c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30);
|
||
w[j++] = l & 0x3fffffff;
|
||
}
|
||
return c;
|
||
}
|
||
// Alternately, set max digit bits to 28 since some
|
||
// browsers slow down when dealing with 32-bit numbers.
|
||
function am3(i, x, w, j, c, n) {
|
||
var xl = x & 0x3fff, xh = x >> 14;
|
||
while (--n >= 0) {
|
||
var l = this[i] & 0x3fff;
|
||
var h = this[i++] >> 14;
|
||
var m = xh * l + h * xl;
|
||
l = xl * l + ((m & 0x3fff) << 14) + w[j] + c;
|
||
c = (l >> 28) + (m >> 14) + xh * h;
|
||
w[j++] = l & 0xfffffff;
|
||
}
|
||
return c;
|
||
}
|
||
if (j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
|
||
BigInteger.prototype.am = am2;
|
||
dbits = 30;
|
||
}
|
||
else if (j_lm && (navigator.appName != "Netscape")) {
|
||
BigInteger.prototype.am = am1;
|
||
dbits = 26;
|
||
}
|
||
else { // Mozilla/Netscape seems to prefer am3
|
||
BigInteger.prototype.am = am3;
|
||
dbits = 28;
|
||
}
|
||
|
||
BigInteger.prototype.DB = dbits;
|
||
BigInteger.prototype.DM = ((1 << dbits) - 1);
|
||
BigInteger.prototype.DV = (1 << dbits);
|
||
|
||
var BI_FP = 52;
|
||
BigInteger.prototype.FV = Math.pow(2, BI_FP);
|
||
BigInteger.prototype.F1 = BI_FP - dbits;
|
||
BigInteger.prototype.F2 = 2 * dbits - BI_FP;
|
||
|
||
// Digit conversions
|
||
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||
var BI_RC = new Array();
|
||
var rr, vv;
|
||
rr = "0".charCodeAt(0);
|
||
for (vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
|
||
rr = "a".charCodeAt(0);
|
||
for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||
rr = "A".charCodeAt(0);
|
||
for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
|
||
|
||
function int2char(n) { return BI_RM.charAt(n); }
|
||
function intAt(s, i) {
|
||
var c = BI_RC[s.charCodeAt(i)];
|
||
return (c == null) ? -1 : c;
|
||
}
|
||
|
||
|
||
|
||
// return bigint initialized to value
|
||
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
|
||
|
||
|
||
// returns bit length of the integer x
|
||
function nbits(x) {
|
||
var r = 1, t;
|
||
if ((t = x >>> 16) != 0) { x = t; r += 16; }
|
||
if ((t = x >> 8) != 0) { x = t; r += 8; }
|
||
if ((t = x >> 4) != 0) { x = t; r += 4; }
|
||
if ((t = x >> 2) != 0) { x = t; r += 2; }
|
||
if ((t = x >> 1) != 0) { x = t; r += 1; }
|
||
return r;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// (protected) copy this to r
|
||
BigInteger.prototype.copyTo = function (r) {
|
||
for (var i = this.t - 1; i >= 0; --i) r[i] = this[i];
|
||
r.t = this.t;
|
||
r.s = this.s;
|
||
};
|
||
|
||
|
||
// (protected) set from integer value x, -DV <= x < DV
|
||
BigInteger.prototype.fromInt = function (x) {
|
||
this.t = 1;
|
||
this.s = (x < 0) ? -1 : 0;
|
||
if (x > 0) this[0] = x;
|
||
else if (x < -1) this[0] = x + DV;
|
||
else this.t = 0;
|
||
};
|
||
|
||
// (protected) set from string and radix
|
||
BigInteger.prototype.fromString = function (s, b) {
|
||
var k;
|
||
if (b == 16) k = 4;
|
||
else if (b == 8) k = 3;
|
||
else if (b == 256) k = 8; // byte array
|
||
else if (b == 2) k = 1;
|
||
else if (b == 32) k = 5;
|
||
else if (b == 4) k = 2;
|
||
else { this.fromRadix(s, b); return; }
|
||
this.t = 0;
|
||
this.s = 0;
|
||
var i = s.length, mi = false, sh = 0;
|
||
while (--i >= 0) {
|
||
var x = (k == 8) ? s[i] & 0xff : intAt(s, i);
|
||
if (x < 0) {
|
||
if (s.charAt(i) == "-") mi = true;
|
||
continue;
|
||
}
|
||
mi = false;
|
||
if (sh == 0)
|
||
this[this.t++] = x;
|
||
else if (sh + k > this.DB) {
|
||
this[this.t - 1] |= (x & ((1 << (this.DB - sh)) - 1)) << sh;
|
||
this[this.t++] = (x >> (this.DB - sh));
|
||
}
|
||
else
|
||
this[this.t - 1] |= x << sh;
|
||
sh += k;
|
||
if (sh >= this.DB) sh -= this.DB;
|
||
}
|
||
if (k == 8 && (s[0] & 0x80) != 0) {
|
||
this.s = -1;
|
||
if (sh > 0) this[this.t - 1] |= ((1 << (this.DB - sh)) - 1) << sh;
|
||
}
|
||
this.clamp();
|
||
if (mi) BigInteger.ZERO.subTo(this, this);
|
||
};
|
||
|
||
|
||
// (protected) clamp off excess high words
|
||
BigInteger.prototype.clamp = function () {
|
||
var c = this.s & this.DM;
|
||
while (this.t > 0 && this[this.t - 1] == c) --this.t;
|
||
};
|
||
|
||
// (protected) r = this << n*DB
|
||
BigInteger.prototype.dlShiftTo = function (n, r) {
|
||
var i;
|
||
for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i];
|
||
for (i = n - 1; i >= 0; --i) r[i] = 0;
|
||
r.t = this.t + n;
|
||
r.s = this.s;
|
||
};
|
||
|
||
// (protected) r = this >> n*DB
|
||
BigInteger.prototype.drShiftTo = function (n, r) {
|
||
for (var i = n; i < this.t; ++i) r[i - n] = this[i];
|
||
r.t = Math.max(this.t - n, 0);
|
||
r.s = this.s;
|
||
};
|
||
|
||
|
||
// (protected) r = this << n
|
||
BigInteger.prototype.lShiftTo = function (n, r) {
|
||
var bs = n % this.DB;
|
||
var cbs = this.DB - bs;
|
||
var bm = (1 << cbs) - 1;
|
||
var ds = Math.floor(n / this.DB), c = (this.s << bs) & this.DM, i;
|
||
for (i = this.t - 1; i >= 0; --i) {
|
||
r[i + ds + 1] = (this[i] >> cbs) | c;
|
||
c = (this[i] & bm) << bs;
|
||
}
|
||
for (i = ds - 1; i >= 0; --i) r[i] = 0;
|
||
r[ds] = c;
|
||
r.t = this.t + ds + 1;
|
||
r.s = this.s;
|
||
r.clamp();
|
||
};
|
||
|
||
|
||
// (protected) r = this >> n
|
||
BigInteger.prototype.rShiftTo = function (n, r) {
|
||
r.s = this.s;
|
||
var ds = Math.floor(n / this.DB);
|
||
if (ds >= this.t) { r.t = 0; return; }
|
||
var bs = n % this.DB;
|
||
var cbs = this.DB - bs;
|
||
var bm = (1 << bs) - 1;
|
||
r[0] = this[ds] >> bs;
|
||
for (var i = ds + 1; i < this.t; ++i) {
|
||
r[i - ds - 1] |= (this[i] & bm) << cbs;
|
||
r[i - ds] = this[i] >> bs;
|
||
}
|
||
if (bs > 0) r[this.t - ds - 1] |= (this.s & bm) << cbs;
|
||
r.t = this.t - ds;
|
||
r.clamp();
|
||
};
|
||
|
||
|
||
// (protected) r = this - a
|
||
BigInteger.prototype.subTo = function (a, r) {
|
||
var i = 0, c = 0, m = Math.min(a.t, this.t);
|
||
while (i < m) {
|
||
c += this[i] - a[i];
|
||
r[i++] = c & this.DM;
|
||
c >>= this.DB;
|
||
}
|
||
if (a.t < this.t) {
|
||
c -= a.s;
|
||
while (i < this.t) {
|
||
c += this[i];
|
||
r[i++] = c & this.DM;
|
||
c >>= this.DB;
|
||
}
|
||
c += this.s;
|
||
}
|
||
else {
|
||
c += this.s;
|
||
while (i < a.t) {
|
||
c -= a[i];
|
||
r[i++] = c & this.DM;
|
||
c >>= this.DB;
|
||
}
|
||
c -= a.s;
|
||
}
|
||
r.s = (c < 0) ? -1 : 0;
|
||
if (c < -1) r[i++] = this.DV + c;
|
||
else if (c > 0) r[i++] = c;
|
||
r.t = i;
|
||
r.clamp();
|
||
};
|
||
|
||
|
||
// (protected) r = this * a, r != this,a (HAC 14.12)
|
||
// "this" should be the larger one if appropriate.
|
||
BigInteger.prototype.multiplyTo = function (a, r) {
|
||
var x = this.abs(), y = a.abs();
|
||
var i = x.t;
|
||
r.t = i + y.t;
|
||
while (--i >= 0) r[i] = 0;
|
||
for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t);
|
||
r.s = 0;
|
||
r.clamp();
|
||
if (this.s != a.s) BigInteger.ZERO.subTo(r, r);
|
||
};
|
||
|
||
|
||
// (protected) r = this^2, r != this (HAC 14.16)
|
||
BigInteger.prototype.squareTo = function (r) {
|
||
var x = this.abs();
|
||
var i = r.t = 2 * x.t;
|
||
while (--i >= 0) r[i] = 0;
|
||
for (i = 0; i < x.t - 1; ++i) {
|
||
var c = x.am(i, x[i], r, 2 * i, 0, 1);
|
||
if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) {
|
||
r[i + x.t] -= x.DV;
|
||
r[i + x.t + 1] = 1;
|
||
}
|
||
}
|
||
if (r.t > 0) r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1);
|
||
r.s = 0;
|
||
r.clamp();
|
||
};
|
||
|
||
|
||
|
||
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
|
||
// r != q, this != m. q or r may be null.
|
||
BigInteger.prototype.divRemTo = function (m, q, r) {
|
||
var pm = m.abs();
|
||
if (pm.t <= 0) return;
|
||
var pt = this.abs();
|
||
if (pt.t < pm.t) {
|
||
if (q != null) q.fromInt(0);
|
||
if (r != null) this.copyTo(r);
|
||
return;
|
||
}
|
||
if (r == null) r = nbi();
|
||
var y = nbi(), ts = this.s, ms = m.s;
|
||
var nsh = this.DB - nbits(pm[pm.t - 1]); // normalize modulus
|
||
if (nsh > 0) { pm.lShiftTo(nsh, y); pt.lShiftTo(nsh, r); }
|
||
else { pm.copyTo(y); pt.copyTo(r); }
|
||
var ys = y.t;
|
||
var y0 = y[ys - 1];
|
||
if (y0 == 0) return;
|
||
var yt = y0 * (1 << this.F1) + ((ys > 1) ? y[ys - 2] >> this.F2 : 0);
|
||
var d1 = this.FV / yt, d2 = (1 << this.F1) / yt, e = 1 << this.F2;
|
||
var i = r.t, j = i - ys, t = (q == null) ? nbi() : q;
|
||
y.dlShiftTo(j, t);
|
||
if (r.compareTo(t) >= 0) {
|
||
r[r.t++] = 1;
|
||
r.subTo(t, r);
|
||
}
|
||
BigInteger.ONE.dlShiftTo(ys, t);
|
||
t.subTo(y, y); // "negative" y so we can replace sub with am later
|
||
while (y.t < ys) y[y.t++] = 0;
|
||
while (--j >= 0) {
|
||
// Estimate quotient digit
|
||
var qd = (r[--i] == y0) ? this.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2);
|
||
if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out
|
||
y.dlShiftTo(j, t);
|
||
r.subTo(t, r);
|
||
while (r[i] < --qd) r.subTo(t, r);
|
||
}
|
||
}
|
||
if (q != null) {
|
||
r.drShiftTo(ys, q);
|
||
if (ts != ms) BigInteger.ZERO.subTo(q, q);
|
||
}
|
||
r.t = ys;
|
||
r.clamp();
|
||
if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder
|
||
if (ts < 0) BigInteger.ZERO.subTo(r, r);
|
||
};
|
||
|
||
|
||
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
|
||
// justification:
|
||
// xy == 1 (mod m)
|
||
// xy = 1+km
|
||
// xy(2-xy) = (1+km)(1-km)
|
||
// x[y(2-xy)] = 1-k^2m^2
|
||
// x[y(2-xy)] == 1 (mod m^2)
|
||
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
|
||
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
|
||
// JS multiply "overflows" differently from C/C++, so care is needed here.
|
||
BigInteger.prototype.invDigit = function () {
|
||
if (this.t < 1) return 0;
|
||
var x = this[0];
|
||
if ((x & 1) == 0) return 0;
|
||
var y = x & 3; // y == 1/x mod 2^2
|
||
y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
|
||
y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
|
||
y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
|
||
// last step - calculate inverse mod DV directly;
|
||
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
|
||
y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits
|
||
// we really want the negative inverse, and -DV < y < DV
|
||
return (y > 0) ? this.DV - y : -y;
|
||
};
|
||
|
||
|
||
// (protected) true iff this is even
|
||
BigInteger.prototype.isEven = function () { return ((this.t > 0) ? (this[0] & 1) : this.s) == 0; };
|
||
|
||
|
||
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
|
||
BigInteger.prototype.exp = function (e, z) {
|
||
if (e > 0xffffffff || e < 1) return BigInteger.ONE;
|
||
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e) - 1;
|
||
g.copyTo(r);
|
||
while (--i >= 0) {
|
||
z.sqrTo(r, r2);
|
||
if ((e & (1 << i)) > 0) z.mulTo(r2, g, r);
|
||
else { var t = r; r = r2; r2 = t; }
|
||
}
|
||
return z.revert(r);
|
||
};
|
||
|
||
|
||
// (public) return string representation in given radix
|
||
BigInteger.prototype.toString = function (b) {
|
||
if (this.s < 0) return "-" + this.negate().toString(b);
|
||
var k;
|
||
if (b == 16) k = 4;
|
||
else if (b == 8) k = 3;
|
||
else if (b == 2) k = 1;
|
||
else if (b == 32) k = 5;
|
||
else if (b == 4) k = 2;
|
||
else return this.toRadix(b);
|
||
var km = (1 << k) - 1, d, m = false, r = "", i = this.t;
|
||
var p = this.DB - (i * this.DB) % k;
|
||
if (i-- > 0) {
|
||
if (p < this.DB && (d = this[i] >> p) > 0) { m = true; r = int2char(d); }
|
||
while (i >= 0) {
|
||
if (p < k) {
|
||
d = (this[i] & ((1 << p) - 1)) << (k - p);
|
||
d |= this[--i] >> (p += this.DB - k);
|
||
}
|
||
else {
|
||
d = (this[i] >> (p -= k)) & km;
|
||
if (p <= 0) { p += this.DB; --i; }
|
||
}
|
||
if (d > 0) m = true;
|
||
if (m) r += int2char(d);
|
||
}
|
||
}
|
||
return m ? r : "0";
|
||
};
|
||
|
||
|
||
// (public) -this
|
||
BigInteger.prototype.negate = function () { var r = nbi(); BigInteger.ZERO.subTo(this, r); return r; };
|
||
|
||
// (public) |this|
|
||
BigInteger.prototype.abs = function () { return (this.s < 0) ? this.negate() : this; };
|
||
|
||
// (public) return + if this > a, - if this < a, 0 if equal
|
||
BigInteger.prototype.compareTo = function (a) {
|
||
var r = this.s - a.s;
|
||
if (r != 0) return r;
|
||
var i = this.t;
|
||
r = i - a.t;
|
||
if (r != 0) return (this.s < 0) ? -r : r;
|
||
while (--i >= 0) if ((r = this[i] - a[i]) != 0) return r;
|
||
return 0;
|
||
}
|
||
|
||
// (public) return the number of bits in "this"
|
||
BigInteger.prototype.bitLength = function () {
|
||
if (this.t <= 0) return 0;
|
||
return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM));
|
||
};
|
||
|
||
// (public) this mod a
|
||
BigInteger.prototype.mod = function (a) {
|
||
var r = nbi();
|
||
this.abs().divRemTo(a, null, r);
|
||
if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r);
|
||
return r;
|
||
}
|
||
|
||
// (public) this^e % m, 0 <= e < 2^32
|
||
BigInteger.prototype.modPowInt = function (e, m) {
|
||
var z;
|
||
if (e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
|
||
return this.exp(e, z);
|
||
};
|
||
|
||
// "constants"
|
||
BigInteger.ZERO = nbv(0);
|
||
BigInteger.ONE = nbv(1);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// Copyright (c) 2005-2009 Tom Wu
|
||
// All Rights Reserved.
|
||
// See "LICENSE" for details.
|
||
// Extended JavaScript BN functions, required for RSA private ops.
|
||
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
|
||
// Version 1.2: square() API, isProbablePrime fix
|
||
|
||
|
||
// return index of lowest 1-bit in x, x < 2^31
|
||
function lbit(x) {
|
||
if (x == 0) return -1;
|
||
var r = 0;
|
||
if ((x & 0xffff) == 0) { x >>= 16; r += 16; }
|
||
if ((x & 0xff) == 0) { x >>= 8; r += 8; }
|
||
if ((x & 0xf) == 0) { x >>= 4; r += 4; }
|
||
if ((x & 3) == 0) { x >>= 2; r += 2; }
|
||
if ((x & 1) == 0) ++r;
|
||
return r;
|
||
}
|
||
|
||
// return number of 1 bits in x
|
||
function cbit(x) {
|
||
var r = 0;
|
||
while (x != 0) { x &= x - 1; ++r; }
|
||
return r;
|
||
}
|
||
|
||
var lowprimes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
|
||
var lplim = (1 << 26) / lowprimes[lowprimes.length - 1];
|
||
|
||
|
||
|
||
// (protected) return x s.t. r^x < DV
|
||
BigInteger.prototype.chunkSize = function (r) { return Math.floor(Math.LN2 * this.DB / Math.log(r)); };
|
||
|
||
// (protected) convert to radix string
|
||
BigInteger.prototype.toRadix = function (b) {
|
||
if (b == null) b = 10;
|
||
if (this.signum() == 0 || b < 2 || b > 36) return "0";
|
||
var cs = this.chunkSize(b);
|
||
var a = Math.pow(b, cs);
|
||
var d = nbv(a), y = nbi(), z = nbi(), r = "";
|
||
this.divRemTo(d, y, z);
|
||
while (y.signum() > 0) {
|
||
r = (a + z.intValue()).toString(b).substr(1) + r;
|
||
y.divRemTo(d, y, z);
|
||
}
|
||
return z.intValue().toString(b) + r;
|
||
};
|
||
|
||
// (protected) convert from radix string
|
||
BigInteger.prototype.fromRadix = function (s, b) {
|
||
this.fromInt(0);
|
||
if (b == null) b = 10;
|
||
var cs = this.chunkSize(b);
|
||
var d = Math.pow(b, cs), mi = false, j = 0, w = 0;
|
||
for (var i = 0; i < s.length; ++i) {
|
||
var x = intAt(s, i);
|
||
if (x < 0) {
|
||
if (s.charAt(i) == "-" && this.signum() == 0) mi = true;
|
||
continue;
|
||
}
|
||
w = b * w + x;
|
||
if (++j >= cs) {
|
||
this.dMultiply(d);
|
||
this.dAddOffset(w, 0);
|
||
j = 0;
|
||
w = 0;
|
||
}
|
||
}
|
||
if (j > 0) {
|
||
this.dMultiply(Math.pow(b, j));
|
||
this.dAddOffset(w, 0);
|
||
}
|
||
if (mi) BigInteger.ZERO.subTo(this, this);
|
||
};
|
||
|
||
// (protected) alternate constructor
|
||
BigInteger.prototype.fromNumber = function (a, b, c) {
|
||
if ("number" == typeof b) {
|
||
// new BigInteger(int,int,RNG)
|
||
if (a < 2) this.fromInt(1);
|
||
else {
|
||
this.fromNumber(a, c);
|
||
if (!this.testBit(a - 1)) // force MSB set
|
||
this.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, this);
|
||
if (this.isEven()) this.dAddOffset(1, 0); // force odd
|
||
while (!this.isProbablePrime(b)) {
|
||
this.dAddOffset(2, 0);
|
||
if (this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a - 1), this);
|
||
}
|
||
}
|
||
}
|
||
else {
|
||
// new BigInteger(int,RNG)
|
||
var x = new Array(), t = a & 7;
|
||
x.length = (a >> 3) + 1;
|
||
b.nextBytes(x);
|
||
if (t > 0) x[0] &= ((1 << t) - 1); else x[0] = 0;
|
||
this.fromString(x, 256);
|
||
}
|
||
};
|
||
|
||
// (protected) r = this op a (bitwise)
|
||
BigInteger.prototype.bitwiseTo = function (a, op, r) {
|
||
var i, f, m = Math.min(a.t, this.t);
|
||
for (i = 0; i < m; ++i) r[i] = op(this[i], a[i]);
|
||
if (a.t < this.t) {
|
||
f = a.s & this.DM;
|
||
for (i = m; i < this.t; ++i) r[i] = op(this[i], f);
|
||
r.t = this.t;
|
||
}
|
||
else {
|
||
f = this.s & this.DM;
|
||
for (i = m; i < a.t; ++i) r[i] = op(f, a[i]);
|
||
r.t = a.t;
|
||
}
|
||
r.s = op(this.s, a.s);
|
||
r.clamp();
|
||
};
|
||
|
||
// (protected) this op (1<<n)
|
||
BigInteger.prototype.changeBit = function (n, op) {
|
||
var r = BigInteger.ONE.shiftLeft(n);
|
||
this.bitwiseTo(r, op, r);
|
||
return r;
|
||
};
|
||
|
||
// (protected) r = this + a
|
||
BigInteger.prototype.addTo = function (a, r) {
|
||
var i = 0, c = 0, m = Math.min(a.t, this.t);
|
||
while (i < m) {
|
||
c += this[i] + a[i];
|
||
r[i++] = c & this.DM;
|
||
c >>= this.DB;
|
||
}
|
||
if (a.t < this.t) {
|
||
c += a.s;
|
||
while (i < this.t) {
|
||
c += this[i];
|
||
r[i++] = c & this.DM;
|
||
c >>= this.DB;
|
||
}
|
||
c += this.s;
|
||
}
|
||
else {
|
||
c += this.s;
|
||
while (i < a.t) {
|
||
c += a[i];
|
||
r[i++] = c & this.DM;
|
||
c >>= this.DB;
|
||
}
|
||
c += a.s;
|
||
}
|
||
r.s = (c < 0) ? -1 : 0;
|
||
if (c > 0) r[i++] = c;
|
||
else if (c < -1) r[i++] = this.DV + c;
|
||
r.t = i;
|
||
r.clamp();
|
||
};
|
||
|
||
// (protected) this *= n, this >= 0, 1 < n < DV
|
||
BigInteger.prototype.dMultiply = function (n) {
|
||
this[this.t] = this.am(0, n - 1, this, 0, 0, this.t);
|
||
++this.t;
|
||
this.clamp();
|
||
};
|
||
|
||
// (protected) this += n << w words, this >= 0
|
||
BigInteger.prototype.dAddOffset = function (n, w) {
|
||
if (n == 0) return;
|
||
while (this.t <= w) this[this.t++] = 0;
|
||
this[w] += n;
|
||
while (this[w] >= this.DV) {
|
||
this[w] -= this.DV;
|
||
if (++w >= this.t) this[this.t++] = 0;
|
||
++this[w];
|
||
}
|
||
};
|
||
|
||
// (protected) r = lower n words of "this * a", a.t <= n
|
||
// "this" should be the larger one if appropriate.
|
||
BigInteger.prototype.multiplyLowerTo = function (a, n, r) {
|
||
var i = Math.min(this.t + a.t, n);
|
||
r.s = 0; // assumes a,this >= 0
|
||
r.t = i;
|
||
while (i > 0) r[--i] = 0;
|
||
var j;
|
||
for (j = r.t - this.t; i < j; ++i) r[i + this.t] = this.am(0, a[i], r, i, 0, this.t);
|
||
for (j = Math.min(a.t, n); i < j; ++i) this.am(0, a[i], r, i, 0, n - i);
|
||
r.clamp();
|
||
};
|
||
|
||
|
||
// (protected) r = "this * a" without lower n words, n > 0
|
||
// "this" should be the larger one if appropriate.
|
||
BigInteger.prototype.multiplyUpperTo = function (a, n, r) {
|
||
--n;
|
||
var i = r.t = this.t + a.t - n;
|
||
r.s = 0; // assumes a,this >= 0
|
||
while (--i >= 0) r[i] = 0;
|
||
for (i = Math.max(n - this.t, 0); i < a.t; ++i)
|
||
r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n);
|
||
r.clamp();
|
||
r.drShiftTo(1, r);
|
||
};
|
||
|
||
// (protected) this % n, n < 2^26
|
||
BigInteger.prototype.modInt = function (n) {
|
||
if (n <= 0) return 0;
|
||
var d = this.DV % n, r = (this.s < 0) ? n - 1 : 0;
|
||
if (this.t > 0)
|
||
if (d == 0) r = this[0] % n;
|
||
else for (var i = this.t - 1; i >= 0; --i) r = (d * r + this[i]) % n;
|
||
return r;
|
||
};
|
||
|
||
|
||
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
|
||
BigInteger.prototype.millerRabin = function (t) {
|
||
var n1 = this.subtract(BigInteger.ONE);
|
||
var k = n1.getLowestSetBit();
|
||
if (k <= 0) return false;
|
||
var r = n1.shiftRight(k);
|
||
t = (t + 1) >> 1;
|
||
if (t > lowprimes.length) t = lowprimes.length;
|
||
var a = nbi();
|
||
for (var i = 0; i < t; ++i) {
|
||
//Pick bases at random, instead of starting at 2
|
||
a.fromInt(lowprimes[Math.floor(Math.random() * lowprimes.length)]);
|
||
var y = a.modPow(r, this);
|
||
if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
|
||
var j = 1;
|
||
while (j++ < k && y.compareTo(n1) != 0) {
|
||
y = y.modPowInt(2, this);
|
||
if (y.compareTo(BigInteger.ONE) == 0) return false;
|
||
}
|
||
if (y.compareTo(n1) != 0) return false;
|
||
}
|
||
}
|
||
return true;
|
||
};
|
||
|
||
|
||
|
||
// (public)
|
||
BigInteger.prototype.clone = function () { var r = nbi(); this.copyTo(r); return r; };
|
||
|
||
// (public) return value as integer
|
||
BigInteger.prototype.intValue = function () {
|
||
if (this.s < 0) {
|
||
if (this.t == 1) return this[0] - this.DV;
|
||
else if (this.t == 0) return -1;
|
||
}
|
||
else if (this.t == 1) return this[0];
|
||
else if (this.t == 0) return 0;
|
||
// assumes 16 < DB < 32
|
||
return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0];
|
||
};
|
||
|
||
|
||
// (public) return value as byte
|
||
BigInteger.prototype.byteValue = function () { return (this.t == 0) ? this.s : (this[0] << 24) >> 24; };
|
||
|
||
// (public) return value as short (assumes DB>=16)
|
||
BigInteger.prototype.shortValue = function () { return (this.t == 0) ? this.s : (this[0] << 16) >> 16; };
|
||
|
||
// (public) 0 if this == 0, 1 if this > 0
|
||
BigInteger.prototype.signum = function () {
|
||
if (this.s < 0) return -1;
|
||
else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
|
||
else return 1;
|
||
};
|
||
|
||
|
||
// (public) convert to bigendian byte array
|
||
BigInteger.prototype.toByteArray = function () {
|
||
var i = this.t, r = new Array();
|
||
r[0] = this.s;
|
||
var p = this.DB - (i * this.DB) % 8, d, k = 0;
|
||
if (i-- > 0) {
|
||
if (p < this.DB && (d = this[i] >> p) != (this.s & this.DM) >> p)
|
||
r[k++] = d | (this.s << (this.DB - p));
|
||
while (i >= 0) {
|
||
if (p < 8) {
|
||
d = (this[i] & ((1 << p) - 1)) << (8 - p);
|
||
d |= this[--i] >> (p += this.DB - 8);
|
||
}
|
||
else {
|
||
d = (this[i] >> (p -= 8)) & 0xff;
|
||
if (p <= 0) { p += this.DB; --i; }
|
||
}
|
||
if ((d & 0x80) != 0) d |= -256;
|
||
if (k == 0 && (this.s & 0x80) != (d & 0x80)) ++k;
|
||
if (k > 0 || d != this.s) r[k++] = d;
|
||
}
|
||
}
|
||
return r;
|
||
};
|
||
|
||
BigInteger.prototype.equals = function (a) { return (this.compareTo(a) == 0); };
|
||
BigInteger.prototype.min = function (a) { return (this.compareTo(a) < 0) ? this : a; };
|
||
BigInteger.prototype.max = function (a) { return (this.compareTo(a) > 0) ? this : a; };
|
||
|
||
// (public) this & a
|
||
function op_and(x, y) { return x & y; }
|
||
BigInteger.prototype.and = function (a) { var r = nbi(); this.bitwiseTo(a, op_and, r); return r; };
|
||
|
||
// (public) this | a
|
||
function op_or(x, y) { return x | y; }
|
||
BigInteger.prototype.or = function (a) { var r = nbi(); this.bitwiseTo(a, op_or, r); return r; };
|
||
|
||
// (public) this ^ a
|
||
function op_xor(x, y) { return x ^ y; }
|
||
BigInteger.prototype.xor = function (a) { var r = nbi(); this.bitwiseTo(a, op_xor, r); return r; };
|
||
|
||
// (public) this & ~a
|
||
function op_andnot(x, y) { return x & ~y; }
|
||
BigInteger.prototype.andNot = function (a) { var r = nbi(); this.bitwiseTo(a, op_andnot, r); return r; };
|
||
|
||
// (public) ~this
|
||
BigInteger.prototype.not = function () {
|
||
var r = nbi();
|
||
for (var i = 0; i < this.t; ++i) r[i] = this.DM & ~this[i];
|
||
r.t = this.t;
|
||
r.s = ~this.s;
|
||
return r;
|
||
};
|
||
|
||
// (public) this << n
|
||
BigInteger.prototype.shiftLeft = function (n) {
|
||
var r = nbi();
|
||
if (n < 0) this.rShiftTo(-n, r); else this.lShiftTo(n, r);
|
||
return r;
|
||
};
|
||
|
||
// (public) this >> n
|
||
BigInteger.prototype.shiftRight = function (n) {
|
||
var r = nbi();
|
||
if (n < 0) this.lShiftTo(-n, r); else this.rShiftTo(n, r);
|
||
return r;
|
||
};
|
||
|
||
// (public) returns index of lowest 1-bit (or -1 if none)
|
||
BigInteger.prototype.getLowestSetBit = function () {
|
||
for (var i = 0; i < this.t; ++i)
|
||
if (this[i] != 0) return i * this.DB + lbit(this[i]);
|
||
if (this.s < 0) return this.t * this.DB;
|
||
return -1;
|
||
};
|
||
|
||
// (public) return number of set bits
|
||
BigInteger.prototype.bitCount = function () {
|
||
var r = 0, x = this.s & this.DM;
|
||
for (var i = 0; i < this.t; ++i) r += cbit(this[i] ^ x);
|
||
return r;
|
||
};
|
||
|
||
// (public) true iff nth bit is set
|
||
BigInteger.prototype.testBit = function (n) {
|
||
var j = Math.floor(n / this.DB);
|
||
if (j >= this.t) return (this.s != 0);
|
||
return ((this[j] & (1 << (n % this.DB))) != 0);
|
||
};
|
||
|
||
// (public) this | (1<<n)
|
||
BigInteger.prototype.setBit = function (n) { return this.changeBit(n, op_or); };
|
||
// (public) this & ~(1<<n)
|
||
BigInteger.prototype.clearBit = function (n) { return this.changeBit(n, op_andnot); };
|
||
// (public) this ^ (1<<n)
|
||
BigInteger.prototype.flipBit = function (n) { return this.changeBit(n, op_xor); };
|
||
// (public) this + a
|
||
BigInteger.prototype.add = function (a) { var r = nbi(); this.addTo(a, r); return r; };
|
||
// (public) this - a
|
||
BigInteger.prototype.subtract = function (a) { var r = nbi(); this.subTo(a, r); return r; };
|
||
// (public) this * a
|
||
BigInteger.prototype.multiply = function (a) { var r = nbi(); this.multiplyTo(a, r); return r; };
|
||
// (public) this / a
|
||
BigInteger.prototype.divide = function (a) { var r = nbi(); this.divRemTo(a, r, null); return r; };
|
||
// (public) this % a
|
||
BigInteger.prototype.remainder = function (a) { var r = nbi(); this.divRemTo(a, null, r); return r; };
|
||
// (public) [this/a,this%a]
|
||
BigInteger.prototype.divideAndRemainder = function (a) {
|
||
var q = nbi(), r = nbi();
|
||
this.divRemTo(a, q, r);
|
||
return new Array(q, r);
|
||
};
|
||
|
||
// (public) this^e % m (HAC 14.85)
|
||
BigInteger.prototype.modPow = function (e, m) {
|
||
var i = e.bitLength(), k, r = nbv(1), z;
|
||
if (i <= 0) return r;
|
||
else if (i < 18) k = 1;
|
||
else if (i < 48) k = 3;
|
||
else if (i < 144) k = 4;
|
||
else if (i < 768) k = 5;
|
||
else k = 6;
|
||
if (i < 8)
|
||
z = new Classic(m);
|
||
else if (m.isEven())
|
||
z = new Barrett(m);
|
||
else
|
||
z = new Montgomery(m);
|
||
|
||
// precomputation
|
||
var g = new Array(), n = 3, k1 = k - 1, km = (1 << k) - 1;
|
||
g[1] = z.convert(this);
|
||
if (k > 1) {
|
||
var g2 = nbi();
|
||
z.sqrTo(g[1], g2);
|
||
while (n <= km) {
|
||
g[n] = nbi();
|
||
z.mulTo(g2, g[n - 2], g[n]);
|
||
n += 2;
|
||
}
|
||
}
|
||
|
||
var j = e.t - 1, w, is1 = true, r2 = nbi(), t;
|
||
i = nbits(e[j]) - 1;
|
||
while (j >= 0) {
|
||
if (i >= k1) w = (e[j] >> (i - k1)) & km;
|
||
else {
|
||
w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
|
||
if (j > 0) w |= e[j - 1] >> (this.DB + i - k1);
|
||
}
|
||
|
||
n = k;
|
||
while ((w & 1) == 0) { w >>= 1; --n; }
|
||
if ((i -= n) < 0) { i += this.DB; --j; }
|
||
if (is1) { // ret == 1, don't bother squaring or multiplying it
|
||
g[w].copyTo(r);
|
||
is1 = false;
|
||
}
|
||
else {
|
||
while (n > 1) { z.sqrTo(r, r2); z.sqrTo(r2, r); n -= 2; }
|
||
if (n > 0) z.sqrTo(r, r2); else { t = r; r = r2; r2 = t; }
|
||
z.mulTo(r2, g[w], r);
|
||
}
|
||
|
||
while (j >= 0 && (e[j] & (1 << i)) == 0) {
|
||
z.sqrTo(r, r2); t = r; r = r2; r2 = t;
|
||
if (--i < 0) { i = this.DB - 1; --j; }
|
||
}
|
||
}
|
||
return z.revert(r);
|
||
};
|
||
|
||
// (public) 1/this % m (HAC 14.61)
|
||
BigInteger.prototype.modInverse = function (m) {
|
||
var ac = m.isEven();
|
||
if ((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
|
||
var u = m.clone(), v = this.clone();
|
||
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
|
||
while (u.signum() != 0) {
|
||
while (u.isEven()) {
|
||
u.rShiftTo(1, u);
|
||
if (ac) {
|
||
if (!a.isEven() || !b.isEven()) { a.addTo(this, a); b.subTo(m, b); }
|
||
a.rShiftTo(1, a);
|
||
}
|
||
else if (!b.isEven()) b.subTo(m, b);
|
||
b.rShiftTo(1, b);
|
||
}
|
||
while (v.isEven()) {
|
||
v.rShiftTo(1, v);
|
||
if (ac) {
|
||
if (!c.isEven() || !d.isEven()) { c.addTo(this, c); d.subTo(m, d); }
|
||
c.rShiftTo(1, c);
|
||
}
|
||
else if (!d.isEven()) d.subTo(m, d);
|
||
d.rShiftTo(1, d);
|
||
}
|
||
if (u.compareTo(v) >= 0) {
|
||
u.subTo(v, u);
|
||
if (ac) a.subTo(c, a);
|
||
b.subTo(d, b);
|
||
}
|
||
else {
|
||
v.subTo(u, v);
|
||
if (ac) c.subTo(a, c);
|
||
d.subTo(b, d);
|
||
}
|
||
}
|
||
if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
|
||
if (d.compareTo(m) >= 0) return d.subtract(m);
|
||
if (d.signum() < 0) d.addTo(m, d); else return d;
|
||
if (d.signum() < 0) return d.add(m); else return d;
|
||
};
|
||
|
||
|
||
// (public) this^e
|
||
BigInteger.prototype.pow = function (e) { return this.exp(e, new NullExp()); };
|
||
|
||
// (public) gcd(this,a) (HAC 14.54)
|
||
BigInteger.prototype.gcd = function (a) {
|
||
var x = (this.s < 0) ? this.negate() : this.clone();
|
||
var y = (a.s < 0) ? a.negate() : a.clone();
|
||
if (x.compareTo(y) < 0) { var t = x; x = y; y = t; }
|
||
var i = x.getLowestSetBit(), g = y.getLowestSetBit();
|
||
if (g < 0) return x;
|
||
if (i < g) g = i;
|
||
if (g > 0) {
|
||
x.rShiftTo(g, x);
|
||
y.rShiftTo(g, y);
|
||
}
|
||
while (x.signum() > 0) {
|
||
if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x);
|
||
if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y);
|
||
if (x.compareTo(y) >= 0) {
|
||
x.subTo(y, x);
|
||
x.rShiftTo(1, x);
|
||
}
|
||
else {
|
||
y.subTo(x, y);
|
||
y.rShiftTo(1, y);
|
||
}
|
||
}
|
||
if (g > 0) y.lShiftTo(g, y);
|
||
return y;
|
||
};
|
||
|
||
// (public) test primality with certainty >= 1-.5^t
|
||
BigInteger.prototype.isProbablePrime = function (t) {
|
||
var i, x = this.abs();
|
||
if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) {
|
||
for (i = 0; i < lowprimes.length; ++i)
|
||
if (x[0] == lowprimes[i]) return true;
|
||
return false;
|
||
}
|
||
if (x.isEven()) return false;
|
||
i = 1;
|
||
while (i < lowprimes.length) {
|
||
var m = lowprimes[i], j = i + 1;
|
||
while (j < lowprimes.length && m < lplim) m *= lowprimes[j++];
|
||
m = x.modInt(m);
|
||
while (i < j) if (m % lowprimes[i++] == 0) return false;
|
||
}
|
||
return x.millerRabin(t);
|
||
};
|
||
|
||
|
||
// JSBN-specific extension
|
||
|
||
// (public) this^2
|
||
BigInteger.prototype.square = function () { var r = nbi(); this.squareTo(r); return r; };
|
||
|
||
|
||
// NOTE: BigInteger interfaces not implemented in jsbn:
|
||
// BigInteger(int signum, byte[] magnitude)
|
||
// double doubleValue()
|
||
// float floatValue()
|
||
// int hashCode()
|
||
// long longValue()
|
||
// static BigInteger valueOf(long val)
|
||
|
||
|
||
|
||
// Copyright Stephan Thomas (start) --- //
|
||
// https://raw.github.com/bitcoinjs/bitcoinjs-lib/07f9d55ccb6abd962efb6befdd37671f85ea4ff9/src/util.js
|
||
// BigInteger monkey patching
|
||
BigInteger.valueOf = nbv;
|
||
|
||
/**
|
||
* Returns a byte array representation of the big integer.
|
||
*
|
||
* This returns the absolute of the contained value in big endian
|
||
* form. A value of zero results in an empty array.
|
||
*/
|
||
BigInteger.prototype.toByteArrayUnsigned = function () {
|
||
var ba = this.abs().toByteArray();
|
||
if (ba.length) {
|
||
if (ba[0] == 0) {
|
||
ba = ba.slice(1);
|
||
}
|
||
return ba.map(function (v) {
|
||
return (v < 0) ? v + 256 : v;
|
||
});
|
||
} else {
|
||
// Empty array, nothing to do
|
||
return ba;
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Turns a byte array into a big integer.
|
||
*
|
||
* This function will interpret a byte array as a big integer in big
|
||
* endian notation and ignore leading zeros.
|
||
*/
|
||
BigInteger.fromByteArrayUnsigned = function (ba) {
|
||
if (!ba.length) {
|
||
return ba.valueOf(0);
|
||
} else if (ba[0] & 0x80) {
|
||
// Prepend a zero so the BigInteger class doesn't mistake this
|
||
// for a negative integer.
|
||
return new BigInteger([0].concat(ba));
|
||
} else {
|
||
return new BigInteger(ba);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Converts big integer to signed byte representation.
|
||
*
|
||
* The format for this value uses a the most significant bit as a sign
|
||
* bit. If the most significant bit is already occupied by the
|
||
* absolute value, an extra byte is prepended and the sign bit is set
|
||
* there.
|
||
*
|
||
* Examples:
|
||
*
|
||
* 0 => 0x00
|
||
* 1 => 0x01
|
||
* -1 => 0x81
|
||
* 127 => 0x7f
|
||
* -127 => 0xff
|
||
* 128 => 0x0080
|
||
* -128 => 0x8080
|
||
* 255 => 0x00ff
|
||
* -255 => 0x80ff
|
||
* 16300 => 0x3fac
|
||
* -16300 => 0xbfac
|
||
* 62300 => 0x00f35c
|
||
* -62300 => 0x80f35c
|
||
*/
|
||
BigInteger.prototype.toByteArraySigned = function () {
|
||
var val = this.abs().toByteArrayUnsigned();
|
||
var neg = this.compareTo(BigInteger.ZERO) < 0;
|
||
|
||
if (neg) {
|
||
if (val[0] & 0x80) {
|
||
val.unshift(0x80);
|
||
} else {
|
||
val[0] |= 0x80;
|
||
}
|
||
} else {
|
||
if (val[0] & 0x80) {
|
||
val.unshift(0x00);
|
||
}
|
||
}
|
||
|
||
return val;
|
||
};
|
||
|
||
/**
|
||
* Parse a signed big integer byte representation.
|
||
*
|
||
* For details on the format please see BigInteger.toByteArraySigned.
|
||
*/
|
||
BigInteger.fromByteArraySigned = function (ba) {
|
||
// Check for negative value
|
||
if (ba[0] & 0x80) {
|
||
// Remove sign bit
|
||
ba[0] &= 0x7f;
|
||
|
||
return BigInteger.fromByteArrayUnsigned(ba).negate();
|
||
} else {
|
||
return BigInteger.fromByteArrayUnsigned(ba);
|
||
}
|
||
};
|
||
// Copyright Stephan Thomas (end) --- //
|
||
|
||
|
||
|
||
|
||
// ****** REDUCTION ******* //
|
||
|
||
// Modular reduction using "classic" algorithm
|
||
function Classic(m) { this.m = m; }
|
||
Classic.prototype.convert = function (x) {
|
||
if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
|
||
else return x;
|
||
};
|
||
Classic.prototype.revert = function (x) { return x; };
|
||
Classic.prototype.reduce = function (x) { x.divRemTo(this.m, null, x); };
|
||
Classic.prototype.mulTo = function (x, y, r) { x.multiplyTo(y, r); this.reduce(r); };
|
||
Classic.prototype.sqrTo = function (x, r) { x.squareTo(r); this.reduce(r); };
|
||
|
||
|
||
|
||
|
||
|
||
// Montgomery reduction
|
||
function Montgomery(m) {
|
||
this.m = m;
|
||
this.mp = m.invDigit();
|
||
this.mpl = this.mp & 0x7fff;
|
||
this.mph = this.mp >> 15;
|
||
this.um = (1 << (m.DB - 15)) - 1;
|
||
this.mt2 = 2 * m.t;
|
||
}
|
||
// xR mod m
|
||
Montgomery.prototype.convert = function (x) {
|
||
var r = nbi();
|
||
x.abs().dlShiftTo(this.m.t, r);
|
||
r.divRemTo(this.m, null, r);
|
||
if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r);
|
||
return r;
|
||
}
|
||
// x/R mod m
|
||
Montgomery.prototype.revert = function (x) {
|
||
var r = nbi();
|
||
x.copyTo(r);
|
||
this.reduce(r);
|
||
return r;
|
||
};
|
||
// x = x/R mod m (HAC 14.32)
|
||
Montgomery.prototype.reduce = function (x) {
|
||
while (x.t <= this.mt2) // pad x so am has enough room later
|
||
x[x.t++] = 0;
|
||
for (var i = 0; i < this.m.t; ++i) {
|
||
// faster way of calculating u0 = x[i]*mp mod DV
|
||
var j = x[i] & 0x7fff;
|
||
var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM;
|
||
// use am to combine the multiply-shift-add into one call
|
||
j = i + this.m.t;
|
||
x[j] += this.m.am(0, u0, x, i, 0, this.m.t);
|
||
// propagate carry
|
||
while (x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
|
||
}
|
||
x.clamp();
|
||
x.drShiftTo(this.m.t, x);
|
||
if (x.compareTo(this.m) >= 0) x.subTo(this.m, x);
|
||
};
|
||
// r = "xy/R mod m"; x,y != r
|
||
Montgomery.prototype.mulTo = function (x, y, r) { x.multiplyTo(y, r); this.reduce(r); };
|
||
// r = "x^2/R mod m"; x != r
|
||
Montgomery.prototype.sqrTo = function (x, r) { x.squareTo(r); this.reduce(r); };
|
||
|
||
|
||
|
||
|
||
|
||
// A "null" reducer
|
||
function NullExp() { }
|
||
NullExp.prototype.convert = function (x) { return x; };
|
||
NullExp.prototype.revert = function (x) { return x; };
|
||
NullExp.prototype.mulTo = function (x, y, r) { x.multiplyTo(y, r); };
|
||
NullExp.prototype.sqrTo = function (x, r) { x.squareTo(r); };
|
||
|
||
|
||
|
||
|
||
|
||
// Barrett modular reduction
|
||
function Barrett(m) {
|
||
// setup Barrett
|
||
this.r2 = nbi();
|
||
this.q3 = nbi();
|
||
BigInteger.ONE.dlShiftTo(2 * m.t, this.r2);
|
||
this.mu = this.r2.divide(m);
|
||
this.m = m;
|
||
}
|
||
Barrett.prototype.convert = function (x) {
|
||
if (x.s < 0 || x.t > 2 * this.m.t) return x.mod(this.m);
|
||
else if (x.compareTo(this.m) < 0) return x;
|
||
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
|
||
};
|
||
Barrett.prototype.revert = function (x) { return x; };
|
||
// x = x mod m (HAC 14.42)
|
||
Barrett.prototype.reduce = function (x) {
|
||
x.drShiftTo(this.m.t - 1, this.r2);
|
||
if (x.t > this.m.t + 1) { x.t = this.m.t + 1; x.clamp(); }
|
||
this.mu.multiplyUpperTo(this.r2, this.m.t + 1, this.q3);
|
||
this.m.multiplyLowerTo(this.q3, this.m.t + 1, this.r2);
|
||
while (x.compareTo(this.r2) < 0) x.dAddOffset(1, this.m.t + 1);
|
||
x.subTo(this.r2, x);
|
||
while (x.compareTo(this.m) >= 0) x.subTo(this.m, x);
|
||
};
|
||
// r = x*y mod m; x,y != r
|
||
Barrett.prototype.mulTo = function (x, y, r) { x.multiplyTo(y, r); this.reduce(r); };
|
||
// r = x^2 mod m; x != r
|
||
Barrett.prototype.sqrTo = function (x, r) { x.squareTo(r); this.reduce(r); };
|
||
|
||
})();
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
//---------------------------------------------------------------------
|
||
// QRCode for JavaScript
|
||
//
|
||
// Copyright (c) 2009 Kazuhiko Arase
|
||
//
|
||
// URL: http://www.d-project.com/
|
||
//
|
||
// Licensed under the MIT license:
|
||
// http://www.opensource.org/licenses/mit-license.php
|
||
//
|
||
// The word "QR Code" is registered trademark of
|
||
// DENSO WAVE INCORPORATED
|
||
// http://www.denso-wave.com/qrcode/faqpatent-e.html
|
||
//
|
||
//---------------------------------------------------------------------
|
||
|
||
(function () {
|
||
//---------------------------------------------------------------------
|
||
// QRCode
|
||
//---------------------------------------------------------------------
|
||
|
||
var QRCode = window.QRCode = function (typeNumber, errorCorrectLevel) {
|
||
this.typeNumber = typeNumber;
|
||
this.errorCorrectLevel = errorCorrectLevel;
|
||
this.modules = null;
|
||
this.moduleCount = 0;
|
||
this.dataCache = null;
|
||
this.dataList = new Array();
|
||
}
|
||
|
||
QRCode.prototype = {
|
||
|
||
addData: function (data) {
|
||
var newData = new QRCode.QR8bitByte(data);
|
||
this.dataList.push(newData);
|
||
this.dataCache = null;
|
||
},
|
||
|
||
isDark: function (row, col) {
|
||
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
|
||
throw new Error(row + "," + col);
|
||
}
|
||
return this.modules[row][col];
|
||
},
|
||
|
||
getModuleCount: function () {
|
||
return this.moduleCount;
|
||
},
|
||
|
||
make: function () {
|
||
this.makeImpl(false, this.getBestMaskPattern());
|
||
},
|
||
|
||
makeImpl: function (test, maskPattern) {
|
||
|
||
this.moduleCount = this.typeNumber * 4 + 17;
|
||
this.modules = new Array(this.moduleCount);
|
||
|
||
for (var row = 0; row < this.moduleCount; row++) {
|
||
|
||
this.modules[row] = new Array(this.moduleCount);
|
||
|
||
for (var col = 0; col < this.moduleCount; col++) {
|
||
this.modules[row][col] = null; //(col + row) % 3;
|
||
}
|
||
}
|
||
|
||
this.setupPositionProbePattern(0, 0);
|
||
this.setupPositionProbePattern(this.moduleCount - 7, 0);
|
||
this.setupPositionProbePattern(0, this.moduleCount - 7);
|
||
this.setupPositionAdjustPattern();
|
||
this.setupTimingPattern();
|
||
this.setupTypeInfo(test, maskPattern);
|
||
|
||
if (this.typeNumber >= 7) {
|
||
this.setupTypeNumber(test);
|
||
}
|
||
|
||
if (this.dataCache == null) {
|
||
this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
|
||
}
|
||
|
||
this.mapData(this.dataCache, maskPattern);
|
||
},
|
||
|
||
setupPositionProbePattern: function (row, col) {
|
||
|
||
for (var r = -1; r <= 7; r++) {
|
||
|
||
if (row + r <= -1 || this.moduleCount <= row + r) continue;
|
||
|
||
for (var c = -1; c <= 7; c++) {
|
||
|
||
if (col + c <= -1 || this.moduleCount <= col + c) continue;
|
||
|
||
if ((0 <= r && r <= 6 && (c == 0 || c == 6))
|
||
|| (0 <= c && c <= 6 && (r == 0 || r == 6))
|
||
|| (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
|
||
this.modules[row + r][col + c] = true;
|
||
} else {
|
||
this.modules[row + r][col + c] = false;
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
getBestMaskPattern: function () {
|
||
|
||
var minLostPoint = 0;
|
||
var pattern = 0;
|
||
|
||
for (var i = 0; i < 8; i++) {
|
||
|
||
this.makeImpl(true, i);
|
||
|
||
var lostPoint = QRCode.Util.getLostPoint(this);
|
||
|
||
if (i == 0 || minLostPoint > lostPoint) {
|
||
minLostPoint = lostPoint;
|
||
pattern = i;
|
||
}
|
||
}
|
||
|
||
return pattern;
|
||
},
|
||
|
||
createMovieClip: function (target_mc, instance_name, depth) {
|
||
|
||
var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
|
||
var cs = 1;
|
||
|
||
this.make();
|
||
|
||
for (var row = 0; row < this.modules.length; row++) {
|
||
|
||
var y = row * cs;
|
||
|
||
for (var col = 0; col < this.modules[row].length; col++) {
|
||
|
||
var x = col * cs;
|
||
var dark = this.modules[row][col];
|
||
|
||
if (dark) {
|
||
qr_mc.beginFill(0, 100);
|
||
qr_mc.moveTo(x, y);
|
||
qr_mc.lineTo(x + cs, y);
|
||
qr_mc.lineTo(x + cs, y + cs);
|
||
qr_mc.lineTo(x, y + cs);
|
||
qr_mc.endFill();
|
||
}
|
||
}
|
||
}
|
||
|
||
return qr_mc;
|
||
},
|
||
|
||
setupTimingPattern: function () {
|
||
|
||
for (var r = 8; r < this.moduleCount - 8; r++) {
|
||
if (this.modules[r][6] != null) {
|
||
continue;
|
||
}
|
||
this.modules[r][6] = (r % 2 == 0);
|
||
}
|
||
|
||
for (var c = 8; c < this.moduleCount - 8; c++) {
|
||
if (this.modules[6][c] != null) {
|
||
continue;
|
||
}
|
||
this.modules[6][c] = (c % 2 == 0);
|
||
}
|
||
},
|
||
|
||
setupPositionAdjustPattern: function () {
|
||
|
||
var pos = QRCode.Util.getPatternPosition(this.typeNumber);
|
||
|
||
for (var i = 0; i < pos.length; i++) {
|
||
|
||
for (var j = 0; j < pos.length; j++) {
|
||
|
||
var row = pos[i];
|
||
var col = pos[j];
|
||
|
||
if (this.modules[row][col] != null) {
|
||
continue;
|
||
}
|
||
|
||
for (var r = -2; r <= 2; r++) {
|
||
|
||
for (var c = -2; c <= 2; c++) {
|
||
|
||
if (r == -2 || r == 2 || c == -2 || c == 2
|
||
|| (r == 0 && c == 0)) {
|
||
this.modules[row + r][col + c] = true;
|
||
} else {
|
||
this.modules[row + r][col + c] = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
setupTypeNumber: function (test) {
|
||
|
||
var bits = QRCode.Util.getBCHTypeNumber(this.typeNumber);
|
||
|
||
for (var i = 0; i < 18; i++) {
|
||
var mod = (!test && ((bits >> i) & 1) == 1);
|
||
this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
|
||
}
|
||
|
||
for (var i = 0; i < 18; i++) {
|
||
var mod = (!test && ((bits >> i) & 1) == 1);
|
||
this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
|
||
}
|
||
},
|
||
|
||
setupTypeInfo: function (test, maskPattern) {
|
||
|
||
var data = (this.errorCorrectLevel << 3) | maskPattern;
|
||
var bits = QRCode.Util.getBCHTypeInfo(data);
|
||
|
||
// vertical
|
||
for (var i = 0; i < 15; i++) {
|
||
|
||
var mod = (!test && ((bits >> i) & 1) == 1);
|
||
|
||
if (i < 6) {
|
||
this.modules[i][8] = mod;
|
||
} else if (i < 8) {
|
||
this.modules[i + 1][8] = mod;
|
||
} else {
|
||
this.modules[this.moduleCount - 15 + i][8] = mod;
|
||
}
|
||
}
|
||
|
||
// horizontal
|
||
for (var i = 0; i < 15; i++) {
|
||
|
||
var mod = (!test && ((bits >> i) & 1) == 1);
|
||
|
||
if (i < 8) {
|
||
this.modules[8][this.moduleCount - i - 1] = mod;
|
||
} else if (i < 9) {
|
||
this.modules[8][15 - i - 1 + 1] = mod;
|
||
} else {
|
||
this.modules[8][15 - i - 1] = mod;
|
||
}
|
||
}
|
||
|
||
// fixed module
|
||
this.modules[this.moduleCount - 8][8] = (!test);
|
||
|
||
},
|
||
|
||
mapData: function (data, maskPattern) {
|
||
|
||
var inc = -1;
|
||
var row = this.moduleCount - 1;
|
||
var bitIndex = 7;
|
||
var byteIndex = 0;
|
||
|
||
for (var col = this.moduleCount - 1; col > 0; col -= 2) {
|
||
|
||
if (col == 6) col--;
|
||
|
||
while (true) {
|
||
|
||
for (var c = 0; c < 2; c++) {
|
||
|
||
if (this.modules[row][col - c] == null) {
|
||
|
||
var dark = false;
|
||
|
||
if (byteIndex < data.length) {
|
||
dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
|
||
}
|
||
|
||
var mask = QRCode.Util.getMask(maskPattern, row, col - c);
|
||
|
||
if (mask) {
|
||
dark = !dark;
|
||
}
|
||
|
||
this.modules[row][col - c] = dark;
|
||
bitIndex--;
|
||
|
||
if (bitIndex == -1) {
|
||
byteIndex++;
|
||
bitIndex = 7;
|
||
}
|
||
}
|
||
}
|
||
|
||
row += inc;
|
||
|
||
if (row < 0 || this.moduleCount <= row) {
|
||
row -= inc;
|
||
inc = -inc;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
};
|
||
|
||
QRCode.PAD0 = 0xEC;
|
||
QRCode.PAD1 = 0x11;
|
||
|
||
QRCode.createData = function (typeNumber, errorCorrectLevel, dataList) {
|
||
|
||
var rsBlocks = QRCode.RSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
|
||
|
||
var buffer = new QRCode.BitBuffer();
|
||
|
||
for (var i = 0; i < dataList.length; i++) {
|
||
var data = dataList[i];
|
||
buffer.put(data.mode, 4);
|
||
buffer.put(data.getLength(), QRCode.Util.getLengthInBits(data.mode, typeNumber));
|
||
data.write(buffer);
|
||
}
|
||
|
||
// calc num max data.
|
||
var totalDataCount = 0;
|
||
for (var i = 0; i < rsBlocks.length; i++) {
|
||
totalDataCount += rsBlocks[i].dataCount;
|
||
}
|
||
|
||
if (buffer.getLengthInBits() > totalDataCount * 8) {
|
||
throw new Error("code length overflow. ("
|
||
+ buffer.getLengthInBits()
|
||
+ ">"
|
||
+ totalDataCount * 8
|
||
+ ")");
|
||
}
|
||
|
||
// end code
|
||
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
|
||
buffer.put(0, 4);
|
||
}
|
||
|
||
// padding
|
||
while (buffer.getLengthInBits() % 8 != 0) {
|
||
buffer.putBit(false);
|
||
}
|
||
|
||
// padding
|
||
while (true) {
|
||
|
||
if (buffer.getLengthInBits() >= totalDataCount * 8) {
|
||
break;
|
||
}
|
||
buffer.put(QRCode.PAD0, 8);
|
||
|
||
if (buffer.getLengthInBits() >= totalDataCount * 8) {
|
||
break;
|
||
}
|
||
buffer.put(QRCode.PAD1, 8);
|
||
}
|
||
|
||
return QRCode.createBytes(buffer, rsBlocks);
|
||
};
|
||
|
||
QRCode.createBytes = function (buffer, rsBlocks) {
|
||
|
||
var offset = 0;
|
||
|
||
var maxDcCount = 0;
|
||
var maxEcCount = 0;
|
||
|
||
var dcdata = new Array(rsBlocks.length);
|
||
var ecdata = new Array(rsBlocks.length);
|
||
|
||
for (var r = 0; r < rsBlocks.length; r++) {
|
||
|
||
var dcCount = rsBlocks[r].dataCount;
|
||
var ecCount = rsBlocks[r].totalCount - dcCount;
|
||
|
||
maxDcCount = Math.max(maxDcCount, dcCount);
|
||
maxEcCount = Math.max(maxEcCount, ecCount);
|
||
|
||
dcdata[r] = new Array(dcCount);
|
||
|
||
for (var i = 0; i < dcdata[r].length; i++) {
|
||
dcdata[r][i] = 0xff & buffer.buffer[i + offset];
|
||
}
|
||
offset += dcCount;
|
||
|
||
var rsPoly = QRCode.Util.getErrorCorrectPolynomial(ecCount);
|
||
var rawPoly = new QRCode.Polynomial(dcdata[r], rsPoly.getLength() - 1);
|
||
|
||
var modPoly = rawPoly.mod(rsPoly);
|
||
ecdata[r] = new Array(rsPoly.getLength() - 1);
|
||
for (var i = 0; i < ecdata[r].length; i++) {
|
||
var modIndex = i + modPoly.getLength() - ecdata[r].length;
|
||
ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
|
||
}
|
||
|
||
}
|
||
|
||
var totalCodeCount = 0;
|
||
for (var i = 0; i < rsBlocks.length; i++) {
|
||
totalCodeCount += rsBlocks[i].totalCount;
|
||
}
|
||
|
||
var data = new Array(totalCodeCount);
|
||
var index = 0;
|
||
|
||
for (var i = 0; i < maxDcCount; i++) {
|
||
for (var r = 0; r < rsBlocks.length; r++) {
|
||
if (i < dcdata[r].length) {
|
||
data[index++] = dcdata[r][i];
|
||
}
|
||
}
|
||
}
|
||
|
||
for (var i = 0; i < maxEcCount; i++) {
|
||
for (var r = 0; r < rsBlocks.length; r++) {
|
||
if (i < ecdata[r].length) {
|
||
data[index++] = ecdata[r][i];
|
||
}
|
||
}
|
||
}
|
||
|
||
return data;
|
||
|
||
};
|
||
|
||
//---------------------------------------------------------------------
|
||
// QR8bitByte
|
||
//---------------------------------------------------------------------
|
||
QRCode.QR8bitByte = function (data) {
|
||
this.mode = QRCode.Mode.MODE_8BIT_BYTE;
|
||
this.data = data;
|
||
}
|
||
|
||
QRCode.QR8bitByte.prototype = {
|
||
getLength: function (buffer) {
|
||
return this.data.length;
|
||
},
|
||
|
||
write: function (buffer) {
|
||
for (var i = 0; i < this.data.length; i++) {
|
||
// not JIS ...
|
||
buffer.put(this.data.charCodeAt(i), 8);
|
||
}
|
||
}
|
||
};
|
||
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRMode
|
||
//---------------------------------------------------------------------
|
||
QRCode.Mode = {
|
||
MODE_NUMBER: 1 << 0,
|
||
MODE_ALPHA_NUM: 1 << 1,
|
||
MODE_8BIT_BYTE: 1 << 2,
|
||
MODE_KANJI: 1 << 3
|
||
};
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRErrorCorrectLevel
|
||
//---------------------------------------------------------------------
|
||
QRCode.ErrorCorrectLevel = {
|
||
L: 1,
|
||
M: 0,
|
||
Q: 3,
|
||
H: 2
|
||
};
|
||
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRMaskPattern
|
||
//---------------------------------------------------------------------
|
||
QRCode.MaskPattern = {
|
||
PATTERN000: 0,
|
||
PATTERN001: 1,
|
||
PATTERN010: 2,
|
||
PATTERN011: 3,
|
||
PATTERN100: 4,
|
||
PATTERN101: 5,
|
||
PATTERN110: 6,
|
||
PATTERN111: 7
|
||
};
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRUtil
|
||
//---------------------------------------------------------------------
|
||
|
||
QRCode.Util = {
|
||
|
||
PATTERN_POSITION_TABLE: [
|
||
[],
|
||
[6, 18],
|
||
[6, 22],
|
||
[6, 26],
|
||
[6, 30],
|
||
[6, 34],
|
||
[6, 22, 38],
|
||
[6, 24, 42],
|
||
[6, 26, 46],
|
||
[6, 28, 50],
|
||
[6, 30, 54],
|
||
[6, 32, 58],
|
||
[6, 34, 62],
|
||
[6, 26, 46, 66],
|
||
[6, 26, 48, 70],
|
||
[6, 26, 50, 74],
|
||
[6, 30, 54, 78],
|
||
[6, 30, 56, 82],
|
||
[6, 30, 58, 86],
|
||
[6, 34, 62, 90],
|
||
[6, 28, 50, 72, 94],
|
||
[6, 26, 50, 74, 98],
|
||
[6, 30, 54, 78, 102],
|
||
[6, 28, 54, 80, 106],
|
||
[6, 32, 58, 84, 110],
|
||
[6, 30, 58, 86, 114],
|
||
[6, 34, 62, 90, 118],
|
||
[6, 26, 50, 74, 98, 122],
|
||
[6, 30, 54, 78, 102, 126],
|
||
[6, 26, 52, 78, 104, 130],
|
||
[6, 30, 56, 82, 108, 134],
|
||
[6, 34, 60, 86, 112, 138],
|
||
[6, 30, 58, 86, 114, 142],
|
||
[6, 34, 62, 90, 118, 146],
|
||
[6, 30, 54, 78, 102, 126, 150],
|
||
[6, 24, 50, 76, 102, 128, 154],
|
||
[6, 28, 54, 80, 106, 132, 158],
|
||
[6, 32, 58, 84, 110, 136, 162],
|
||
[6, 26, 54, 82, 110, 138, 166],
|
||
[6, 30, 58, 86, 114, 142, 170]
|
||
],
|
||
|
||
G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
|
||
G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
|
||
G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
|
||
|
||
getBCHTypeInfo: function (data) {
|
||
var d = data << 10;
|
||
while (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G15) >= 0) {
|
||
d ^= (QRCode.Util.G15 << (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G15)));
|
||
}
|
||
return ((data << 10) | d) ^ QRCode.Util.G15_MASK;
|
||
},
|
||
|
||
getBCHTypeNumber: function (data) {
|
||
var d = data << 12;
|
||
while (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G18) >= 0) {
|
||
d ^= (QRCode.Util.G18 << (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G18)));
|
||
}
|
||
return (data << 12) | d;
|
||
},
|
||
|
||
getBCHDigit: function (data) {
|
||
|
||
var digit = 0;
|
||
|
||
while (data != 0) {
|
||
digit++;
|
||
data >>>= 1;
|
||
}
|
||
|
||
return digit;
|
||
},
|
||
|
||
getPatternPosition: function (typeNumber) {
|
||
return QRCode.Util.PATTERN_POSITION_TABLE[typeNumber - 1];
|
||
},
|
||
|
||
getMask: function (maskPattern, i, j) {
|
||
|
||
switch (maskPattern) {
|
||
|
||
case QRCode.MaskPattern.PATTERN000: return (i + j) % 2 == 0;
|
||
case QRCode.MaskPattern.PATTERN001: return i % 2 == 0;
|
||
case QRCode.MaskPattern.PATTERN010: return j % 3 == 0;
|
||
case QRCode.MaskPattern.PATTERN011: return (i + j) % 3 == 0;
|
||
case QRCode.MaskPattern.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
|
||
case QRCode.MaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0;
|
||
case QRCode.MaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
|
||
case QRCode.MaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
|
||
|
||
default:
|
||
throw new Error("bad maskPattern:" + maskPattern);
|
||
}
|
||
},
|
||
|
||
getErrorCorrectPolynomial: function (errorCorrectLength) {
|
||
|
||
var a = new QRCode.Polynomial([1], 0);
|
||
|
||
for (var i = 0; i < errorCorrectLength; i++) {
|
||
a = a.multiply(new QRCode.Polynomial([1, QRCode.Math.gexp(i)], 0));
|
||
}
|
||
|
||
return a;
|
||
},
|
||
|
||
getLengthInBits: function (mode, type) {
|
||
|
||
if (1 <= type && type < 10) {
|
||
|
||
// 1 - 9
|
||
|
||
switch (mode) {
|
||
case QRCode.Mode.MODE_NUMBER: return 10;
|
||
case QRCode.Mode.MODE_ALPHA_NUM: return 9;
|
||
case QRCode.Mode.MODE_8BIT_BYTE: return 8;
|
||
case QRCode.Mode.MODE_KANJI: return 8;
|
||
default:
|
||
throw new Error("mode:" + mode);
|
||
}
|
||
|
||
} else if (type < 27) {
|
||
|
||
// 10 - 26
|
||
|
||
switch (mode) {
|
||
case QRCode.Mode.MODE_NUMBER: return 12;
|
||
case QRCode.Mode.MODE_ALPHA_NUM: return 11;
|
||
case QRCode.Mode.MODE_8BIT_BYTE: return 16;
|
||
case QRCode.Mode.MODE_KANJI: return 10;
|
||
default:
|
||
throw new Error("mode:" + mode);
|
||
}
|
||
|
||
} else if (type < 41) {
|
||
|
||
// 27 - 40
|
||
|
||
switch (mode) {
|
||
case QRCode.Mode.MODE_NUMBER: return 14;
|
||
case QRCode.Mode.MODE_ALPHA_NUM: return 13;
|
||
case QRCode.Mode.MODE_8BIT_BYTE: return 16;
|
||
case QRCode.Mode.MODE_KANJI: return 12;
|
||
default:
|
||
throw new Error("mode:" + mode);
|
||
}
|
||
|
||
} else {
|
||
throw new Error("type:" + type);
|
||
}
|
||
},
|
||
|
||
getLostPoint: function (qrCode) {
|
||
|
||
var moduleCount = qrCode.getModuleCount();
|
||
|
||
var lostPoint = 0;
|
||
|
||
// LEVEL1
|
||
|
||
for (var row = 0; row < moduleCount; row++) {
|
||
|
||
for (var col = 0; col < moduleCount; col++) {
|
||
|
||
var sameCount = 0;
|
||
var dark = qrCode.isDark(row, col);
|
||
|
||
for (var r = -1; r <= 1; r++) {
|
||
|
||
if (row + r < 0 || moduleCount <= row + r) {
|
||
continue;
|
||
}
|
||
|
||
for (var c = -1; c <= 1; c++) {
|
||
|
||
if (col + c < 0 || moduleCount <= col + c) {
|
||
continue;
|
||
}
|
||
|
||
if (r == 0 && c == 0) {
|
||
continue;
|
||
}
|
||
|
||
if (dark == qrCode.isDark(row + r, col + c)) {
|
||
sameCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (sameCount > 5) {
|
||
lostPoint += (3 + sameCount - 5);
|
||
}
|
||
}
|
||
}
|
||
|
||
// LEVEL2
|
||
|
||
for (var row = 0; row < moduleCount - 1; row++) {
|
||
for (var col = 0; col < moduleCount - 1; col++) {
|
||
var count = 0;
|
||
if (qrCode.isDark(row, col)) count++;
|
||
if (qrCode.isDark(row + 1, col)) count++;
|
||
if (qrCode.isDark(row, col + 1)) count++;
|
||
if (qrCode.isDark(row + 1, col + 1)) count++;
|
||
if (count == 0 || count == 4) {
|
||
lostPoint += 3;
|
||
}
|
||
}
|
||
}
|
||
|
||
// LEVEL3
|
||
|
||
for (var row = 0; row < moduleCount; row++) {
|
||
for (var col = 0; col < moduleCount - 6; col++) {
|
||
if (qrCode.isDark(row, col)
|
||
&& !qrCode.isDark(row, col + 1)
|
||
&& qrCode.isDark(row, col + 2)
|
||
&& qrCode.isDark(row, col + 3)
|
||
&& qrCode.isDark(row, col + 4)
|
||
&& !qrCode.isDark(row, col + 5)
|
||
&& qrCode.isDark(row, col + 6)) {
|
||
lostPoint += 40;
|
||
}
|
||
}
|
||
}
|
||
|
||
for (var col = 0; col < moduleCount; col++) {
|
||
for (var row = 0; row < moduleCount - 6; row++) {
|
||
if (qrCode.isDark(row, col)
|
||
&& !qrCode.isDark(row + 1, col)
|
||
&& qrCode.isDark(row + 2, col)
|
||
&& qrCode.isDark(row + 3, col)
|
||
&& qrCode.isDark(row + 4, col)
|
||
&& !qrCode.isDark(row + 5, col)
|
||
&& qrCode.isDark(row + 6, col)) {
|
||
lostPoint += 40;
|
||
}
|
||
}
|
||
}
|
||
|
||
// LEVEL4
|
||
|
||
var darkCount = 0;
|
||
|
||
for (var col = 0; col < moduleCount; col++) {
|
||
for (var row = 0; row < moduleCount; row++) {
|
||
if (qrCode.isDark(row, col)) {
|
||
darkCount++;
|
||
}
|
||
}
|
||
}
|
||
|
||
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
|
||
lostPoint += ratio * 10;
|
||
|
||
return lostPoint;
|
||
}
|
||
|
||
};
|
||
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRMath
|
||
//---------------------------------------------------------------------
|
||
|
||
QRCode.Math = {
|
||
|
||
glog: function (n) {
|
||
|
||
if (n < 1) {
|
||
throw new Error("glog(" + n + ")");
|
||
}
|
||
|
||
return QRCode.Math.LOG_TABLE[n];
|
||
},
|
||
|
||
gexp: function (n) {
|
||
|
||
while (n < 0) {
|
||
n += 255;
|
||
}
|
||
|
||
while (n >= 256) {
|
||
n -= 255;
|
||
}
|
||
|
||
return QRCode.Math.EXP_TABLE[n];
|
||
},
|
||
|
||
EXP_TABLE: new Array(256),
|
||
|
||
LOG_TABLE: new Array(256)
|
||
|
||
};
|
||
|
||
for (var i = 0; i < 8; i++) {
|
||
QRCode.Math.EXP_TABLE[i] = 1 << i;
|
||
}
|
||
for (var i = 8; i < 256; i++) {
|
||
QRCode.Math.EXP_TABLE[i] = QRCode.Math.EXP_TABLE[i - 4]
|
||
^ QRCode.Math.EXP_TABLE[i - 5]
|
||
^ QRCode.Math.EXP_TABLE[i - 6]
|
||
^ QRCode.Math.EXP_TABLE[i - 8];
|
||
}
|
||
for (var i = 0; i < 255; i++) {
|
||
QRCode.Math.LOG_TABLE[QRCode.Math.EXP_TABLE[i]] = i;
|
||
}
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRPolynomial
|
||
//---------------------------------------------------------------------
|
||
|
||
QRCode.Polynomial = function (num, shift) {
|
||
|
||
if (num.length == undefined) {
|
||
throw new Error(num.length + "/" + shift);
|
||
}
|
||
|
||
var offset = 0;
|
||
|
||
while (offset < num.length && num[offset] == 0) {
|
||
offset++;
|
||
}
|
||
|
||
this.num = new Array(num.length - offset + shift);
|
||
for (var i = 0; i < num.length - offset; i++) {
|
||
this.num[i] = num[i + offset];
|
||
}
|
||
}
|
||
|
||
QRCode.Polynomial.prototype = {
|
||
|
||
get: function (index) {
|
||
return this.num[index];
|
||
},
|
||
|
||
getLength: function () {
|
||
return this.num.length;
|
||
},
|
||
|
||
multiply: function (e) {
|
||
|
||
var num = new Array(this.getLength() + e.getLength() - 1);
|
||
|
||
for (var i = 0; i < this.getLength(); i++) {
|
||
for (var j = 0; j < e.getLength(); j++) {
|
||
num[i + j] ^= QRCode.Math.gexp(QRCode.Math.glog(this.get(i)) + QRCode.Math.glog(e.get(j)));
|
||
}
|
||
}
|
||
|
||
return new QRCode.Polynomial(num, 0);
|
||
},
|
||
|
||
mod: function (e) {
|
||
|
||
if (this.getLength() - e.getLength() < 0) {
|
||
return this;
|
||
}
|
||
|
||
var ratio = QRCode.Math.glog(this.get(0)) - QRCode.Math.glog(e.get(0));
|
||
|
||
var num = new Array(this.getLength());
|
||
|
||
for (var i = 0; i < this.getLength(); i++) {
|
||
num[i] = this.get(i);
|
||
}
|
||
|
||
for (var i = 0; i < e.getLength(); i++) {
|
||
num[i] ^= QRCode.Math.gexp(QRCode.Math.glog(e.get(i)) + ratio);
|
||
}
|
||
|
||
// recursive call
|
||
return new QRCode.Polynomial(num, 0).mod(e);
|
||
}
|
||
};
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRRSBlock
|
||
//---------------------------------------------------------------------
|
||
|
||
QRCode.RSBlock = function (totalCount, dataCount) {
|
||
this.totalCount = totalCount;
|
||
this.dataCount = dataCount;
|
||
}
|
||
|
||
QRCode.RSBlock.RS_BLOCK_TABLE = [
|
||
|
||
// L
|
||
// M
|
||
// Q
|
||
// H
|
||
|
||
// 1
|
||
[1, 26, 19],
|
||
[1, 26, 16],
|
||
[1, 26, 13],
|
||
[1, 26, 9],
|
||
|
||
// 2
|
||
[1, 44, 34],
|
||
[1, 44, 28],
|
||
[1, 44, 22],
|
||
[1, 44, 16],
|
||
|
||
// 3
|
||
[1, 70, 55],
|
||
[1, 70, 44],
|
||
[2, 35, 17],
|
||
[2, 35, 13],
|
||
|
||
// 4
|
||
[1, 100, 80],
|
||
[2, 50, 32],
|
||
[2, 50, 24],
|
||
[4, 25, 9],
|
||
|
||
// 5
|
||
[1, 134, 108],
|
||
[2, 67, 43],
|
||
[2, 33, 15, 2, 34, 16],
|
||
[2, 33, 11, 2, 34, 12],
|
||
|
||
// 6
|
||
[2, 86, 68],
|
||
[4, 43, 27],
|
||
[4, 43, 19],
|
||
[4, 43, 15],
|
||
|
||
// 7
|
||
[2, 98, 78],
|
||
[4, 49, 31],
|
||
[2, 32, 14, 4, 33, 15],
|
||
[4, 39, 13, 1, 40, 14],
|
||
|
||
// 8
|
||
[2, 121, 97],
|
||
[2, 60, 38, 2, 61, 39],
|
||
[4, 40, 18, 2, 41, 19],
|
||
[4, 40, 14, 2, 41, 15],
|
||
|
||
// 9
|
||
[2, 146, 116],
|
||
[3, 58, 36, 2, 59, 37],
|
||
[4, 36, 16, 4, 37, 17],
|
||
[4, 36, 12, 4, 37, 13],
|
||
|
||
// 10
|
||
[2, 86, 68, 2, 87, 69],
|
||
[4, 69, 43, 1, 70, 44],
|
||
[6, 43, 19, 2, 44, 20],
|
||
[6, 43, 15, 2, 44, 16]
|
||
|
||
];
|
||
|
||
QRCode.RSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
|
||
|
||
var rsBlock = QRCode.RSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
|
||
|
||
if (rsBlock == undefined) {
|
||
throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
|
||
}
|
||
|
||
var length = rsBlock.length / 3;
|
||
|
||
var list = new Array();
|
||
|
||
for (var i = 0; i < length; i++) {
|
||
|
||
var count = rsBlock[i * 3 + 0];
|
||
var totalCount = rsBlock[i * 3 + 1];
|
||
var dataCount = rsBlock[i * 3 + 2];
|
||
|
||
for (var j = 0; j < count; j++) {
|
||
list.push(new QRCode.RSBlock(totalCount, dataCount));
|
||
}
|
||
}
|
||
|
||
return list;
|
||
};
|
||
|
||
QRCode.RSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) {
|
||
|
||
switch (errorCorrectLevel) {
|
||
case QRCode.ErrorCorrectLevel.L:
|
||
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
|
||
case QRCode.ErrorCorrectLevel.M:
|
||
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
|
||
case QRCode.ErrorCorrectLevel.Q:
|
||
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
|
||
case QRCode.ErrorCorrectLevel.H:
|
||
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
|
||
default:
|
||
return undefined;
|
||
}
|
||
};
|
||
|
||
//---------------------------------------------------------------------
|
||
// QRBitBuffer
|
||
//---------------------------------------------------------------------
|
||
|
||
QRCode.BitBuffer = function () {
|
||
this.buffer = new Array();
|
||
this.length = 0;
|
||
}
|
||
|
||
QRCode.BitBuffer.prototype = {
|
||
|
||
get: function (index) {
|
||
var bufIndex = Math.floor(index / 8);
|
||
return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
|
||
},
|
||
|
||
put: function (num, length) {
|
||
for (var i = 0; i < length; i++) {
|
||
this.putBit(((num >>> (length - i - 1)) & 1) == 1);
|
||
}
|
||
},
|
||
|
||
getLengthInBits: function () {
|
||
return this.length;
|
||
},
|
||
|
||
putBit: function (bit) {
|
||
|
||
var bufIndex = Math.floor(this.length / 8);
|
||
if (this.buffer.length <= bufIndex) {
|
||
this.buffer.push(0);
|
||
}
|
||
|
||
if (bit) {
|
||
this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
|
||
}
|
||
|
||
this.length++;
|
||
}
|
||
};
|
||
})();
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
/*
|
||
Copyright (c) 2011 Stefan Thomas
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
*/
|
||
|
||
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/1a7fc9d063f864058809d06ef4542af40be3558f/src/bitcoin.js
|
||
(function (exports) {
|
||
var Bitcoin = exports;
|
||
})(
|
||
'object' === typeof module ? module.exports : (window.Bitcoin = {})
|
||
);
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/c952aaeb3ee472e3776655b8ea07299ebed702c7/src/base58.js
|
||
(function (Bitcoin) {
|
||
Bitcoin.Base58 = {
|
||
alphabet: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",
|
||
validRegex: /^[1-9A-HJ-NP-Za-km-z]+$/,
|
||
base: BigInteger.valueOf(58),
|
||
|
||
/**
|
||
* Convert a byte array to a base58-encoded string.
|
||
*
|
||
* Written by Mike Hearn for BitcoinJ.
|
||
* Copyright (c) 2011 Google Inc.
|
||
*
|
||
* Ported to JavaScript by Stefan Thomas.
|
||
*/
|
||
encode: function (input) {
|
||
var bi = BigInteger.fromByteArrayUnsigned(input);
|
||
var chars = [];
|
||
|
||
while (bi.compareTo(B58.base) >= 0) {
|
||
var mod = bi.mod(B58.base);
|
||
chars.unshift(B58.alphabet[mod.intValue()]);
|
||
bi = bi.subtract(mod).divide(B58.base);
|
||
}
|
||
chars.unshift(B58.alphabet[bi.intValue()]);
|
||
|
||
// Convert leading zeros too.
|
||
for (var i = 0; i < input.length; i++) {
|
||
if (input[i] == 0x00) {
|
||
chars.unshift(B58.alphabet[0]);
|
||
} else break;
|
||
}
|
||
|
||
return chars.join('');
|
||
},
|
||
|
||
/**
|
||
* Convert a base58-encoded string to a byte array.
|
||
*
|
||
* Written by Mike Hearn for BitcoinJ.
|
||
* Copyright (c) 2011 Google Inc.
|
||
*
|
||
* Ported to JavaScript by Stefan Thomas.
|
||
*/
|
||
decode: function (input) {
|
||
var bi = BigInteger.valueOf(0);
|
||
var leadingZerosNum = 0;
|
||
for (var i = input.length - 1; i >= 0; i--) {
|
||
var alphaIndex = B58.alphabet.indexOf(input[i]);
|
||
if (alphaIndex < 0) {
|
||
throw "Invalid character";
|
||
}
|
||
bi = bi.add(BigInteger.valueOf(alphaIndex)
|
||
.multiply(B58.base.pow(input.length - 1 - i)));
|
||
|
||
// This counts leading zero bytes
|
||
if (input[i] == "1") leadingZerosNum++;
|
||
else leadingZerosNum = 0;
|
||
}
|
||
var bytes = bi.toByteArrayUnsigned();
|
||
|
||
// Add leading zeros
|
||
while (leadingZerosNum-- > 0) bytes.unshift(0);
|
||
|
||
return bytes;
|
||
}
|
||
};
|
||
|
||
var B58 = Bitcoin.Base58;
|
||
})(
|
||
'undefined' != typeof Bitcoin ? Bitcoin : module.exports
|
||
);
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/09e8c6e184d6501a0c2c59d73ca64db5c0d3eb95/src/address.js
|
||
Bitcoin.Address = function (bytes) {
|
||
if ("string" == typeof bytes) {
|
||
bytes = Bitcoin.Address.decodeString(bytes);
|
||
}
|
||
this.hash = bytes;
|
||
this.version = Bitcoin.Address.networkVersion;
|
||
};
|
||
|
||
Bitcoin.Address.networkVersion = 0x30; // mainnet
|
||
|
||
/**
|
||
* Serialize this object as a standard Bitcoin address.
|
||
*
|
||
* Returns the address as a base58-encoded string in the standardized format.
|
||
*/
|
||
Bitcoin.Address.prototype.toString = function () {
|
||
// Get a copy of the hash
|
||
var hash = this.hash.slice(0);
|
||
|
||
// Version
|
||
hash.unshift(this.version);
|
||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true });
|
||
var bytes = hash.concat(checksum.slice(0, 4));
|
||
return Bitcoin.Base58.encode(bytes);
|
||
};
|
||
|
||
Bitcoin.Address.prototype.getHashBase64 = function () {
|
||
return Crypto.util.bytesToBase64(this.hash);
|
||
};
|
||
|
||
/**
|
||
* Parse a Bitcoin address contained in a string.
|
||
*/
|
||
Bitcoin.Address.decodeString = function (string) {
|
||
var bytes = Bitcoin.Base58.decode(string);
|
||
var hash = bytes.slice(0, 21);
|
||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true });
|
||
|
||
if (checksum[0] != bytes[21] ||
|
||
checksum[1] != bytes[22] ||
|
||
checksum[2] != bytes[23] ||
|
||
checksum[3] != bytes[24]) {
|
||
throw "Checksum validation failed!";
|
||
}
|
||
|
||
var version = hash.shift();
|
||
|
||
if (version != 0) {
|
||
throw "Version " + version + " not supported!";
|
||
}
|
||
|
||
return hash;
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/e90780d3d3b8fc0d027d2bcb38b80479902f223e/src/ecdsa.js
|
||
Bitcoin.ECDSA = (function () {
|
||
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||
var rng = new SecureRandom();
|
||
|
||
var P_OVER_FOUR = null;
|
||
|
||
function implShamirsTrick(P, k, Q, l) {
|
||
var m = Math.max(k.bitLength(), l.bitLength());
|
||
var Z = P.add2D(Q);
|
||
var R = P.curve.getInfinity();
|
||
|
||
for (var i = m - 1; i >= 0; --i) {
|
||
R = R.twice2D();
|
||
|
||
R.z = BigInteger.ONE;
|
||
|
||
if (k.testBit(i)) {
|
||
if (l.testBit(i)) {
|
||
R = R.add2D(Z);
|
||
} else {
|
||
R = R.add2D(P);
|
||
}
|
||
} else {
|
||
if (l.testBit(i)) {
|
||
R = R.add2D(Q);
|
||
}
|
||
}
|
||
}
|
||
|
||
return R;
|
||
};
|
||
|
||
var ECDSA = {
|
||
getBigRandom: function (limit) {
|
||
return new BigInteger(limit.bitLength(), rng)
|
||
.mod(limit.subtract(BigInteger.ONE))
|
||
.add(BigInteger.ONE);
|
||
},
|
||
sign: function (hash, priv) {
|
||
var d = priv;
|
||
var n = ecparams.getN();
|
||
var e = BigInteger.fromByteArrayUnsigned(hash);
|
||
|
||
do {
|
||
var k = ECDSA.getBigRandom(n);
|
||
var G = ecparams.getG();
|
||
var Q = G.multiply(k);
|
||
var r = Q.getX().toBigInteger().mod(n);
|
||
} while (r.compareTo(BigInteger.ZERO) <= 0);
|
||
|
||
var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
|
||
|
||
return ECDSA.serializeSig(r, s);
|
||
},
|
||
|
||
verify: function (hash, sig, pubkey) {
|
||
var r, s;
|
||
if (Bitcoin.Util.isArray(sig)) {
|
||
var obj = ECDSA.parseSig(sig);
|
||
r = obj.r;
|
||
s = obj.s;
|
||
} else if ("object" === typeof sig && sig.r && sig.s) {
|
||
r = sig.r;
|
||
s = sig.s;
|
||
} else {
|
||
throw "Invalid value for signature";
|
||
}
|
||
|
||
var Q;
|
||
if (pubkey instanceof ec.PointFp) {
|
||
Q = pubkey;
|
||
} else if (Bitcoin.Util.isArray(pubkey)) {
|
||
Q = EllipticCurve.PointFp.decodeFrom(ecparams.getCurve(), pubkey);
|
||
} else {
|
||
throw "Invalid format for pubkey value, must be byte array or ec.PointFp";
|
||
}
|
||
var e = BigInteger.fromByteArrayUnsigned(hash);
|
||
|
||
return ECDSA.verifyRaw(e, r, s, Q);
|
||
},
|
||
|
||
verifyRaw: function (e, r, s, Q) {
|
||
var n = ecparams.getN();
|
||
var G = ecparams.getG();
|
||
|
||
if (r.compareTo(BigInteger.ONE) < 0 ||
|
||
r.compareTo(n) >= 0)
|
||
return false;
|
||
|
||
if (s.compareTo(BigInteger.ONE) < 0 ||
|
||
s.compareTo(n) >= 0)
|
||
return false;
|
||
|
||
var c = s.modInverse(n);
|
||
|
||
var u1 = e.multiply(c).mod(n);
|
||
var u2 = r.multiply(c).mod(n);
|
||
|
||
// TODO(!!!): For some reason Shamir's trick isn't working with
|
||
// signed message verification!? Probably an implementation
|
||
// error!
|
||
//var point = implShamirsTrick(G, u1, Q, u2);
|
||
var point = G.multiply(u1).add(Q.multiply(u2));
|
||
|
||
var v = point.getX().toBigInteger().mod(n);
|
||
|
||
return v.equals(r);
|
||
},
|
||
|
||
/**
|
||
* Serialize a signature into DER format.
|
||
*
|
||
* Takes two BigIntegers representing r and s and returns a byte array.
|
||
*/
|
||
serializeSig: function (r, s) {
|
||
var rBa = r.toByteArraySigned();
|
||
var sBa = s.toByteArraySigned();
|
||
|
||
var sequence = [];
|
||
sequence.push(0x02); // INTEGER
|
||
sequence.push(rBa.length);
|
||
sequence = sequence.concat(rBa);
|
||
|
||
sequence.push(0x02); // INTEGER
|
||
sequence.push(sBa.length);
|
||
sequence = sequence.concat(sBa);
|
||
|
||
sequence.unshift(sequence.length);
|
||
sequence.unshift(0x30); // SEQUENCE
|
||
|
||
return sequence;
|
||
},
|
||
|
||
/**
|
||
* Parses a byte array containing a DER-encoded signature.
|
||
*
|
||
* This function will return an object of the form:
|
||
*
|
||
* {
|
||
* r: BigInteger,
|
||
* s: BigInteger
|
||
* }
|
||
*/
|
||
parseSig: function (sig) {
|
||
var cursor;
|
||
if (sig[0] != 0x30)
|
||
throw new Error("Signature not a valid DERSequence");
|
||
|
||
cursor = 2;
|
||
if (sig[cursor] != 0x02)
|
||
throw new Error("First element in signature must be a DERInteger"); ;
|
||
var rBa = sig.slice(cursor + 2, cursor + 2 + sig[cursor + 1]);
|
||
|
||
cursor += 2 + sig[cursor + 1];
|
||
if (sig[cursor] != 0x02)
|
||
throw new Error("Second element in signature must be a DERInteger");
|
||
var sBa = sig.slice(cursor + 2, cursor + 2 + sig[cursor + 1]);
|
||
|
||
cursor += 2 + sig[cursor + 1];
|
||
|
||
//if (cursor != sig.length)
|
||
// throw new Error("Extra bytes in signature");
|
||
|
||
var r = BigInteger.fromByteArrayUnsigned(rBa);
|
||
var s = BigInteger.fromByteArrayUnsigned(sBa);
|
||
|
||
return { r: r, s: s };
|
||
},
|
||
|
||
parseSigCompact: function (sig) {
|
||
if (sig.length !== 65) {
|
||
throw "Signature has the wrong length";
|
||
}
|
||
|
||
// Signature is prefixed with a type byte storing three bits of
|
||
// information.
|
||
var i = sig[0] - 27;
|
||
if (i < 0 || i > 7) {
|
||
throw "Invalid signature type";
|
||
}
|
||
|
||
var n = ecparams.getN();
|
||
var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n);
|
||
var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n);
|
||
|
||
return { r: r, s: s, i: i };
|
||
},
|
||
|
||
/**
|
||
* Recover a public key from a signature.
|
||
*
|
||
* See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
|
||
* Key Recovery Operation".
|
||
*
|
||
* http://www.secg.org/download/aid-780/sec1-v2.pdf
|
||
*/
|
||
recoverPubKey: function (r, s, hash, i) {
|
||
// The recovery parameter i has two bits.
|
||
i = i & 3;
|
||
|
||
// The less significant bit specifies whether the y coordinate
|
||
// of the compressed point is even or not.
|
||
var isYEven = i & 1;
|
||
|
||
// The more significant bit specifies whether we should use the
|
||
// first or second candidate key.
|
||
var isSecondKey = i >> 1;
|
||
|
||
var n = ecparams.getN();
|
||
var G = ecparams.getG();
|
||
var curve = ecparams.getCurve();
|
||
var p = curve.getQ();
|
||
var a = curve.getA().toBigInteger();
|
||
var b = curve.getB().toBigInteger();
|
||
|
||
// We precalculate (p + 1) / 4 where p is if the field order
|
||
if (!P_OVER_FOUR) {
|
||
P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4));
|
||
}
|
||
|
||
// 1.1 Compute x
|
||
var x = isSecondKey ? r.add(n) : r;
|
||
|
||
// 1.3 Convert x to point
|
||
var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p);
|
||
var beta = alpha.modPow(P_OVER_FOUR, p);
|
||
|
||
var xorOdd = beta.isEven() ? (i % 2) : ((i + 1) % 2);
|
||
// If beta is even, but y isn't or vice versa, then convert it,
|
||
// otherwise we're done and y == beta.
|
||
var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta);
|
||
|
||
// 1.4 Check that nR is at infinity
|
||
var R = new EllipticCurve.PointFp(curve,
|
||
curve.fromBigInteger(x),
|
||
curve.fromBigInteger(y));
|
||
R.validate();
|
||
|
||
// 1.5 Compute e from M
|
||
var e = BigInteger.fromByteArrayUnsigned(hash);
|
||
var eNeg = BigInteger.ZERO.subtract(e).mod(n);
|
||
|
||
// 1.6 Compute Q = r^-1 (sR - eG)
|
||
var rInv = r.modInverse(n);
|
||
var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv);
|
||
|
||
Q.validate();
|
||
if (!ECDSA.verifyRaw(e, r, s, Q)) {
|
||
throw "Pubkey recovery unsuccessful";
|
||
}
|
||
|
||
var pubKey = new Bitcoin.ECKey();
|
||
pubKey.pub = Q;
|
||
return pubKey;
|
||
},
|
||
|
||
/**
|
||
* Calculate pubkey extraction parameter.
|
||
*
|
||
* When extracting a pubkey from a signature, we have to
|
||
* distinguish four different cases. Rather than putting this
|
||
* burden on the verifier, Bitcoin includes a 2-bit value with the
|
||
* signature.
|
||
*
|
||
* This function simply tries all four cases and returns the value
|
||
* that resulted in a successful pubkey recovery.
|
||
*/
|
||
calcPubkeyRecoveryParam: function (address, r, s, hash) {
|
||
for (var i = 0; i < 4; i++) {
|
||
try {
|
||
var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
|
||
if (pubkey.getBitcoinAddress().toString() == address) {
|
||
return i;
|
||
}
|
||
} catch (e) { }
|
||
}
|
||
throw "Unable to find valid recovery factor";
|
||
}
|
||
};
|
||
|
||
return ECDSA;
|
||
})();
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
//https://raw.github.com/pointbiz/bitcoinjs-lib/9b2f94a028a7bc9bed94e0722563e9ff1d8e8db8/src/eckey.js
|
||
Bitcoin.ECKey = (function () {
|
||
var ECDSA = Bitcoin.ECDSA;
|
||
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||
var rng = new SecureRandom();
|
||
|
||
var ECKey = function (input) {
|
||
if (!input) {
|
||
// Generate new key
|
||
var n = ecparams.getN();
|
||
this.priv = ECDSA.getBigRandom(n);
|
||
} else if (input instanceof BigInteger) {
|
||
// Input is a private key value
|
||
this.priv = input;
|
||
} else if (Bitcoin.Util.isArray(input)) {
|
||
// Prepend zero byte to prevent interpretation as negative integer
|
||
this.priv = BigInteger.fromByteArrayUnsigned(input);
|
||
} else if ("string" == typeof input) {
|
||
var bytes = null;
|
||
if (ECKey.isWalletImportFormat(input)) {
|
||
bytes = ECKey.decodeWalletImportFormat(input);
|
||
} else if (ECKey.isCompressedWalletImportFormat(input)) {
|
||
bytes = ECKey.decodeCompressedWalletImportFormat(input);
|
||
this.compressed = true;
|
||
} else if (ECKey.isMiniFormat(input)) {
|
||
bytes = Crypto.SHA256(input, { asBytes: true });
|
||
} else if (ECKey.isHexFormat(input)) {
|
||
bytes = Crypto.util.hexToBytes(input);
|
||
} else if (ECKey.isBase64Format(input)) {
|
||
bytes = Crypto.util.base64ToBytes(input);
|
||
}
|
||
|
||
if (bytes == null || bytes.length != 32) {
|
||
this.priv = null;
|
||
} else {
|
||
// Prepend zero byte to prevent interpretation as negative integer
|
||
this.priv = BigInteger.fromByteArrayUnsigned(bytes);
|
||
}
|
||
}
|
||
|
||
this.compressed = (this.compressed == undefined) ? !!ECKey.compressByDefault : this.compressed;
|
||
};
|
||
|
||
ECKey.privateKeyPrefix = 0xb0; // mainnet 0xb0 testnet 0xEF
|
||
|
||
/**
|
||
* Whether public keys should be returned compressed by default.
|
||
*/
|
||
ECKey.compressByDefault = false;
|
||
|
||
/**
|
||
* Set whether the public key should be returned compressed or not.
|
||
*/
|
||
ECKey.prototype.setCompressed = function (v) {
|
||
this.compressed = !!v;
|
||
if (this.pubPoint) this.pubPoint.compressed = this.compressed;
|
||
};
|
||
|
||
/*
|
||
* Return public key as a byte array in DER encoding
|
||
*/
|
||
ECKey.prototype.getPub = function () {
|
||
if (this.compressed) {
|
||
if (this.pubComp) return this.pubComp;
|
||
return this.pubComp = this.getPubPoint().getEncoded(1);
|
||
} else {
|
||
if (this.pubUncomp) return this.pubUncomp;
|
||
return this.pubUncomp = this.getPubPoint().getEncoded(0);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Return public point as ECPoint object.
|
||
*/
|
||
ECKey.prototype.getPubPoint = function () {
|
||
if (!this.pubPoint) {
|
||
this.pubPoint = ecparams.getG().multiply(this.priv);
|
||
this.pubPoint.compressed = this.compressed;
|
||
}
|
||
return this.pubPoint;
|
||
};
|
||
|
||
ECKey.prototype.getPubKeyHex = function () {
|
||
if (this.compressed) {
|
||
if (this.pubKeyHexComp) return this.pubKeyHexComp;
|
||
return this.pubKeyHexComp = Crypto.util.bytesToHex(this.getPub()).toString().toUpperCase();
|
||
} else {
|
||
if (this.pubKeyHexUncomp) return this.pubKeyHexUncomp;
|
||
return this.pubKeyHexUncomp = Crypto.util.bytesToHex(this.getPub()).toString().toUpperCase();
|
||
}
|
||
};
|
||
|
||
/**
|
||
* Get the pubKeyHash for this key.
|
||
*
|
||
* This is calculated as RIPE160(SHA256([encoded pubkey])) and returned as
|
||
* a byte array.
|
||
*/
|
||
ECKey.prototype.getPubKeyHash = function () {
|
||
if (this.compressed) {
|
||
if (this.pubKeyHashComp) return this.pubKeyHashComp;
|
||
return this.pubKeyHashComp = Bitcoin.Util.sha256ripe160(this.getPub());
|
||
} else {
|
||
if (this.pubKeyHashUncomp) return this.pubKeyHashUncomp;
|
||
return this.pubKeyHashUncomp = Bitcoin.Util.sha256ripe160(this.getPub());
|
||
}
|
||
};
|
||
|
||
ECKey.prototype.getBitcoinAddress = function () {
|
||
var hash = this.getPubKeyHash();
|
||
var addr = new Bitcoin.Address(hash);
|
||
return addr.toString();
|
||
};
|
||
|
||
/*
|
||
* Takes a public point as a hex string or byte array
|
||
*/
|
||
ECKey.prototype.setPub = function (pub) {
|
||
// byte array
|
||
if (Bitcoin.Util.isArray(pub)) {
|
||
pub = Crypto.util.bytesToHex(pub).toString().toUpperCase();
|
||
}
|
||
var ecPoint = ecparams.getCurve().decodePointHex(pub);
|
||
this.setCompressed(ecPoint.compressed);
|
||
this.pubPoint = ecPoint;
|
||
};
|
||
|
||
// Sipa Private Key Wallet Import Format
|
||
ECKey.prototype.getBitcoinWalletImportFormat = function () {
|
||
var bytes = this.getBitcoinPrivateKeyByteArray();
|
||
bytes.unshift(ECKey.privateKeyPrefix); // prepend 0x80 byte
|
||
if (this.compressed) bytes.push(0x01); // append 0x01 byte for compressed format
|
||
var checksum = Crypto.SHA256(Crypto.SHA256(bytes, { asBytes: true }), { asBytes: true });
|
||
bytes = bytes.concat(checksum.slice(0, 4));
|
||
var privWif = Bitcoin.Base58.encode(bytes);
|
||
return privWif;
|
||
};
|
||
|
||
// Private Key Hex Format
|
||
ECKey.prototype.getBitcoinHexFormat = function () {
|
||
return Crypto.util.bytesToHex(this.getBitcoinPrivateKeyByteArray()).toString().toUpperCase();
|
||
};
|
||
|
||
// Private Key Base64 Format
|
||
ECKey.prototype.getBitcoinBase64Format = function () {
|
||
return Crypto.util.bytesToBase64(this.getBitcoinPrivateKeyByteArray());
|
||
};
|
||
|
||
ECKey.prototype.getBitcoinPrivateKeyByteArray = function () {
|
||
// Get a copy of private key as a byte array
|
||
var bytes = this.priv.toByteArrayUnsigned();
|
||
// zero pad if private key is less than 32 bytes
|
||
while (bytes.length < 32) bytes.unshift(0x00);
|
||
return bytes;
|
||
};
|
||
|
||
ECKey.prototype.toString = function (format) {
|
||
format = format || "";
|
||
if (format.toString().toLowerCase() == "base64" || format.toString().toLowerCase() == "b64") {
|
||
return this.getBitcoinBase64Format();
|
||
}
|
||
// Wallet Import Format
|
||
else if (format.toString().toLowerCase() == "wif") {
|
||
return this.getBitcoinWalletImportFormat();
|
||
}
|
||
else {
|
||
return this.getBitcoinHexFormat();
|
||
}
|
||
};
|
||
|
||
ECKey.prototype.sign = function (hash) {
|
||
return ECDSA.sign(hash, this.priv);
|
||
};
|
||
|
||
ECKey.prototype.verify = function (hash, sig) {
|
||
return ECDSA.verify(hash, sig, this.getPub());
|
||
};
|
||
|
||
/**
|
||
* Parse a wallet import format private key contained in a string.
|
||
*/
|
||
ECKey.decodeWalletImportFormat = function (privStr) {
|
||
var bytes = Bitcoin.Base58.decode(privStr);
|
||
var hash = bytes.slice(0, 33);
|
||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true });
|
||
if (checksum[0] != bytes[33] ||
|
||
checksum[1] != bytes[34] ||
|
||
checksum[2] != bytes[35] ||
|
||
checksum[3] != bytes[36]) {
|
||
throw "Checksum validation failed!";
|
||
}
|
||
var version = hash.shift();
|
||
if (version != ECKey.privateKeyPrefix) {
|
||
throw "Version " + version + " not supported!";
|
||
}
|
||
return hash;
|
||
};
|
||
|
||
/**
|
||
* Parse a compressed wallet import format private key contained in a string.
|
||
*/
|
||
ECKey.decodeCompressedWalletImportFormat = function (privStr) {
|
||
var bytes = Bitcoin.Base58.decode(privStr);
|
||
var hash = bytes.slice(0, 34);
|
||
var checksum = Crypto.SHA256(Crypto.SHA256(hash, { asBytes: true }), { asBytes: true });
|
||
if (checksum[0] != bytes[34] ||
|
||
checksum[1] != bytes[35] ||
|
||
checksum[2] != bytes[36] ||
|
||
checksum[3] != bytes[37]) {
|
||
throw "Checksum validation failed!";
|
||
}
|
||
var version = hash.shift();
|
||
if (version != ECKey.privateKeyPrefix) {
|
||
throw "Version " + version + " not supported!";
|
||
}
|
||
hash.pop();
|
||
return hash;
|
||
};
|
||
|
||
// 64 characters [0-9A-F]
|
||
ECKey.isHexFormat = function (key) {
|
||
key = key.toString();
|
||
return /^[A-Fa-f0-9]{64}$/.test(key);
|
||
};
|
||
|
||
// 51 characters base58, always starts with a '6'
|
||
ECKey.isWalletImportFormat = function (key) {
|
||
key = key.toString();
|
||
return (ECKey.privateKeyPrefix == 0xb0) ?
|
||
(/^6[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{50}$/.test(key)) :
|
||
(/^9[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{50}$/.test(key));
|
||
};
|
||
|
||
// 52 characters base58
|
||
ECKey.isCompressedWalletImportFormat = function (key) {
|
||
key = key.toString();
|
||
return (ECKey.privateKeyPrefix == 0xb0) ?
|
||
(/^T[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{51}$/.test(key)) :
|
||
(/^c[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{51}$/.test(key));
|
||
};
|
||
|
||
// 44 characters
|
||
ECKey.isBase64Format = function (key) {
|
||
key = key.toString();
|
||
return (/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789=+\/]{44}$/.test(key));
|
||
};
|
||
|
||
// 22, 26 or 30 characters, always starts with an 'S'
|
||
ECKey.isMiniFormat = function (key) {
|
||
key = key.toString();
|
||
var validChars22 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21}$/.test(key);
|
||
var validChars26 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{25}$/.test(key);
|
||
var validChars30 = /^S[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{29}$/.test(key);
|
||
var testBytes = Crypto.SHA256(key + "?", { asBytes: true });
|
||
|
||
return ((testBytes[0] === 0x00 || testBytes[0] === 0x01) && (validChars22 || validChars26 || validChars30));
|
||
};
|
||
|
||
return ECKey;
|
||
})();
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
//https://raw.github.com/bitcoinjs/bitcoinjs-lib/09e8c6e184d6501a0c2c59d73ca64db5c0d3eb95/src/util.js
|
||
// Bitcoin utility functions
|
||
Bitcoin.Util = {
|
||
/**
|
||
* Cross-browser compatibility version of Array.isArray.
|
||
*/
|
||
isArray: Array.isArray || function (o) {
|
||
return Object.prototype.toString.call(o) === '[object Array]';
|
||
},
|
||
/**
|
||
* Create an array of a certain length filled with a specific value.
|
||
*/
|
||
makeFilledArray: function (len, val) {
|
||
var array = [];
|
||
var i = 0;
|
||
while (i < len) {
|
||
array[i++] = val;
|
||
}
|
||
return array;
|
||
},
|
||
/**
|
||
* Turn an integer into a "var_int".
|
||
*
|
||
* "var_int" is a variable length integer used by Bitcoin's binary format.
|
||
*
|
||
* Returns a byte array.
|
||
*/
|
||
numToVarInt: function (i) {
|
||
if (i < 0xfd) {
|
||
// unsigned char
|
||
return [i];
|
||
} else if (i <= 1 << 16) {
|
||
// unsigned short (LE)
|
||
return [0xfd, i >>> 8, i & 255];
|
||
} else if (i <= 1 << 32) {
|
||
// unsigned int (LE)
|
||
return [0xfe].concat(Crypto.util.wordsToBytes([i]));
|
||
} else {
|
||
// unsigned long long (LE)
|
||
return [0xff].concat(Crypto.util.wordsToBytes([i >>> 32, i]));
|
||
}
|
||
},
|
||
/**
|
||
* Parse a Bitcoin value byte array, returning a BigInteger.
|
||
*/
|
||
valueToBigInt: function (valueBuffer) {
|
||
if (valueBuffer instanceof BigInteger) return valueBuffer;
|
||
|
||
// Prepend zero byte to prevent interpretation as negative integer
|
||
return BigInteger.fromByteArrayUnsigned(valueBuffer);
|
||
},
|
||
/**
|
||
* Format a Bitcoin value as a string.
|
||
*
|
||
* Takes a BigInteger or byte-array and returns that amount of Bitcoins in a
|
||
* nice standard formatting.
|
||
*
|
||
* Examples:
|
||
* 12.3555
|
||
* 0.1234
|
||
* 900.99998888
|
||
* 34.00
|
||
*/
|
||
formatValue: function (valueBuffer) {
|
||
var value = this.valueToBigInt(valueBuffer).toString();
|
||
var integerPart = value.length > 8 ? value.substr(0, value.length - 8) : '0';
|
||
var decimalPart = value.length > 8 ? value.substr(value.length - 8) : value;
|
||
while (decimalPart.length < 8) decimalPart = "0" + decimalPart;
|
||
decimalPart = decimalPart.replace(/0*$/, '');
|
||
while (decimalPart.length < 2) decimalPart += "0";
|
||
return integerPart + "." + decimalPart;
|
||
},
|
||
/**
|
||
* Parse a floating point string as a Bitcoin value.
|
||
*
|
||
* Keep in mind that parsing user input is messy. You should always display
|
||
* the parsed value back to the user to make sure we understood his input
|
||
* correctly.
|
||
*/
|
||
parseValue: function (valueString) {
|
||
// TODO: Detect other number formats (e.g. comma as decimal separator)
|
||
var valueComp = valueString.split('.');
|
||
var integralPart = valueComp[0];
|
||
var fractionalPart = valueComp[1] || "0";
|
||
while (fractionalPart.length < 8) fractionalPart += "0";
|
||
fractionalPart = fractionalPart.replace(/^0+/g, '');
|
||
var value = BigInteger.valueOf(parseInt(integralPart));
|
||
value = value.multiply(BigInteger.valueOf(100000000));
|
||
value = value.add(BigInteger.valueOf(parseInt(fractionalPart)));
|
||
return value;
|
||
},
|
||
/**
|
||
* Calculate RIPEMD160(SHA256(data)).
|
||
*
|
||
* Takes an arbitrary byte array as inputs and returns the hash as a byte
|
||
* array.
|
||
*/
|
||
sha256ripe160: function (data) {
|
||
return Crypto.RIPEMD160(Crypto.SHA256(data, { asBytes: true }), { asBytes: true });
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style type="text/css">
|
||
.more { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDEvMDIvMTLltnQyAAAB1UlEQVQ4jYWTS04bQRCGv3q0x8gMYJCwknCGLDgLVwiH4grhLFaUXdhkQ0A8pBg/FOLpnmbhMYzxRKlNS1Vdf/31V5XknGnb+eXJCBjzbzu9OLu+azu845Opysej4wHmshF4uJ2TUrb3CV0gIBAKRboC5C2vdkDE9fdty6/xDegvXz+NgDbFUejZ+PjDgExmtpxS9vYwMe5u5iyX8RRoa5Ic+C4qx9KUN1MGu4E618yqJ5axAp44KA7ZL3eYzp/HKdVIw7WK8d6BuDvcod9TQlBEIOXEdPlElSoUJabIIs4Z7h9yNDwgqOMayLXw7epHVIBggrsgspZPUBQyiCgugRQji7TAVDF1XB2TlQoOYCqovkmpopS9fcoiM3ue0rOCYf8IU8NklWxiiOQ3EPXtWagIqo6KYWYEc4IGvMViA6RrnCJKVS9B8ypRHG1YKNa0Ur+C+MPt/I2BKWVZUO4FgvQ47PcptEDF+T2Z8TiZUMWIyGtpd+Bze5VTSqP57O/4YG+AN/RXbSiPkwmL5z/be/L+mM4vT2JKeUW7EXD1erMz/Lo4u77f0K9DDhdA1XG11jh9vWBb99Z9gAg5QZ2hzpmUa0RSW4f/gqSY0s3Vz+tufEjvHS8Tg6BXC7qVbQAAAABJRU5ErkJggg==)
|
||
no-repeat left center; width: 17px; height: 17px; display: inline-block; float: right; }
|
||
.less { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAARCAYAAAA7bUf6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAAAWdEVYdENyZWF0aW9uIFRpbWUAMDEvMDIvMTLltnQyAAABuklEQVQ4ja2US25TQRBFT336OSEY5ESyBfEakNiLt0AW5S2QvQQxAiZIYBwSz/yByH7dxcB2bPMME+hJS/W5fetWVUtE8K/HfzdcXfdfqsr4onuGuRz4Jrdzcg6Gg9HfQYAxAqmlSMMlQJO5/oliE4AtQLcR++btZQ+wPVsvVXbTfXFGEMyWU9rVM0yMu/Gc5bJ+DdztxWcH3otKVzbPmyq5LnwfzSgEBMxlhqJEBFWVKKUgG66rur53oH7aOeWkUlJSRCBHZracssorlLXttHpCpzonaYukjmsiivDu08daAZIJ7oLIVg9BUQgQUVwSua5Z5AWmiqnj6pisVXAAU0F1J6WK0q6e024Fs4cplbXonFxgapisk00MkdiBqDd7oSKoOiqGmZHMSZrwPRYHIMfaKaKsyhI01oni6IaFYptSyiOIT27nOwaq5FyQrUAIC/nBhK+UErRSos55z4878CrneJyTnHOvquymf3mOb+hvy/jw+QuLh5/NORkORvsGrq77dc6xpr0RcH07y3oF8G04GN0f6HdEDhdA1XG1vXb6dsAa+3Z8AREiQwkoEeQoiBzocHDkf/wnvwC5IpRVsUDNUgAAAABJRU5ErkJggg==)
|
||
no-repeat left center; width: 17px; height: 17px; display: inline-block; float: right; }
|
||
.right { text-align: right; }
|
||
.walletarea { display: none; border: 2px solid green; }
|
||
.keyarea { font-family: Courier New; height: 110px; text-align: left; position: relative; padding: 5px; }
|
||
.keyarea .public { float: left; }
|
||
.keyarea .pubaddress { display: inline-block; height: 40px; padding: 0 0 0 10px; float: left; }
|
||
.keyarea .privwif { margin: 0; float: right; text-align: right; padding: 0 10px 0 0; position: relative; }
|
||
.keyarea .label { text-decoration: underline; }
|
||
.keyarea .output { display: block; }
|
||
.keyarea .qrcode_public { display: inline-block; float: left; }
|
||
.keyarea .qrcode_private { display: inline-block; position: relative; top: 28px; float: right; }
|
||
.pubkeyhex { word-wrap: break-word; }
|
||
.faqs ol { padding: 0 0 0 25px; }
|
||
.faqs li { padding: 3px 0; }
|
||
body { font-family: Arial; }
|
||
#main { position: relative; text-align: center; margin: 0px auto; width: 945px; }
|
||
#logo { width: 578px; height: 80px; }
|
||
#generate { font-family: Courier New; height: 158px; text-align: left; position: relative; padding: 5px; border: 2px solid green; }
|
||
#generate span { padding: 5px 5px 0 5px; }
|
||
#menu { visibility: hidden; }
|
||
#culturemenu { text-align: right; padding: 0 20px; }
|
||
#culturemenu span { padding: 3px; }
|
||
#culturemenu .selected { text-decoration: none; color: #000000; }
|
||
|
||
#paperarea { min-height: 120px; display: none; }
|
||
#paperarea .keyarea { border: 2px solid green; border-top: 0; }
|
||
#paperarea .keyarea.art { display: block; height: auto; border: 0; font-family: Ubuntu, Arial; padding: 0; margin: 0; }
|
||
#paperarea .artwallet .papersvg { width: 486px; height: 261px; border: 0; margin: 0; padding: 0; left: 0; }
|
||
#paperarea .artwallet .qrcode_public { top: 52px; left: 17px; z-index: 100; margin: 0; float: none; display: block; position: absolute; background-color: #FFFFFF;
|
||
padding: 5px 5px 2px 5px; }
|
||
#paperarea .artwallet .qrcode_private { top: 104px; left: 360px; z-index: 100; margin: 0; float: none; display: block; position: absolute; background-color: #FFFFFF;
|
||
padding: 5px 5px 2px 5px; }
|
||
#paperarea .artwallet .btcaddress
|
||
{
|
||
position: absolute; top: 240px; left: 139px; z-index: 100; font-size: 10px; background-color: transparent;
|
||
font-weight:bold; color: #000000; margin: 0;
|
||
-webkit-transform-origin:top left; -webkit-transform:rotate(-90deg);
|
||
-moz-transform-origin:top left; -moz-transform:rotate(-90deg);
|
||
-ms-transform-origin:top left; -ms-transform:rotate(-90deg);
|
||
-o-transform-origin:top left; -o-transform:rotate(-90deg);
|
||
transform-origin:top left; transform:rotate(-90deg);
|
||
}
|
||
#paperarea .artwallet .btcprivwif
|
||
{
|
||
position: absolute; top: 236px; left: 346px; z-index: 100; font-size: 7px; background-color: transparent;
|
||
font-weight:bold; color: #000000; margin: 0;
|
||
-webkit-transform-origin:top left; -webkit-transform:rotate(-90deg);
|
||
-moz-transform-origin:top left; -moz-transform:rotate(-90deg);
|
||
-ms-transform-origin:top left; -ms-transform:rotate(-90deg);
|
||
-o-transform-origin:top left; -o-transform:rotate(-90deg);
|
||
transform-origin:top left; transform:rotate(-90deg);
|
||
}
|
||
#bulkarea .body { padding: 5px 0 0 0; }
|
||
#bulkarea .format { font-style: italic; font-size: 90%; }
|
||
#bulktextarea { font-size: 90%; width: 98%; margin: 4px 0 0 0; }
|
||
.bulkquestion { padding: 10px 15px; text-align: left; cursor: pointer; }
|
||
.bulkquestion:hover, .expandable:hover { color: #77777A; }
|
||
.bulkanswer { padding: 0 15px 10px 25px; text-align: left; display: none; font-size: 80%; }
|
||
.bulkfaq { border: 0; border-top: 2px solid green; }
|
||
#brainarea .keyarea { visibility: hidden; min-height: 110px; }
|
||
#detailkeyarea { padding: 10px; }
|
||
#detailarea { margin: 0; text-align: left; }
|
||
#detailarea .notes { text-align: left; font-size: 80%; padding: 0 0 20px 0; }
|
||
#detailarea .item { margin: 10px 0; position: relative; }
|
||
#detailarea .label { display: block; text-decoration: underline; }
|
||
#detailarea .output { display: block; min-height: 20px; }
|
||
#detailarea #detailqrcodepublic { position: relative; float: left; margin: 0 10px 0 0; }
|
||
#detailarea #detailqrcodepubliccomp { position: relative; float: right; margin: 0 0 0 10px; }
|
||
#detailarea #detailqrcodeprivate { position: relative; float: left; margin: 0 10px 0 0; }
|
||
#detailarea #detailqrcodeprivatecomp { position: relative; float: right; margin: 0 0 0 10px; }
|
||
#vanityarea { text-align: left; }
|
||
#vanityarea .label { text-decoration: underline; }
|
||
#vanityarea .output { display: block; }
|
||
#vanityarea .notes { text-align: left; font-size: 80%; padding: 0 0 20px 0; }
|
||
#vanitystep1area { display: none; text-align: left; position: relative; padding: 15px; border-bottom: 2px solid green; }
|
||
#vanitystep1label { padding-left: 5px; }
|
||
#vanitystep2area { border-top: 2px solid green; display: block; padding: 15px; }
|
||
#vanitystep2inputs { padding: 0 15px 10px 15px; }
|
||
#vanitycalc { margin-top: 5px; }
|
||
|
||
.englishjson { text-align: center; padding: 40px 0 20px 0; }
|
||
.unittests { text-align: center; }
|
||
.unittests div { width: 894px; font-family: monospace; text-align: left; margin: auto; padding: 5px; border: 1px solid black; }
|
||
#testnet { font-family: Tahoma; display: none; background-color: Orange; color: #000000; border-radius: 5px; font-weight: bold; padding: 10px 0; margin: 0 auto 20px auto; }
|
||
|
||
/* IE8 */
|
||
.qrcodetable { border-width: 0px; border-style: none; border-color: #0000ff; border-collapse: collapse; }
|
||
.qrcodetddark { border-width: 0px; border-style: none; border-color: #0000ff; border-collapse: collapse; padding: 0; margin: 0; width: 2px; height: 2px; background-color: #000000; }
|
||
.qrcodetdlight { border-width: 0px; border-style: none; border-color: #0000ff; border-collapse: collapse; padding: 0; margin: 0; width: 2px; height: 2px; background-color: #ffffff; }
|
||
|
||
@media screen
|
||
{
|
||
#tagline { margin: 0 0 15px 0; font-style: italic; }
|
||
.menu { text-align: left; }
|
||
.menu .tab { border-top-left-radius: 5px; border-top-right-radius: 5px; display: inline-block; background-color: #6C8C6C;
|
||
border: 2px solid green; padding: 5px; margin: 0 2px 0 0; position: relative; top: 2px; z-index: 110; cursor: pointer; }
|
||
.menu .tab:hover { color: #FFF; }
|
||
.menu .tab.selected { background-color: #FFF; border-bottom: 2px solid #FFF; cursor: default; }
|
||
.menu .tab.selected:hover { color: #000; }
|
||
.pagebreak { height: 50px; }
|
||
.commands { border-bottom: 2px solid green; padding: 10px 0; margin-bottom: 0; }
|
||
.commands span { padding: 0 10px; }
|
||
.commands span.print { float: right; }
|
||
.commands span.right { float: right; }
|
||
.expandable { padding: 10px 15px; text-align: left; cursor: pointer; }
|
||
|
||
#papercommands { padding: 10px 0; border: 2px solid green; }
|
||
#braincommands .row { text-align: left; }
|
||
#braincommands .row .label { width: 150px; display: inline-block; }
|
||
#braincommands .row.extra { padding: 6px 0 0 0; }
|
||
#braincommands .notes { font-size: 80%; display: block; padding: 5px 10px; }
|
||
#brainpassphrase { width: 280px; }
|
||
#brainpassphraseconfirm { width: 280px; }
|
||
#detailcommands { padding: 10px 0; }
|
||
#detailcommands span { padding: 0 10px; }
|
||
#detailprivkey { width: 250px; }
|
||
.paper #commands { border-bottom: 2px solid green; padding: 0; margin-bottom: 0; }
|
||
#bulkstartindex, #paperlimit, #paperlimitperpage { width: 35px; }
|
||
#bulklimit { width: 45px; }
|
||
|
||
.footer { font-family: Arial; font-size: 90%; clear: both; width: 700px; padding: 10px 0 10px 0; margin: 50px auto auto auto; }
|
||
.footer div span.item { padding: 10px; }
|
||
.footer .authorbtc { float: left; width: 470px; }
|
||
.footer .authorbtc span.item { text-align: left; display: block; padding: 0 20px; }
|
||
.footer .authorbtc div { position: relative; z-index: 100; }
|
||
.footer .authorpgp { position: relative; }
|
||
.footer .authorpgp span.item { text-align: right; display: block; padding: 0 20px; }
|
||
.footer .copyright { font-size: 80%; clear: both; padding: 5px 0; }
|
||
.footer .copyright span { padding: 10px 2px; }
|
||
}
|
||
@media print
|
||
{
|
||
#main { width: auto; }
|
||
#culturemenu { display: none; }
|
||
#paperarea .keyarea:first-child { border-top: 2px solid green; }
|
||
#paperarea .keyarea.art:first-child { border: 0; }
|
||
.pagebreak { height: 1px; }
|
||
.paper #logo { display: none; }
|
||
.menu { display: none; }
|
||
.footer { display: none; }
|
||
.commands { display: none; }
|
||
#tagline { display: none; }
|
||
#faqs { display: none; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body onclick="SecureRandom.seedTime();" onkeypress="SecureRandom.seedTime();" onmousemove="ninja.seeder.seed(event);">
|
||
<div id="main">
|
||
<div id="culturemenu">
|
||
<span><a href="?culture=en" id="cultureen" class="selected">English</a></span> |
|
||
<span><a href="?culture=es" id="culturees" class="">Espa<EFBFBD>ol</a></span>
|
||
</div>
|
||
<img alt="liteaddress.org" title="liteaddress.org" id="logo" src="data:image/png;base64,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" />
|
||
<div id="tagline">Open Source JavaScript Client-Side Litecoin Wallet Generator</div>
|
||
<div id="testnet"></div>
|
||
<div class="menu" id="menu">
|
||
<div class="tab selected" id="singlewallet" onclick="ninja.tabSwitch(this);">Single Wallet</div>
|
||
<div class="tab" id="paperwallet" onclick="ninja.tabSwitch(this);">Paper Wallet</div>
|
||
<div class="tab" id="bulkwallet" onclick="ninja.tabSwitch(this);">Bulk Wallet</div>
|
||
<div class="tab" id="brainwallet" onclick="ninja.tabSwitch(this);">Brain Wallet</div>
|
||
<div class="tab" id="vanitywallet" onclick="ninja.tabSwitch(this);">Vanity Wallet</div>
|
||
<div class="tab" id="detailwallet" onclick="ninja.tabSwitch(this);">Wallet Details</div>
|
||
</div>
|
||
|
||
<div id="generate">
|
||
<span id="generatelabelbitcoinaddress">Generating Litecoin Address...</span><br />
|
||
<span id="generatelabelmovemouse">MOVE your mouse around to add some extra randomness...</span><br />
|
||
</div>
|
||
|
||
<div id="wallets">
|
||
<div id="singlearea" class="walletarea">
|
||
<div class="commands">
|
||
<div id="singlecommands">
|
||
<span><input type="button" id="newaddress" value="Generate New Address" onclick="ninja.wallets.singlewallet.generateNewAddressAndKey();" /></span>
|
||
<span class="print"><input type="button" name="print" value="Print" id="singleprint" onclick="window.print();" /></span>
|
||
</div>
|
||
</div>
|
||
<div id="keyarea" class="keyarea">
|
||
<div class="public">
|
||
<div id="qrcode_public" class="qrcode_public"></div>
|
||
<div class="pubaddress">
|
||
<span class="label" id="singlelabelbitcoinaddress">Litecoin Address:</span>
|
||
<span class="output" id="btcaddress"></span>
|
||
</div>
|
||
</div>
|
||
<div class="private">
|
||
<div id="qrcode_private" class="qrcode_private"></div>
|
||
<div class="privwif">
|
||
<span class="label" id="singlelabelprivatekey">Private Key (Wallet Import Format):</span>
|
||
<span class="output" id="btcprivwif"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="paperarea">
|
||
<div id="papercommands" class="commands">
|
||
<span><label id="paperlabelhideart">Hide Art?</label> <input type="checkbox" id="paperart" onchange="ninja.wallets.paperwallet.toggleArt(this);" /></span>
|
||
<span><label id="paperlabeladdressesperpage">Addresses per page:</label> <input type="text" id="paperlimitperpage" /></span>
|
||
<span><label id="paperlabeladdressestogenerate">Addresses to generate:</label> <input type="text" id="paperlimit" /></span>
|
||
<span><input type="button" id="papergenerate" value="Generate" onclick="ninja.wallets.paperwallet.build(document.getElementById('paperlimit').value * 1, document.getElementById('paperlimitperpage').value * 1, !document.getElementById('paperart').checked);" /></span>
|
||
<span class="print"><input type="button" name="print" value="Print" id="paperprint" onclick="window.print();" /></span>
|
||
</div>
|
||
<div id="paperkeyarea"></div>
|
||
</div>
|
||
|
||
<div id="bulkarea" class="walletarea">
|
||
<div id="bulkcommands" class="commands">
|
||
<span><label id="bulklabelstartindex">Start index:</label> <input type="text" id="bulkstartindex" value="1" /></span>
|
||
<span><label id="bulklabelrowstogenerate">Rows to generate:</label> <input type="text" id="bulklimit" value="3" /></span>
|
||
<span><input type="button" id="bulkgenerate" value="Generate" onclick="ninja.wallets.bulkwallet.buildCSV(document.getElementById('bulklimit').value * 1, document.getElementById('bulkstartindex').value * 1);" /> </span>
|
||
<span class="print"><input type="button" name="print" id="bulkprint" value="Print" onclick="window.print();" /></span>
|
||
</div>
|
||
<div class="body">
|
||
<span class="label" id="bulklabelcsv">Comma Separated Values:</span> <span class="format" id="bulklabelformat">Index,Address,Private Key (WIF)</span>
|
||
<textarea rows="20" cols="88" id="bulktextarea"></textarea>
|
||
</div>
|
||
<div class="faqs">
|
||
<div id="bulkfaq1" class="bulkfaq">
|
||
<div id="bulkq1" class="bulkquestion" onclick="ninja.wallets.bulkwallet.openCloseFaq(1);">
|
||
<span id="bulklabelq1">Why should I use a Bulk Wallet to accept Litecoins on my website?</span>
|
||
<div id="bulke1" class="more"></div>
|
||
</div>
|
||
<div id="bulka1" class="bulkanswer">
|
||
The traditional approach to accepting litecoins on your website requires that
|
||
you install the official litecoin client daemon ("litecoind"). Many website hosting packages
|
||
don't support installing the litecoin daemon. Also, running the litecoin daemon on your
|
||
web server means your private keys are hosted on the server and could get stolen if your web
|
||
server is hacked. When using a Bulk Wallet you can upload only the litecoin addresses
|
||
and not the private keys to your web server. Then you don't have to worry about your
|
||
litecoin wallet being stolen if your web server is hacked.
|
||
</div>
|
||
</div>
|
||
<div id="bulkfaq2" class="bulkfaq">
|
||
<div id="bulkq2" class="bulkquestion" onclick="ninja.wallets.bulkwallet.openCloseFaq(2);">
|
||
<span id="bulklabelq2">How do I use a Bulk Wallet to accept Litecoins on my website?</span>
|
||
<div id="bulke2" class="more"></div>
|
||
</div>
|
||
<div id="bulka2" class="bulkanswer">
|
||
<ol>
|
||
<li id="bulklabela2li1">Use the Bulk Wallet tab to pre-generate a large number of litecoin addresses (10,000+). Copy and paste the generated
|
||
comma separated values (CSV) list to a secure text file on your computer. Backup the file you just created to a secure location.</li>
|
||
<li id="bulklabela2li2">Import the litecoin addresses into a database table on your web server.
|
||
(Don't put the wallet/private keys on your web server, otherwise you risk hackers stealing your coins.
|
||
Just the litecoin addresses as they will be shown to customers.)</li>
|
||
<li id="bulklabela2li3">Provide an option on your website's shopping cart for your customer to pay in Litecoin. When the customer chooses to pay in Litecoin you will
|
||
then display one of the addresses from your database to the customer as his "payment address" and save it with his shopping cart order.</li>
|
||
<li id="bulklabela2li4">You now need to be notified when the payment arrives. Google "litecoin payment notification" and subscribe to at least
|
||
one litecoin payment notification service. There are various services that will notify you via Web Services, API, SMS, Email, etc.
|
||
Once you receive this notification, which could be programmatically automated, you can process the customer's order.
|
||
To manually check if a payment has arrived you can use Block Explorer. Replace THEADDRESSGOESHERE with the litecoin address
|
||
you are checking. It could take between 10 minutes to one hour for the transaction to be confirmed.
|
||
<br />
|
||
http://www.blockexplorer.com/address/THEADDRESSGOESHERE
|
||
<br /><br />
|
||
Unconfirmed transactions can be viewed at: http://blockchain.info/ <br />
|
||
You should see the transaction there within 30 seconds.
|
||
</li>
|
||
<li id="bulklabela2li5">Litecoins will safely pile up on the block chain. Use the original wallet file you generated in step 1 to spend them.</li>
|
||
</ol>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="brainarea" class="walletarea">
|
||
<div id="braincommands" class="commands">
|
||
<div class="row">
|
||
<span id="brainlabelenterpassphrase" class="label">Enter Passphrase: </span>
|
||
<input tabindex="1" type="password" id="brainpassphrase" value="" onfocus="this.select();" onkeypress="if (event.keyCode == 13) ninja.wallets.brainwallet.view();" />
|
||
<span><label id="brainlabelshow">Show?</label> <input type="checkbox" id="brainpassphraseshow" onchange="ninja.wallets.brainwallet.showToggle(this);" /></span>
|
||
<span class="print"><input type="button" name="print" id="brainprint" value="Print" onclick="window.print();" /></span>
|
||
</div>
|
||
<div class="row extra">
|
||
<span class="label" id="brainlabelconfirm">Confirm Passphrase: </span>
|
||
<input tabindex="2" type="password" id="brainpassphraseconfirm" value="" onfocus="this.select();" onkeypress="if (event.keyCode == 13) ninja.wallets.brainwallet.view();" />
|
||
<span><input tabindex="3" type="button" id="brainview" value="View" onclick="ninja.wallets.brainwallet.view();" /></span>
|
||
<span id="brainalgorithm" class="notes right">Algorithm: SHA256(passphrase)</span>
|
||
</div>
|
||
</div>
|
||
<div id="brainkeyarea" class="keyarea">
|
||
<div class="public">
|
||
<div id="brainqrcodepublic" class="qrcode_public"></div>
|
||
<div class="pubaddress">
|
||
<span class="label" id="brainlabelbitcoinaddress">Litecoin Address:</span>
|
||
<span class="output" id="brainbtcaddress"></span>
|
||
</div>
|
||
</div>
|
||
<div class="private">
|
||
<div id="brainqrcodeprivate" class="qrcode_private"></div>
|
||
<div class="privwif">
|
||
<span class="label" id="brainlabelprivatekey">Private Key (Wallet Import Format):</span>
|
||
<span class="output" id="brainbtcprivwif"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="vanityarea" class="walletarea">
|
||
<div id="vanitystep1label" class="commands expandable" onclick="ninja.wallets.vanitywallet.openCloseStep(1);">
|
||
<span><label id="vanitylabelstep1">Step 1 - Generate your "Step1 Key Pair"</label> <input type="button" id="vanitynewkeypair"
|
||
value="Generate" onclick="ninja.wallets.vanitywallet.generateKeyPair();" /></span>
|
||
<div id="vanitystep1icon" class="more"></div>
|
||
</div>
|
||
<div id="vanitystep1area">
|
||
<div>
|
||
<span class="label" id="vanitylabelstep1publickey">Step 1 Public Key:</span>
|
||
<div class="output pubkeyhex" id="vanitypubkey"></div>
|
||
<br /><div class="notes" id="vanitylabelstep1pubnotes">Copy and paste the above into the Your-Part-Public-Key field in the Vanity Pool Website.</div>
|
||
</div>
|
||
<div>
|
||
<span class="label" id="vanitylabelstep1privatekey">Step 1 Private Key:</span>
|
||
<span class="output" id="vanityprivatekey"></span>
|
||
<br /><div class="notes" id="vanitylabelstep1privnotes">Copy and paste the above Private Key field into a text file. Ideally save to an encrypted drive.
|
||
You will need this to retrieve the Litecoin Private Key once the Pool has found your prefix.</div>
|
||
</div>
|
||
</div>
|
||
<div id="vanitystep2label" class="expandable" onclick="ninja.wallets.vanitywallet.openCloseStep(2);">
|
||
<span id="vanitylabelstep2calculateyourvanitywallet">Step 2 - Calculate your Vanity Wallet</span>
|
||
<div id="vanitystep2icon" class="more"></div>
|
||
</div>
|
||
<div id="vanitystep2inputs">
|
||
<div>
|
||
<span id="vanitylabelenteryourpart">Enter Your Part Private Key (generated in Step 1 above and previously saved):</span>
|
||
<br /><span class="notes" id="vanitylabelnote1">[NOTE: this input box can accept a public key or private key]</span>
|
||
</div>
|
||
<div><textarea id="vanityinput1" rows="2" cols="90" onfocus="this.select();"></textarea></div>
|
||
<div>
|
||
<span id="vanitylabelenteryourpoolpart">Enter Pool Part Private Key (from Vanity Pool):</span>
|
||
<br /><span class="notes" id="vanitylabelnote2">[NOTE: this input box can accept a public key or private key]</span>
|
||
</div>
|
||
<div><textarea id="vanityinput2" rows="2" cols="90" onfocus="this.select();"></textarea></div>
|
||
<div>
|
||
<label for="vanityradioadd" id="vanitylabelradioadd">Add</label> <input type="radio" id="vanityradioadd" name="vanityradio" value="add" checked />
|
||
<label for="vanityradiomultiply" id="vanitylabelradiomultiply">Multiply</label> <input type="radio" id="vanityradiomultiply" name="vanityradio" value="multiply" />
|
||
</div>
|
||
<div><input type="button" id="vanitycalc" value="Calculate Vanity Wallet" onclick="ninja.wallets.vanitywallet.addKeys();" /></div>
|
||
</div>
|
||
<div id="vanitystep2area">
|
||
<div>
|
||
<span class="label" id="vanitylabelbitcoinaddress">Vanity Litecoin Address:</span>
|
||
<span class="output" id="vanityaddress"></span>
|
||
<br /><div class="notes" id="vanitylabelnotesbitcoinaddress">The above is your new address that should include your required prefix.</div>
|
||
</div>
|
||
|
||
<div>
|
||
<span class="label" id="vanitylabelpublickeyhex">Vanity Public Key (HEX):</span>
|
||
<span class="output pubkeyhex" id="vanitypublickeyhex"></span>
|
||
<br /><div class="notes" id="vanitylabelnotespublickeyhex">The above is the Public Key in hexadecimal format. </div>
|
||
</div>
|
||
|
||
<div>
|
||
<span class="label" id="vanitylabelprivatekey">Vanity Private Key (WIF):</span>
|
||
<span class="output" id="vanityprivatekeywif"></span>
|
||
<br /><div class="notes" id="vanitylabelnotesprivatekey">The above is the Private Key to load into your wallet. </div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="detailarea" class="walletarea">
|
||
<div id="detailcommands" class="commands">
|
||
<span><label id="detaillabelenterprivatekey">Enter Private Key (any format)</label> <input type="text" id="detailprivkey" value="" onfocus="this.select();" onkeypress="if (event.keyCode == 13) ninja.wallets.detailwallet.viewDetails();" /></span>
|
||
<span><input type="button" id="detailview" value="View Details" onclick="ninja.wallets.detailwallet.viewDetails();" /></span>
|
||
<span class="print"><input type="button" name="print" id="detailprint" value="Print" onclick="window.print();" /></span>
|
||
</div>
|
||
<div id="detailkeyarea">
|
||
<div class="notes">
|
||
<span id="detaillabelnote1">Your Litecoin Private Key is a unique secret number that only you know. It can be encoded in a number of different formats.
|
||
Below we show the Litecoin Address and Public Key that corresponds to your Private Key as well as your Private Key in the most popular encoding formats (WIF, HEX, B64, MINI).</span>
|
||
<br /><br />
|
||
<span id="detaillabelnote2">Litecoin v0.6+ stores public keys in compressed format. The client now also supports import and export of private keys with importprivkey/dumpprivkey. The format of the exported
|
||
private key is determined by whether the address was generated in an old or new wallet.</span>
|
||
</div>
|
||
<div class="item">
|
||
<div id="detailqrcodepublic" class="qrcode_public"></div>
|
||
<span class="label" id="detaillabelbitcoinaddress">Litecoin Address:</span>
|
||
<span class="output" id="detailaddress"></span>
|
||
</div>
|
||
<br />
|
||
<div class="item right">
|
||
<div id="detailqrcodepubliccomp" class="qrcode_public"></div>
|
||
<span class="label" id="detaillabelbitcoinaddresscomp">Litecoin Address (compressed):</span>
|
||
<span class="output" id="detailaddresscomp"></span>
|
||
</div>
|
||
<br />
|
||
<div class="item">
|
||
<span class="label" id="detaillabelpublickey">Public Key (130 characters [0-9A-F]):</span>
|
||
<span class="output pubkeyhex" id="detailpubkey"></span>
|
||
</div>
|
||
<div class="item">
|
||
<span class="label" id="detaillabelpublickeycomp">Public Key (compressed, 66 characters [0-9A-F]):</span>
|
||
<span class="output" id="detailpubkeycomp"></span>
|
||
</div>
|
||
<hr />
|
||
<div class="item">
|
||
<div id="detailqrcodeprivate" class="qrcode_private"></div>
|
||
<span class="label"><span id="detaillabelprivwif">Private Key WIF (51 characters base58, starts with a</span> <span id="detailwifprefix">'6'</span>):</span>
|
||
<span class="output" id="detailprivwif"></span>
|
||
</div>
|
||
<br /><br />
|
||
<div class="item right">
|
||
<div id="detailqrcodeprivatecomp" class="qrcode_private"></div>
|
||
<span class="label"><span id="detaillabelprivwifcomp">Private Key WIF (compressed, 52 characters base58, starts with a</span> <span id="detailcompwifprefix">'T'</span>):</span>
|
||
<span class="output" id="detailprivwifcomp"></span>
|
||
</div>
|
||
<br /><br />
|
||
<div class="item">
|
||
<span class="label" id="detaillabelprivhex">Private Key Hexadecimal Format (64 characters [0-9A-F]):</span>
|
||
<span class="output" id="detailprivhex"></span>
|
||
</div>
|
||
<div class="item">
|
||
<span class="label" id="detaillabelprivb64">Private Key Base64 (44 characters):</span>
|
||
<span class="output" id="detailprivb64"></span>
|
||
</div>
|
||
<div class="item" style="display: none;" id="detailmini">
|
||
<span class="label" id="detaillabelprivmini">Private Key Mini Format (22, 26 or 30 characters, starts with an 'S'):</span>
|
||
<span class="output" id="detailprivmini"></span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="footer" class="footer">
|
||
<div class="authorbtc">
|
||
<div>
|
||
<span class="item"><span id="footerlabeldonations">Donations:</span> <b>1NiNja</b>1bUmhSoTXozBRBEtR8LeF9TGbZBN</span>
|
||
<span class="item"><a href="http://firstbits.com/1ninja" target="_blank">firstbits.com/1ninja</a></span>
|
||
<span class="item" id="footerlabeltranslatedby"></span>
|
||
</div>
|
||
</div>
|
||
<div class="authorpgp">
|
||
<span class="item"><a href="https://www.bitaddress.org/ninja_bitaddress.org.txt" target="_blank" id="footerlabelpgp">PGP Public Key</a></span>
|
||
<span class="item"><a href="https://www.bitaddress.org/pgpsignedmsg.txt" target="_blank"><span id="footerlabelversion">Signed Version History</span> (v2.3)</a></span>
|
||
<span class="item"><a href="https://github.com/litecoin-project/bitaddress.org" target="_blank" id="footerlabelgithub">GitHub Repository</a></span>
|
||
</div>
|
||
<div class="copyright">
|
||
<span id="footerlabelcopyright1">Copyright bitaddress.org.</span>
|
||
<span id="footerlabelcopyright2">JavaScript copyrights are included in the source.</span>
|
||
<span id="footerlabelnowarranty">No warranty.</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script type="text/javascript">
|
||
var ninja = { wallets: {} };
|
||
|
||
ninja.privateKey = {
|
||
isPrivateKey: function (key) {
|
||
return (
|
||
Bitcoin.ECKey.isWalletImportFormat(key) ||
|
||
Bitcoin.ECKey.isCompressedWalletImportFormat(key) ||
|
||
Bitcoin.ECKey.isHexFormat(key) ||
|
||
Bitcoin.ECKey.isBase64Format(key) ||
|
||
Bitcoin.ECKey.isMiniFormat(key)
|
||
);
|
||
},
|
||
getECKeyFromAdding: function (privKey1, privKey2) {
|
||
var n = EllipticCurve.getSECCurveByName("secp256k1").getN();
|
||
var ecKey1 = new Bitcoin.ECKey(privKey1);
|
||
var ecKey2 = new Bitcoin.ECKey(privKey2);
|
||
// if both keys are the same return null
|
||
if (ecKey1.getBitcoinHexFormat() == ecKey2.getBitcoinHexFormat()) return null;
|
||
if (ecKey1 == null || ecKey2 == null) return null;
|
||
var combinedPrivateKey = new Bitcoin.ECKey(ecKey1.priv.add(ecKey2.priv).mod(n));
|
||
// compressed when both keys are compressed
|
||
if (ecKey1.compressed && ecKey2.compressed) combinedPrivateKey.setCompressed(true);
|
||
return combinedPrivateKey;
|
||
},
|
||
getECKeyFromMultiplying: function (privKey1, privKey2) {
|
||
var n = EllipticCurve.getSECCurveByName("secp256k1").getN();
|
||
var ecKey1 = new Bitcoin.ECKey(privKey1);
|
||
var ecKey2 = new Bitcoin.ECKey(privKey2);
|
||
// if both keys are the same return null
|
||
if (ecKey1.getBitcoinHexFormat() == ecKey2.getBitcoinHexFormat()) return null;
|
||
if (ecKey1 == null || ecKey2 == null) return null;
|
||
var combinedPrivateKey = new Bitcoin.ECKey(ecKey1.priv.multiply(ecKey2.priv).mod(n));
|
||
// compressed when both keys are compressed
|
||
if (ecKey1.compressed && ecKey2.compressed) combinedPrivateKey.setCompressed(true);
|
||
return combinedPrivateKey;
|
||
}
|
||
};
|
||
|
||
ninja.publicKey = {
|
||
isPublicKeyHexFormat: function (key) {
|
||
key = key.toString();
|
||
return ninja.publicKey.isUncompressedPublicKeyHexFormat(key) || ninja.publicKey.isCompressedPublicKeyHexFormat(key);
|
||
},
|
||
// 130 characters [0-9A-F] starts with 04
|
||
isUncompressedPublicKeyHexFormat: function (key) {
|
||
key = key.toString();
|
||
return /^04[A-Fa-f0-9]{128}$/.test(key);
|
||
},
|
||
// 66 characters [0-9A-F] starts with 02 or 03
|
||
isCompressedPublicKeyHexFormat: function (key) {
|
||
key = key.toString();
|
||
return /^0[2-3][A-Fa-f0-9]{64}$/.test(key);
|
||
},
|
||
getBitcoinAddressFromByteArray: function (pubKeyByteArray) {
|
||
var pubKeyHash = Bitcoin.Util.sha256ripe160(pubKeyByteArray);
|
||
var addr = new Bitcoin.Address(pubKeyHash);
|
||
return addr.toString();
|
||
},
|
||
getHexFromByteArray: function (pubKeyByteArray) {
|
||
return Crypto.util.bytesToHex(pubKeyByteArray).toString().toUpperCase();
|
||
},
|
||
getByteArrayFromAdding: function (pubKeyHex1, pubKeyHex2) {
|
||
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||
var curve = ecparams.getCurve();
|
||
var ecPoint1 = curve.decodePointHex(pubKeyHex1);
|
||
var ecPoint2 = curve.decodePointHex(pubKeyHex2);
|
||
// if both points are the same return null
|
||
if (ecPoint1.equals(ecPoint2)) return null;
|
||
var compressed = (ecPoint1.compressed && ecPoint2.compressed);
|
||
var pubKey = ecPoint1.add(ecPoint2).getEncoded(compressed);
|
||
return pubKey;
|
||
},
|
||
getByteArrayFromMultiplying: function (pubKeyHex, ecKey) {
|
||
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||
var ecPoint = ecparams.getCurve().decodePointHex(pubKeyHex);
|
||
var compressed = (ecPoint.compressed && ecKey.compressed);
|
||
// if both points are the same return null
|
||
ecKey.setCompressed(false);
|
||
if(ecPoint.equals(ecKey.getPubPoint())) {
|
||
return null;
|
||
}
|
||
var bigInt = ecKey.priv;
|
||
var pubKey = ecPoint.multiply(bigInt).getEncoded(compressed);
|
||
return pubKey;
|
||
},
|
||
// used by unit test
|
||
getDecompressedPubKeyHex: function (pubKeyHexComp) {
|
||
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||
var ecPoint = ecparams.getCurve().decodePointHex(pubKeyHexComp);
|
||
var pubByteArray = ecPoint.getEncoded(0);
|
||
var pubHexUncompressed = ninja.publicKey.getHexFromByteArray(pubByteArray);
|
||
return pubHexUncompressed;
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.seeder = {
|
||
// number of mouse movements to wait for
|
||
seedLimit: (function () {
|
||
var num = Crypto.util.randomBytes(12)[11];
|
||
return 50 + Math.floor(num);
|
||
})(),
|
||
|
||
seedCount: 0, // counter
|
||
|
||
// seed function exists to wait for mouse movement to add more entropy before generating an address
|
||
seed: function (evt) {
|
||
if (!evt) var evt = window.event;
|
||
|
||
// seed a bunch (minimum seedLimit) of times based on mouse moves
|
||
SecureRandom.seedTime();
|
||
// seed mouse position X and Y
|
||
if (evt) SecureRandom.seedInt((evt.clientX * evt.clientY));
|
||
|
||
ninja.seeder.seedCount++;
|
||
// seeding is over now we generate and display the address
|
||
if (ninja.seeder.seedCount == ninja.seeder.seedLimit) {
|
||
ninja.wallets.singlewallet.open();
|
||
// UI
|
||
document.getElementById("generate").style.display = "none";
|
||
document.getElementById("menu").style.visibility = "visible";
|
||
}
|
||
},
|
||
|
||
// If user has not moved the mouse or if they are on a mobile device
|
||
// we will force the generation after a random period of time.
|
||
forceGenerate: function () {
|
||
// if the mouse has not moved enough
|
||
if (ninja.seeder.seedCount < ninja.seeder.seedLimit) {
|
||
SecureRandom.seedTime();
|
||
ninja.seeder.seedCount = ninja.seeder.seedLimit - 1;
|
||
ninja.seeder.seed();
|
||
}
|
||
}
|
||
};
|
||
|
||
ninja.qrCode = {
|
||
// determine which type number is big enough for the input text length
|
||
getTypeNumber: function (text) {
|
||
var lengthCalculation = text.length * 8 + 12; // length as calculated by the QRCode
|
||
if (lengthCalculation < 72) { return 1; }
|
||
else if (lengthCalculation < 128) { return 2; }
|
||
else if (lengthCalculation < 208) { return 3; }
|
||
else if (lengthCalculation < 288) { return 4; }
|
||
else if (lengthCalculation < 368) { return 5; }
|
||
else if (lengthCalculation < 480) { return 6; }
|
||
else if (lengthCalculation < 528) { return 7; }
|
||
else if (lengthCalculation < 688) { return 8; }
|
||
else if (lengthCalculation < 800) { return 9; }
|
||
else if (lengthCalculation < 976) { return 10; }
|
||
return null;
|
||
},
|
||
|
||
createCanvas: function (text, sizeMultiplier) {
|
||
sizeMultiplier = (sizeMultiplier == undefined) ? 2 : sizeMultiplier; // default 2
|
||
// create the qrcode itself
|
||
var typeNumber = ninja.qrCode.getTypeNumber(text);
|
||
var qrcode = new QRCode(typeNumber, QRCode.ErrorCorrectLevel.H);
|
||
qrcode.addData(text);
|
||
qrcode.make();
|
||
var width = qrcode.getModuleCount() * sizeMultiplier;
|
||
var height = qrcode.getModuleCount() * sizeMultiplier;
|
||
// create canvas element
|
||
var canvas = document.createElement('canvas');
|
||
var scale = 10.0;
|
||
canvas.width = width * scale;
|
||
canvas.height = height * scale;
|
||
canvas.style.width = width + 'px';
|
||
canvas.style.height = height + 'px';
|
||
var ctx = canvas.getContext('2d');
|
||
ctx.scale(scale, scale);
|
||
// compute tileW/tileH based on width/height
|
||
var tileW = width / qrcode.getModuleCount();
|
||
var tileH = height / qrcode.getModuleCount();
|
||
// draw in the canvas
|
||
for (var row = 0; row < qrcode.getModuleCount(); row++) {
|
||
for (var col = 0; col < qrcode.getModuleCount(); col++) {
|
||
ctx.fillStyle = qrcode.isDark(row, col) ? "#000000" : "#ffffff";
|
||
ctx.fillRect(col * tileW, row * tileH, tileW, tileH);
|
||
}
|
||
}
|
||
// return just built canvas
|
||
return canvas;
|
||
},
|
||
|
||
// generate a QRCode and return it's representation as an Html table
|
||
createTableHtml: function (text) {
|
||
var typeNumber = ninja.qrCode.getTypeNumber(text);
|
||
var qr = new QRCode(typeNumber, QRCode.ErrorCorrectLevel.H);
|
||
qr.addData(text);
|
||
qr.make();
|
||
var tableHtml = "<table class='qrcodetable'>";
|
||
for (var r = 0; r < qr.getModuleCount(); r++) {
|
||
tableHtml += "<tr>";
|
||
for (var c = 0; c < qr.getModuleCount(); c++) {
|
||
if (qr.isDark(r, c)) {
|
||
tableHtml += "<td class='qrcodetddark'/>";
|
||
} else {
|
||
tableHtml += "<td class='qrcodetdlight'/>";
|
||
}
|
||
}
|
||
tableHtml += "</tr>";
|
||
}
|
||
tableHtml += "</table>";
|
||
return tableHtml;
|
||
},
|
||
|
||
// show QRCodes with canvas OR table (IE8)
|
||
// parameter: keyValuePair
|
||
// example: { "id1": "string1", "id2": "string2"}
|
||
// "id1" is the id of a div element where you want a QRCode inserted.
|
||
// "string1" is the string you want encoded into the QRCode.
|
||
showQrCode: function (keyValuePair, sizeMultiplier) {
|
||
for (var key in keyValuePair) {
|
||
var value = keyValuePair[key];
|
||
try {
|
||
if (document.getElementById(key)) {
|
||
document.getElementById(key).innerHTML = "";
|
||
document.getElementById(key).appendChild(ninja.qrCode.createCanvas(value, sizeMultiplier));
|
||
}
|
||
}
|
||
catch (e) {
|
||
// for browsers that do not support canvas (IE8)
|
||
document.getElementById(key).innerHTML = ninja.qrCode.createTableHtml(value);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
ninja.tabSwitch = function (walletTab) {
|
||
if (walletTab.className.indexOf("selected") == -1) {
|
||
// unselect all tabs
|
||
for (var wType in ninja.wallets) {
|
||
document.getElementById(wType).className = "tab";
|
||
ninja.wallets[wType].close();
|
||
}
|
||
walletTab.className += " selected";
|
||
ninja.wallets[walletTab.getAttribute("id")].open();
|
||
}
|
||
};
|
||
|
||
ninja.getQueryString = function () {
|
||
var result = {}, queryString = location.search.substring(1), re = /([^&=]+)=([^&]*)/g, m;
|
||
while (m = re.exec(queryString)) {
|
||
result[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
|
||
}
|
||
return result;
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.translator = {
|
||
currentCulture: "en",
|
||
|
||
translate: function (culture) {
|
||
var dict = ninja.translator.translations[culture];
|
||
if (dict) {
|
||
// set current culture
|
||
ninja.translator.currentCulture = culture;
|
||
// update menu UI
|
||
for (var cult in ninja.translator.translations) {
|
||
document.getElementById("culture" + cult).setAttribute("class", "");
|
||
}
|
||
document.getElementById("culture" + culture).setAttribute("class", "selected");
|
||
// apply translations
|
||
for (var id in dict) {
|
||
if (document.getElementById(id) && document.getElementById(id).value) {
|
||
document.getElementById(id).value = dict[id];
|
||
}
|
||
else if (document.getElementById(id)) {
|
||
document.getElementById(id).innerHTML = dict[id];
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
get: function (id) {
|
||
var translation = ninja.translator.translations[ninja.translator.currentCulture][id];
|
||
return translation;
|
||
},
|
||
|
||
translations: {
|
||
"en": {
|
||
// javascript alerts or messages
|
||
"testneteditionactivated": "TESTNET EDITION ACTIVATED",
|
||
"paperlabelbitcoinaddress": "Litecoin Address:",
|
||
"paperlabelprivatekey": "Private Key (Wallet Import Format):",
|
||
"bulkgeneratingaddresses": "Generating addresses... ",
|
||
"brainalertpassphrasetooshort": "The passphrase you entered is too short.\n\nWarning: Choosing a strong passphrase is important to avoid brute force attempts to guess your passphrase and steal your bitcoins.",
|
||
"brainalertpassphrasedoesnotmatch": "The passphrase does not match the confirm passphrase.",
|
||
"detailalertnotvalidprivatekey": "The text you entered is not a valid Private Key",
|
||
"detailconfirmsha256": "The text you entered is not a valid Private Key!\n\nWould you like to use the entered text as a passphrase and create a Private Key using a SHA256 hash of the passphrase?\n\nWarning: Choosing a strong passphrase is important to avoid brute force attempts to guess your passphrase and steal your bitcoins.",
|
||
"vanityinvalidinputcouldnotcombinekeys": "Invalid input. Could not combine keys.",
|
||
"vanityalertinvalidinputcompressedprivatekeys": "Invalid input. Compressed Private Keys not supported.",
|
||
"vanityalertinvalidinputpublickeysmatch": "Invalid input. The Public Key of both entries match. You must input two different keys.",
|
||
"vanityalertinvalidinputcannotmultiple": "Invalid input. Cannot multiply two public keys. Select 'Add' to add two public keys to get a bitcoin address.",
|
||
"vanityprivatekeyonlyavailable": "Only available when combining two private keys",
|
||
"vanityalertinvalidinputprivatekeysmatch": "Invalid input. The Private Key of both entries match. You must input two different keys."
|
||
},
|
||
|
||
"es": {
|
||
// javascript alerts or messages
|
||
"testneteditionactivated": "TESTNET EDITION ACTIVATED", //TODO: please translate
|
||
"paperlabelbitcoinaddress": "Direcci<63>n Litecoin:",
|
||
"paperlabelprivatekey": "Clave privada (formato para importar):",
|
||
"bulkgeneratingaddresses": "Generating addresses... ", //TODO: please translate
|
||
"brainalertpassphrasetooshort": "La contrase<73>a introducida es demasiado corta.\n\nAviso: Es importante escoger una contrase<73>a fuerte para evitar ataques de fuerza bruta a fin de adivinarla y robar tus bitcoins.",
|
||
"brainalertpassphrasedoesnotmatch": "Las contrase<73>as no coinciden.",
|
||
"detailalertnotvalidprivatekey": "El texto que has introducido no es una clave privada v<>lida",
|
||
"detailconfirmsha256": "El texto que has introducido no es una clave privada v<>lida\n\n<>Quieres usar ese texto como si fuera una contrase<73>a y generar una clave privada usando un hash SHA256 de tal contrase<73>a?\n\nAviso: Es importante escoger una contrase<73>a fuerte para evitar ataques de fuerza bruta a fin de adivinarla y robar tus bitcoins.",
|
||
"vanityinvalidinputcouldnotcombinekeys": "Invalid input. Could not combine keys.", //TODO: please translate
|
||
"vanityalertinvalidinputcompressedprivatekeys": "Invalid input. Compressed Private Keys not supported.", //TODO: please translate
|
||
"vanityalertinvalidinputpublickeysmatch": "Invalid input. The Public Key of both entries match. You must input two different keys.", //TODO: please translate
|
||
"vanityalertinvalidinputcannotmultiple": "Invalid input. Cannot multiple two public keys. Select 'Add' to add two public keys to get a bitcoin address.", //TODO: please translate
|
||
"vanityprivatekeyonlyavailable": "Only available when combining two private keys", //TODO: please translate
|
||
"vanityalertinvalidinputprivatekeysmatch": "Invalid input. The Private Key of both entries match. You must input two different keys.", //TODO: please translate
|
||
|
||
// header and menu html
|
||
"tagline": "Generador de carteras Litecoin de c<>digo abierto en lado de cliente con Javascript",
|
||
"generatelabelbitcoinaddress": "Generando direcci<63>n Litecoin...",
|
||
"generatelabelmovemouse": "Mueve un poco el rat<61>n para crear entrop<6F>a...",
|
||
"singlewallet": "Una sola cartera",
|
||
"paperwallet": "Cartera en papel",
|
||
"bulkwallet": "Direcciones en masa",
|
||
"brainwallet": "Cartera mental",
|
||
"vanitywallet": "Cartera personalizada",
|
||
"detailwallet": "Detalles de la cartera",
|
||
|
||
// footer html
|
||
"footerlabeldonations": "Donaciones:",
|
||
"footerlabeltranslatedby": "Traducci<63>n: <b>12345</b>Vypv2QSmuRXcciT5oEB27mPbWGeva",
|
||
"footerlabelpgp": "Clave p<>blica PGP",
|
||
"footerlabelversion": "Hist<73>rico de versiones",
|
||
"footerlabelgithub": "Repositorio GitHub",
|
||
"footerlabelcopyright1": "Copyright bitaddress.org.",
|
||
"footerlabelcopyright2": "Copyright del c<>digo JavaScript: en el fuente.",
|
||
"footerlabelnowarranty": "Sin garant<6E>a.",
|
||
|
||
// single wallet html
|
||
"newaddress": "Generar direcci<63>n",
|
||
"singleprint": "Imprimir",
|
||
"singlelabelbitcoinaddress": "Direcci<63>n Litecoin",
|
||
"singlelabelprivatekey": "Clave privada (formato para importar):",
|
||
|
||
// paper wallet html
|
||
"paperlabelhideart": "Ocultar dise<73>o",
|
||
"paperlabeladdressesperpage": "Direcciones por p<>gina:",
|
||
"paperlabeladdressestogenerate": "Direcciones en total:",
|
||
"papergenerate": "Generar",
|
||
"paperprint": "Imprimir",
|
||
|
||
// bulk wallet html
|
||
"bulklabelstartindex": "Empezar en:",
|
||
"bulklabelrowstogenerate": "Filas a generar:",
|
||
"bulkgenerate": "Generar",
|
||
"bulkprint": "Imprimir",
|
||
"bulklabelcsv": "Valores separados por coma:",
|
||
"bulklabelformat": "<22>ndice,Direcci<63>n,Clave privada (formato para importar)",
|
||
"bulklabelq1": "<22>Por qu<71> debo usar \"Direcciones en masa\" para aceptar Litecoins en mi web?",
|
||
"bulka1": "La forma tradicional de aceptar bitcoins en tu web requiere tener instalado el cliente oficial de bitcoin (\"bitcoind\"). Sin embargo muchos servicios de hosting no permiten instalar dicho cliente. Adem<65>s, ejecutar el cliente en tu servidor supone que las claves privadas est<73>n tambi<62>n en el servidor y podr<64>an ser comprometidas en caso de intrusi<73>n. Al usar este mecanismo, puedes subir al servidor s<>lo las direcci<63>n de bitcoin y no las claves privadas. De esta forma no te tienes que preocupar de que alguien robe la cartera si se cuelan en el servidor.",
|
||
"bulklabelq2": "<22>C<EFBFBD>mo uso \"Direcciones en masa\" para aceptar bitcoins en mi web?",
|
||
"bulklabela2li1": "Usa el tab \"Direcciones en masa\" para generar por anticipado muchas direcciones (m<>s de 10000). Copia y pega la lista de valores separados por comas (CSV) a un archivo de texto seguro (cifrado) en tu ordenador. Guarda una copia de seguridad en alg<6C>n lugar seguro.",
|
||
"bulklabela2li2": "Importa las direcciones en la base de datos de tu servidor. No subas la cartera ni las claves p<>blicas, o de lo contrario te lo pueden robar. Sube s<>lo las direcciones, ya que es lo que se va a mostrar a los clientes.",
|
||
"bulklabela2li3": "Ofrece una alternativa en el carro de la compra de tu web para que los clientes paguen con Litecoin. Cuando el cliente elija pagar con Litecoin, les muestras una de las direcciones de la base de datos como su \"direcci<63>n de pago\" y guardas esto junto con el pedido.",
|
||
"bulklabela2li4": "Ahora te hace falta recibir una notificaci<63>n del pago. Busca en google \"notificaci<63>n de pagos bitcoin\" (o \"bitcoin payment notification\" en ingl<67>s) y suscr<63>bete a alguno de los servicios que aparezcan. Hay varios de ellos, que te pueden notificar v<>a Web services, API, SMS, email, etc. Una vez te llegue la notificaci<63>n, lo cual puede ser automatizado, entonces ya puedes procesar el pedido. Para comprobar a mano si has recibido un pago, puedes usar Block Explorer: reemplaza DIRECCION a continuaci<63>n por la direcci<63>n que est<73>s comprobando. La transacci<63>n puede tardar entre 10 minutos y una hora en ser confirmada. <br />http://www.blockexplorer.com/address/DIRECCION<br /><br />Puedes ver las transacciones sin confirmar en: http://blockchain.info/ <br />Las transacciones sin confirmar suelen aparecer ah<61> en unos 30 segundos.",
|
||
"bulklabela2li5": "Las bitcoins que recibas se almacenar<61>n de forma segura en la cadena de bloques. Usa la cartera original que generaste en el paso 1 para usarlas.",
|
||
|
||
// brain wallet html
|
||
"brainlabelenterpassphrase": "Contrase<73>a:",
|
||
"brainlabelshow": "Mostrar",
|
||
"brainprint": "Imprimir",
|
||
"brainlabelconfirm": "Confirmar contrase<73>a:",
|
||
"brainview": "Ver",
|
||
"brainalgorithm": "Algoritmo: SHA256(contrase<73>a)",
|
||
"brainlabelbitcoinaddress": "Direcci<63>n Litecoin:",
|
||
"brainlabelprivatekey": "Clave privada (formato para importar):",
|
||
|
||
// vanity wallet html
|
||
"vanitylabelstep1": "Paso 1 - Genera tu par de claves",
|
||
"vanitynewkeypair": "Generar",
|
||
"vanitylabelstep1publickey": "Clave p<>blica:",
|
||
"vanitylabelstep1pubnotes": "Copia y pega la l<>nea de arriba en el campo \"Your-Part-Public-Key\" de la web de Vanity Pool.",
|
||
"vanitylabelstep1privatekey": "Clave privada:",
|
||
"vanitylabelstep1privnotes": "Copia y pega la clave p<>blica de arriba en un archivo de texto. Es mejor que lo almacenes en un volumen cifrado. Lo necesitar<61>s para recuperar la clave privada una vez Vanity Pool haya encontrado tu prefijo.",
|
||
"vanitylabelstep2calculateyourvanitywallet": "Paso 2 - Calcula tu cartera personalizada",
|
||
"vanitylabelenteryourpart": "Introduce la clave privada generada en el paso 1, y que has guardado:",
|
||
"vanitylabelenteryourpoolpart": "Introduce la clave privada obtenida de la Vanity Pool:",
|
||
"vanitylabelnote1": "[NOTE: this input box can accept a public key or private key]", //TODO: please translate
|
||
"vanitylabelnote2": "[NOTE: this input box can accept a public key or private key]", //TODO: please translate
|
||
"vanitylabelradioadd": "Add", //TODO: please translate
|
||
"vanitylabelradiomultiply": "Multiply", //TODO: please translate
|
||
"vanitycalc": "Calcular cartera personalizada",
|
||
"vanitylabelbitcoinaddress": "Direcci<63>n Litecoin personalizada:",
|
||
"vanitylabelnotesbitcoinaddress": "Esta es tu nueva direcci<63>n, que deber<65>a tener el prefijo deseado.",
|
||
"vanitylabelpublickeyhex": "Vanity Public Key (HEX):", //TODO: please translate
|
||
"vanitylabelnotespublickeyhex": "The above is the Public Key in hexadecimal format.", //TODO: please translate
|
||
"vanitylabelprivatekey": "Clave privada personalizada (formato para importar):",
|
||
"vanitylabelnotesprivatekey": "Esto es la clave privada para introducir en tu cartera.",
|
||
|
||
// detail wallet html
|
||
"detaillabelenterprivatekey": "Introduce la clave privada (en cualquier formato)",
|
||
"detailview": "Ver detalles",
|
||
"detailprint": "Imprimir",
|
||
"detaillabelnote1": "Tu clave privada es un n<>mero secreto, <20>nico, que s<>lo t<> conoces. Se puede expresar en varios formatos. Aqu<71> abajo mostramos la direcci<63>n y la clave p<>blica que se corresponden con tu clave privada, as<61> como la clave privada en los formatos m<>s conocidos (para importar, hex, base64 y mini).",
|
||
"detaillabelnote2": "Litecoin v0.6+ almacena las claves p<>blicas comprimidas. El cliente tambi<62>n soporta importar/exportar claves privadas usando importprivkey/dumpprivkey. El formato de las claves privadas exportadas depende de si la direcci<63>n se gener<65> en una cartera antigua o nueva.",
|
||
"detaillabelbitcoinaddress": "Direcci<63>n Litecoin:",
|
||
"detaillabelbitcoinaddresscomp": "Direcci<63>n Litecoin (comprimida):",
|
||
"detaillabelpublickey": "Clave p<>blica (130 caracteres [0-9A-F]):",
|
||
"detaillabelpublickeycomp": "Clave p<>blica (comprimida, 66 caracteres [0-9A-F]):",
|
||
"detaillabelprivwif": "Clave privada para importar (51 caracteres en base58, empieza con un",
|
||
"detaillabelprivwifcomp": "Clave privada para importar (comprimida, 52 caracteres en base58, empieza con",
|
||
"detailcompwifprefix": "'T'",
|
||
"detaillabelprivhex": "Clave privada en formato hexadecimal (64 caracteres [0-9A-F]):",
|
||
"detaillabelprivb64": "Clave privada en base64 (44 caracteres):",
|
||
"detaillabelprivmini": "Clave privada en formato mini (22, 26 o 30 caracteres, empieza por 'S'):"
|
||
}
|
||
}
|
||
};
|
||
|
||
ninja.translator.showEnglishJson = function () {
|
||
var english = ninja.translator.translations["en"];
|
||
var spanish = ninja.translator.translations["es"];
|
||
var spanishClone = {};
|
||
for (var key in spanish) {
|
||
spanishClone[key] = spanish[key];
|
||
}
|
||
var newLang = {};
|
||
for (var key in english) {
|
||
newLang[key] = english[key];
|
||
delete spanishClone[key];
|
||
}
|
||
for (var key in spanishClone) {
|
||
if (document.getElementById(key)) {
|
||
if (document.getElementById(key).value) {
|
||
newLang[key] = document.getElementById(key).value;
|
||
}
|
||
else {
|
||
newLang[key] = document.getElementById(key).innerHTML;
|
||
}
|
||
}
|
||
}
|
||
var div = document.createElement("div");
|
||
div.setAttribute("class", "englishjson");
|
||
div.innerHTML = "<h3>English Json</h3>";
|
||
var elem = document.createElement("textarea");
|
||
elem.setAttribute("rows", "35");
|
||
elem.setAttribute("cols", "110");
|
||
var langJson = "{\n";
|
||
for (var key in newLang) {
|
||
langJson += " \"" + key + "\"" + " = " + "\"" + newLang[key] + "\",\n";
|
||
}
|
||
langJson = langJson.substr(0, langJson.length - 2);
|
||
langJson += "\n}\n";
|
||
elem.innerHTML = langJson;
|
||
div.appendChild(elem);
|
||
document.body.appendChild(div);
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.wallets.singlewallet = {
|
||
open: function () {
|
||
if (document.getElementById("btcaddress").innerHTML == "") {
|
||
ninja.wallets.singlewallet.generateNewAddressAndKey();
|
||
}
|
||
document.getElementById("singlearea").style.display = "block";
|
||
},
|
||
|
||
close: function () {
|
||
document.getElementById("singlearea").style.display = "none";
|
||
},
|
||
|
||
// generate bitcoin address and private key and update information in the HTML
|
||
generateNewAddressAndKey: function () {
|
||
try {
|
||
var key = new Bitcoin.ECKey(false);
|
||
var bitcoinAddress = key.getBitcoinAddress();
|
||
var privateKeyWif = key.getBitcoinWalletImportFormat();
|
||
document.getElementById("btcaddress").innerHTML = bitcoinAddress;
|
||
document.getElementById("btcprivwif").innerHTML = privateKeyWif;
|
||
var keyValuePair = {
|
||
"qrcode_public": bitcoinAddress,
|
||
"qrcode_private": privateKeyWif
|
||
};
|
||
ninja.qrCode.showQrCode(keyValuePair);
|
||
}
|
||
catch (e) {
|
||
// browser does not have sufficient JavaScript support to generate a bitcoin address
|
||
alert(e);
|
||
document.getElementById("btcaddress").innerHTML = "error";
|
||
document.getElementById("btcprivwif").innerHTML = "error";
|
||
document.getElementById("qrcode_public").innerHTML = "";
|
||
document.getElementById("qrcode_private").innerHTML = "";
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.wallets.paperwallet = {
|
||
open: function () {
|
||
document.getElementById("main").setAttribute("class", "paper"); // add 'paper' class to main div
|
||
var paperArea = document.getElementById("paperarea");
|
||
paperArea.style.display = "block";
|
||
var perPageLimitElement = document.getElementById("paperlimitperpage");
|
||
var limitElement = document.getElementById("paperlimit");
|
||
var pageBreakAt = (ninja.wallets.paperwallet.useArtisticWallet) ? ninja.wallets.paperwallet.pageBreakAtArtisticDefault : ninja.wallets.paperwallet.pageBreakAtDefault;
|
||
if (perPageLimitElement && perPageLimitElement.value < 1) {
|
||
perPageLimitElement.value = pageBreakAt;
|
||
}
|
||
if (limitElement && limitElement.value < 1) {
|
||
limitElement.value = pageBreakAt;
|
||
}
|
||
if (document.getElementById("paperkeyarea").innerHTML == "") {
|
||
ninja.wallets.paperwallet.build(pageBreakAt, pageBreakAt, !document.getElementById('paperart').checked);
|
||
}
|
||
},
|
||
|
||
close: function () {
|
||
document.getElementById("paperarea").style.display = "none";
|
||
document.getElementById("main").setAttribute("class", ""); // remove 'paper' class from main div
|
||
},
|
||
|
||
remaining: null, // use to keep track of how many addresses are left to process when building the paper wallet
|
||
count: 0,
|
||
pageBreakAtDefault: 7,
|
||
pageBreakAtArtisticDefault: 3,
|
||
useArtisticWallet: true,
|
||
pageBreakAt: null,
|
||
|
||
build: function (numWallets, pageBreakAt, useArtisticWallet) {
|
||
if (numWallets < 1) numWallets = 1;
|
||
ninja.wallets.paperwallet.remaining = numWallets;
|
||
ninja.wallets.paperwallet.count = 0;
|
||
ninja.wallets.paperwallet.useArtisticWallet = useArtisticWallet;
|
||
ninja.wallets.paperwallet.pageBreakAt = pageBreakAt;
|
||
document.getElementById("paperkeyarea").innerHTML = "";
|
||
setTimeout(ninja.wallets.paperwallet.batch, 0);
|
||
},
|
||
|
||
batch: function () {
|
||
if (ninja.wallets.paperwallet.remaining > 0) {
|
||
var paperArea = document.getElementById("paperkeyarea");
|
||
ninja.wallets.paperwallet.count++;
|
||
var i = ninja.wallets.paperwallet.count;
|
||
var pageBreakAt = ninja.wallets.paperwallet.pageBreakAt;
|
||
var div = document.createElement("div");
|
||
div.setAttribute("id", "keyarea" + i);
|
||
if (ninja.wallets.paperwallet.useArtisticWallet) {
|
||
div.innerHTML = ninja.wallets.paperwallet.templateArtisticHtml(i);
|
||
div.setAttribute("class", "keyarea art");
|
||
}
|
||
else {
|
||
div.innerHTML = ninja.wallets.paperwallet.templateHtml(i);
|
||
div.setAttribute("class", "keyarea");
|
||
}
|
||
if (paperArea.innerHTML != "") {
|
||
// page break
|
||
if (i % pageBreakAt == 1 && ninja.wallets.paperwallet.count >= pageBreakAt) {
|
||
var pBreak = document.createElement("div");
|
||
pBreak.setAttribute("class", "pagebreak");
|
||
document.getElementById("paperkeyarea").appendChild(pBreak);
|
||
div.style.pageBreakBefore = "always";
|
||
if (!ninja.wallets.paperwallet.useArtisticWallet) {
|
||
div.style.borderTop = "2px solid green";
|
||
}
|
||
}
|
||
}
|
||
document.getElementById("paperkeyarea").appendChild(div);
|
||
ninja.wallets.paperwallet.generateNewWallet(i);
|
||
ninja.wallets.paperwallet.remaining--;
|
||
setTimeout(ninja.wallets.paperwallet.batch, 0);
|
||
}
|
||
},
|
||
|
||
// generate bitcoin address, private key, QR Code and update information in the HTML
|
||
// idPostFix: 1, 2, 3, etc.
|
||
generateNewWallet: function (idPostFix) {
|
||
var key = new Bitcoin.ECKey(false);
|
||
var bitcoinAddress = key.getBitcoinAddress();
|
||
var privateKeyWif = key.getBitcoinWalletImportFormat();
|
||
if (ninja.wallets.paperwallet.useArtisticWallet) {
|
||
ninja.wallets.paperwallet.showArtisticWallet(idPostFix, bitcoinAddress, privateKeyWif);
|
||
}
|
||
else {
|
||
ninja.wallets.paperwallet.showWallet(idPostFix, bitcoinAddress, privateKeyWif);
|
||
}
|
||
},
|
||
|
||
templateHtml: function (i) {
|
||
var walletHtml =
|
||
"<div class='public'>" +
|
||
"<div id='qrcode_public" + i + "' class='qrcode_public'></div>" +
|
||
"<div class='pubaddress'>" +
|
||
"<span class='label'>" + ninja.translator.get("paperlabelbitcoinaddress") + "</span>" +
|
||
"<span class='output' id='btcaddress" + i + "'></span>" +
|
||
"</div>" +
|
||
"</div>" +
|
||
"<div class='private'>" +
|
||
"<div id='qrcode_private" + i + "' class='qrcode_private'></div>" +
|
||
"<div class='privwif'>" +
|
||
"<span class='label'>" + ninja.translator.get("paperlabelprivatekey") + "</span>" +
|
||
"<span class='output' id='btcprivwif" + i + "'></span>" +
|
||
"</div>" +
|
||
"</div>";
|
||
return walletHtml;
|
||
},
|
||
|
||
showWallet: function (idPostFix, bitcoinAddress, privateKeyWif) {
|
||
document.getElementById("btcaddress" + idPostFix).innerHTML = bitcoinAddress;
|
||
document.getElementById("btcprivwif" + idPostFix).innerHTML = privateKeyWif;
|
||
var keyValuePair = {};
|
||
keyValuePair["qrcode_public" + idPostFix] = bitcoinAddress;
|
||
keyValuePair["qrcode_private" + idPostFix] = privateKeyWif;
|
||
ninja.qrCode.showQrCode(keyValuePair);
|
||
document.getElementById("keyarea" + idPostFix).style.display = "block";
|
||
},
|
||
|
||
templateArtisticHtml: function (i) {
|
||
var walletHtml =
|
||
"<div class='artwallet' id='artwallet" + i + "'>" +
|
||
//"<iframe src='bitcoin-wallet-01.svg' id='papersvg" + i + "' class='papersvg' ></iframe>" +
|
||
"<img id='papersvg" + i + "' class='papersvg' src='data:image/png;base64,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KpVw+vRp3HzzzRgaGoLFYkEgEMCJEyfwmc98BpFIBHfccQfC4bCYYdkf96DBYEBnZyemp6fx4Q9/GK+99hoCgQDe8573YP369TAajbj++uvh9/tx8uRJvPOd78TAwAA0TcPy5csRj8cRi8Vw4sQJPP3007j11ltx66234sSJE5iZmcEtt9yC4eFhNBoNnD17FldddRXOnDmDW265BadOncJ73/te7N69G48//jhuuukmEaje8Y534NSpU4hEIvjgBz8oPm+n04n7778f/f39eO9734tcLofu7m4AwL/+67/CZrNh586diEQi2LhxI0ZGRrBx40ZUq1W0t7fjmWeewdGjR/HRj34UN954Iz796U9jcnISt99+O775zW/i2muvhaZp+Kd/+id88IMfxMDAAEqlEh599FF86Utfkhj9Rx99FO9///tx/PhxJJNJbNy4EQ888AA2btyILVu2wOfz4aGHHsKOHTtwxx13IBAI4L777sOqVauwceNGAMCqVavw2GOP4cUXX8TAwAC2b9+OmZkZvPLKK7jttttw4MABrF27FmvWrMEbb7yBF154AR/72Mfw+OOP4/nnn8ddd90lceKlUgkbNmxANpvFihUrcPz4caxevVpozNVXX41qtYpoNCravfbjH/+4ofodVaKjR4+qYDMSX5V4qGhREiaVqLEP9rsUQydwhshFbl41Vk7tk/0SLKH2p2pHxWKxSTBRtR39c6qEjO9iNBrFnOTz+USrpVanArJU7VwVVAjI0zQN09PTcg9KoZxINSzObDYjGo0Kg/V6vU3vlc/nMTExgTVr1mB6ehoul0t+SwZMEFC9XseJEycwPDws4Lb29nbRQvj+NKuHQiGk02mJtTSZTEIYi8WijGM+n4fH45H/ZAzqXNFMbrPZcMcdd7ytOOy77roLkUikKcmOOudqXDHHmoyEz7gUU29VlmLkqu+YfXFN6pk770nLi+rrJwNW6/keRBKr9QR3cW7ITNX4ZgpUXEPqNRHJZKhEWauJU3jN/AlWq1WYK4U63iOXywk4iMlPnE4nstksPB4PGo2GMNF4PA6PxyNt0uk0fD4fotGoJDNxu91IJBKCuPX7/VLP+Nr5+XkEg0Fks1lJckKMSTQalQQ7vJ6ZmUEoFEI2m4Xf70ckEkFnZydqtRoikQi6urpEaM5kMggEAlhYWBANSa232WyIRqNI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'/>" +
|
||
"<div id='qrcode_public" + i + "' class='qrcode_public'></div>" +
|
||
"<div id='qrcode_private" + i + "' class='qrcode_private'></div>" +
|
||
"<div class='btcaddress' id='btcaddress" + i + "'></div>" +
|
||
"<div class='btcprivwif' id='btcprivwif" + i + "'></div>" +
|
||
"</div>";
|
||
return walletHtml;
|
||
},
|
||
|
||
showArtisticWallet: function (idPostFix, bitcoinAddress, privateKeyWif) {
|
||
var keyValuePair = {};
|
||
keyValuePair["qrcode_public" + idPostFix] = bitcoinAddress;
|
||
keyValuePair["qrcode_private" + idPostFix] = privateKeyWif;
|
||
ninja.qrCode.showQrCode(keyValuePair, 2.5);
|
||
document.getElementById("btcaddress" + idPostFix).innerHTML = bitcoinAddress;
|
||
document.getElementById("btcprivwif" + idPostFix).innerHTML = privateKeyWif;
|
||
|
||
// CODE to modify SVG DOM elements
|
||
//var paperSvg = document.getElementById("papersvg" + idPostFix);
|
||
//if (paperSvg) {
|
||
// svgDoc = paperSvg.contentDocument;
|
||
// if (svgDoc) {
|
||
// var bitcoinAddressElement = svgDoc.getElementById("bitcoinaddress");
|
||
// var privateKeyElement = svgDoc.getElementById("privatekey");
|
||
// if (bitcoinAddressElement && privateKeyElement) {
|
||
// bitcoinAddressElement.textContent = bitcoinAddress;
|
||
// privateKeyElement.textContent = privateKeyWif;
|
||
// }
|
||
// }
|
||
//}
|
||
},
|
||
|
||
toggleArt: function (element) {
|
||
if (!element.checked) {
|
||
// show Art
|
||
document.getElementById("paperlimitperpage").value = ninja.wallets.paperwallet.pageBreakAtArtisticDefault;
|
||
document.getElementById("paperlimit").value = ninja.wallets.paperwallet.pageBreakAtArtisticDefault;
|
||
}
|
||
else {
|
||
// hide Art
|
||
document.getElementById("paperlimitperpage").value = ninja.wallets.paperwallet.pageBreakAtDefault;
|
||
document.getElementById("paperlimit").value = ninja.wallets.paperwallet.pageBreakAtDefault;
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.wallets.bulkwallet = {
|
||
open: function () {
|
||
document.getElementById("bulkarea").style.display = "block";
|
||
// show a default CSV list if the text area is empty
|
||
if (document.getElementById("bulktextarea").value == "") {
|
||
// return control of the thread to the browser to render the tab switch UI then build a default CSV list
|
||
setTimeout(function () { ninja.wallets.bulkwallet.buildCSV(3, 1); }, 200);
|
||
}
|
||
},
|
||
|
||
close: function () {
|
||
document.getElementById("bulkarea").style.display = "none";
|
||
},
|
||
|
||
// use this function to bulk generate addresses
|
||
// rowLimit: number of Bitcoin Addresses to generate
|
||
// startIndex: add this number to the row index for output purposes
|
||
// returns:
|
||
// index,bitcoinAddress,privateKeyWif
|
||
buildCSV: function (rowLimit, startIndex) {
|
||
var bulkWallet = ninja.wallets.bulkwallet;
|
||
document.getElementById("bulktextarea").value = ninja.translator.get("bulkgeneratingaddresses") + rowLimit;
|
||
bulkWallet.csv = [];
|
||
bulkWallet.csvRowLimit = rowLimit;
|
||
bulkWallet.csvRowsRemaining = rowLimit;
|
||
bulkWallet.csvStartIndex = --startIndex;
|
||
setTimeout(bulkWallet.batchCSV, 0);
|
||
},
|
||
|
||
csv: [],
|
||
csvRowsRemaining: null, // use to keep track of how many rows are left to process when building a large CSV array
|
||
csvRowLimit: 0,
|
||
csvStartIndex: 0,
|
||
|
||
batchCSV: function () {
|
||
var bulkWallet = ninja.wallets.bulkwallet;
|
||
if (bulkWallet.csvRowsRemaining > 0) {
|
||
bulkWallet.csvRowsRemaining--;
|
||
var key = new Bitcoin.ECKey(false);
|
||
|
||
bulkWallet.csv.push((bulkWallet.csvRowLimit - bulkWallet.csvRowsRemaining + bulkWallet.csvStartIndex)
|
||
+ ",\"" + key.getBitcoinAddress() + "\",\"" + key.toString("wif")
|
||
//+ "\",\"" + key.toString("wifcomp") // uncomment these lines to add different private key formats to the CSV
|
||
//+ "\",\"" + key.getBitcoinHexFormat()
|
||
//+ "\",\"" + key.toString("base64")
|
||
+ "\"");
|
||
|
||
document.getElementById("bulktextarea").value = ninja.translator.get("bulkgeneratingaddresses") + bulkWallet.csvRowsRemaining;
|
||
|
||
// release thread to browser to render UI
|
||
setTimeout(bulkWallet.batchCSV, 0);
|
||
}
|
||
// processing is finished so put CSV in text area
|
||
else if (bulkWallet.csvRowsRemaining === 0) {
|
||
document.getElementById("bulktextarea").value = bulkWallet.csv.join("\n");
|
||
}
|
||
},
|
||
|
||
openCloseFaq: function (faqNum) {
|
||
// do close
|
||
if (document.getElementById("bulka" + faqNum).style.display == "block") {
|
||
document.getElementById("bulka" + faqNum).style.display = "none";
|
||
document.getElementById("bulke" + faqNum).setAttribute("class", "more");
|
||
}
|
||
// do open
|
||
else {
|
||
document.getElementById("bulka" + faqNum).style.display = "block";
|
||
document.getElementById("bulke" + faqNum).setAttribute("class", "less");
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.wallets.brainwallet = {
|
||
open: function () {
|
||
document.getElementById("brainarea").style.display = "block";
|
||
document.getElementById("brainpassphrase").focus();
|
||
},
|
||
|
||
close: function () {
|
||
document.getElementById("brainarea").style.display = "none";
|
||
},
|
||
|
||
minPassphraseLength: 15,
|
||
|
||
view: function () {
|
||
var key = document.getElementById("brainpassphrase").value.toString().replace(/^\s+|\s+$/g, ""); // trim white space
|
||
document.getElementById("brainpassphrase").value = key;
|
||
var keyConfirm = document.getElementById("brainpassphraseconfirm").value.toString().replace(/^\s+|\s+$/g, ""); // trim white space
|
||
document.getElementById("brainpassphraseconfirm").value = keyConfirm;
|
||
|
||
if (key == keyConfirm || document.getElementById("brainpassphraseshow").checked) {
|
||
// enforce a minimum passphrase length
|
||
if (key.length >= ninja.wallets.brainwallet.minPassphraseLength) {
|
||
var bytes = Crypto.SHA256(key, { asBytes: true });
|
||
var btcKey = new Bitcoin.ECKey(bytes);
|
||
var bitcoinAddress = btcKey.getBitcoinAddress();
|
||
var privWif = btcKey.getBitcoinWalletImportFormat();
|
||
document.getElementById("brainbtcaddress").innerHTML = bitcoinAddress;
|
||
document.getElementById("brainbtcprivwif").innerHTML = privWif;
|
||
ninja.qrCode.showQrCode({
|
||
"brainqrcodepublic": bitcoinAddress,
|
||
"brainqrcodeprivate": privWif
|
||
});
|
||
document.getElementById("brainkeyarea").style.visibility = "visible";
|
||
}
|
||
else {
|
||
alert(ninja.translator.get("brainalertpassphrasetooshort"));
|
||
ninja.wallets.brainwallet.clear();
|
||
}
|
||
}
|
||
else {
|
||
alert(ninja.translator.get("brainalertpassphrasedoesnotmatch"));
|
||
ninja.wallets.brainwallet.clear();
|
||
}
|
||
},
|
||
|
||
clear: function () {
|
||
document.getElementById("brainkeyarea").style.visibility = "hidden";
|
||
},
|
||
|
||
showToggle: function (element) {
|
||
if (element.checked) {
|
||
document.getElementById("brainpassphrase").setAttribute("type", "text");
|
||
document.getElementById("brainpassphraseconfirm").style.visibility = "hidden";
|
||
document.getElementById("brainlabelconfirm").style.visibility = "hidden";
|
||
}
|
||
else {
|
||
document.getElementById("brainpassphrase").setAttribute("type", "password");
|
||
document.getElementById("brainpassphraseconfirm").style.visibility = "visible";
|
||
document.getElementById("brainlabelconfirm").style.visibility = "visible";
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.wallets.vanitywallet = {
|
||
open: function () {
|
||
document.getElementById("vanityarea").style.display = "block";
|
||
},
|
||
|
||
close: function () {
|
||
document.getElementById("vanityarea").style.display = "none";
|
||
document.getElementById("vanitystep1area").style.display = "none";
|
||
document.getElementById("vanitystep2area").style.display = "none";
|
||
document.getElementById("vanitystep1icon").setAttribute("class", "more");
|
||
document.getElementById("vanitystep2icon").setAttribute("class", "more");
|
||
},
|
||
|
||
generateKeyPair: function () {
|
||
var key = new Bitcoin.ECKey(false);
|
||
var publicKey = key.getPubKeyHex();
|
||
var privateKey = key.getBitcoinHexFormat();
|
||
document.getElementById("vanitypubkey").innerHTML = publicKey;
|
||
document.getElementById("vanityprivatekey").innerHTML = privateKey;
|
||
document.getElementById("vanityarea").style.display = "block";
|
||
document.getElementById("vanitystep1area").style.display = "none";
|
||
},
|
||
|
||
addKeys: function () {
|
||
var privateKeyWif = ninja.translator.get("vanityinvalidinputcouldnotcombinekeys");
|
||
var bitcoinAddress = ninja.translator.get("vanityinvalidinputcouldnotcombinekeys");
|
||
var publicKeyHex = ninja.translator.get("vanityinvalidinputcouldnotcombinekeys");
|
||
try {
|
||
var input1KeyString = document.getElementById("vanityinput1").value;
|
||
var input2KeyString = document.getElementById("vanityinput2").value;
|
||
|
||
// both inputs are public keys
|
||
if (ninja.publicKey.isPublicKeyHexFormat(input1KeyString) && ninja.publicKey.isPublicKeyHexFormat(input2KeyString)) {
|
||
// add both public keys together
|
||
if (document.getElementById("vanityradioadd").checked) {
|
||
var pubKeyByteArray = ninja.publicKey.getByteArrayFromAdding(input1KeyString, input2KeyString);
|
||
if (pubKeyByteArray == null) {
|
||
alert(ninja.translator.get("vanityalertinvalidinputpublickeysmatch"));
|
||
}
|
||
else {
|
||
privateKeyWif = ninja.translator.get("vanityprivatekeyonlyavailable");
|
||
bitcoinAddress = ninja.publicKey.getBitcoinAddressFromByteArray(pubKeyByteArray);
|
||
publicKeyHex = ninja.publicKey.getHexFromByteArray(pubKeyByteArray);
|
||
}
|
||
}
|
||
else {
|
||
alert(ninja.translator.get("vanityalertinvalidinputcannotmultiple"));
|
||
}
|
||
}
|
||
// one public key and one private key
|
||
else if ((ninja.publicKey.isPublicKeyHexFormat(input1KeyString) && ninja.privateKey.isPrivateKey(input2KeyString))
|
||
|| (ninja.publicKey.isPublicKeyHexFormat(input2KeyString) && ninja.privateKey.isPrivateKey(input1KeyString))
|
||
) {
|
||
privateKeyWif = ninja.translator.get("vanityprivatekeyonlyavailable");
|
||
var pubKeyHex = (ninja.publicKey.isPublicKeyHexFormat(input1KeyString)) ? input1KeyString : input2KeyString;
|
||
var ecKey = (ninja.privateKey.isPrivateKey(input1KeyString)) ? new Bitcoin.ECKey(input1KeyString) : new Bitcoin.ECKey(input2KeyString);
|
||
// add
|
||
if (document.getElementById("vanityradioadd").checked) {
|
||
var pubKeyCombined = ninja.publicKey.getByteArrayFromAdding(pubKeyHex, ecKey.getPubKeyHex());
|
||
}
|
||
// multiply
|
||
else {
|
||
var pubKeyCombined = ninja.publicKey.getByteArrayFromMultiplying(pubKeyHex, ecKey);
|
||
}
|
||
if (pubKeyCombined == null) {
|
||
alert(ninja.translator.get("vanityalertinvalidinputpublickeysmatch"));
|
||
} else {
|
||
bitcoinAddress = ninja.publicKey.getBitcoinAddressFromByteArray(pubKeyCombined);
|
||
publicKeyHex = ninja.publicKey.getHexFromByteArray(pubKeyCombined);
|
||
}
|
||
}
|
||
// both inputs are private keys
|
||
else if (ninja.privateKey.isPrivateKey(input1KeyString) && ninja.privateKey.isPrivateKey(input2KeyString)) {
|
||
var combinedPrivateKey;
|
||
// add both private keys together
|
||
if (document.getElementById("vanityradioadd").checked) {
|
||
combinedPrivateKey = ninja.privateKey.getECKeyFromAdding(input1KeyString, input2KeyString);
|
||
}
|
||
// multiply both private keys together
|
||
else {
|
||
combinedPrivateKey = ninja.privateKey.getECKeyFromMultiplying(input1KeyString, input2KeyString);
|
||
}
|
||
if (combinedPrivateKey == null) {
|
||
alert(ninja.translator.get("vanityalertinvalidinputprivatekeysmatch"));
|
||
}
|
||
else {
|
||
bitcoinAddress = combinedPrivateKey.getBitcoinAddress();
|
||
privateKeyWif = combinedPrivateKey.getBitcoinWalletImportFormat();
|
||
publicKeyHex = combinedPrivateKey.getPubKeyHex();
|
||
}
|
||
}
|
||
} catch (e) {
|
||
alert(e);
|
||
}
|
||
document.getElementById("vanityprivatekeywif").innerHTML = privateKeyWif;
|
||
document.getElementById("vanityaddress").innerHTML = bitcoinAddress;
|
||
document.getElementById("vanitypublickeyhex").innerHTML = publicKeyHex;
|
||
document.getElementById("vanitystep2area").style.display = "block";
|
||
document.getElementById("vanitystep2icon").setAttribute("class", "less");
|
||
},
|
||
|
||
openCloseStep: function (num) {
|
||
// do close
|
||
if (document.getElementById("vanitystep" + num + "area").style.display == "block") {
|
||
document.getElementById("vanitystep" + num + "area").style.display = "none";
|
||
document.getElementById("vanitystep" + num + "icon").setAttribute("class", "more");
|
||
}
|
||
// do open
|
||
else {
|
||
document.getElementById("vanitystep" + num + "area").style.display = "block";
|
||
document.getElementById("vanitystep" + num + "icon").setAttribute("class", "less");
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
ninja.wallets.detailwallet = {
|
||
open: function () {
|
||
document.getElementById("detailarea").style.display = "block";
|
||
document.getElementById("detailprivkey").focus();
|
||
},
|
||
|
||
close: function () {
|
||
document.getElementById("detailarea").style.display = "none";
|
||
},
|
||
|
||
viewDetails: function () {
|
||
var key = document.getElementById("detailprivkey").value.toString().replace(/^\s+|\s+$/g, ""); // trim white space
|
||
document.getElementById("detailprivkey").value = key;
|
||
if (Bitcoin.ECKey.isMiniFormat(key)) {
|
||
// show Private Key Mini Format
|
||
document.getElementById("detailprivmini").innerHTML = key;
|
||
document.getElementById("detailmini").style.display = "block";
|
||
}
|
||
else {
|
||
// hide Private Key Mini Format
|
||
document.getElementById("detailmini").style.display = "none";
|
||
}
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.priv == null) {
|
||
// enforce a minimum passphrase length
|
||
if (key.length >= ninja.wallets.brainwallet.minPassphraseLength) {
|
||
// Deterministic Wallet confirm box to ask if user wants to SHA256 the input to get a private key
|
||
var usePassphrase = confirm(ninja.translator.get("detailconfirmsha256"));
|
||
if (usePassphrase) {
|
||
var bytes = Crypto.SHA256(key, { asBytes: true });
|
||
var btcKey = new Bitcoin.ECKey(bytes);
|
||
}
|
||
else {
|
||
ninja.wallets.detailwallet.clear();
|
||
}
|
||
}
|
||
else {
|
||
alert(ninja.translator.get("detailalertnotvalidprivatekey"));
|
||
ninja.wallets.detailwallet.clear();
|
||
}
|
||
}
|
||
if (btcKey.priv != null) {
|
||
btcKey.setCompressed(false);
|
||
document.getElementById("detailprivhex").innerHTML = btcKey.toString().toUpperCase();
|
||
document.getElementById("detailprivb64").innerHTML = btcKey.toString("base64");
|
||
var bitcoinAddress = btcKey.getBitcoinAddress();
|
||
var wif = btcKey.getBitcoinWalletImportFormat();
|
||
document.getElementById("detailpubkey").innerHTML = btcKey.getPubKeyHex();
|
||
document.getElementById("detailaddress").innerHTML = bitcoinAddress;
|
||
document.getElementById("detailprivwif").innerHTML = wif;
|
||
btcKey.setCompressed(true);
|
||
var bitcoinAddressComp = btcKey.getBitcoinAddress();
|
||
var wifComp = btcKey.getBitcoinWalletImportFormat();
|
||
document.getElementById("detailpubkeycomp").innerHTML = btcKey.getPubKeyHex();
|
||
document.getElementById("detailaddresscomp").innerHTML = bitcoinAddressComp;
|
||
document.getElementById("detailprivwifcomp").innerHTML = wifComp;
|
||
|
||
ninja.qrCode.showQrCode({
|
||
"detailqrcodepublic": bitcoinAddress,
|
||
"detailqrcodepubliccomp": bitcoinAddressComp,
|
||
"detailqrcodeprivate": wif,
|
||
"detailqrcodeprivatecomp": wifComp
|
||
});
|
||
}
|
||
},
|
||
|
||
clear: function () {
|
||
document.getElementById("detailpubkey").innerHTML = "";
|
||
document.getElementById("detailpubkeycomp").innerHTML = "";
|
||
document.getElementById("detailaddress").innerHTML = "";
|
||
document.getElementById("detailaddresscomp").innerHTML = "";
|
||
document.getElementById("detailprivwif").innerHTML = "";
|
||
document.getElementById("detailprivwifcomp").innerHTML = "";
|
||
document.getElementById("detailprivhex").innerHTML = "";
|
||
document.getElementById("detailprivb64").innerHTML = "";
|
||
document.getElementById("detailprivmini").innerHTML = "";
|
||
document.getElementById("detailqrcodepublic").innerHTML = "";
|
||
document.getElementById("detailqrcodepubliccomp").innerHTML = "";
|
||
document.getElementById("detailqrcodeprivate").innerHTML = "";
|
||
document.getElementById("detailqrcodeprivatecomp").innerHTML = "";
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
(function (ninja) {
|
||
var ut = ninja.unitTests = {
|
||
runTests: function () {
|
||
var div = document.createElement("div");
|
||
div.setAttribute("class", "unittests");
|
||
var testResults = "";
|
||
var passCount = 0;
|
||
var testCount = 0;
|
||
for (var test in ut.tests) {
|
||
var exceptionMsg = "";
|
||
var resultBool = false;
|
||
try {
|
||
resultBool = ut.tests[test]();
|
||
} catch (ex) {
|
||
exceptionMsg = ex.toString();
|
||
resultBool = false;
|
||
}
|
||
if (resultBool == true) {
|
||
var passFailStr = "pass";
|
||
passCount++;
|
||
}
|
||
else {
|
||
var passFailStr = "<b>FAIL " + exceptionMsg + "</b>";
|
||
}
|
||
testCount++;
|
||
testResults += test + ": " + passFailStr + "<br/>";
|
||
}
|
||
testResults += passCount + " of " + testCount + " tests passed";
|
||
div.innerHTML = "<h3>Unit Tests</h3><div>" + testResults + "</div>";
|
||
document.body.appendChild(div);
|
||
if (passCount < testCount) {
|
||
alert((testCount - passCount) + " unit test(s) failed");
|
||
}
|
||
},
|
||
|
||
tests: {
|
||
//ninja.publicKey tests
|
||
testIsPublicKeyHexFormat: function () {
|
||
var key = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var bool = ninja.publicKey.isPublicKeyHexFormat(key);
|
||
if (bool != true) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetHexFromByteArray: function () {
|
||
var bytes = [4, 120, 152, 47, 64, 250, 12, 11, 122, 85, 113, 117, 131, 175, 201, 154, 78, 223, 211, 1, 162, 114, 157, 197, 155, 11, 142, 185, 225, 134, 146, 188, 181, 33, 240, 84, 250, 217, 130, 175, 76, 193, 147, 58, 253, 31, 27, 86, 62, 167, 121, 166, 170, 108, 206, 54, 163, 11, 148, 125, 214, 83, 230, 62, 68];
|
||
var key = ninja.publicKey.getHexFromByteArray(bytes);
|
||
if (key != "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testHexToBytes: function () {
|
||
var key = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var bytes = Crypto.util.hexToBytes(key);
|
||
if (bytes.toString() != "4,120,152,47,64,250,12,11,122,85,113,117,131,175,201,154,78,223,211,1,162,114,157,197,155,11,142,185,225,134,146,188,181,33,240,84,250,217,130,175,76,193,147,58,253,31,27,86,62,167,121,166,170,108,206,54,163,11,148,125,214,83,230,62,68") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetBitcoinAddressFromByteArray: function () {
|
||
var bytes = [4, 120, 152, 47, 64, 250, 12, 11, 122, 85, 113, 117, 131, 175, 201, 154, 78, 223, 211, 1, 162, 114, 157, 197, 155, 11, 142, 185, 225, 134, 146, 188, 181, 33, 240, 84, 250, 217, 130, 175, 76, 193, 147, 58, 253, 31, 27, 86, 62, 167, 121, 166, 170, 108, 206, 54, 163, 11, 148, 125, 214, 83, 230, 62, 68];
|
||
var address = ninja.publicKey.getBitcoinAddressFromByteArray(bytes);
|
||
if (address != "1Cnz9ULjzBPYhDw1J8bpczDWCEXnC9HuU1") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromAdding: function () {
|
||
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var key2 = "0419153E53FECAD7FF07FEC26F7DDEB1EDD66957711AA4554B8475F10AFBBCD81C0159DC0099AD54F733812892EB9A11A8C816A201B3BAF0D97117EBA2033C9AB2";
|
||
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
|
||
if (bytes.toString() != "4,151,19,227,152,54,37,184,255,4,83,115,216,102,189,76,82,170,57,4,196,253,2,41,74,6,226,33,167,199,250,74,235,223,128,233,99,150,147,92,57,39,208,84,196,71,68,248,166,106,138,95,172,253,224,70,187,65,62,92,81,38,253,79,0") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromAddingCompressed: function () {
|
||
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
|
||
var key2 = "0219153E53FECAD7FF07FEC26F7DDEB1EDD66957711AA4554B8475F10AFBBCD81C";
|
||
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
|
||
var hex = ninja.publicKey.getHexFromByteArray(bytes);
|
||
if (hex != "029713E3983625B8FF045373D866BD4C52AA3904C4FD02294A06E221A7C7FA4AEB") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromAddingUncompressedAndCompressed: function () {
|
||
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var key2 = "0219153E53FECAD7FF07FEC26F7DDEB1EDD66957711AA4554B8475F10AFBBCD81C";
|
||
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
|
||
if (bytes.toString() != "4,151,19,227,152,54,37,184,255,4,83,115,216,102,189,76,82,170,57,4,196,253,2,41,74,6,226,33,167,199,250,74,235,223,128,233,99,150,147,92,57,39,208,84,196,71,68,248,166,106,138,95,172,253,224,70,187,65,62,92,81,38,253,79,0") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromAddingShouldReturnNullWhenSameKey1: function () {
|
||
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var key2 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
|
||
if (bytes != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromAddingShouldReturnNullWhenSameKey2: function () {
|
||
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var key2 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
|
||
var bytes = ninja.publicKey.getByteArrayFromAdding(key1, key2);
|
||
if (bytes != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromMultiplying: function () {
|
||
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
|
||
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
|
||
if (bytes.toString() != "4,102,230,163,180,107,9,21,17,48,35,245,227,110,199,119,144,57,41,112,64,245,182,40,224,41,230,41,5,26,206,138,57,115,35,54,105,7,180,5,106,217,57,229,127,174,145,215,79,121,163,191,211,143,215,50,48,156,211,178,72,226,68,150,52") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromMultiplyingCompressedOutputsUncompressed: function () {
|
||
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
|
||
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
|
||
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
|
||
if (bytes.toString() != "4,102,230,163,180,107,9,21,17,48,35,245,227,110,199,119,144,57,41,112,64,245,182,40,224,41,230,41,5,26,206,138,57,115,35,54,105,7,180,5,106,217,57,229,127,174,145,215,79,121,163,191,211,143,215,50,48,156,211,178,72,226,68,150,52") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromMultiplyingCompressedOutputsCompressed: function () {
|
||
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
|
||
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
|
||
var ecKey = new Bitcoin.ECKey(key2);
|
||
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, ecKey);
|
||
if (bytes.toString() != "2,102,230,163,180,107,9,21,17,48,35,245,227,110,199,119,144,57,41,112,64,245,182,40,224,41,230,41,5,26,206,138,57") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromMultiplyingShouldReturnNullWhenSameKey1: function () {
|
||
var key1 = "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44";
|
||
var key2 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
|
||
if (bytes != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetByteArrayFromMultiplyingShouldReturnNullWhenSameKey2: function () {
|
||
var key1 = "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5";
|
||
var key2 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||
var bytes = ninja.publicKey.getByteArrayFromMultiplying(key1, new Bitcoin.ECKey(key2));
|
||
if (bytes != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
// confirms multiplication is working and BigInteger was created correctly (Pub Key B vs Priv Key A)
|
||
testGetPubHexFromMultiplyingPrivAPubB: function () {
|
||
var keyPub = "04F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F98938020F36EBBDE6F1BEAF98E5BD0E425747E68B0F2FB7A2A59EDE93F43C0D78156FF";
|
||
var keyPriv = "B1202A137E917536B3B4C5010C3FF5DDD4784917B3EEF21D3A3BF21B2E03310C";
|
||
var bytes = ninja.publicKey.getByteArrayFromMultiplying(keyPub, new Bitcoin.ECKey(keyPriv));
|
||
var pubHex = ninja.publicKey.getHexFromByteArray(bytes);
|
||
if (pubHex != "04C6732006AF4AE571C7758DF7A7FB9E3689DFCF8B53D8724D3A15517D8AB1B4DBBE0CB8BB1C4525F8A3001771FC7E801D3C5986A555E2E9441F1AD6D181356076") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
// confirms multiplication is working and BigInteger was created correctly (Pub Key A vs Priv Key B)
|
||
testGetPubHexFromMultiplyingPrivBPubA: function () {
|
||
var keyPub = "0429BF26C0AF7D31D608474CEBD49DA6E7C541B8FAD95404B897643476CE621CFD05E24F7AE8DE8033AADE5857DB837E0B704A31FDDFE574F6ECA879643A0D3709";
|
||
var keyPriv = "7DE52819F1553C2BFEDE6A2628B6FDDF03C2A07EB21CF77ACA6C2C3D252E1FD9";
|
||
var bytes = ninja.publicKey.getByteArrayFromMultiplying(keyPub, new Bitcoin.ECKey(keyPriv));
|
||
var pubHex = ninja.publicKey.getHexFromByteArray(bytes);
|
||
if (pubHex != "04C6732006AF4AE571C7758DF7A7FB9E3689DFCF8B53D8724D3A15517D8AB1B4DBBE0CB8BB1C4525F8A3001771FC7E801D3C5986A555E2E9441F1AD6D181356076") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
|
||
// Private Key tests
|
||
testBadKeyIsNotWif: function () {
|
||
return !(Bitcoin.ECKey.isWalletImportFormat("bad key"));
|
||
},
|
||
testBadKeyIsNotWifCompressed: function () {
|
||
return !(Bitcoin.ECKey.isCompressedWalletImportFormat("bad key"));
|
||
},
|
||
testBadKeyIsNotHex: function () {
|
||
return !(Bitcoin.ECKey.isHexFormat("bad key"));
|
||
},
|
||
testBadKeyIsNotBase64: function () {
|
||
return !(Bitcoin.ECKey.isBase64Format("bad key"));
|
||
},
|
||
testBadKeyIsNotMini: function () {
|
||
return !(Bitcoin.ECKey.isMiniFormat("bad key"));
|
||
},
|
||
testBadKeyReturnsNullPrivFromECKey: function () {
|
||
var key = "bad key";
|
||
var ecKey = new Bitcoin.ECKey(key);
|
||
if (ecKey.priv != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetBitcoinPrivateKeyByteArray: function () {
|
||
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var bytes = [41, 38, 101, 195, 135, 36, 24, 173, 241, 218, 127, 250, 58, 100, 111, 47, 6, 2, 36, 109, 166, 9, 138, 145, 210, 41, 195, 33, 80, 242, 113, 139];
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinPrivateKeyByteArray().toString() != bytes.toString()) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testECKeyDecodeWalletImportFormat: function () {
|
||
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var bytes1 = [41, 38, 101, 195, 135, 36, 24, 173, 241, 218, 127, 250, 58, 100, 111, 47, 6, 2, 36, 109, 166, 9, 138, 145, 210, 41, 195, 33, 80, 242, 113, 139];
|
||
var bytes2 = Bitcoin.ECKey.decodeWalletImportFormat(key);
|
||
if (bytes1.toString() != bytes2.toString()) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testECKeyDecodeCompressedWalletImportFormat: function () {
|
||
var key = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||
var bytes1 = [41, 38, 101, 195, 135, 36, 24, 173, 241, 218, 127, 250, 58, 100, 111, 47, 6, 2, 36, 109, 166, 9, 138, 145, 210, 41, 195, 33, 80, 242, 113, 139];
|
||
var bytes2 = Bitcoin.ECKey.decodeCompressedWalletImportFormat(key);
|
||
if (bytes1.toString() != bytes2.toString()) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testWifToPubKeyHex: function () {
|
||
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getPubKeyHex() != "0478982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB521F054FAD982AF4CC1933AFD1F1B563EA779A6AA6CCE36A30B947DD653E63E44"
|
||
|| btcKey.getPubPoint().compressed != false) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testWifToPubKeyHexCompressed: function () {
|
||
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
btcKey.setCompressed(true);
|
||
if (btcKey.getPubKeyHex() != "0278982F40FA0C0B7A55717583AFC99A4EDFD301A2729DC59B0B8EB9E18692BCB5"
|
||
|| btcKey.getPubPoint().compressed != true) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testBase64ToECKey: function () {
|
||
var key = "KSZlw4ckGK3x2n/6OmRvLwYCJG2mCYqR0inDIVDycYs=";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinBase64Format() != "KSZlw4ckGK3x2n/6OmRvLwYCJG2mCYqR0inDIVDycYs=") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testHexToECKey: function () {
|
||
var key = "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinHexFormat() != "292665C3872418ADF1DA7FFA3A646F2F0602246DA6098A91D229C32150F2718B") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testCompressedWifToECKey: function () {
|
||
var key = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinWalletImportFormat() != "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S"
|
||
|| btcKey.getPubPoint().compressed != true) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testWifToECKey: function () {
|
||
var key = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testBrainToECKey: function () {
|
||
var key = "bitaddress.org unit test";
|
||
var bytes = Crypto.SHA256(key, { asBytes: true });
|
||
var btcKey = new Bitcoin.ECKey(bytes);
|
||
if (btcKey.getBitcoinWalletImportFormat() != "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testMini30CharsToECKey: function () {
|
||
var key = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinWalletImportFormat() != "5JrBLQseeZdYw4jWEAHmNxGMr5fxh9NJU3fUwnv4khfKcg2rJVh") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromAdding: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
|
||
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
|
||
if (ecKey.getBitcoinWalletImportFormat() != "5KAJTSqSjpsZ11KyEE3qu5PrJVjR4ZCbNxK3Nb1F637oe41m1c2") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromAddingCompressed: function () {
|
||
var key1 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
|
||
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
|
||
if (ecKey.getBitcoinWalletImportFormat() != "L3A43j2pc2J8F2SjBNbYprPrcDpDCh8Aju8dUH65BEM2r7RFSLv4") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromAddingUncompressedAndCompressed: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
|
||
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
|
||
if (ecKey.getBitcoinWalletImportFormat() != "5KAJTSqSjpsZ11KyEE3qu5PrJVjR4ZCbNxK3Nb1F637oe41m1c2") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromAddingShouldReturnNullWhenSameKey1: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
|
||
if (ecKey != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromAddingShouldReturnNullWhenSameKey2: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||
var ecKey = ninja.privateKey.getECKeyFromAdding(key1, key2);
|
||
if (ecKey != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromMultiplying: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "SQE6yipP5oW8RBaStWoB47xsRQ8pat";
|
||
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
|
||
if (ecKey.getBitcoinWalletImportFormat() != "5KetpZ5mCGagCeJnMmvo18n4iVrtPSqrpnW5RP92Gv2BQy7GPCk") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromMultiplyingCompressed: function () {
|
||
var key1 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
|
||
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
|
||
if (ecKey.getBitcoinWalletImportFormat() != "L5LFitc24jme2PfVChJS3bKuQAPBp54euuqLWciQdF2CxnaU3M8t") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromMultiplyingUncompressedAndCompressed: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "L1n4cgNZAo2KwdUc15zzstvo1dcxpBw26NkrLqfDZtU9AEbPkLWu";
|
||
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
|
||
if (ecKey.getBitcoinWalletImportFormat() != "5KetpZ5mCGagCeJnMmvo18n4iVrtPSqrpnW5RP92Gv2BQy7GPCk") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromMultiplyingShouldReturnNullWhenSameKey1: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
|
||
if (ecKey != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testGetECKeyFromMultiplyingShouldReturnNullWhenSameKey2: function () {
|
||
var key1 = "5J8QhiQtAiozKwyk3GCycAscg1tNaYhNdiiLey8vaDK8Bzm4znb";
|
||
var key2 = "KxbhchnQquYQ2dfSxz7rrEaQTCukF4uCV57TkamyTbLzjFWcdi3S";
|
||
var ecKey = ninja.privateKey.getECKeyFromMultiplying(key1, key2);
|
||
if (ecKey != null) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
|
||
// EllipticCurve tests
|
||
testDecodePointEqualsDecodeFrom: function () {
|
||
var key = "04F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F98938020F36EBBDE6F1BEAF98E5BD0E425747E68B0F2FB7A2A59EDE93F43C0D78156FF";
|
||
var ecparams = EllipticCurve.getSECCurveByName("secp256k1");
|
||
var ecPoint1 = EllipticCurve.PointFp.decodeFrom(ecparams.getCurve(), Crypto.util.hexToBytes(key));
|
||
var ecPoint2 = ecparams.getCurve().decodePointHex(key);
|
||
if (!ecPoint1.equals(ecPoint2)) {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testDecodePointHexForCompressedPublicKey: function () {
|
||
var key = "03F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F989380";
|
||
var pubHexUncompressed = ninja.publicKey.getDecompressedPubKeyHex(key);
|
||
if (pubHexUncompressed != "04F04BF260DCCC46061B5868F60FE962C77B5379698658C98A93C3129F5F98938020F36EBBDE6F1BEAF98E5BD0E425747E68B0F2FB7A2A59EDE93F43C0D78156FF") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
// old bugs
|
||
testBugWithLeadingZeroBytePublicKey: function () {
|
||
var key = "5Je7CkWTzgdo1RpwjYhwnVKxQXt8EPRq17WZFtWcq5umQdsDtTP";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinAddress() != "1M6dsMZUjFxjdwsyVk8nJytWcfr9tfUa9E") {
|
||
return false;
|
||
}
|
||
return true;
|
||
},
|
||
testBugWithLeadingZeroBytePrivateKey: function () {
|
||
var key = "0004d30da67214fa65a41a6493576944c7ea86713b14db437446c7a8df8e13da";
|
||
var btcKey = new Bitcoin.ECKey(key);
|
||
if (btcKey.getBitcoinAddress() != "1NAjZjF81YGfiJ3rTKc7jf1nmZ26KN7Gkn") {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
};
|
||
})(ninja);
|
||
</script>
|
||
|
||
<script type="text/javascript">
|
||
// run unit tests
|
||
if (ninja.getQueryString()["unittests"] == "true" || ninja.getQueryString()["unittests"] == "1") {
|
||
ninja.unitTests.runTests();
|
||
ninja.translator.showEnglishJson();
|
||
}
|
||
|
||
// change language
|
||
if (ninja.getQueryString()["culture"] != undefined) {
|
||
ninja.translator.translate(ninja.getQueryString()["culture"]);
|
||
}
|
||
|
||
// testnet, check if testnet edition should be activated
|
||
if (ninja.getQueryString()["testnet"] == "true" || ninja.getQueryString()["testnet"] == "1") {
|
||
document.getElementById("testnet").innerHTML = ninja.translator.get("testneteditionactivated");
|
||
document.getElementById("testnet").style.display = "block";
|
||
document.getElementById("detailwifprefix").innerHTML = "'9'";
|
||
document.getElementById("detailcompwifprefix").innerHTML = "'c'";
|
||
Bitcoin.Address.networkVersion = 0x6F; // testnet
|
||
Bitcoin.ECKey.privateKeyPrefix = 0xEF; // testnet
|
||
ninja.testnetMode = true;
|
||
}
|
||
|
||
// if users does not move mouse after random amount of time then generate the key anyway.
|
||
setTimeout(ninja.seeder.forceGenerate, ninja.seeder.seedLimit * 20);
|
||
</script>
|
||
</body>
|
||
</html> |