]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/BIP39.git/blobdiff - src/js/index.js
Entropy can be supplied by user
[perso/Immae/Projets/Cryptomonnaies/BIP39.git] / src / js / index.js
index 0e4cc052a4d704fa749bf9076c9bc68fc5145530..cd7f281b5489f8e1a956a19fb4784e3fa3c1cb8c 100644 (file)
     var showPubKey = true;
     var showPrivKey = true;
 
+    var entropyChangeTimeoutEvent = null;
     var phraseChangeTimeoutEvent = null;
     var rootKeyChangedTimeoutEvent = null;
 
     var DOM = {};
     DOM.network = $(".network");
     DOM.phraseNetwork = $("#network-phrase");
+    DOM.useEntropy = $(".use-entropy");
+    DOM.entropyContainer = $(".entropy-container");
+    DOM.entropy = $(".entropy");
+    DOM.entropyError = $(".entropy-error");
     DOM.phrase = $(".phrase");
     DOM.passphrase = $(".passphrase");
+    DOM.generateContainer = $(".generate-container");
     DOM.generate = $(".generate");
     DOM.seed = $(".seed");
     DOM.rootKey = $(".root-key");
@@ -53,6 +59,8 @@
     function init() {
         // Events
         DOM.network.on("change", networkChanged);
+        DOM.useEntropy.on("change", setEntropyVisibility);
+        DOM.entropy.on("input", delayedEntropyChanged);
         DOM.phrase.on("input", delayedPhraseChanged);
         DOM.passphrase.on("input", delayedPhraseChanged);
         DOM.generate.on("click", generateClicked);
         }
     }
 
+    function setEntropyVisibility() {
+        if (isUsingOwnEntropy()) {
+            DOM.entropyContainer.removeClass("hidden");
+            DOM.generateContainer.addClass("hidden");
+            DOM.phrase.prop("readonly", true);
+            DOM.entropy.focus();
+            entropyChanged();
+        }
+        else {
+            DOM.entropyContainer.addClass("hidden");
+            DOM.generateContainer.removeClass("hidden");
+            DOM.phrase.prop("readonly", false);
+        }
+    }
+
     function delayedPhraseChanged() {
         hideValidationError();
         showPending();
         hidePending();
     }
 
+    function delayedEntropyChanged() {
+        hideValidationError();
+        showPending();
+        if (entropyChangeTimeoutEvent != null) {
+            clearTimeout(entropyChangeTimeoutEvent);
+        }
+        entropyChangeTimeoutEvent = setTimeout(entropyChanged, 400);
+    }
+
+    function entropyChanged() {
+        setMnemonicFromEntropy();
+        phraseChanged();
+    }
+
     function delayedRootKeyChanged() {
         // Warn if there is an existing mnemonic or passphrase.
         if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) {
     }
 
     function generateClicked() {
+        if (isUsingOwnEntropy()) {
+            return;
+        }
         clearDisplay();
         showPending();
         setTimeout(function() {
     }
 
     function getLanguageFromUrl() {
-        return window.location.hash.substring(1);
+        for (var language in WORDLISTS) {
+            if (window.location.hash.indexOf(language) > -1) {
+                return language;
+            }
+        }
+        return "";
     }
 
     function setMnemonicLanguage() {
         return phrase;
     }
 
+    function isUsingOwnEntropy() {
+        return DOM.useEntropy.prop("checked");
+    }
+
+    function setMnemonicFromEntropy() {
+        hideEntropyError();
+        // Work out minimum base for entropy
+        var entropyStr = DOM.entropy.val();
+        var entropy = Entropy.fromString(entropyStr);
+        if (entropy.hexStr.length == 0) {
+            return;
+        }
+        // Show entropy details
+        var extraBits = 32 - (entropy.binaryStr.length % 32);
+        var extraChars = Math.ceil(extraBits * Math.log(2) / Math.log(entropy.base.asInt));
+        var strength = "an extremely weak";
+        if (entropy.hexStr.length >= 8) {
+            strength = "a very weak";
+        }
+        if (entropy.hexStr.length >= 12) {
+            strength = "a weak";
+        }
+        if (entropy.hexStr.length >= 24) {
+            strength = "a strong";
+        }
+        if (entropy.hexStr.length >= 32) {
+            strength = "a very strong";
+        }
+        if (entropy.hexStr.length >= 40) {
+            strength = "an extremely strong";
+        }
+        if (entropy.hexStr.length >=48) {
+            strength = "an even stronger"
+        }
+        var msg = "Have " + entropy.binaryStr.length + " bits of entropy, " + extraChars + " more " + entropy.base.str + " chars required to generate " + strength + " mnemonic: " + entropy.cleanStr;
+        showEntropyError(msg);
+        // Discard trailing entropy
+        var hexStr = entropy.hexStr.substring(0, Math.floor(entropy.hexStr.length / 8) * 8);
+        // Convert entropy string to numeric array
+        var entropyArr = [];
+        for (var i=0; i<hexStr.length / 2; i++) {
+            var entropyByte = parseInt(hexStr[i*2].concat(hexStr[i*2+1]), 16);
+            entropyArr.push(entropyByte)
+        }
+        // Convert entropy array to mnemonic
+        var phrase = mnemonic.toMnemonic(entropyArr);
+        // Set the mnemonic in the UI
+        DOM.phrase.val(phrase);
+    }
+
+    function hideEntropyError() {
+        DOM.entropyError.addClass("hidden");
+    }
+
+    function showEntropyError(msg) {
+        DOM.entropyError.text(msg);
+        DOM.entropyError.removeClass("hidden");
+    }
+
     var networks = [
         {
             name: "Bitcoin",