bitaddress.org/src/ninja.misc.js
2014-03-24 22:41:40 +01:00

266 lines
No EOL
9.4 KiB
JavaScript

ninja.seeder = {
init: (function () {
document.getElementById("generatekeyinput").value = "";
})(),
// number of mouse movements to wait for
seedLimit: (function () {
var num = Crypto.util.randomBytes(12)[11];
return 200 + Math.floor(num);
})(),
seedCount: 0, // counter
lastInputTime: new Date().getTime(),
seedPoints: [],
// 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;
var timeStamp = new Date().getTime();
// seeding is over now we generate and display the address
if (ninja.seeder.seedCount == ninja.seeder.seedLimit) {
ninja.seeder.seedCount++;
ninja.wallets.singlewallet.open();
document.getElementById("generate").style.display = "none";
document.getElementById("menu").style.visibility = "visible";
ninja.seeder.removePoints();
}
// seed mouse position X and Y when mouse movements are greater than 40ms apart.
else if ((ninja.seeder.seedCount < ninja.seeder.seedLimit) && evt && (timeStamp - ninja.seeder.lastInputTime) > 40) {
SecureRandom.seedTime();
SecureRandom.seedInt16((evt.clientX * evt.clientY));
ninja.seeder.showPoint(evt.clientX, evt.clientY);
ninja.seeder.seedCount++;
ninja.seeder.lastInputTime = new Date().getTime();
ninja.seeder.showPool();
}
},
// seed function exists to wait for mouse movement to add more entropy before generating an address
seedKeyPress: function (evt) {
if (!evt) var evt = window.event;
// seeding is over now we generate and display the address
if (ninja.seeder.seedCount == ninja.seeder.seedLimit) {
ninja.seeder.seedCount++;
ninja.wallets.singlewallet.open();
document.getElementById("generate").style.display = "none";
document.getElementById("menu").style.visibility = "visible";
ninja.seeder.removePoints();
}
// seed key press character
else if ((ninja.seeder.seedCount < ninja.seeder.seedLimit) && evt.which) {
var timeStamp = new Date().getTime();
// seed a bunch (minimum seedLimit) of times
SecureRandom.seedTime();
SecureRandom.seedInt8(evt.which);
var keyPressTimeDiff = timeStamp - ninja.seeder.lastInputTime;
SecureRandom.seedInt8(keyPressTimeDiff);
ninja.seeder.seedCount++;
ninja.seeder.lastInputTime = new Date().getTime();
ninja.seeder.showPool();
}
},
showPool: function () {
var poolHex;
if (SecureRandom.poolCopyOnInit != null) {
poolHex = Crypto.util.bytesToHex(SecureRandom.poolCopyOnInit);
document.getElementById("seedpool").innerHTML = poolHex;
document.getElementById("seedpooldisplay").innerHTML = poolHex;
}
else {
poolHex = Crypto.util.bytesToHex(SecureRandom.pool);
document.getElementById("seedpool").innerHTML = poolHex;
document.getElementById("seedpooldisplay").innerHTML = poolHex;
}
document.getElementById("mousemovelimit").innerHTML = (ninja.seeder.seedLimit - ninja.seeder.seedCount);
},
showPoint: function (x, y) {
var div = document.createElement("div");
div.setAttribute("class", "seedpoint");
div.style.top = y + "px";
div.style.left = x + "px";
document.body.appendChild(div);
ninja.seeder.seedPoints.push(div);
},
removePoints: function () {
for (var i = 0; i < ninja.seeder.seedPoints.length; i++) {
document.body.removeChild(ninja.seeder.seedPoints[i]);
}
ninja.seeder.seedPoints = [];
}
};
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.envSecurityCheck = function() {
var innerHTML = "";
switch(window.location.protocol) {
case 'http:':
case 'https:':
innerHTML = '<span style="color: #990000;">You appear to be running this generator off of a live website, which is not recommended for creating valuable wallets. Instead, use the download link at the bottom of this page to download the ZIP file from GitHub and run this generator offline as a \'local\' HTML file.</span>';
break;
case 'file:':
innerHTML = '<span style="color: #009900;">You are running this generator from your own download.</span>';
break;
default:
}
document.getElementById('envSecurityCheck').innerHTML = innerHTML;
};
ninja.browserSecurityCheck = function() {
var innerHTML = "";
if (window.crypto && window.crypto.getRandomValues) {
innerHTML = '<span style="color: #009900;">Your browser is capable of generating cryptographically random keys using window.crypto.getRandomValues</span>';
} else {
innerHTML = '<span style="color: #990000;">Your browser does NOT support window.crypto.getRandomValues(), which is important for generating the most secure random numbers possible. Please use a more modern browser.</span>';
}
document.getElementById('browserSecurityCheck').innerHTML = innerHTML;
}
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;
};
// use when passing an Array of Functions
ninja.runSerialized = function (functions, onComplete) {
onComplete = onComplete || function () { };
if (functions.length === 0) onComplete();
else {
// run the first function, and make it call this
// function when finished with the rest of the list
var f = functions.shift();
f(function () { ninja.runSerialized(functions, onComplete); });
}
};
ninja.forSerialized = function (initial, max, whatToDo, onComplete) {
onComplete = onComplete || function () { };
if (initial === max) { onComplete(); }
else {
// same idea as runSerialized
whatToDo(initial, function () { ninja.forSerialized(++initial, max, whatToDo, onComplete); });
}
};
// use when passing an Object (dictionary) of Functions
ninja.foreachSerialized = function (collection, whatToDo, onComplete) {
var keys = [];
for (var name in collection) {
keys.push(name);
}
ninja.forSerialized(0, keys.length, function (i, callback) {
whatToDo(keys[i], callback);
}, onComplete);
};