more entropy

This commit is contained in:
pointbiz 2013-12-09 19:30:16 -04:00
parent 4f11d4fb62
commit db6d3e9acc
6 changed files with 130 additions and 30 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -21,6 +21,7 @@ body { font-family: Arial; }
.answer { padding: 0 15px 10px 25px; text-align: left; display: none; font-size: 80%; } .answer { padding: 0 15px 10px 25px; text-align: left; display: none; font-size: 80%; }
.faq { border: 0; border-top: 2px solid green; } .faq { border: 0; border-top: 2px solid green; }
#seedpoolarea { display: none; }
#keyarea { height: 250px; font-family: Arial; } #keyarea { height: 250px; font-family: Arial; }
#keyarea .pubaddress { float: none; display: block; padding: 0; height: auto; } #keyarea .pubaddress { float: none; display: block; padding: 0; height: auto; }
#keyarea .label { text-decoration: none; } #keyarea .label { text-decoration: none; }
@ -183,4 +184,5 @@ body { font-family: Arial; }
#detailprivwif { width: 285px; word-wrap: break-word; } #detailprivwif { width: 285px; word-wrap: break-word; }
#detailprivwifcomp { width: 285px; word-wrap: break-word; text-align: right; } #detailprivwifcomp { width: 285px; word-wrap: break-word; text-align: right; }
#detailarea .privqr .item { width: 285px; } #detailarea .privqr .item { width: 285px; }
#seedpoolarea { display: none; }
} }

View file

@ -2,7 +2,7 @@ ninja.seeder = {
// number of mouse movements to wait for // number of mouse movements to wait for
seedLimit: (function () { seedLimit: (function () {
var num = Crypto.util.randomBytes(12)[11]; var num = Crypto.util.randomBytes(12)[11];
return 50 + Math.floor(num); return 100 + Math.floor(num);
})(), })(),
seedCount: 0, // counter seedCount: 0, // counter
@ -24,6 +24,12 @@ ninja.seeder = {
document.getElementById("generate").style.display = "none"; document.getElementById("generate").style.display = "none";
document.getElementById("menu").style.visibility = "visible"; document.getElementById("menu").style.visibility = "visible";
} }
if (SecureRandom.poolCopyOnInit != null) {
document.getElementById("seedpool").innerHTML = Crypto.util.bytesToHex(SecureRandom.poolCopyOnInit);
}
else {
document.getElementById("seedpool").innerHTML = Crypto.util.bytesToHex(SecureRandom.pool);
}
}, },
// If user has not moved the mouse or if they are on a mobile device // If user has not moved the mouse or if they are on a mobile device

View file

@ -21,5 +21,9 @@ if (ninja.getQueryString()["testnet"] == "true" || ninja.getQueryString()["testn
Bitcoin.ECKey.privateKeyPrefix = 0xEF; // testnet Bitcoin.ECKey.privateKeyPrefix = 0xEF; // testnet
ninja.testnetMode = true; ninja.testnetMode = true;
} }
if (ninja.getQueryString()["showseedpool"] == "true" || ninja.getQueryString()["showseedpool"] == "1") {
document.getElementById("seedpoolarea").style.display = "block";
}
// if users does not move mouse after random amount of time then generate the key anyway. // if users does not move mouse after random amount of time then generate the key anyway.
setTimeout(ninja.seeder.forceGenerate, ninja.seeder.seedLimit * 20); setTimeout(ninja.seeder.forceGenerate, ninja.seeder.seedLimit * 100);

View file

