DOM.useEntropy = $(".use-entropy");
DOM.entropyContainer = $(".entropy-container");
DOM.entropy = $(".entropy");
- DOM.entropyFeedback = $(".entropy-feedback");
- DOM.entropyFiltered = DOM.entropyFeedback.find(".filtered");
- DOM.entropyType = DOM.entropyFeedback.find(".type");
- DOM.entropyStrength = DOM.entropyFeedback.find(".strength");
- DOM.entropyEventCount = DOM.entropyFeedback.find(".event-count");
- DOM.entropyBits = DOM.entropyFeedback.find(".bits");
- DOM.entropyBitsPerEvent = DOM.entropyFeedback.find(".bits-per-event");
- DOM.entropyMnemonicLength = DOM.entropyFeedback.find(".mnemonic-length");
+ DOM.entropyFiltered = DOM.entropyContainer.find(".filtered");
+ DOM.entropyType = DOM.entropyContainer.find(".type");
+ DOM.entropyStrength = DOM.entropyContainer.find(".strength");
+ DOM.entropyEventCount = DOM.entropyContainer.find(".event-count");
+ DOM.entropyBits = DOM.entropyContainer.find(".bits");
+ DOM.entropyBitsPerEvent = DOM.entropyContainer.find(".bits-per-event");
+ DOM.entropyWordCount = DOM.entropyContainer.find(".word-count");
+ DOM.entropyBinary = DOM.entropyContainer.find(".binary");
+ DOM.entropyMnemonicLength = DOM.entropyContainer.find(".mnemonic-length");
DOM.phrase = $(".phrase");
DOM.passphrase = $(".passphrase");
DOM.generateContainer = $(".generate-container");
DOM.network.on("change", networkChanged);
DOM.useEntropy.on("change", setEntropyVisibility);
DOM.entropy.on("input", delayedEntropyChanged);
+ DOM.entropyMnemonicLength.on("change", entropyChanged);
DOM.phrase.on("input", delayedPhraseChanged);
DOM.passphrase.on("input", delayedPhraseChanged);
DOM.generate.on("click", generateClicked);
// If blank entropy, clear mnemonic, addresses, errors
if (DOM.entropy.val().trim().length == 0) {
clearDisplay();
- hideEntropyFeedback();
+ clearEntropyFeedback();
DOM.phrase.val("");
showValidationError("Blank entropy");
return;
}
function setMnemonicFromEntropy() {
- hideEntropyFeedback();
+ clearEntropyFeedback();
// Get entropy value
var entropyStr = DOM.entropy.val();
// Work out minimum base for entropy
}
// Show entropy details
showEntropyFeedback(entropy);
+ // Use entropy hash if not using raw entropy
+ var bits = entropy.binaryStr;
+ var mnemonicLength = DOM.entropyMnemonicLength.val();
+ if (mnemonicLength != "raw") {
+ // Get bits by hashing entropy with SHA256
+ var hash = sjcl.hash.sha256.hash(entropy.cleanStr);
+ var hex = sjcl.codec.hex.fromBits(hash);
+ bits = BigInteger.parse(hex, 16).toString(2);
+ for (var i=0; i<256-bits.length; i++) {
+ bits = "0" + bits;
+ }
+ // Truncate hash to suit number of words
+ mnemonicLength = parseInt(mnemonicLength);
+ var numberOfBits = 32 * mnemonicLength / 3;
+ bits = bits.substring(0, numberOfBits);
+ }
// Discard trailing entropy
- var bitsToUse = Math.floor(entropy.binaryStr.length / 32) * 32;
- var binaryStr = entropy.binaryStr.substring(0, bitsToUse);
+ var bitsToUse = Math.floor(bits.length / 32) * 32;
+ var binaryStr = bits.substring(0, bitsToUse);
// Convert entropy string to numeric array
var entropyArr = [];
for (var i=0; i<binaryStr.length / 8; i++) {
DOM.phrase.val(phrase);
}
- function hideEntropyFeedback() {
- DOM.entropyFeedback.addClass("hidden");
- DOM.entropyFiltered.text("");
+ function clearEntropyFeedback() {
+ DOM.entropyStrength.text("...");
DOM.entropyType.text("");
- DOM.entropyStrength.text("");
- DOM.entropyEventCount.text("");
- DOM.entropyBits.text("");
- DOM.entropyBitsPerEvent.text("");
+ DOM.entropyWordCount.text("0");
+ DOM.entropyEventCount.text("0");
+ DOM.entropyBitsPerEvent.text("0");
+ DOM.entropyBits.text("0");
+ DOM.entropyFiltered.html(" ");
+ DOM.entropyBinary.html(" ");
}
function showEntropyFeedback(entropy) {
if (entropy.binaryStr.length >= 192) {
strength = "extremely strong";
}
- var bitsStr = entropy.binaryStr.length;
- if (entropy.base.asInt != 2) {
- bitsStr += " (" + entropy.binaryStr + ")";
+ // If time to crack is less than one day, and password is considered
+ // strong or better based on the number of bits, rename strength to
+ // 'easily cracked'.
+ var z = zxcvbn(entropy.cleanStr);
+ var timeToCrack = z.crack_times_seconds.offline_fast_hashing_1e10_per_second;
+ if (timeToCrack < 86400 && entropy.binaryStr.length >= 128) {
+ strength = "easily cracked";
+ if (z.feedback.warning != "") {
+ strength = strength + " - " + z.feedback.warning;
+ };
}
- DOM.entropyFiltered.text(entropy.cleanStr);
+ var bitsStr = entropy.binaryStr.length;
+ var wordCount = Math.floor(entropy.binaryStr.length / 32) * 3;
+ DOM.entropyFiltered.html(entropy.cleanHtml);
DOM.entropyType.text(entropy.base.str);
DOM.entropyStrength.text(strength);
DOM.entropyEventCount.text(entropy.base.ints.length);
DOM.entropyBits.text(bitsStr);
+ DOM.entropyWordCount.text(wordCount);
+ DOM.entropyBinary.text(entropy.binaryStr);
DOM.entropyBitsPerEvent.text(Math.log2(entropy.base.asInt).toFixed(2));
- DOM.entropyFeedback.removeClass("hidden");
}
var networks = [