aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/index.html60
-rw-r--r--src/js/entropy.js47
-rw-r--r--src/js/index.js79
3 files changed, 108 insertions, 78 deletions
diff --git a/src/index.html b/src/index.html
index cb7a781..feefbd8 100644
--- a/src/index.html
+++ b/src/index.html
@@ -95,17 +95,57 @@
95 </div> 95 </div>
96 </div> 96 </div>
97 <div class="entropy-container hidden"> 97 <div class="entropy-container hidden">
98 <label for="entropy" class="col-sm-2 control-label">Entropy</label> 98 <div class="form-group">
99 <div class="col-sm-10"> 99 <label for="entropy" class="col-sm-2 control-label">Entropy</label>
100 <input id="entropy" class="entropy form-control" placeholder="Accepts binary, base 6, 6-sided dice, base 10, hexadecimal"> 100 <div class="col-sm-10">
101 <span class="help-block"> 101 <input id="entropy" class="entropy form-control" placeholder="Accepts binary, base 6, 6-sided dice, base 10, hexadecimal">
102 <div class="text-danger"> 102 <span class="help-block">
103 This is an advanced feature. 103 <div class="text-danger">
104 Your mnemonic may be insecure if this feature is used incorrectly. 104 This is an advanced feature.
105 <a href="#entropy-notes">Read more</a> 105 Your mnemonic may be insecure if this feature is used incorrectly.
106 <a href="#entropy-notes">Read more</a>
107 </div>
108 </span>
109 </div>
110 </div>
111 <div class="entropy-feedback">
112 <div class="form-group">
113 <label class="col-sm-2 control-label">Filtered</label>
114 <div class="filtered col-sm-10 form-control-static"></div>
115 </div>
116 <div class="form-group">
117 <label class="col-sm-2 control-label">Type</label>
118 <div class="type col-sm-10 form-control-static"></div>
119 </div>
120 <div class="form-group">
121 <label class="col-sm-2 control-label">Strength</label>
122 <div class="strength col-sm-10 form-control-static"></div>
123 </div>
124 <div class="form-group">
125 <label class="col-sm-2 control-label">Event Count</label>
126 <div class="event-count col-sm-10 form-control-static"></div>
127 </div>
128 <div class="form-group">
129 <label class="col-sm-2 control-label">Bits Per Event</label>
130 <div class="bits-per-event col-sm-10 form-control-static"></div>
131 </div>
132 <div class="form-group">
133 <label class="col-sm-2 control-label">Bits</label>
134 <div class="bits col-sm-10 form-control-static"></div>
135 </div>
136 <div class="form-group">
137 <label class="col-sm-2 control-label">Mnemonic Length</label>
138 <div class="col-sm-10">
139 <select class="mnemonic-length form-control">
140 <option value="raw">From entropy length</option>
141 <option value="12">12 Words</option>
142 <option value="15">15 Words</option>
143 <option value="18">18 Words</option>
144 <option value="21">21 Words</option>
145 <option value="24">24 Words</option>
146 </select>
106 </div> 147 </div>
107 <div class="text-danger entropy-error"></div> 148 </div>
108 </span>
109 </div> 149 </div>
110 </div> 150 </div>
111 <div class="form-group"> 151 <div class="form-group">
diff --git a/src/js/entropy.js b/src/js/entropy.js
index db4051b..cd9b375 100644
--- a/src/js/entropy.js
+++ b/src/js/entropy.js
@@ -96,40 +96,6 @@ window.Entropy = new (function() {
96 base: base, 96 base: base,
97 }; 97 };
98 } 98 }
99 // Pull leading zeros off
100 var leadingZeros = [];
101 while (base.ints[0] == "0") {
102 leadingZeros.push("0");
103 base.ints.shift();
104 }
105 // Convert leading zeros to binary equivalent
106 var numBinLeadingZeros = Math.floor(Math.log2(base.asInt) * leadingZeros.length);
107 var binLeadingZeros = "";
108 for (var i=0; i<numBinLeadingZeros; i++) {
109 binLeadingZeros += "0";
110 }
111 // Handle entropy of zero
112 if (base.ints.length == 0) {
113 return {
114 binaryStr: binLeadingZeros,
115 cleanStr: leadingZeros.join(""),
116 base: base,
117 }
118 }
119 // If the first integer is small, it must be padded with zeros.
120 // Otherwise the chance of the first bit being 1 is 100%, which is
121 // obviously incorrect.
122 // This is not perfect for unusual bases, so is only done for bases
123 // of 2^n, eg octal or hexadecimal
124 if (base.asInt == 16) {
125 var firstInt = base.ints[0];
126 var firstIntBits = firstInt.toString(2).length;
127 var maxFirstIntBits = (base.asInt-1).toString(2).length;
128 var missingFirstIntBits = maxFirstIntBits - firstIntBits;
129 for (var i=0; i<missingFirstIntBits; i++) {
130 binLeadingZeros += "0";
131 }
132 }
133 // Convert base.ints to BigInteger. 99 // Convert base.ints to BigInteger.
134 // Due to using unusual bases, eg cards of base52, this is not as simple as 100 // Due to using unusual bases, eg cards of base52, this is not as simple as
135 // using BigInteger.parse() 101 // using BigInteger.parse()
@@ -140,8 +106,17 @@ window.Entropy = new (function() {
140 var additionalEntropy = BigInteger.parse(base.asInt).pow(power).multiply(thisInt); 106 var additionalEntropy = BigInteger.parse(base.asInt).pow(power).multiply(thisInt);
141 entropyInt = entropyInt.add(additionalEntropy); 107 entropyInt = entropyInt.add(additionalEntropy);
142 } 108 }
143 // Convert entropy to different formats 109 // Convert entropy to binary
144 var entropyBin = binLeadingZeros + entropyInt.toString(2); 110 var entropyBin = entropyInt.toString(2);
111 // If the first integer is small, it must be padded with zeros.
112 // Otherwise the chance of the first bit being 1 is 100%, which is
113 // obviously incorrect.
114 // This is not perfect for non-2^n bases.
115 var expectedBits = Math.floor(base.parts.length * Math.log2(base.asInt));
116 while (entropyBin.length < expectedBits) {
117 entropyBin = "0" + entropyBin;
118 }
119 // Supply a 'filtered' entropy string for display purposes
145 var entropyClean = base.parts.join(""); 120 var entropyClean = base.parts.join("");
146 if (base.asInt == 52) { 121 if (base.asInt == 52) {
147 entropyClean = base.parts.join(" ").toUpperCase(); 122 entropyClean = base.parts.join(" ").toUpperCase();
diff --git a/src/js/index.js b/src/js/index.js
index 45db7b1..45f378d 100644
--- a/src/js/index.js
+++ b/src/js/index.js
@@ -24,7 +24,14 @@
24 DOM.useEntropy = $(".use-entropy"); 24 DOM.useEntropy = $(".use-entropy");
25 DOM.entropyContainer = $(".entropy-container"); 25 DOM.entropyContainer = $(".entropy-container");
26 DOM.entropy = $(".entropy"); 26 DOM.entropy = $(".entropy");
27 DOM.entropyError = $(".entropy-error"); 27 DOM.entropyFeedback = $(".entropy-feedback");
28 DOM.entropyFiltered = DOM.entropyFeedback.find(".filtered");
29 DOM.entropyType = DOM.entropyFeedback.find(".type");
30 DOM.entropyStrength = DOM.entropyFeedback.find(".strength");
31 DOM.entropyEventCount = DOM.entropyFeedback.find(".event-count");
32 DOM.entropyBits = DOM.entropyFeedback.find(".bits");
33 DOM.entropyBitsPerEvent = DOM.entropyFeedback.find(".bits-per-event");
34 DOM.entropyMnemonicLength = DOM.entropyFeedback.find(".mnemonic-length");
28 DOM.phrase = $(".phrase"); 35 DOM.phrase = $(".phrase");
29 DOM.passphrase = $(".passphrase"); 36 DOM.passphrase = $(".passphrase");
30 DOM.generateContainer = $(".generate-container"); 37 DOM.generateContainer = $(".generate-container");
@@ -153,7 +160,7 @@
153 // If blank entropy, clear mnemonic, addresses, errors 160 // If blank entropy, clear mnemonic, addresses, errors
154 if (DOM.entropy.val().trim().length == 0) { 161 if (DOM.entropy.val().trim().length == 0) {
155 clearDisplay(); 162 clearDisplay();
156 hideEntropyError(); 163 hideEntropyFeedback();
157 DOM.phrase.val(""); 164 DOM.phrase.val("");
158 showValidationError("Blank entropy"); 165 showValidationError("Blank entropy");
159 return; 166 return;
@@ -727,7 +734,7 @@
727 } 734 }
728 735
729 function setMnemonicFromEntropy() { 736 function setMnemonicFromEntropy() {
730 hideEntropyError(); 737 hideEntropyFeedback();
731 // Get entropy value 738 // Get entropy value
732 var entropyStr = DOM.entropy.val(); 739 var entropyStr = DOM.entropy.val();
733 // Work out minimum base for entropy 740 // Work out minimum base for entropy
@@ -736,30 +743,7 @@
736 return; 743 return;
737 } 744 }
738 // Show entropy details 745 // Show entropy details
739 var extraBits = 32 - (entropy.binaryStr.length % 32); 746 showEntropyFeedback(entropy);
740 var extraChars = Math.ceil(extraBits * Math.log(2) / Math.log(entropy.base.asInt));
741 var words = Math.floor(entropy.binaryStr.length / 32) * 3;
742 var strength = "an extremely weak";
743 if (words >= 3) {
744 strength = "a very weak";
745 }
746 if (words >= 6) {
747 strength = "a weak";
748 }
749 if (words >= 9) {
750 strength = "a strong";
751 }
752 if (words >= 12) {
753 strength = "a very strong";
754 }
755 if (words >= 15) {
756 strength = "an extremely strong";
757 }
758 if (words >= 18) {
759 strength = "an even stronger"
760 }
761 var msg = "Have " + entropy.binaryStr.length + " bits of entropy, " + extraChars + " more " + entropy.base.str + " chars required to generate " + strength + " mnemonic: " + entropy.cleanStr;
762 showEntropyError(msg);
763 // Discard trailing entropy 747 // Discard trailing entropy
764 var bitsToUse = Math.floor(entropy.binaryStr.length / 32) * 32; 748 var bitsToUse = Math.floor(entropy.binaryStr.length / 32) * 32;
765 var binaryStr = entropy.binaryStr.substring(0, bitsToUse); 749 var binaryStr = entropy.binaryStr.substring(0, bitsToUse);
@@ -776,13 +760,44 @@
776 DOM.phrase.val(phrase); 760 DOM.phrase.val(phrase);
777 } 761 }
778 762
779 function hideEntropyError() { 763 function hideEntropyFeedback() {
780 DOM.entropyError.addClass("hidden"); 764 DOM.entropyFeedback.addClass("hidden");
765 DOM.entropyFiltered.text("");
766 DOM.entropyType.text("");
767 DOM.entropyStrength.text("");
768 DOM.entropyEventCount.text("");
769 DOM.entropyBits.text("");
770 DOM.entropyBitsPerEvent.text("");
781 } 771 }
782 772
783 function showEntropyError(msg) { 773 function showEntropyFeedback(entropy) {
784 DOM.entropyError.text(msg); 774 var strength = "extremely weak";
785 DOM.entropyError.removeClass("hidden"); 775 if (entropy.binaryStr.length >= 64) {
776 strength = "very weak";
777 }
778 if (entropy.binaryStr.length >= 96) {
779 strength = "weak";
780 }
781 if (entropy.binaryStr.length >= 128) {
782 strength = "strong";
783 }
784 if (entropy.binaryStr.length >= 160) {
785 strength = "very strong";
786 }
787 if (entropy.binaryStr.length >= 192) {
788 strength = "extremely strong";
789 }
790 var bitsStr = entropy.binaryStr.length;
791 if (entropy.base.asInt != 2) {
792 bitsStr += " (" + entropy.binaryStr + ")";
793 }
794 DOM.entropyFiltered.text(entropy.cleanStr);
795 DOM.entropyType.text(entropy.base.str);
796 DOM.entropyStrength.text(strength);
797 DOM.entropyEventCount.text(entropy.base.ints.length);
798 DOM.entropyBits.text(bitsStr);
799 DOM.entropyBitsPerEvent.text(Math.log2(entropy.base.asInt).toFixed(2));
800 DOM.entropyFeedback.removeClass("hidden");
786 } 801 }
787 802
788 var networks = [ 803 var networks = [