diff options
author | Ian Coleman <coleman.ian@gmail.com> | 2016-11-16 11:46:25 +1100 |
---|---|---|
committer | Ian Coleman <coleman.ian@gmail.com> | 2016-11-16 11:58:26 +1100 |
commit | 391c7f267f6be3356d0bffa74e2726245b5f45b2 (patch) | |
tree | 0db89de6cbbf6ab1c45a6ce53b6301d9724245d8 | |
parent | 02f05d3e467ba8ccf3fca2811eda847fc71e511f (diff) | |
download | BIP39-391c7f267f6be3356d0bffa74e2726245b5f45b2.tar.gz BIP39-391c7f267f6be3356d0bffa74e2726245b5f45b2.tar.zst BIP39-391c7f267f6be3356d0bffa74e2726245b5f45b2.zip |
Card duplicates and use of full deck is detected
-rw-r--r-- | src/js/index.js | 45 | ||||
-rw-r--r-- | tests.js | 42 |
2 files changed, 85 insertions, 2 deletions
diff --git a/src/js/index.js b/src/js/index.js index 89f8d0d..e064185 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -820,8 +820,9 @@ | |||
820 | } | 820 | } |
821 | var bitsStr = getNumberOfEntropyBits(entropy); | 821 | var bitsStr = getNumberOfEntropyBits(entropy); |
822 | var wordCount = Math.floor(entropy.binaryStr.length / 32) * 3; | 822 | var wordCount = Math.floor(entropy.binaryStr.length / 32) * 3; |
823 | var entropyTypeStr = getEntropyTypeStr(entropy); | ||
823 | DOM.entropyFiltered.html(entropy.cleanHtml); | 824 | DOM.entropyFiltered.html(entropy.cleanHtml); |
824 | DOM.entropyType.text(entropy.base.str); | 825 | DOM.entropyType.text(entropyTypeStr); |
825 | DOM.entropyStrength.text(strength); | 826 | DOM.entropyStrength.text(strength); |
826 | DOM.entropyEventCount.text(entropy.base.ints.length); | 827 | DOM.entropyEventCount.text(entropy.base.ints.length); |
827 | DOM.entropyBits.text(bitsStr); | 828 | DOM.entropyBits.text(bitsStr); |
@@ -847,6 +848,48 @@ | |||
847 | return bitsStr | 848 | return bitsStr |
848 | } | 849 | } |
849 | 850 | ||
851 | function getEntropyTypeStr(entropy) { | ||
852 | var typeStr = entropy.base.str; | ||
853 | // Add some detail if these are cards | ||
854 | if (entropy.base.asInt == 52) { | ||
855 | var cardDetail = []; // array of message strings | ||
856 | // Detect duplicates | ||
857 | var dupes = []; | ||
858 | var dupeTracker = {}; | ||
859 | for (var i=0; i<entropy.base.parts.length; i++) { | ||
860 | var card = entropy.base.parts[i]; | ||
861 | if (card in dupeTracker) { | ||
862 | dupes.push(card); | ||
863 | } | ||
864 | dupeTracker[card] = true; | ||
865 | } | ||
866 | if (dupes.length > 0) { | ||
867 | var dupeWord = "duplicates"; | ||
868 | if (dupes.length == 1) { | ||
869 | dupeWord = "duplicate"; | ||
870 | } | ||
871 | var msg = dupes.length + " " + dupeWord + ": " + dupes.slice(0,3).join(" "); | ||
872 | if (dupes.length > 3) { | ||
873 | msg += "..."; | ||
874 | } | ||
875 | cardDetail.push(msg); | ||
876 | } | ||
877 | // Detect full deck | ||
878 | var uniqueCards = []; | ||
879 | for (var uniqueCard in dupeTracker) { | ||
880 | uniqueCards.push(uniqueCard); | ||
881 | } | ||
882 | if (uniqueCards.length == 52) { | ||
883 | cardDetail.unshift("full deck"); | ||
884 | } | ||
885 | // Add card details to typeStr | ||
886 | if (cardDetail.length > 0) { | ||
887 | typeStr += " (" + cardDetail.join(", ") + ")"; | ||
888 | } | ||
889 | } | ||
890 | return typeStr; | ||
891 | } | ||
892 | |||
850 | // Depends on BigInteger | 893 | // Depends on BigInteger |
851 | function factorial(n) { | 894 | function factorial(n) { |
852 | if (n == 0) { | 895 | if (n == 0) { |
@@ -2624,6 +2624,46 @@ page.open(url, function(status) { | |||
2624 | words: 18, | 2624 | words: 18, |
2625 | strength: "extremely strong", | 2625 | strength: "extremely strong", |
2626 | }, | 2626 | }, |
2627 | { | ||
2628 | entropy: "7d", | ||
2629 | type: "card", | ||
2630 | events: 1, | ||
2631 | bits: 5, | ||
2632 | words: 0, | ||
2633 | strength: "extremely weak", | ||
2634 | }, | ||
2635 | { | ||
2636 | entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks", | ||
2637 | type: "card (full deck)", | ||
2638 | events: 52, | ||
2639 | bits: 226, | ||
2640 | words: 27, | ||
2641 | strength: "extremely strong", | ||
2642 | }, | ||
2643 | { | ||
2644 | entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqsks3d", | ||
2645 | type: "card (full deck, 1 duplicate: 3d)", | ||
2646 | events: 53, | ||
2647 | bits: 226, | ||
2648 | words: 27, | ||
2649 | strength: "extremely strong", | ||
2650 | }, | ||
2651 | { | ||
2652 | entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqs3d4d", | ||
2653 | type: "card (2 duplicates: 3d 4d)", | ||
2654 | events: 53, | ||
2655 | bits: 226, | ||
2656 | words: 27, | ||
2657 | strength: "extremely strong", | ||
2658 | }, | ||
2659 | { | ||
2660 | entropy: "ac2c3c4c5c6c7c8c9ctcjcqckcad2d3d4d5d6d7d8d9dtdjdqdkdah2h3h4h5h6h7h8h9hthjhqhkhas2s3s4s5s6s7s8s9stsjsqs3d4d5d6d", | ||
2661 | type: "card (4 duplicates: 3d 4d 5d...)", | ||
2662 | events: 53, | ||
2663 | bits: 226, | ||
2664 | words: 27, | ||
2665 | strength: "extremely strong", | ||
2666 | }, | ||
2627 | ]; | 2667 | ]; |
2628 | // use entropy | 2668 | // use entropy |
2629 | page.evaluate(function() { | 2669 | page.evaluate(function() { |
@@ -2631,7 +2671,7 @@ page.open(url, function(status) { | |||
2631 | }); | 2671 | }); |
2632 | var nextTest = function runNextTest(i) { | 2672 | var nextTest = function runNextTest(i) { |
2633 | function getFeedbackError(expected, actual) { | 2673 | function getFeedbackError(expected, actual) { |
2634 | if (actual.indexOf(expected.filtered) == -1) { | 2674 | if ("filtered" in expected && actual.indexOf(expected.filtered) == -1) { |
2635 | return "Filtered value not in feedback"; | 2675 | return "Filtered value not in feedback"; |
2636 | } | 2676 | } |
2637 | if (actual.indexOf(expected.type) == -1) { | 2677 | if (actual.indexOf(expected.type) == -1) { |