Skip to content

Commit bc3c7fb

Browse files
committed
fix: fix low entropy calc when using Mnemonic XOR
This commit add a fix for shannon entropy calculation of a choosen entroypy bytes before operate the XOR between input and current mnemonic.
1 parent e07b797 commit bc3c7fb

1 file changed

Lines changed: 41 additions & 5 deletions

File tree

src/krux/pages/home_pages/mnemonic_xor.py

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
# THE SOFTWARE.
2222

23+
import math
2324
from .. import Menu, LETTERS, MENU_CONTINUE, MENU_EXIT
2425
from ..login import MnemonicLoader
2526
from ...krux_settings import Settings, t
@@ -28,6 +29,8 @@
2829
from ...key import Key
2930
from ...wallet import Wallet
3031

32+
NORMALIZED_THRESHOLD = 30
33+
3134

3235
class MnemonicXOR(MnemonicLoader):
3336
"""
@@ -53,13 +56,46 @@ def _xor_bytes(a: bytes, b: bytes) -> bytearray:
5356

5457
return out
5558

59+
@staticmethod
60+
def _shannon_sum(distribution, sample_size):
61+
"""Calculates Shannon's entropy of a given distribution.
62+
63+
Example:
64+
65+
0x00 *
66+
0x01 **
67+
Ox02 ********
68+
... ***
69+
0xFD **
70+
OxFE ***
71+
0xFD **
72+
OxFF *
73+
"""
74+
# Calculate entropy
75+
unit_entropy = 0
76+
for count in distribution:
77+
probability = count / sample_size
78+
unit_entropy -= probability * (probability and math.log2(probability))
79+
return unit_entropy
80+
5681
@staticmethod
5782
def _validate_entropy(entropy: bytes | bytearray) -> None:
58-
"""Check for low entropy (all zeros or all ones)"""
59-
# TODO: apply a shannon low entropy check for XOR
60-
all_zeros = bytes(len(entropy))
61-
all_ones = b"\xff" * len(entropy)
62-
if entropy in (all_zeros, all_ones):
83+
"""Check for low entropy against its distribution"""
84+
n = len(entropy)
85+
86+
# Differences lie in [-255, +255], then 511 buckets
87+
derivatives = (entropy[i] - entropy[i - 1] for i in range(1, n))
88+
d_counts = [0] * 511
89+
total_derivatives = 0
90+
for d in derivatives:
91+
d_counts[d + 255] += 1
92+
total_derivatives += 1
93+
94+
d_entropy = MnemonicXOR._shannon_sum(d_counts, total_derivatives)
95+
max_d_entropy = math.log2(len(d_counts))
96+
normalized = (d_entropy / max_d_entropy) * 100.0
97+
98+
if normalized < NORMALIZED_THRESHOLD:
6399
raise ValueError("Low entropy mnemonic")
64100

65101
@staticmethod

0 commit comments

Comments
 (0)