diff options
Diffstat (limited to 'src/js')
-rw-r--r-- | src/js/entropy.js | 47 | ||||
-rw-r--r-- | src/js/index.js | 79 |
2 files changed, 58 insertions, 68 deletions
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 = [ |