Guest User

Untitled

a guest
Aug 8th, 2026
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 29.94 KB | Cryptocurrency | 0 0
  1. #!/usr/bin/env python3
  2. """
  3. OFFLINE BIP-39 SEED PROCESSOR
  4. ==============================
  5. Turns hand-collected coin/dice entropy into a 24-word BIP-39 mnemonic.
  6.  
  7. WHAT THIS SCRIPT DOES NOT DO (by design):
  8.  - No network access is used or required.
  9.  - No files are read or written, ever.
  10.  - No third-party packages are imported (Python standard library only).
  11.  - Nothing is logged, cached, or saved to disk.
  12.  - Command-line arguments are never used, so nothing you type ends up
  13.    in shell history or a process list. All input comes from interactive
  14.    prompts (input()) read directly into RAM.
  15.  
  16. RUN IT WITH:  python3 seed_logic.py
  17. (No installation needed - Tails ships Python 3 by default.)
  18.  
  19. Read this whole file before running it. There is no obfuscation and
  20. nothing hidden - what you see is everything the script does.
  21. """
  22.  
  23. import sys
  24. import hashlib
  25.  
  26. # =====================================================================
  27. # STEP 0: the embedded BIP-39 English wordlist (2048 words)
  28. # =====================================================================
  29. # Verified byte-for-byte identical (SHA-256: 2f5eed53a4727b4bf8880d8f...)
  30. # across three independent sources:
  31. #   1) bitcoin/bips  (the canonical BIP-39 specification repository)
  32. #   2) trezor/python-mnemonic (independent reference implementation)
  33. #   3) bitcoinjs/bip39 (independent JS reference implementation)
  34. WORDLIST = [
  35.     "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract",
  36.     "absurd", "abuse", "access", "accident", "account", "accuse", "achieve", "acid",
  37.     "acoustic", "acquire", "across", "act", "action", "actor", "actress", "actual",
  38.     "adapt", "add", "addict", "address", "adjust", "admit", "adult", "advance",
  39.     "advice", "aerobic", "affair", "afford", "afraid", "again", "age", "agent",
  40.     "agree", "ahead", "aim", "air", "airport", "aisle", "alarm", "album",
  41.     "alcohol", "alert", "alien", "all", "alley", "allow", "almost", "alone",
  42.     "alpha", "already", "also", "alter", "always", "amateur", "amazing", "among",
  43.     "amount", "amused", "analyst", "anchor", "ancient", "anger", "angle", "angry",
  44.     "animal", "ankle", "announce", "annual", "another", "answer", "antenna", "antique",
  45.     "anxiety", "any", "apart", "apology", "appear", "apple", "approve", "april",
  46.     "arch", "arctic", "area", "arena", "argue", "arm", "armed", "armor",
  47.     "army", "around", "arrange", "arrest", "arrive", "arrow", "art", "artefact",
  48.     "artist", "artwork", "ask", "aspect", "assault", "asset", "assist", "assume",
  49.     "asthma", "athlete", "atom", "attack", "attend", "attitude", "attract", "auction",
  50.     "audit", "august", "aunt", "author", "auto", "autumn", "average", "avocado",
  51.     "avoid", "awake", "aware", "away", "awesome", "awful", "awkward", "axis",
  52.     "baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony", "ball",
  53.     "bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel", "base",
  54.     "basic", "basket", "battle", "beach", "bean", "beauty", "because", "become",
  55.     "beef", "before", "begin", "behave", "behind", "believe", "below", "belt",
  56.     "bench", "benefit", "best", "betray", "better", "between", "beyond", "bicycle",
  57.     "bid", "bike", "bind", "biology", "bird", "birth", "bitter", "black",
  58.     "blade", "blame", "blanket", "blast", "bleak", "bless", "blind", "blood",
  59.     "blossom", "blouse", "blue", "blur", "blush", "board", "boat", "body",
  60.     "boil", "bomb", "bone", "bonus", "book", "boost", "border", "boring",
  61.     "borrow", "boss", "bottom", "bounce", "box", "boy", "bracket", "brain",
  62.     "brand", "brass", "brave", "bread", "breeze", "brick", "bridge", "brief",
  63.     "bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom", "brother",
  64.     "brown", "brush", "bubble", "buddy", "budget", "buffalo", "build", "bulb",
  65.     "bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst", "bus",
  66.     "business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin", "cable",
  67.     "cactus", "cage", "cake", "call", "calm", "camera", "camp", "can",
  68.     "canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon", "capable",
  69.     "capital", "captain", "car", "carbon", "card", "cargo", "carpet", "carry",
  70.     "cart", "case", "cash", "casino", "castle", "casual", "cat", "catalog",
  71.     "catch", "category", "cattle", "caught", "cause", "caution", "cave", "ceiling",
  72.     "celery", "cement", "census", "century", "cereal", "certain", "chair", "chalk",
  73.     "champion", "change", "chaos", "chapter", "charge", "chase", "chat", "cheap",
  74.     "check", "cheese", "chef", "cherry", "chest", "chicken", "chief", "child",
  75.     "chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn", "cigar",
  76.     "cinnamon", "circle", "citizen", "city", "civil", "claim", "clap", "clarify",
  77.     "claw", "clay", "clean", "clerk", "clever", "click", "client", "cliff",
  78.     "climb", "clinic", "clip", "clock", "clog", "close", "cloth", "cloud",
  79.     "clown", "club", "clump", "cluster", "clutch", "coach", "coast", "coconut",
  80.     "code", "coffee", "coil", "coin", "collect", "color", "column", "combine",
  81.     "come", "comfort", "comic", "common", "company", "concert", "conduct", "confirm",
  82.     "congress", "connect", "consider", "control", "convince", "cook", "cool", "copper",
  83.     "copy", "coral", "core", "corn", "correct", "cost", "cotton", "couch",
  84.     "country", "couple", "course", "cousin", "cover", "coyote", "crack", "cradle",
  85.     "craft", "cram", "crane", "crash", "crater", "crawl", "crazy", "cream",
  86.     "credit", "creek", "crew", "cricket", "crime", "crisp", "critic", "crop",
  87.     "cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble", "crunch",
  88.     "crush", "cry", "crystal", "cube", "culture", "cup", "cupboard", "curious",
  89.     "current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad",
  90.     "damage", "damp", "dance", "danger", "daring", "dash", "daughter", "dawn",
  91.     "day", "deal", "debate", "debris", "decade", "december", "decide", "decline",
  92.     "decorate", "decrease", "deer", "defense", "define", "defy", "degree", "delay",
  93.     "deliver", "demand", "demise", "denial", "dentist", "deny", "depart", "depend",
  94.     "deposit", "depth", "deputy", "derive", "describe", "desert", "design", "desk",
  95.     "despair", "destroy", "detail", "detect", "develop", "device", "devote", "diagram",
  96.     "dial", "diamond", "diary", "dice", "diesel", "diet", "differ", "digital",
  97.     "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt", "disagree", "discover",
  98.     "disease", "dish", "dismiss", "disorder", "display", "distance", "divert", "divide",
  99.     "divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin", "domain",
  100.     "donate", "donkey", "donor", "door", "dose", "double", "dove", "draft",
  101.     "dragon", "drama", "drastic", "draw", "dream", "dress", "drift", "drill",
  102.     "drink", "drip", "drive", "drop", "drum", "dry", "duck", "dumb",
  103.     "dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic", "eager",
  104.     "eagle", "early", "earn", "earth", "easily", "east", "easy", "echo",
  105.     "ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight",
  106.     "either", "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator",
  107.     "elite", "else", "embark", "embody", "embrace", "emerge", "emotion", "employ",
  108.     "empower", "empty", "enable", "enact", "end", "endless", "endorse", "enemy",
  109.     "energy", "enforce", "engage", "engine", "enhance", "enjoy", "enlist", "enough",
  110.     "enrich", "enroll", "ensure", "enter", "entire", "entry", "envelope", "episode",
  111.     "equal", "equip", "era", "erase", "erode", "erosion", "error", "erupt",
  112.     "escape", "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil",
  113.     "evoke", "evolve", "exact", "example", "excess", "exchange", "excite", "exclude",
  114.     "excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit",
  115.     "exotic", "expand", "expect", "expire", "explain", "expose", "express", "extend",
  116.     "extra", "eye", "eyebrow", "fabric", "face", "faculty", "fade", "faint",
  117.     "faith", "fall", "false", "fame", "family", "famous", "fan", "fancy",
  118.     "fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue", "fault",
  119.     "favorite", "feature", "february", "federal", "fee", "feed", "feel", "female",
  120.     "fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field",
  121.     "figure", "file", "film", "filter", "final", "find", "fine", "finger",
  122.     "finish", "fire", "firm", "first", "fiscal", "fish", "fit", "fitness",
  123.     "fix", "flag", "flame", "flash", "flat", "flavor", "flee", "flight",
  124.     "flip", "float", "flock", "floor", "flower", "fluid", "flush", "fly",
  125.     "foam", "focus", "fog", "foil", "fold", "follow", "food", "foot",
  126.     "force", "forest", "forget", "fork", "fortune", "forum", "forward", "fossil",
  127.     "foster", "found", "fox", "fragile", "frame", "frequent", "fresh", "friend",
  128.     "fringe", "frog", "front", "frost", "frown", "frozen", "fruit", "fuel",
  129.     "fun", "funny", "furnace", "fury", "future", "gadget", "gain", "galaxy",
  130.     "gallery", "game", "gap", "garage", "garbage", "garden", "garlic", "garment",
  131.     "gas", "gasp", "gate", "gather", "gauge", "gaze", "general", "genius",
  132.     "genre", "gentle", "genuine", "gesture", "ghost", "giant", "gift", "giggle",
  133.     "ginger", "giraffe", "girl", "give", "glad", "glance", "glare", "glass",
  134.     "glide", "glimpse", "globe", "gloom", "glory", "glove", "glow", "glue",
  135.     "goat", "goddess", "gold", "good", "goose", "gorilla", "gospel", "gossip",
  136.     "govern", "gown", "grab", "grace", "grain", "grant", "grape", "grass",
  137.     "gravity", "great", "green", "grid", "grief", "grit", "grocery", "group",
  138.     "grow", "grunt", "guard", "guess", "guide", "guilt", "guitar", "gun",
  139.     "gym", "habit", "hair", "half", "hammer", "hamster", "hand", "happy",
  140.     "harbor", "hard", "harsh", "harvest", "hat", "have", "hawk", "hazard",
  141.     "head", "health", "heart", "heavy", "hedgehog", "height", "hello", "helmet",
  142.     "help", "hen", "hero", "hidden", "high", "hill", "hint", "hip",
  143.     "hire", "history", "hobby", "hockey", "hold", "hole", "holiday", "hollow",
  144.     "home", "honey", "hood", "hope", "horn", "horror", "horse", "hospital",
  145.     "host", "hotel", "hour", "hover", "hub", "huge", "human", "humble",
  146.     "humor", "hundred", "hungry", "hunt", "hurdle", "hurry", "hurt", "husband",
  147.     "hybrid", "ice", "icon", "idea", "identify", "idle", "ignore", "ill",
  148.     "illegal", "illness", "image", "imitate", "immense", "immune", "impact", "impose",
  149.     "improve", "impulse", "inch", "include", "income", "increase", "index", "indicate",
  150.     "indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit", "initial",
  151.     "inject", "injury", "inmate", "inner", "innocent", "input", "inquiry", "insane",
  152.     "insect", "inside", "inspire", "install", "intact", "interest", "into", "invest",
  153.     "invite", "involve", "iron", "island", "isolate", "issue", "item", "ivory",
  154.     "jacket", "jaguar", "jar", "jazz", "jealous", "jeans", "jelly", "jewel",
  155.     "job", "join", "joke", "journey", "joy", "judge", "juice", "jump",
  156.     "jungle", "junior", "junk", "just", "kangaroo", "keen", "keep", "ketchup",
  157.     "key", "kick", "kid", "kidney", "kind", "kingdom", "kiss", "kit",
  158.     "kitchen", "kite", "kitten", "kiwi", "knee", "knife", "knock", "know",
  159.     "lab", "label", "labor", "ladder", "lady", "lake", "lamp", "language",
  160.     "laptop", "large", "later", "latin", "laugh", "laundry", "lava", "law",
  161.     "lawn", "lawsuit", "layer", "lazy", "leader", "leaf", "learn", "leave",
  162.     "lecture", "left", "leg", "legal", "legend", "leisure", "lemon", "lend",
  163.     "length", "lens", "leopard", "lesson", "letter", "level", "liar", "liberty",
  164.     "library", "license", "life", "lift", "light", "like", "limb", "limit",
  165.     "link", "lion", "liquid", "list", "little", "live", "lizard", "load",
  166.     "loan", "lobster", "local", "lock", "logic", "lonely", "long", "loop",
  167.     "lottery", "loud", "lounge", "love", "loyal", "lucky", "luggage", "lumber",
  168.     "lunar", "lunch", "luxury", "lyrics", "machine", "mad", "magic", "magnet",
  169.     "maid", "mail", "main", "major", "make", "mammal", "man", "manage",
  170.     "mandate", "mango", "mansion", "manual", "maple", "marble", "march", "margin",
  171.     "marine", "market", "marriage", "mask", "mass", "master", "match", "material",
  172.     "math", "matrix", "matter", "maximum", "maze", "meadow", "mean", "measure",
  173.     "meat", "mechanic", "medal", "media", "melody", "melt", "member", "memory",
  174.     "mention", "menu", "mercy", "merge", "merit", "merry", "mesh", "message",
  175.     "metal", "method", "middle", "midnight", "milk", "million", "mimic", "mind",
  176.     "minimum", "minor", "minute", "miracle", "mirror", "misery", "miss", "mistake",
  177.     "mix", "mixed", "mixture", "mobile", "model", "modify", "mom", "moment",
  178.     "monitor", "monkey", "monster", "month", "moon", "moral", "more", "morning",
  179.     "mosquito", "mother", "motion", "motor", "mountain", "mouse", "move", "movie",
  180.     "much", "muffin", "mule", "multiply", "muscle", "museum", "mushroom", "music",
  181.     "must", "mutual", "myself", "mystery", "myth", "naive", "name", "napkin",
  182.     "narrow", "nasty", "nation", "nature", "near", "neck", "need", "negative",
  183.     "neglect", "neither", "nephew", "nerve", "nest", "net", "network", "neutral",
  184.     "never", "news", "next", "nice", "night", "noble", "noise", "nominee",
  185.     "noodle", "normal", "north", "nose", "notable", "note", "nothing", "notice",
  186.     "novel", "now", "nuclear", "number", "nurse", "nut", "oak", "obey",
  187.     "object", "oblige", "obscure", "observe", "obtain", "obvious", "occur", "ocean",
  188.     "october", "odor", "off", "offer", "office", "often", "oil", "okay",
  189.     "old", "olive", "olympic", "omit", "once", "one", "onion", "online",
  190.     "only", "open", "opera", "opinion", "oppose", "option", "orange", "orbit",
  191.     "orchard", "order", "ordinary", "organ", "orient", "original", "orphan", "ostrich",
  192.     "other", "outdoor", "outer", "output", "outside", "oval", "oven", "over",
  193.     "own", "owner", "oxygen", "oyster", "ozone", "pact", "paddle", "page",
  194.     "pair", "palace", "palm", "panda", "panel", "panic", "panther", "paper",
  195.     "parade", "parent", "park", "parrot", "party", "pass", "patch", "path",
  196.     "patient", "patrol", "pattern", "pause", "pave", "payment", "peace", "peanut",
  197.     "pear", "peasant", "pelican", "pen", "penalty", "pencil", "people", "pepper",
  198.     "perfect", "permit", "person", "pet", "phone", "photo", "phrase", "physical",
  199.     "piano", "picnic", "picture", "piece", "pig", "pigeon", "pill", "pilot",
  200.     "pink", "pioneer", "pipe", "pistol", "pitch", "pizza", "place", "planet",
  201.     "plastic", "plate", "play", "please", "pledge", "pluck", "plug", "plunge",
  202.     "poem", "poet", "point", "polar", "pole", "police", "pond", "pony",
  203.     "pool", "popular", "portion", "position", "possible", "post", "potato", "pottery",
  204.     "poverty", "powder", "power", "practice", "praise", "predict", "prefer", "prepare",
  205.     "present", "pretty", "prevent", "price", "pride", "primary", "print", "priority",
  206.     "prison", "private", "prize", "problem", "process", "produce", "profit", "program",
  207.     "project", "promote", "proof", "property", "prosper", "protect", "proud", "provide",
  208.     "public", "pudding", "pull", "pulp", "pulse", "pumpkin", "punch", "pupil",
  209.     "puppy", "purchase", "purity", "purpose", "purse", "push", "put", "puzzle",
  210.     "pyramid", "quality", "quantum", "quarter", "question", "quick", "quit", "quiz",
  211.     "quote", "rabbit", "raccoon", "race", "rack", "radar", "radio", "rail",
  212.     "rain", "raise", "rally", "ramp", "ranch", "random", "range", "rapid",
  213.     "rare", "rate", "rather", "raven", "raw", "razor", "ready", "real",
  214.     "reason", "rebel", "rebuild", "recall", "receive", "recipe", "record", "recycle",
  215.     "reduce", "reflect", "reform", "refuse", "region", "regret", "regular", "reject",
  216.     "relax", "release", "relief", "rely", "remain", "remember", "remind", "remove",
  217.     "render", "renew", "rent", "reopen", "repair", "repeat", "replace", "report",
  218.     "require", "rescue", "resemble", "resist", "resource", "response", "result", "retire",
  219.     "retreat", "return", "reunion", "reveal", "review", "reward", "rhythm", "rib",
  220.     "ribbon", "rice", "rich", "ride", "ridge", "rifle", "right", "rigid",
  221.     "ring", "riot", "ripple", "risk", "ritual", "rival", "river", "road",
  222.     "roast", "robot", "robust", "rocket", "romance", "roof", "rookie", "room",
  223.     "rose", "rotate", "rough", "round", "route", "royal", "rubber", "rude",
  224.     "rug", "rule", "run", "runway", "rural", "sad", "saddle", "sadness",
  225.     "safe", "sail", "salad", "salmon", "salon", "salt", "salute", "same",
  226.     "sample", "sand", "satisfy", "satoshi", "sauce", "sausage", "save", "say",
  227.     "scale", "scan", "scare", "scatter", "scene", "scheme", "school", "science",
  228.     "scissors", "scorpion", "scout", "scrap", "screen", "script", "scrub", "sea",
  229.     "search", "season", "seat", "second", "secret", "section", "security", "seed",
  230.     "seek", "segment", "select", "sell", "seminar", "senior", "sense", "sentence",
  231.     "series", "service", "session", "settle", "setup", "seven", "shadow", "shaft",
  232.     "shallow", "share", "shed", "shell", "sheriff", "shield", "shift", "shine",
  233.     "ship", "shiver", "shock", "shoe", "shoot", "shop", "short", "shoulder",
  234.     "shove", "shrimp", "shrug", "shuffle", "shy", "sibling", "sick", "side",
  235.     "siege", "sight", "sign", "silent", "silk", "silly", "silver", "similar",
  236.     "simple", "since", "sing", "siren", "sister", "situate", "six", "size",
  237.     "skate", "sketch", "ski", "skill", "skin", "skirt", "skull", "slab",
  238.     "slam", "sleep", "slender", "slice", "slide", "slight", "slim", "slogan",
  239.     "slot", "slow", "slush", "small", "smart", "smile", "smoke", "smooth",
  240.     "snack", "snake", "snap", "sniff", "snow", "soap", "soccer", "social",
  241.     "sock", "soda", "soft", "solar", "soldier", "solid", "solution", "solve",
  242.     "someone", "song", "soon", "sorry", "sort", "soul", "sound", "soup",
  243.     "source", "south", "space", "spare", "spatial", "spawn", "speak", "special",
  244.     "speed", "spell", "spend", "sphere", "spice", "spider", "spike", "spin",
  245.     "spirit", "split", "spoil", "sponsor", "spoon", "sport", "spot", "spray",
  246.     "spread", "spring", "spy", "square", "squeeze", "squirrel", "stable", "stadium",
  247.     "staff", "stage", "stairs", "stamp", "stand", "start", "state", "stay",
  248.     "steak", "steel", "stem", "step", "stereo", "stick", "still", "sting",
  249.     "stock", "stomach", "stone", "stool", "story", "stove", "strategy", "street",
  250.     "strike", "strong", "struggle", "student", "stuff", "stumble", "style", "subject",
  251.     "submit", "subway", "success", "such", "sudden", "suffer", "sugar", "suggest",
  252.     "suit", "summer", "sun", "sunny", "sunset", "super", "supply", "supreme",
  253.     "sure", "surface", "surge", "surprise", "surround", "survey", "suspect", "sustain",
  254.     "swallow", "swamp", "swap", "swarm", "swear", "sweet", "swift", "swim",
  255.     "swing", "switch", "sword", "symbol", "symptom", "syrup", "system", "table",
  256.     "tackle", "tag", "tail", "talent", "talk", "tank", "tape", "target",
  257.     "task", "taste", "tattoo", "taxi", "teach", "team", "tell", "ten",
  258.     "tenant", "tennis", "tent", "term", "test", "text", "thank", "that",
  259.     "theme", "then", "theory", "there", "they", "thing", "this", "thought",
  260.     "three", "thrive", "throw", "thumb", "thunder", "ticket", "tide", "tiger",
  261.     "tilt", "timber", "time", "tiny", "tip", "tired", "tissue", "title",
  262.     "toast", "tobacco", "today", "toddler", "toe", "together", "toilet", "token",
  263.     "tomato", "tomorrow", "tone", "tongue", "tonight", "tool", "tooth", "top",
  264.     "topic", "topple", "torch", "tornado", "tortoise", "toss", "total", "tourist",
  265.     "toward", "tower", "town", "toy", "track", "trade", "traffic", "tragic",
  266.     "train", "transfer", "trap", "trash", "travel", "tray", "treat", "tree",
  267.     "trend", "trial", "tribe", "trick", "trigger", "trim", "trip", "trophy",
  268.     "trouble", "truck", "true", "truly", "trumpet", "trust", "truth", "try",
  269.     "tube", "tuition", "tumble", "tuna", "tunnel", "turkey", "turn", "turtle",
  270.     "twelve", "twenty", "twice", "twin", "twist", "two", "type", "typical",
  271.     "ugly", "umbrella", "unable", "unaware", "uncle", "uncover", "under", "undo",
  272.     "unfair", "unfold", "unhappy", "uniform", "unique", "unit", "universe", "unknown",
  273.     "unlock", "until", "unusual", "unveil", "update", "upgrade", "uphold", "upon",
  274.     "upper", "upset", "urban", "urge", "usage", "use", "used", "useful",
  275.     "useless", "usual", "utility", "vacant", "vacuum", "vague", "valid", "valley",
  276.     "valve", "van", "vanish", "vapor", "various", "vast", "vault", "vehicle",
  277.     "velvet", "vendor", "venture", "venue", "verb", "verify", "version", "very",
  278.     "vessel", "veteran", "viable", "vibrant", "vicious", "victory", "video", "view",
  279.     "village", "vintage", "violin", "virtual", "virus", "visa", "visit", "visual",
  280.     "vital", "vivid", "vocal", "voice", "void", "volcano", "volume", "vote",
  281.     "voyage", "wage", "wagon", "wait", "walk", "wall", "walnut", "want",
  282.     "warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave",
  283.     "way", "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding",
  284.     "weekend", "weird", "welcome", "west", "wet", "whale", "what", "wheat",
  285.     "wheel", "when", "where", "whip", "whisper", "wide", "width", "wife",
  286.     "wild", "will", "win", "window", "wine", "wing", "wink", "winner",
  287.     "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman",
  288.     "wonder", "wood", "wool", "word", "work", "world", "worry", "worth",
  289.     "wrap", "wreck", "wrestle", "wrist", "write", "wrong", "yard", "year",
  290.     "yellow", "you", "young", "youth", "zebra", "zero", "zone", "zoo",
  291. ]
  292.  
  293.  
  294. def banner(text):
  295.     """Print a section header so each stage of processing is easy to follow."""
  296.     print("\n" + "=" * 60)
  297.     print(text)
  298.     print("=" * 60)
  299.  
  300.  
  301. # =====================================================================
  302. # STEP 1: ask how many entropy sources, and what type each one is
  303. # =====================================================================
  304. def ask_source_count():
  305.     while True:
  306.         raw = input("How many entropy sources do you have? (1, 2, or 3): ").strip()
  307.         if raw in ("1", "2", "3"):
  308.             return int(raw)
  309.         print("  -> Please enter exactly one digit: 1, 2, or 3.")
  310.  
  311.  
  312. def ask_source_type(index):
  313.     while True:
  314.         raw = input(f"Source #{index+1}: is it a coin or a die? (coin/die): ").strip().lower()
  315.         if raw in ("coin", "die"):
  316.             return raw
  317.         print("  -> Please type exactly 'coin' or 'die'.")
  318.  
  319.  
  320. # =====================================================================
  321. # STEP 2: collect and strictly validate the raw rolls/flips
  322. # =====================================================================
  323. def ask_raw_data(index, source_type):
  324.     label = "coin flips (only letters H and T, e.g. HTTHHTT...)" \
  325.         if source_type == "coin" else \
  326.         "die rolls (only digits 1-6, e.g. 612435...)"
  327.     print(f"Source #{index+1} ({source_type}): enter your raw {label}")
  328.     while True:
  329.         raw = input("> ").strip().upper() if source_type == "coin" else input("> ").strip()
  330.  
  331.         if len(raw) < 2:
  332.             print("  -> Need at least 2 characters (one pair). Try again.")
  333.             continue
  334.         if len(raw) > 9999:
  335.             print("  -> Max 9999 characters per source. Try again.")
  336.             continue
  337.  
  338.         if source_type == "coin":
  339.             bad_chars = set(raw) - {"H", "T"}
  340.         else:
  341.             bad_chars = set(raw) - set("123456")
  342.  
  343.         if bad_chars:
  344.             print(f"  -> Invalid character(s) found: {sorted(bad_chars)}. "
  345.                   f"Only {'H/T' if source_type == 'coin' else '1-6'} allowed. "
  346.                   f"Please re-enter the whole source.")
  347.             continue
  348.  
  349.         return raw
  350.  
  351.  
  352. # =====================================================================
  353. # STEP 3: von Neumann-style pairwise extraction (unbiased regardless
  354. # of how loaded the coin/die is)
  355. # =====================================================================
  356. def extract_coin_bits(flips):
  357.     """HT -> 1, TH -> 0, HH/TT discarded. Non-overlapping pairs."""
  358.     bits = []
  359.     for i in range(0, len(flips) - 1, 2):
  360.         pair = flips[i:i + 2]
  361.         if pair == "HT":
  362.             bits.append(1)
  363.         elif pair == "TH":
  364.             bits.append(0)
  365.         # HH and TT are discarded - no bit produced
  366.     return bits
  367.  
  368.  
  369. def extract_die_bits(rolls):
  370.     """Compare two consecutive rolls: bigger-first -> 1, smaller-first -> 0, tie discarded."""
  371.     bits = []
  372.     for i in range(0, len(rolls) - 1, 2):
  373.         first, second = rolls[i], rolls[i + 1]
  374.         if first == second:
  375.             continue
  376.         bits.append(1 if first > second else 0)
  377.     return bits
  378.  
  379.  
  380. # =====================================================================
  381. # STEP 4: combine multiple sources
  382. # =====================================================================
  383. def truncate_to_shortest(bit_lists):
  384.     """All streams must be equal length before combining, so we cut
  385.    every stream down to the length of the shortest one."""
  386.     shortest = min(len(b) for b in bit_lists)
  387.     return [b[:shortest] for b in bit_lists]
  388.  
  389.  
  390. def xor_combine(bit_lists):
  391.     """
  392.    Bitwise XOR (= parity) across however many streams you have.
  393.    This is ONE formula that works correctly whether you have 1, 2, or 3
  394.    sources - XOR is associative, so chaining it across any number of
  395.    streams automatically computes "odd number of 1s -> 1" at every
  396.    position. No special-casing needed for 2 vs 3 sources.
  397.    """
  398.     length = len(bit_lists[0])
  399.     combined = []
  400.     for position in range(length):
  401.         parity = 0
  402.         for stream in bit_lists:
  403.             parity ^= stream[position]
  404.         combined.append(parity)
  405.     return combined
  406.  
  407.  
  408. # =====================================================================
  409. # STEP 5: fold down to exactly 256 bits
  410. # =====================================================================
  411. def fold_to_256(bits):
  412.     """
  413.    If we have more than 256 true-random bits, don't throw the extra
  414.    away: XOR them back into the front of the string, wrapping around
  415.    as many times as needed. This is a single linear pass that handles
  416.    any surplus length in one step (no repeated halving required) and
  417.    stays uniform as long as the input bits were uniform.
  418.    """
  419.     if len(bits) < 256:
  420.         raise ValueError(
  421.             f"Only {len(bits)} true bits survived extraction - that's not "
  422.             f"enough. You need at least 256. Please collect more rolls/flips "
  423.             f"and start over."
  424.         )
  425.     folded = bits[:256]
  426.     overflow = bits[256:]
  427.     for i, bit in enumerate(overflow):
  428.         folded[i % 256] ^= bit
  429.     return folded
  430.  
  431.  
  432. # =====================================================================
  433. # STEP 6: SHA-256 checksum + BIP-39 word mapping
  434. # =====================================================================
  435. def bits_to_bytes(bits):
  436.     assert len(bits) % 8 == 0
  437.     out = bytearray()
  438.     for i in range(0, len(bits), 8):
  439.         byte_val = 0
  440.         for bit in bits[i:i + 8]:
  441.             byte_val = (byte_val << 1) | bit
  442.         out.append(byte_val)
  443.     return bytes(out)
  444.  
  445.  
  446. def byte_to_bits(byte_val, n_bits=8):
  447.     return [(byte_val >> (7 - i)) & 1 for i in range(n_bits)]
  448.  
  449.  
  450. def bits_to_int(bits):
  451.     value = 0
  452.     for bit in bits:
  453.         value = (value << 1) | bit
  454.     return value
  455.  
  456.  
  457. def build_mnemonic(entropy_256_bits):
  458.     entropy_bytes = bits_to_bytes(entropy_256_bits)
  459.     digest = hashlib.sha256(entropy_bytes).digest()
  460.     checksum_bits = byte_to_bits(digest[0], 8)  # first 8 bits of SHA-256(entropy)
  461.  
  462.     full_bits = entropy_256_bits + checksum_bits  # 264 bits total
  463.     words = []
  464.     for i in range(0, 264, 11):
  465.         group = full_bits[i:i + 11]
  466.         idx = bits_to_int(group)
  467.         words.append(WORDLIST[idx])
  468.     return words
  469.  
  470.  
  471. # =====================================================================
  472. # MAIN
  473. # =====================================================================
  474. def main():
  475.     banner("OFFLINE BIP-39 SEED PROCESSOR - nothing leaves this process")
  476.  
  477.     n_sources = ask_source_count()
  478.     source_types = [ask_source_type(i) for i in range(n_sources)]
  479.  
  480.     banner("STEP 1/5: collecting raw rolls/flips")
  481.     raw_streams = [ask_raw_data(i, t) for i, t in enumerate(source_types)]
  482.  
  483.     banner("STEP 2/5: applying von Neumann extraction to each source")
  484.     true_bit_streams = []
  485.     for i, (raw, t) in enumerate(zip(raw_streams, source_types)):
  486.         bits = extract_coin_bits(raw) if t == "coin" else extract_die_bits(raw)
  487.         print(f"Source #{i+1} ({t}): {len(raw)} raw entries -> {len(bits)} true bits")
  488.         true_bit_streams.append(bits)
  489.  
  490.     banner("STEP 3/5: truncating to equal length, then combining")
  491.     true_bit_streams = truncate_to_shortest(true_bit_streams)
  492.     print(f"All sources truncated to {len(true_bit_streams[0])} bits each")
  493.  
  494.     if len(true_bit_streams) > 1:
  495.         combined = xor_combine(true_bit_streams)
  496.         print(f"XOR-combined {len(true_bit_streams)} sources -> {len(combined)} bits")
  497.     else:
  498.         combined = true_bit_streams[0]
  499.         print("Only one source - nothing to XOR, using it directly")
  500.  
  501.     banner("STEP 4/5: folding to exactly 256 bits")
  502.     entropy_256 = fold_to_256(combined)
  503.     print("Final 256-bit entropy (hex): " + bits_to_bytes(entropy_256).hex())
  504.  
  505.     banner("STEP 5/5: SHA-256 checksum + 24-word mnemonic")
  506.     words = build_mnemonic(entropy_256)
  507.  
  508.     banner("YOUR 24-WORD MNEMONIC - WRITE THIS DOWN ON PAPER NOW")
  509.     for i in range(0, 24, 4):
  510.         row = "   ".join(f"{i+j+1:>2}. {words[i+j]}" for j in range(4))
  511.         print(row)
  512.  
  513.     input("\nPress Enter ONLY once you have physically written down all 24 "
  514.           "words and verified them by re-reading the screen twice.")
  515.     print("\nClearing screen. Reboot Tails now to fully clear RAM.")
  516.     print("\n" * 100)  # push everything out of the visible terminal window
  517.  
  518.  
  519. if __name__ == "__main__":
  520.     try:
  521.         main()
  522.     except (KeyboardInterrupt, EOFError):
  523.         print("\nAborted. No data was written anywhere.")
  524.         sys.exit(1)
Add Comment
Please, Sign In to add comment