Created
June 4, 2023 05:10
-
-
Save 4rmx/b6f4eb41405f8341caf3e23109889c09 to your computer and use it in GitHub Desktop.
from https://github.com/veebch/Bip39-Dice/tree/master change rolls.txt to input method
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # The 24th Word - a tool for a fully offline wallet generation (run on an airgapped machine) | |
| import os | |
| import sys | |
| import hashlib | |
| import binascii | |
| class Bip39Check(object): | |
| def __init__(self, language): | |
| self.radix = 2048 | |
| self.worddict = {} | |
| self.wordlist = [] | |
| counter = 0 | |
| with open('%s/%s.txt' % (self._get_directory(), language), 'r') as file: | |
| for w in file.readlines(): | |
| word = w.strip() if sys.version < '3' else w.strip() | |
| self.worddict[word] = counter | |
| self.wordlist.append(word) | |
| counter = counter + 1 | |
| if(len(self.worddict) != self.radix): | |
| raise ValueError('Expecting %d words, not %d', self.radix, len(self.worddict)) | |
| @classmethod | |
| def _get_directory(cls): | |
| return os.path.join(os.path.dirname(__file__), 'wordlist') | |
| def _check_size(self, phrase): | |
| self.size = len(phrase) + 1 | |
| if (self.size != 24): | |
| raise ValueError('Expecting 23 words') | |
| def _compute_entropy(self, phrase): | |
| print("---------------------") | |
| self.entropy = 0 | |
| for w in phrase: | |
| idx = self.worddict[w] | |
| print('Word "' + w + '", index at words list ' + str(idx + 1)) | |
| self.entropy = (self.entropy << 11) + idx | |
| print('Entropy: ' + bin(self.entropy)[2:]) | |
| return self.entropy | |
| def _scan(self): | |
| checksum_bits = self.size // 3 | |
| entropy_len = (self.size * 11 - checksum_bits) // 8 #Entropy could be beetween 128 and 256 bits. Recover this size in bytes. | |
| entropy_to_fill = 11 - checksum_bits | |
| entropy_base = self.entropy << (entropy_to_fill) | |
| couldbe=[] | |
| print("---------------------") | |
| print('Candidates: ') | |
| for i in range(0, 2 ** entropy_to_fill): | |
| entropy_candidate = entropy_base | i | |
| print('Candidate ' + str(i+1)) | |
| binary = bin(entropy_candidate)[2:] | |
| print(' > Binary:', binary) | |
| entropy_str = (entropy_candidate).to_bytes((entropy_candidate.bit_length() + 7) // 8, 'big') | |
| hash = (hashlib.sha256(entropy_str).digest()[0]) | |
| checksum = hash >> (8 - checksum_bits) | |
| final_word_idx = (i << checksum_bits) + checksum | |
| checkword = self.wordlist[final_word_idx] | |
| couldbe.append(checkword) | |
| return couldbe | |
| def main(): | |
| fullwordlist = [] | |
| counter = 0 | |
| while counter < 23: | |
| print(counter, ":", end=" ") | |
| word = input() | |
| fullwordlist.append(word) | |
| counter = counter + 1 | |
| m = Bip39Check('english') | |
| print("---------------------") | |
| phrase=fullwordlist | |
| print("23 words from dice rolls:\n") | |
| print(fullwordlist) | |
| m._check_size(phrase) | |
| m._compute_entropy(phrase) | |
| candidates=m._scan() | |
| print("---------------------") | |
| print ("Valid 24th words: ") | |
| print (candidates) | |
| print ("Pick one of these, write it down with the other 23") | |
| print ("You now have a valid bitcoin wallet seed. Restore it in the software of your choice") | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment