diff options
author | Ian Coleman <coleman.ian@gmail.com> | 2016-11-17 14:28:26 +1100 |
---|---|---|
committer | Ian Coleman <coleman.ian@gmail.com> | 2016-11-17 14:28:26 +1100 |
commit | 6422c1cd57afbb4f0c71b0157ba6ad9598f82bc4 (patch) | |
tree | 935e8579a4f71fdd6e6f50ebf2294a46a80357ff /src | |
parent | bbc29c80f429d7493fdb9cb7987000d633734db5 (diff) | |
download | BIP39-6422c1cd57afbb4f0c71b0157ba6ad9598f82bc4.tar.gz BIP39-6422c1cd57afbb4f0c71b0157ba6ad9598f82bc4.tar.zst BIP39-6422c1cd57afbb4f0c71b0157ba6ad9598f82bc4.zip |
Entropy library assumes cards are discarded
and removed the duplicate logic from the UI logic.
Diffstat (limited to 'src')
-rw-r--r-- | src/js/entropy.js | 46 | ||||
-rw-r--r-- | src/js/index.js | 52 |
2 files changed, 56 insertions, 42 deletions
diff --git a/src/js/entropy.js b/src/js/entropy.js index c28620a..5900346 100644 --- a/src/js/entropy.js +++ b/src/js/entropy.js | |||
@@ -117,6 +117,40 @@ window.Entropy = new (function() { | |||
117 | while (entropyBin.length < expectedBits) { | 117 | while (entropyBin.length < expectedBits) { |
118 | entropyBin = "0" + entropyBin; | 118 | entropyBin = "0" + entropyBin; |
119 | } | 119 | } |
120 | // Assume cards are NOT replaced. | ||
121 | // Additional entropy decreases as more cards are used. This means | ||
122 | // entropy is measured using n!, not base^n. | ||
123 | // eg the second last card can be only one of two, not one of fifty two | ||
124 | // so the added entropy for that card is only one bit at most | ||
125 | if (base.asInt == 52) { | ||
126 | // Get the maximum value without replacement | ||
127 | var totalDecks = Math.ceil(base.parts.length / 52); | ||
128 | var totalCards = totalDecks * 52; | ||
129 | var totalCombos = factorial(52).pow(totalDecks); | ||
130 | var totalRemainingCards = totalCards - base.parts.length; | ||
131 | var remainingDecks = Math.floor(totalRemainingCards / 52); | ||
132 | var remainingCards = totalRemainingCards % 52; | ||
133 | var remainingCombos = factorial(52).pow(remainingDecks).multiply(factorial(remainingCards)); | ||
134 | var currentCombos = totalCombos.divide(remainingCombos); | ||
135 | var numberOfBits = Math.log2(currentCombos); | ||
136 | var maxWithoutReplace = BigInteger.pow(2, numberOfBits); | ||
137 | // aggresive flooring of numberOfBits by BigInteger.pow means a | ||
138 | // more accurate result can be had for small numbers using the | ||
139 | // built-in Math.pow function. | ||
140 | if (numberOfBits < 32) { | ||
141 | maxWithoutReplace = BigInteger(Math.round(Math.pow(2, numberOfBits))); | ||
142 | } | ||
143 | // Get the maximum value with replacement | ||
144 | var maxWithReplace = BigInteger.pow(52, base.parts.length); | ||
145 | // Calculate the new value by scaling the original value down | ||
146 | var withoutReplace = entropyInt.multiply(maxWithoutReplace).divide(maxWithReplace); | ||
147 | // Left pad with zeros based on number of bits | ||
148 | var entropyBin = withoutReplace.toString(2); | ||
149 | var numberOfBitsInt = Math.floor(numberOfBits); | ||
150 | while (entropyBin.length < numberOfBitsInt) { | ||
151 | entropyBin = "0" + entropyBin; | ||
152 | } | ||
153 | } | ||
120 | // Supply a 'filtered' entropy string for display purposes | 154 | // Supply a 'filtered' entropy string for display purposes |
121 | var entropyClean = base.parts.join(""); | 155 | var entropyClean = base.parts.join(""); |
122 | var entropyHtml = base.parts.join(""); | 156 | var entropyHtml = base.parts.join(""); |
@@ -221,4 +255,16 @@ window.Entropy = new (function() { | |||
221 | return BigInteger.log(x) / BigInteger.log(2); | 255 | return BigInteger.log(x) / BigInteger.log(2); |
222 | }; | 256 | }; |
223 | 257 | ||
258 | // Depends on BigInteger | ||
259 | function factorial(n) { | ||
260 | if (n == 0) { | ||
261 | return 1; | ||
262 | } | ||
263 | f = BigInteger.ONE; | ||
264 | for (var i=1; i<=n; i++) { | ||
265 | f = f.multiply(new BigInteger(i)); | ||
266 | } | ||
267 | return f; | ||
268 | } | ||
269 | |||
224 | })(); | 270 | })(); |
diff --git a/src/js/index.js b/src/js/index.js index f4163ee..254b62f 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -791,20 +791,21 @@ | |||
791 | } | 791 | } |
792 | 792 | ||
793 | function showEntropyFeedback(entropy) { | 793 | function showEntropyFeedback(entropy) { |
794 | var numberOfBits = entropy.binaryStr.length; | ||
794 | var strength = "extremely weak"; | 795 | var strength = "extremely weak"; |
795 | if (entropy.binaryStr.length >= 64) { | 796 | if (numberOfBits >= 64) { |
796 | strength = "very weak"; | 797 | strength = "very weak"; |
797 | } | 798 | } |
798 | if (entropy.binaryStr.length >= 96) { | 799 | if (numberOfBits >= 96) { |
799 | strength = "weak"; | 800 | strength = "weak"; |
800 | } | 801 | } |
801 | if (entropy.binaryStr.length >= 128) { | 802 | if (numberOfBits >= 128) { |
802 | strength = "strong"; | 803 | strength = "strong"; |
803 | } | 804 | } |
804 | if (entropy.binaryStr.length >= 160) { | 805 | if (numberOfBits >= 160) { |
805 | strength = "very strong"; | 806 | strength = "very strong"; |
806 | } | 807 | } |
807 | if (entropy.binaryStr.length >= 192) { | 808 | if (numberOfBits >= 192) { |
808 | strength = "extremely strong"; | 809 | strength = "extremely strong"; |
809 | } | 810 | } |
810 | // If time to crack is less than one day, and password is considered | 811 | // If time to crack is less than one day, and password is considered |
@@ -825,38 +826,17 @@ | |||
825 | console.log("Error detecting entropy strength with zxcvbn:"); | 826 | console.log("Error detecting entropy strength with zxcvbn:"); |
826 | console.log(e); | 827 | console.log(e); |
827 | } | 828 | } |
828 | var bitsStr = getNumberOfEntropyBits(entropy); | ||
829 | var wordCount = Math.floor(entropy.binaryStr.length / 32) * 3; | ||
830 | var entropyTypeStr = getEntropyTypeStr(entropy); | 829 | var entropyTypeStr = getEntropyTypeStr(entropy); |
830 | var wordCount = Math.floor(numberOfBits / 32) * 3; | ||
831 | var bitsPerEvent = Math.log2(entropy.base.asInt).toFixed(2); | ||
831 | DOM.entropyFiltered.html(entropy.cleanHtml); | 832 | DOM.entropyFiltered.html(entropy.cleanHtml); |
832 | DOM.entropyType.text(entropyTypeStr); | 833 | DOM.entropyType.text(entropyTypeStr); |
833 | DOM.entropyStrength.text(strength); | 834 | DOM.entropyStrength.text(strength); |
834 | DOM.entropyEventCount.text(entropy.base.ints.length); | 835 | DOM.entropyEventCount.text(entropy.base.ints.length); |
835 | DOM.entropyBits.text(bitsStr); | 836 | DOM.entropyBits.text(numberOfBits); |
836 | DOM.entropyWordCount.text(wordCount); | 837 | DOM.entropyWordCount.text(wordCount); |
837 | DOM.entropyBinary.text(entropy.binaryStr); | 838 | DOM.entropyBinary.text(entropy.binaryStr); |
838 | DOM.entropyBitsPerEvent.text(Math.log2(entropy.base.asInt).toFixed(2)); | 839 | DOM.entropyBitsPerEvent.text(bitsPerEvent); |
839 | } | ||
840 | |||
841 | function getNumberOfEntropyBits(entropy) { | ||
842 | var bitsStr = entropy.binaryStr.length.toString(); | ||
843 | // If using cards, assume they are not reused, thus additional entropy | ||
844 | // decreases as more cards are used. This means entropy is measured | ||
845 | // using n!, not base^n. | ||
846 | // eg the second last card can be only one of two, not one of fifty two | ||
847 | // so the added entropy for that card is only one bit at most | ||
848 | if (entropy.base.asInt == 52) { | ||
849 | var totalDecks = Math.ceil(entropy.base.parts.length / 52); | ||
850 | var totalCards = totalDecks * 52; | ||
851 | var totalCombos = factorial(52).pow(totalDecks); | ||
852 | var totalRemainingCards = totalCards - entropy.base.parts.length; | ||
853 | var remainingDecks = Math.floor(totalRemainingCards / 52); | ||
854 | var remainingCards = totalRemainingCards % 52; | ||
855 | var remainingCombos = factorial(52).pow(remainingDecks) * factorial(remainingCards); | ||
856 | var currentCombos = totalCombos.divide(remainingCombos); | ||
857 | bitsStr = currentCombos.toString(2).length.toString(); | ||
858 | } | ||
859 | return bitsStr | ||
860 | } | 840 | } |
861 | 841 | ||
862 | function getEntropyTypeStr(entropy) { | 842 | function getEntropyTypeStr(entropy) { |
@@ -922,18 +902,6 @@ | |||
922 | return typeStr; | 902 | return typeStr; |
923 | } | 903 | } |
924 | 904 | ||
925 | // Depends on BigInteger | ||
926 | function factorial(n) { | ||
927 | if (n == 0) { | ||
928 | return 1; | ||
929 | } | ||
930 | f = BigInteger.ONE; | ||
931 | for (var i=1; i<=n; i++) { | ||
932 | f = f.multiply(new BigInteger(i)); | ||
933 | } | ||
934 | return f; | ||
935 | } | ||
936 | |||
937 | var networks = [ | 905 | var networks = [ |
938 | { | 906 | { |
939 | name: "Bitcoin", | 907 | name: "Bitcoin", |