@ -17,6 +17,7 @@
sr.state; sr.state;
sr.pool; sr.pool;
sr.pptr; sr.pptr;
sr.poolCopyOnInit;
// Pool size must be a multiple of 4 and greater than 32. // 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() // An array of bytes the size of the pool will be passed to init()
@ -46,8 +47,9 @@
sr.seedTime(); sr.seedTime();
sr.state = sr.ArcFour(); // Plug in your RNG constructor here sr.state = sr.ArcFour(); // Plug in your RNG constructor here
sr.state.init(sr.pool); sr.state.init(sr.pool);
sr.poolCopyOnInit = [];
for (sr.pptr = 0; sr.pptr < sr.pool.length; ++sr.pptr) for (sr.pptr = 0; sr.pptr < sr.pool.length; ++sr.pptr)
sr.pool[sr.pptr] = 0; sr.poolCopyOnInit[sr.pptr] = sr.pool[sr.pptr];
sr.pptr = 0; sr.pptr = 0;
} }
// TODO: allow reseeding after first request // TODO: allow reseeding after first request
@ -56,13 +58,17 @@
// Mix in a 32-bit integer into the pool // Mix in a 32-bit integer into the pool
sr.seedInt = function (x) { sr.seedInt = function (x) {
sr.pool[sr.pptr++] ^= x & 255; sr.seedInt8(x);
sr.pool[sr.pptr++] ^= (x >> 8) & 255; sr.seedInt8((x >> 8));
sr.pool[sr.pptr++] ^= (x >> 16) & 255; sr.seedInt8((x >> 16));
sr.pool[sr.pptr++] ^= (x >> 24) & 255; sr.seedInt8((x >> 24));
if (sr.pptr >= sr.poolSize) sr.pptr -= sr.poolSize;
} }
// Mix in a 8-bit integer into the pool
sr.seedInt8 = function (x) {
sr.pool[sr.pptr++] ^= x & 255;
if (sr.pptr >= sr.poolSize) sr.pptr -= sr.poolSize;
}
// Arcfour is a PRNG // Arcfour is a PRNG
sr.ArcFour = function () { sr.ArcFour = function () {
@ -110,11 +116,14 @@
sr.pool = new Array(); sr.pool = new Array();
sr.pptr = 0; sr.pptr = 0;
var t; var t;
if (navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) { if (window.crypto && window.crypto.getRandomValues) {
// Extract entropy (256 bits) from NS4 RNG if available try {
var z = window.crypto.random(32); // Use webcrypto if available
for (t = 0; t < z.length; ++t) var ua = new Uint8Array(32);
sr.pool[sr.pptr++] = z.charCodeAt(t) & 255; window.crypto.getRandomValues(ua);
for (t = 0; t < 32; ++t)
sr.pool[sr.pptr++] = ua[t];
} catch (e) { alert(e); }
} }
while (sr.pptr < sr.poolSize) { // extract some randomness from Math.random() while (sr.pptr < sr.poolSize) { // extract some randomness from Math.random()
t = Math.floor(65536 * Math.random()); t = Math.floor(65536 * Math.random());
@ -124,7 +133,35 @@
sr.pptr = 0; sr.pptr = 0;
sr.seedTime(); sr.seedTime();
// entropy // entropy
sr.seedInt(window.screenX); var entropyStr = "";
sr.seedInt(window.screenY); // screen size and color depth: ~4.8 to ~5.4 bits
entropyStr += (window.screen.height * window.screen.width * window.screen.colorDepth);
entropyStr += (window.screen.availHeight * window.screen.availWidth * window.screen.pixelDepth);
// time zone offset: ~4 bits
var dateObj = new Date();
var timeZoneOffset = dateObj.getTimezoneOffset();
entropyStr += timeZoneOffset;
// user agent: ~8.3 to ~11.6 bits
entropyStr += navigator.userAgent;
// browser plugin details: ~16.2 to ~21.8 bits
var pluginsStr = "";
for (var i = 0; i < navigator.plugins.length; i++) {
pluginsStr += navigator.plugins[i].name + " " + navigator.plugins[i].filename + " " + navigator.plugins[i].description + " " + navigator.plugins[i].version + ", ";
}
var mimeTypesStr = "";
for (var i = 0; i < navigator.mimeTypes.length; i++) {
mimeTypesStr += navigator.mimeTypes[i].description + " " + navigator.mimeTypes[i].type + " " + navigator.mimeTypes[i].suffixes + ", ";
}
entropyStr += pluginsStr + mimeTypesStr;
// cookies and storage: 1 bit
entropyStr += navigator.cookieEnabled + typeof (sessionStorage) + typeof (localStorage);
var entropyBytes = Crypto.SHA256(entropyStr, { asBytes: true });
sr.seedInt8(entropyBytes[0]);
sr.seedInt8(entropyBytes[1]);
sr.seedInt8(entropyBytes[2]);
sr.seedInt8(entropyBytes[3]);
sr.seedInt8(entropyBytes[4]);
sr.seedInt8(entropyBytes[5]);
} }
})(); })();