Bitcoin Stack Exchange is a question and answer site for Bitcoin crypto-currency enthusiasts. It only takes a minute to sign up.
Sign up to join this communityAnybody can ask a question
Anybody can answer
The best answers are voted up and rise to the top
tell me how to add or add reading line by line file array
#!/usr/bin/env python3 import argparse import hashlib # for checking integrity of wordlist and mnemonic phrase checksum import hmac # for toseed functionality import unicodedata # as required by toseed functionality to perform NFKD normalization of mnemonic phrase from typing import Tuple, Dict, Optional, List # for typing ######################################################################################################################## ### Wordlist definition ################################################################################################ ######################################################################################################################## def verify_wordlist(*words: str) -> Tuple[str, ...]: """Verifies that the words given in this source file match the English wordlist specified in BIP39. The SHA256 hash below is derived from the original wordlist at: https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt """ words_sha256 = hashlib.sha256(("\n".join(words) + "\n").encode()).hexdigest() assert words_sha256 == "2f5eed53a4727b4bf8880d8f3f199efc90e58503646d9ff8eff3a2ed3b24dbda" return words # The BIP39 wordlist (English) is directly integrated to this Python file to make it a standalone file. # Used by the encode function to map 0-based word indices to the specified words. # fmt: off INDEX_TO_WORD_TABLE: Tuple[str, ...] = verify_wordlist( "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract", "absurd", "abuse", "access", "accident", "account", "accuse", "achieve", "acid", "acoustic", "acquire", "across", "act", "action", "actor", "actress", "actual", "adapt", "add", "addict", "address", "adjust", "admit", "adult", "advance", "advice", "aerobic", "affair", "afford", "afraid", "again", "age", "agent", "agree", "ahead", "aim", "air", "airport", "aisle", "alarm", "album", "alcohol", "alert", "alien", "all", "alley", "allow", "almost", "alone", "alpha", "already", "also", "alter", "always", "amateur", "amazing", "among", "amount", "amused", "analyst", "anchor", "ancient", "anger", "angle", "angry", "animal", "ankle", "announce", "annual", "another", "answer", "antenna", "antique", "anxiety", "any", "apart", "apology", "appear", "apple", "approve", "april", "arch", "arctic", "area", "arena", "argue", "arm", "armed", "armor", "army", "around", "arrange", "arrest", "arrive", "arrow", "art", "artefact", "artist", "artwork", "ask", "aspect", "assault", "asset", "assist", "assume", "asthma", "athlete", "atom", "attack", "attend", "attitude", "attract", "auction", "audit", "august", "aunt", "author", "auto", "autumn", "average", "avocado", "avoid", "awake", "aware", "away", "awesome", "awful", "awkward", "axis", "baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony", "ball", "bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel", "base", "basic", "basket", "battle", "beach", "bean", "beauty", "because", "become", "beef", "before", "begin", "behave", "behind", "believe", "below", "belt", "bench", "benefit", "best", "betray", "better", "between", "beyond", "bicycle", "bid", "bike", "bind", "biology", "bird", "birth", "bitter", "black", "blade", "blame", "blanket", "blast", "bleak", "bless", "blind", "blood", "blossom", "blouse", "blue", "blur", "blush", "board", "boat", "body", "boil", "bomb", "bone", "bonus", "book", "boost", "border", "boring", "borrow", "boss", "bottom", "bounce", "box", "boy", "bracket", "brain", "brand", "brass", "brave", "bread", "breeze", "brick", "bridge", "brief", "bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom", "brother", "brown", "brush", "bubble", "buddy", "budget", "buffalo", "build", "bulb", "bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst", "bus", "business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin", "cable", "cactus", "cage", "cake", "call", "calm", "camera", "camp", "can", "canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon", "capable", "capital", "captain", "car", "carbon", "card", "cargo", "carpet", "carry", "cart", "case", "cash", "casino", "castle", "casual", "cat", "catalog", "catch", "category", "cattle", "caught", "cause", "caution", "cave", "ceiling", "celery", "cement", "census", "century", "cereal", "certain", "chair", "chalk", "champion", "change", "chaos", "chapter", "charge", "chase", "chat", "cheap", "check", "cheese", "chef", "cherry", "chest", "chicken", "chief", "child", "chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn", "cigar", "cinnamon", "circle", "citizen", "city", "civil", "claim", "clap", "clarify", "claw", "clay", "clean", "clerk", "clever", "click", "client", "cliff", "climb", "clinic", "clip", "clock", "clog", "close", "cloth", "cloud", "clown", "club", "clump", "cluster", "clutch", "coach", "coast", "coconut", "code", "coffee", "coil", "coin", "collect", "color", "column", "combine", "come", "comfort", "comic", "common", "company", "concert", "conduct", "confirm", "congress", "connect", "consider", "control", "convince", "cook", "cool", "copper", "copy", "coral", "core", "corn", "correct", "cost", "cotton", "couch", "country", "couple", "course", "cousin", "cover", "coyote", "crack", "cradle", "craft", "cram", "crane", "crash", "crater", "crawl", "crazy", "cream", "credit", "creek", "crew", "cricket", "crime", "crisp", "critic", "crop", "cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble", "crunch", "crush", "cry", "crystal", "cube", "culture", "cup", "cupboard", "curious", "current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad", "damage", "damp", "dance", "danger", "daring", "dash", "daughter", "dawn", "day", "deal", "debate", "debris", "decade", "december", "decide", "decline", "decorate", "decrease", "deer", "defense", "define", "defy", "degree", "delay", "deliver", "demand", "demise", "denial", "dentist", "deny", "depart", "depend", "deposit", "depth", "deputy", "derive", "describe", "desert", "design", "desk", "despair", "destroy", "detail", "detect", "develop", "device", "devote", "diagram", "dial", "diamond", "diary", "dice", "diesel", "diet", "differ", "digital", "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt", "disagree", "discover", "disease", "dish", "dismiss", "disorder", "display", "distance", "divert", "divide", "divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin", "domain", "donate", "donkey", "donor", "door", "dose", "double", "dove", "draft", "dragon", "drama", "drastic", "draw", "dream", "dress", "drift", "drill", "drink", "drip", "drive", "drop", "drum", "dry", "duck", "dumb", "dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic", "eager", "eagle", "early", "earn", "earth", "easily", "east", "easy", "echo", "ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight", "either", "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator", "elite", "else", "embark", "embody", "embrace", "emerge", "emotion", "employ", "empower", "empty", "enable", "enact", "end", "endless", "endorse", "enemy", "energy", "enforce", "engage", "engine", "enhance", "enjoy", "enlist", "enough", "enrich", "enroll", "ensure", "enter", "entire", "entry", "envelope", "episode", "equal", "equip", "era", "erase", "erode", "erosion", "error", "erupt", "escape", "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil", "evoke", "evolve", "exact", "example", "excess", "exchange", "excite", "exclude", "excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit", "exotic", "expand", "expect", "expire", "explain", "expose", "express", "extend", "extra", "eye", "eyebrow", "fabric", "face", "faculty", "fade", "faint", "faith", "fall", "false", "fame", "family", "famous", "fan", "fancy", "fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue", "fault", "favorite", "feature", "february", "federal", "fee", "feed", "feel", "female", "fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field", "figure", "file", "film", "filter", "final", "find", "fine", "finger", "finish", "fire", "firm", "first", "fiscal", "fish", "fit", "fitness", "fix", "flag", "flame", "flash", "flat", "flavor", "flee", "flight", "warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave", "way", "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding", "weekend", "weird", "welcome", "west", "wet", "whale", "what", "wheat", "wheel", "when", "where", "whip", "whisper", "wide", "width", "wife", "wild", "will", "win", "window", "wine", "wing", "wink", "winner", "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman", "wonder", "wood", "wool", "word", "work", "world", "worry", "worth", "wrap", "wreck", "wrestle", "wrist", "write", "wrong", "yard", "year", "yellow", "you", "young", "youth", "zebra", "zero", "zone", "zoo", ) # fmt: on # Used by the decode function to map the given words back to their 0-based indices. WORD_TO_INDEX_TABLE: Dict[str, int] = {word: i for i, word in enumerate(INDEX_TO_WORD_TABLE)} # Number of PBKDF2 round to generate seed PBKDF2_ROUNDS = 2048 ######################################################################################################################## ### BIP39 encoding and decoding ######################################################################################## ######################################################################################################################## ### ### ### Functions to convert from and to BIP39 compatible mnemonic phrases. ### ### This implementation deliberately considers only the official english word list. ### ### ### ### Correspondence between the number of words (MS), bits of entropy (ENT) and checksum length (CS) ### ### ### ### CS = ENT / 32 ### ### MS = (ENT + CS) / 11 ### ### ### ### | ENT | CS | ENT+CS | MS | ### ### +-------+----+--------+------+ ### ### | 128 | 4 | 132 | 12 | ### ### | 160 | 5 | 165 | 15 | ### ### | 192 | 6 | 198 | 18 | ### ### | 224 | 7 | 231 | 21 | ### ### | 256 | 8 | 264 | 24 | ### ### ### ### See https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki ### ### ### ######################################################################################################################## def encode_bytes(entropy: bytes) -> str: """Converts a given sequence of bytes into a BIP39 mnemonic phrase. This implementation only covers the English BIP39 wordlist as other wordlist are often poorly supported by other software and hardware devices. """ num_bits_entropy = len(entropy) * 8 num_bits_checksum = num_bits_entropy // 32 num_words = (num_bits_entropy + num_bits_checksum) // 11 if num_bits_entropy not in {128, 160, 192, 224, 256}: raise EncodingError( "Invalid number of bytes provided, " "BIP39 mnemonic phrases are only specified for 128, 160, 192, 224, or 256 bits." ) # Compute the checksum as the first bits of the sha256 hash of the data. # As the checksum has at most 8 bits, we can directly access the first byte of the hash. checksum = hashlib.sha256(entropy).digest()[0] >> (8 - num_bits_checksum) # Covert the entropy to a number of easier handling of the 11-bit parts and append the checksum. entropy_and_checksum = (int.from_bytes(entropy, byteorder="big") << num_bits_checksum) | checksum # Convert each 11 bit chunk into a word. remaining_data = entropy_and_checksum words: List[str] = [] for _ in range(num_words): words.append(INDEX_TO_WORD_TABLE[remaining_data & 0b111_1111_1111]) remaining_data >>= 11 # As we started with the conversion progress with the rightmost bits of `entropy_and_checksum` the list of words # needs to be reversed before we can join and return the final mnemonic phrase. words.reverse() return " ".join(words) def decode_phrase(phrase: str) -> bytes: """Converts a given BIP39 mnemonic phrase to a sequence of bytes. The (weak) integrated checksum is verified and a `DecodingError` is raised in case the mnemonic is invalid. This implementation only covers the English BIP39 wordlist as other wordlist are often poorly supported by other software and hardware devices. """ if not all(c in " abcdefghijklmnopqrstuvwxyz" for c in phrase): raise DecodingError(f"Invalid mnemonic phrase {repr(phrase)} provided, phrase contains an invalid character.") words = phrase.split() num_bits_entropy = get_entropy_bits(len(words)) num_bits_checksum = num_bits_entropy // 32 bits = 0 for word in words: bits <<= 11 try: bits |= WORD_TO_INDEX_TABLE[word] except KeyError: raise DecodingError( f"Invalid mnemonic phrase {repr(phrase)} provided, word '{word}' is not in the BIP39 wordlist." ) checksum = bits & (2 ** num_bits_checksum - 1) bits >>= num_bits_checksum data = bits.to_bytes(num_bits_entropy // 8, byteorder="big") checksum_for_verification = hashlib.sha256(data).digest()[0] >> (8 - num_bits_checksum) if checksum != checksum_for_verification: raise DecodingError(f"Invalid mnemonic phrase {repr(phrase)} provided, checksum invalid!") return data def check_phrase(phrase: str) -> bool: """ Only checks the checksum of a phrase and returns true if valid and false otherwise """ try: decode_phrase(phrase) except DecodingError: return False return True def normalize_string(txt: str) -> str: """ As we only consider english wordlists and str input """ assert type(txt) is str return unicodedata.normalize("NFKD", txt) def phrase_to_seed(phrase: str, passphrase: str = "") -> bytes: decode_phrase(phrase) # check phrase and raise exception on error phrase = normalize_string(phrase) passphrase = "mnemonic" + normalize_string(passphrase) phrase_bytes = phrase.encode("utf-8") passphrase_bytes = passphrase.encode("utf-8") stretched = hashlib.pbkdf2_hmac( "sha512", phrase_bytes, passphrase_bytes, PBKDF2_ROUNDS ) return stretched[:64] def get_entropy_bits(num_words: int) -> int: """Returns the number of entropy bits in a mnemonic phrase with the given number of words. Raises a `DecodingError` if the given number of words is invalid. """ try: return {12: 128, 15: 160, 18: 192, 21: 224, 24: 256}[num_words] except KeyError: raise DecodingError( "Invalid number of words provided, " "BIP39 mnemonic phrases are only specified for 12, 15, 18, 21, or 24 words." ) ######################################################################################################################## ### Error definitions ################################################################################################## ######################################################################################################################## class AppError(Exception): def __init__(self, message: str): super().__init__(f"ERROR: {message} \nExiting.\n") class EncodingError(AppError): """Raised if a given sequences of bytes cannot be encoded as BIP39 mnemonic phrase.""" class DecodingError(AppError): """Raised if a given BIP39 mnemonic phrase cannot be decoded into a sequence of bytes.""" ######################################################################################################################## ### Cli Client ######################################################################################################## ######################################################################################################################## def main(): parser = cli_argparse_setup() args = parser.parse_args() if args.verbose: print("Parsed command line arguments:") #pprint.pprint(vars(args)) print(vars(args)) print() try: if args.command == "encode": cli_encode(**vars(args)) elif args.command == "decode": cli_decode(**vars(args)) elif args.command == "toseed": cli_toseed(**vars(args)) else: raise NotImplementedError except AppError as e: print() print(e, file=sys.stderr) def cli_argparse_setup() -> argparse.ArgumentParser: root_parser = argparse.ArgumentParser( description="bip39: A simple self-contained implementation of BIP39 in python", epilog="For details see https://github.com/de-centralized-systems/python-bip39", ) root_parser.add_argument( "-v", "--verbose", action="store_true", help="display additional information", ) parsers = root_parser.add_subparsers( title="commands", dest="command", required=True, metavar="encode|decode|toseed", ) cli_argparse_setup_encode(parsers.add_parser( "encode", help="Encode given bytes to BIP39 mnemonic phrase")) cli_argparse_setup_decode(parsers.add_parser( "decode", help="Decode given BIP39 mnemonic phrase to bytes")) cli_argparse_setup_toseed(parsers.add_parser( "toseed", help="recover a BIP39 mnemonic phrase from a set of shares", #usage='usage: bip39.py [-h] ', ) ) return root_parser def cli_argparse_setup_encode(parser: argparse.ArgumentParser): parser.add_argument( "data", type=str, help="The data bytes in given format as string", ) def cli_argparse_setup_decode(parser: argparse.ArgumentParser): parser.add_argument( "phrase", type=str, help="The BIP39 mnemonic phrase (12, 15, 18, 21, or 24 words supported, English only)", ) def cli_argparse_setup_toseed(parser: argparse.ArgumentParser): parser.add_argument( "phrase", type=str, help="The BIP39 mnemonic phrase (12, 15, 18, 21, or 24 words supported, English only)", ) parser.add_argument( "passphrase", type=str, help="The BIP39 mnemonic passphrase used with PBKDF2 to generate the master seed", ) def cli_encode( data: str, verbose: bool = False, _selftest_enabled: bool = True, **_, ) -> List[Tuple[int, str]]: if verbose: print("Encondig data : ",data) data_bytes = bytes.fromhex(data) mnc = encode_bytes(data_bytes) if verbose: print("Mnemoinic : ",end="") print(mnc) def cli_decode( phrase: str, verbose: bool = False, _selftest_enabled: bool = True, **_, ) -> List[Tuple[int, str]]: if verbose: print("Decoding mnemonic : ",phrase) data_bytes = decode_phrase(phrase) if verbose: print("Data : ",end="") print(data_bytes.hex()) def cli_toseed( phrase: str, passphrase: str, verbose: bool = False, _selftest_enabled: bool = True, **_, ) -> List[Tuple[int, str]]: if verbose: print("Mnemonic : ",phrase) print("Passphrase : ",passphrase) seed_bytes = phrase_to_seed(phrase,passphrase) if verbose: print("Seed : ",end="") print(seed_bytes.hex()) ######################################################################################################################## ### Entry Point ####################################################################################################### ######################################################################################################################## if __name__ == "__main__": main()
You can get bonuses upto $100 FREE BONUS when you:
π° Install these recommended apps:
π² SocialGood - 100% Crypto Back on Everyday Shopping
π² xPortal - The DeFi For The Next Billion
π² CryptoTab Browser - Lightweight, fast, and ready to mine!
π° Register on these recommended exchanges:
π‘ Binanceπ‘ Bitfinexπ‘ Bitmartπ‘ Bittrexπ‘ Bitget
π‘ CoinExπ‘ Crypto.comπ‘ Gate.ioπ‘ Huobiπ‘ Kucoin.
Comments