Skip to content

Instantly share code, notes, and snippets.

@odudex
Last active December 26, 2022 11:24
Show Gist options
  • Save odudex/7077b72a06532f7decbf503a223852c8 to your computer and use it in GitHub Desktop.
Save odudex/7077b72a06532f7decbf503a223852c8 to your computer and use it in GitHub Desktop.
Compare your devices dice generated seed with the ones generated by this script and check how each word and checksum were calculated
"""Compare your devices dice seed creation with the ones generated by this script
and check how each word and checksum were calculated.
Ex:
python dice.py 565256126243114366655152522264552364231641333461455456111566561236253463223236163643465622462251536
Entropy bytes: b'565256126243114366655152522264552364231641333461455456111566561236253463223236163643465622462251536'
Hashed bytes: 2e364baddcfa80dfc910fc92b634e962d2f844e9e9a210428d8e4d899a6883ae
Hashed bits: 0b10111000110110010010111010110111011100111110101000000011011111110010010001000011111100100100101011011000110100111010010110001011010010111110000100010011101001111010011010001000010000010000101000110110001110010011011000100110011010011010001000001110101110
Seed words: comfort rather twin rigid pool husband cattle buzz naive random demise shield convince carbon police crowd aware behave glory only often crowd attitude share
BIP39 seed numbers: [370, 1427, 1884, 1488, 1345, 896, 291, 253, 1174, 1422, 467, 1582, 381, 276, 1342, 419, 131, 164, 797, 1241, 1230, 419, 118, 1578]
Bit chunks:
00101110001: 369
10110010010: 1426
11101011011: 1883
10111001111: 1487
10101000000: 1344
01101111111: 895
00100100010: 290
00011111100: 252
10010010101: 1173
10110001101: 1421
00111010010: 466
11000101101: 1581
00101111100: 380
00100010011: 275
10100111101: 1341
00110100010: 418
00010000010: 130
00010100011: 163
01100011100: 796
10011011000: 1240
10011001101: 1229
00110100010: 418
00001110101: 117
110_00101001: 1577
Code created in colaboration with @qecez"""
import sys
import hashlib
from embit import bip39
from embit.wordlists.bip39 import WORDLIST
def check_sum(seed_numbers):
"""Dinamically calculates checksum"""
# Inspired in Jimmy Song's HDPrivateKey.from_mnemonic() method
binary_seed = bytearray()
offset = 0
for tiny_seed_number in seed_numbers:
index = tiny_seed_number - 1 if tiny_seed_number > 1 else 0
remaining = 11
while remaining > 0:
bits_needed = 8 - offset
if remaining == bits_needed:
if bits_needed == 8:
binary_seed.append(index)
else:
binary_seed[-1] |= index
offset = 0
remaining = 0
elif remaining > bits_needed:
if bits_needed == 8:
binary_seed.append(index >> (remaining - 8))
else:
binary_seed[-1] |= index >> (remaining - bits_needed)
remaining -= bits_needed
offset = 0
# lop off the top 8 bits
index &= (1 << remaining) - 1
else:
binary_seed.append(index << (8 - remaining))
offset = remaining
remaining = 0
checksum_length_bits = len(seed_numbers) * 11 // 33
num_remainder = checksum_length_bits % 8
if num_remainder:
checksum_length = checksum_length_bits // 8 + 1
else:
checksum_length = checksum_length_bits // 8
raw = bytes(binary_seed)
data = raw[:-checksum_length]
computed_checksum = int.from_bytes(
hashlib.sha256(data).digest()[:checksum_length], "big"
)
checksum = computed_checksum >> (8 - checksum_length_bits)
return checksum, checksum_length_bits
if len(sys.argv) > 1:
rolls = sys.argv[1]
if len(rolls) <= 50:
num_bytes = 16
num_bits = 128
else:
num_bytes = 32
num_bits = 256
entropy_bytes = rolls.encode()
print("Entropy bytes: " + str(entropy_bytes))
hashed_bytes = hashlib.sha256(entropy_bytes).digest()[:num_bytes]
print("\nHashed bytes: " + str(hashed_bytes.hex()))
print("\nHashed bits: " + str(bin(int.from_bytes(hashed_bytes, "big"))))
seed_words = bip39.mnemonic_from_bytes(hashed_bytes)
print("\nSeed words: " + str(seed_words))
seed_numbers = []
for word in seed_words.split():
seed_numbers.append(WORDLIST.index(word)+1)
print("\nBIP39 seed numbers: " + str(seed_numbers))
print("\nBit chunks:")
full_bit_string = str(bin(int.from_bytes(hashed_bytes, "big"))).split("b")[1].zfill(num_bits)
bit_strings = [full_bit_string[i:i+11] for i in range(0, num_bits, 11)]
for index, bit_string in enumerate(bit_strings):
if index == len(bit_strings)-1:
ck_sum, check_sum_len = check_sum(seed_numbers)
decimal = int(bit_string, 2)<<check_sum_len
decimal += ck_sum
bit_checksum = str(bin(ck_sum)).split("b")[1].zfill(check_sum_len)
print(str(bit_string) + "_" + bit_checksum +": "+str(decimal))
else:
decimal = int(bit_string, 2)
print(str(bit_string) +": "+str(decimal))
else:
print("Inform rolls")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment