Release research code for fast BIP39 mnemonic generation
This commit is contained in:
parent
9e00e1d5e3
commit
b04f2605fe
|
@ -0,0 +1,3 @@
|
||||||
|
# ignore binaries
|
||||||
|
bx_seed_walker_bip39_mnemonic
|
||||||
|
bx_seed_walker_bip39_mnemonic_*bit
|
|
@ -0,0 +1,10 @@
|
||||||
|
all: bx_seed_walker_bip39_mnemonic_128bit bx_seed_walker_bip39_mnemonic_192bit bx_seed_walker_bip39_mnemonic_256bit
|
||||||
|
|
||||||
|
bx_seed_walker_bip39_mnemonic_128bit: bx_seed_walker_bip39_mnemonic.cpp sha256.c sha256.h bip39_dictionary.hpp
|
||||||
|
g++ -std=c++11 bx_seed_walker_bip39_mnemonic.cpp sha256.c -O3 -march=native -DBIT_LENGTH=128 -o bx_seed_walker_bip39_mnemonic_128bit
|
||||||
|
|
||||||
|
bx_seed_walker_bip39_mnemonic_192bit: bx_seed_walker_bip39_mnemonic.cpp sha256.c sha256.h bip39_dictionary.hpp
|
||||||
|
g++ -std=c++11 bx_seed_walker_bip39_mnemonic.cpp sha256.c -O3 -march=native -DBIT_LENGTH=192 -o bx_seed_walker_bip39_mnemonic_192bit
|
||||||
|
|
||||||
|
bx_seed_walker_bip39_mnemonic_256bit: bx_seed_walker_bip39_mnemonic.cpp sha256.c sha256.h bip39_dictionary.hpp
|
||||||
|
g++ -std=c++11 bx_seed_walker_bip39_mnemonic.cpp sha256.c -O3 -march=native -DBIT_LENGTH=256 -o bx_seed_walker_bip39_mnemonic_256bit
|
|
@ -0,0 +1,46 @@
|
||||||
|
# bx seed walker for BIP39 mnemonics
|
||||||
|
|
||||||
|
Optimized proof-of-concept program to derive all possible `2^32` weak mnemonics for `CVE-2023-39910` on a given key length without the need for slow `bx` calls.
|
||||||
|
|
||||||
|
Basic operation:
|
||||||
|
* Walk over all possible PRNG seeding states
|
||||||
|
* For each PRNG configuration:
|
||||||
|
* simulate the `bx seed` behavior to derive the corresponding weak seed
|
||||||
|
* simulate `bx mnemonic-new` to construct a BIP39 mnemonic
|
||||||
|
* output the resulting data on stdout
|
||||||
|
|
||||||
|
This program does not perform any filtering of the recovered mnemonics by any criteria.
|
||||||
|
|
||||||
|
With some modifications to the PRNG consumption pattern, this program should also be able to generate mnemonics for `CVE-2023-31290`, although we didn't test this.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
* Build: see `Makefile`.
|
||||||
|
* Parameters set at build time using build variables.
|
||||||
|
* Output to stdout.
|
||||||
|
* Warning: when directed to the file system, the output files for a complete key range will be large (several 100 GiB).
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
This is experimental, unmaintained code. Use only as research inspiration.
|
||||||
|
|
||||||
|
This program was helpful as a quick proof-of-concept implementation during early experimentation and research in July 2023. It remains in an experimental state.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This folder contains adapted code from multiple sources, as well as derived code. See the file headers for more information.
|
||||||
|
|
||||||
|
Due to the derivative usage of libbitcoin code, the primary license is `GNU Affero General Public License` in version 3 or later.
|
||||||
|
|
||||||
|
Other code snippets fall under different licenses, namely some versions of CC BY SA.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
Written by Christian Reitter. Based on code from libbitcoin and other authors.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Example to compare output with stock `bx` behavior for a given `FAKETIME` value == PRNG seed id:
|
||||||
|
```
|
||||||
|
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1 FAKETIME_FMT=%s FAKETIME=4.294967294 ./bx-linux-x64-qrcode seed -b 256 | ./bx-linux-x64-qrcode mnemonic-new
|
||||||
|
```
|
|
@ -0,0 +1,395 @@
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Adapted code from
|
||||||
|
// * https://github.com/libbitcoin/libbitcoin-system/blob/a012c9b7219fb2b85ecbc981a4982eecdd37263a/include/bitcoin/system/wallet/dictionary.hpp
|
||||||
|
// * https://github.com/libbitcoin/libbitcoin-system/blob/c818b39b8beaf9c7f54ac8bc7d055f30e91baf10/src/wallet/dictionary.cpp
|
||||||
|
//
|
||||||
|
// Underlying BIP39 wordlist data is identical to
|
||||||
|
// https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2011-2023 libbitcoin developers (see AUTHORS)
|
||||||
|
*
|
||||||
|
* This file is part of libbitcoin.
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A dictionary for creating mnemonics.
|
||||||
|
* The bip39 spec calls this a "wordlist".
|
||||||
|
* This is a POD type, which means the compiler can write it directly
|
||||||
|
* to static memory with no run-time overhead.
|
||||||
|
*/
|
||||||
|
typedef std::array<const char *, 2048> dictionary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of candidate dictionaries for mnemonic validation.
|
||||||
|
*/
|
||||||
|
typedef std::vector<const dictionary *> dictionary_list;
|
||||||
|
|
||||||
|
namespace language {
|
||||||
|
// only include english dictionary at the moment, which is the standard
|
||||||
|
extern const dictionary en;
|
||||||
|
} // namespace language
|
||||||
|
|
||||||
|
const dictionary en = {
|
||||||
|
{"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", "flip", "float",
|
||||||
|
"flock", "floor", "flower", "fluid", "flush", "fly",
|
||||||
|
"foam", "focus", "fog", "foil", "fold", "follow",
|
||||||
|
"food", "foot", "force", "forest", "forget", "fork",
|
||||||
|
"fortune", "forum", "forward", "fossil", "foster", "found",
|
||||||
|
"fox", "fragile", "frame", "frequent", "fresh", "friend",
|
||||||
|
"fringe", "frog", "front", "frost", "frown", "frozen",
|
||||||
|
"fruit", "fuel", "fun", "funny", "furnace", "fury",
|
||||||
|
"future", "gadget", "gain", "galaxy", "gallery", "game",
|
||||||
|
"gap", "garage", "garbage", "garden", "garlic", "garment",
|
||||||
|
"gas", "gasp", "gate", "gather", "gauge", "gaze",
|
||||||
|
"general", "genius", "genre", "gentle", "genuine", "gesture",
|
||||||
|
"ghost", "giant", "gift", "giggle", "ginger", "giraffe",
|
||||||
|
"girl", "give", "glad", "glance", "glare", "glass",
|
||||||
|
"glide", "glimpse", "globe", "gloom", "glory", "glove",
|
||||||
|
"glow", "glue", "goat", "goddess", "gold", "good",
|
||||||
|
"goose", "gorilla", "gospel", "gossip", "govern", "gown",
|
||||||
|
"grab", "grace", "grain", "grant", "grape", "grass",
|
||||||
|
"gravity", "great", "green", "grid", "grief", "grit",
|
||||||
|
"grocery", "group", "grow", "grunt", "guard", "guess",
|
||||||
|
"guide", "guilt", "guitar", "gun", "gym", "habit",
|
||||||
|
"hair", "half", "hammer", "hamster", "hand", "happy",
|
||||||
|
"harbor", "hard", "harsh", "harvest", "hat", "have",
|
||||||
|
"hawk", "hazard", "head", "health", "heart", "heavy",
|
||||||
|
"hedgehog", "height", "hello", "helmet", "help", "hen",
|
||||||
|
"hero", "hidden", "high", "hill", "hint", "hip",
|
||||||
|
"hire", "history", "hobby", "hockey", "hold", "hole",
|
||||||
|
"holiday", "hollow", "home", "honey", "hood", "hope",
|
||||||
|
"horn", "horror", "horse", "hospital", "host", "hotel",
|
||||||
|
"hour", "hover", "hub", "huge", "human", "humble",
|
||||||
|
"humor", "hundred", "hungry", "hunt", "hurdle", "hurry",
|
||||||
|
"hurt", "husband", "hybrid", "ice", "icon", "idea",
|
||||||
|
"identify", "idle", "ignore", "ill", "illegal", "illness",
|
||||||
|
"image", "imitate", "immense", "immune", "impact", "impose",
|
||||||
|
"improve", "impulse", "inch", "include", "income", "increase",
|
||||||
|
"index", "indicate", "indoor", "industry", "infant", "inflict",
|
||||||
|
"inform", "inhale", "inherit", "initial", "inject", "injury",
|
||||||
|
"inmate", "inner", "innocent", "input", "inquiry", "insane",
|
||||||
|
"insect", "inside", "inspire", "install", "intact", "interest",
|
||||||
|
"into", "invest", "invite", "involve", "iron", "island",
|
||||||
|
"isolate", "issue", "item", "ivory", "jacket", "jaguar",
|
||||||
|
"jar", "jazz", "jealous", "jeans", "jelly", "jewel",
|
||||||
|
"job", "join", "joke", "journey", "joy", "judge",
|
||||||
|
"juice", "jump", "jungle", "junior", "junk", "just",
|
||||||
|
"kangaroo", "keen", "keep", "ketchup", "key", "kick",
|
||||||
|
"kid", "kidney", "kind", "kingdom", "kiss", "kit",
|
||||||
|
"kitchen", "kite", "kitten", "kiwi", "knee", "knife",
|
||||||
|
"knock", "know", "lab", "label", "labor", "ladder",
|
||||||
|
"lady", "lake", "lamp", "language", "laptop", "large",
|
||||||
|
"later", "latin", "laugh", "laundry", "lava", "law",
|
||||||
|
"lawn", "lawsuit", "layer", "lazy", "leader", "leaf",
|
||||||
|
"learn", "leave", "lecture", "left", "leg", "legal",
|
||||||
|
"legend", "leisure", "lemon", "lend", "length", "lens",
|
||||||
|
"leopard", "lesson", "letter", "level", "liar", "liberty",
|
||||||
|
"library", "license", "life", "lift", "light", "like",
|
||||||
|
"limb", "limit", "link", "lion", "liquid", "list",
|
||||||
|
"little", "live", "lizard", "load", "loan", "lobster",
|
||||||
|
"local", "lock", "logic", "lonely", "long", "loop",
|
||||||
|
"lottery", "loud", "lounge", "love", "loyal", "lucky",
|
||||||
|
"luggage", "lumber", "lunar", "lunch", "luxury", "lyrics",
|
||||||
|
"machine", "mad", "magic", "magnet", "maid", "mail",
|
||||||
|
"main", "major", "make", "mammal", "man", "manage",
|
||||||
|
"mandate", "mango", "mansion", "manual", "maple", "marble",
|
||||||
|
"march", "margin", "marine", "market", "marriage", "mask",
|
||||||
|
"mass", "master", "match", "material", "math", "matrix",
|
||||||
|
"matter", "maximum", "maze", "meadow", "mean", "measure",
|
||||||
|
"meat", "mechanic", "medal", "media", "melody", "melt",
|
||||||
|
"member", "memory", "mention", "menu", "mercy", "merge",
|
||||||
|
"merit", "merry", "mesh", "message", "metal", "method",
|
||||||
|
"middle", "midnight", "milk", "million", "mimic", "mind",
|
||||||
|
"minimum", "minor", "minute", "miracle", "mirror", "misery",
|
||||||
|
"miss", "mistake", "mix", "mixed", "mixture", "mobile",
|
||||||
|
"model", "modify", "mom", "moment", "monitor", "monkey",
|
||||||
|
"monster", "month", "moon", "moral", "more", "morning",
|
||||||
|
"mosquito", "mother", "motion", "motor", "mountain", "mouse",
|
||||||
|
"move", "movie", "much", "muffin", "mule", "multiply",
|
||||||
|
"muscle", "museum", "mushroom", "music", "must", "mutual",
|
||||||
|
"myself", "mystery", "myth", "naive", "name", "napkin",
|
||||||
|
"narrow", "nasty", "nation", "nature", "near", "neck",
|
||||||
|
"need", "negative", "neglect", "neither", "nephew", "nerve",
|
||||||
|
"nest", "net", "network", "neutral", "never", "news",
|
||||||
|
"next", "nice", "night", "noble", "noise", "nominee",
|
||||||
|
"noodle", "normal", "north", "nose", "notable", "note",
|
||||||
|
"nothing", "notice", "novel", "now", "nuclear", "number",
|
||||||
|
"nurse", "nut", "oak", "obey", "object", "oblige",
|
||||||
|
"obscure", "observe", "obtain", "obvious", "occur", "ocean",
|
||||||
|
"october", "odor", "off", "offer", "office", "often",
|
||||||
|
"oil", "okay", "old", "olive", "olympic", "omit",
|
||||||
|
"once", "one", "onion", "online", "only", "open",
|
||||||
|
"opera", "opinion", "oppose", "option", "orange", "orbit",
|
||||||
|
"orchard", "order", "ordinary", "organ", "orient", "original",
|
||||||
|
"orphan", "ostrich", "other", "outdoor", "outer", "output",
|
||||||
|
"outside", "oval", "oven", "over", "own", "owner",
|
||||||
|
"oxygen", "oyster", "ozone", "pact", "paddle", "page",
|
||||||
|
"pair", "palace", "palm", "panda", "panel", "panic",
|
||||||
|
"panther", "paper", "parade", "parent", "park", "parrot",
|
||||||
|
"party", "pass", "patch", "path", "patient", "patrol",
|
||||||
|
"pattern", "pause", "pave", "payment", "peace", "peanut",
|
||||||
|
"pear", "peasant", "pelican", "pen", "penalty", "pencil",
|
||||||
|
"people", "pepper", "perfect", "permit", "person", "pet",
|
||||||
|
"phone", "photo", "phrase", "physical", "piano", "picnic",
|
||||||
|
"picture", "piece", "pig", "pigeon", "pill", "pilot",
|
||||||
|
"pink", "pioneer", "pipe", "pistol", "pitch", "pizza",
|
||||||
|
"place", "planet", "plastic", "plate", "play", "please",
|
||||||
|
"pledge", "pluck", "plug", "plunge", "poem", "poet",
|
||||||
|
"point", "polar", "pole", "police", "pond", "pony",
|
||||||
|
"pool", "popular", "portion", "position", "possible", "post",
|
||||||
|
"potato", "pottery", "poverty", "powder", "power", "practice",
|
||||||
|
"praise", "predict", "prefer", "prepare", "present", "pretty",
|
||||||
|
"prevent", "price", "pride", "primary", "print", "priority",
|
||||||
|
"prison", "private", "prize", "problem", "process", "produce",
|
||||||
|
"profit", "program", "project", "promote", "proof", "property",
|
||||||
|
"prosper", "protect", "proud", "provide", "public", "pudding",
|
||||||
|
"pull", "pulp", "pulse", "pumpkin", "punch", "pupil",
|
||||||
|
"puppy", "purchase", "purity", "purpose", "purse", "push",
|
||||||
|
"put", "puzzle", "pyramid", "quality", "quantum", "quarter",
|
||||||
|
"question", "quick", "quit", "quiz", "quote", "rabbit",
|
||||||
|
"raccoon", "race", "rack", "radar", "radio", "rail",
|
||||||
|
"rain", "raise", "rally", "ramp", "ranch", "random",
|
||||||
|
"range", "rapid", "rare", "rate", "rather", "raven",
|
||||||
|
"raw", "razor", "ready", "real", "reason", "rebel",
|
||||||
|
"rebuild", "recall", "receive", "recipe", "record", "recycle",
|
||||||
|
"reduce", "reflect", "reform", "refuse", "region", "regret",
|
||||||
|
"regular", "reject", "relax", "release", "relief", "rely",
|
||||||
|
"remain", "remember", "remind", "remove", "render", "renew",
|
||||||
|
"rent", "reopen", "repair", "repeat", "replace", "report",
|
||||||
|
"require", "rescue", "resemble", "resist", "resource", "response",
|
||||||
|
"result", "retire", "retreat", "return", "reunion", "reveal",
|
||||||
|
"review", "reward", "rhythm", "rib", "ribbon", "rice",
|
||||||
|
"rich", "ride", "ridge", "rifle", "right", "rigid",
|
||||||
|
"ring", "riot", "ripple", "risk", "ritual", "rival",
|
||||||
|
"river", "road", "roast", "robot", "robust", "rocket",
|
||||||
|
"romance", "roof", "rookie", "room", "rose", "rotate",
|
||||||
|
"rough", "round", "route", "royal", "rubber", "rude",
|
||||||
|
"rug", "rule", "run", "runway", "rural", "sad",
|
||||||
|
"saddle", "sadness", "safe", "sail", "salad", "salmon",
|
||||||
|
"salon", "salt", "salute", "same", "sample", "sand",
|
||||||
|
"satisfy", "satoshi", "sauce", "sausage", "save", "say",
|
||||||
|
"scale", "scan", "scare", "scatter", "scene", "scheme",
|
||||||
|
"school", "science", "scissors", "scorpion", "scout", "scrap",
|
||||||
|
"screen", "script", "scrub", "sea", "search", "season",
|
||||||
|
"seat", "second", "secret", "section", "security", "seed",
|
||||||
|
"seek", "segment", "select", "sell", "seminar", "senior",
|
||||||
|
"sense", "sentence", "series", "service", "session", "settle",
|
||||||
|
"setup", "seven", "shadow", "shaft", "shallow", "share",
|
||||||
|
"shed", "shell", "sheriff", "shield", "shift", "shine",
|
||||||
|
"ship", "shiver", "shock", "shoe", "shoot", "shop",
|
||||||
|
"short", "shoulder", "shove", "shrimp", "shrug", "shuffle",
|
||||||
|
"shy", "sibling", "sick", "side", "siege", "sight",
|
||||||
|
"sign", "silent", "silk", "silly", "silver", "similar",
|
||||||
|
"simple", "since", "sing", "siren", "sister", "situate",
|
||||||
|
"six", "size", "skate", "sketch", "ski", "skill",
|
||||||
|
"skin", "skirt", "skull", "slab", "slam", "sleep",
|
||||||
|
"slender", "slice", "slide", "slight", "slim", "slogan",
|
||||||
|
"slot", "slow", "slush", "small", "smart", "smile",
|
||||||
|
"smoke", "smooth", "snack", "snake", "snap", "sniff",
|
||||||
|
"snow", "soap", "soccer", "social", "sock", "soda",
|
||||||
|
"soft", "solar", "soldier", "solid", "solution", "solve",
|
||||||
|
"someone", "song", "soon", "sorry", "sort", "soul",
|
||||||
|
"sound", "soup", "source", "south", "space", "spare",
|
||||||
|
"spatial", "spawn", "speak", "special", "speed", "spell",
|
||||||
|
"spend", "sphere", "spice", "spider", "spike", "spin",
|
||||||
|
"spirit", "split", "spoil", "sponsor", "spoon", "sport",
|
||||||
|
"spot", "spray", "spread", "spring", "spy", "square",
|
||||||
|
"squeeze", "squirrel", "stable", "stadium", "staff", "stage",
|
||||||
|
"stairs", "stamp", "stand", "start", "state", "stay",
|
||||||
|
"steak", "steel", "stem", "step", "stereo", "stick",
|
||||||
|
"still", "sting", "stock", "stomach", "stone", "stool",
|
||||||
|
"story", "stove", "strategy", "street", "strike", "strong",
|
||||||
|
"struggle", "student", "stuff", "stumble", "style", "subject",
|
||||||
|
"submit", "subway", "success", "such", "sudden", "suffer",
|
||||||
|
"sugar", "suggest", "suit", "summer", "sun", "sunny",
|
||||||
|
"sunset", "super", "supply", "supreme", "sure", "surface",
|
||||||
|
"surge", "surprise", "surround", "survey", "suspect", "sustain",
|
||||||
|
"swallow", "swamp", "swap", "swarm", "swear", "sweet",
|
||||||
|
"swift", "swim", "swing", "switch", "sword", "symbol",
|
||||||
|
"symptom", "syrup", "system", "table", "tackle", "tag",
|
||||||
|
"tail", "talent", "talk", "tank", "tape", "target",
|
||||||
|
"task", "taste", "tattoo", "taxi", "teach", "team",
|
||||||
|
"tell", "ten", "tenant", "tennis", "tent", "term",
|
||||||
|
"test", "text", "thank", "that", "theme", "then",
|
||||||
|
"theory", "there", "they", "thing", "this", "thought",
|
||||||
|
"three", "thrive", "throw", "thumb", "thunder", "ticket",
|
||||||
|
"tide", "tiger", "tilt", "timber", "time", "tiny",
|
||||||
|
"tip", "tired", "tissue", "title", "toast", "tobacco",
|
||||||
|
"today", "toddler", "toe", "together", "toilet", "token",
|
||||||
|
"tomato", "tomorrow", "tone", "tongue", "tonight", "tool",
|
||||||
|
"tooth", "top", "topic", "topple", "torch", "tornado",
|
||||||
|
"tortoise", "toss", "total", "tourist", "toward", "tower",
|
||||||
|
"town", "toy", "track", "trade", "traffic", "tragic",
|
||||||
|
"train", "transfer", "trap", "trash", "travel", "tray",
|
||||||
|
"treat", "tree", "trend", "trial", "tribe", "trick",
|
||||||
|
"trigger", "trim", "trip", "trophy", "trouble", "truck",
|
||||||
|
"true", "truly", "trumpet", "trust", "truth", "try",
|
||||||
|
"tube", "tuition", "tumble", "tuna", "tunnel", "turkey",
|
||||||
|
"turn", "turtle", "twelve", "twenty", "twice", "twin",
|
||||||
|
"twist", "two", "type", "typical", "ugly", "umbrella",
|
||||||
|
"unable", "unaware", "uncle", "uncover", "under", "undo",
|
||||||
|
"unfair", "unfold", "unhappy", "uniform", "unique", "unit",
|
||||||
|
"universe", "unknown", "unlock", "until", "unusual", "unveil",
|
||||||
|
"update", "upgrade", "uphold", "upon", "upper", "upset",
|
||||||
|
"urban", "urge", "usage", "use", "used", "useful",
|
||||||
|
"useless", "usual", "utility", "vacant", "vacuum", "vague",
|
||||||
|
"valid", "valley", "valve", "van", "vanish", "vapor",
|
||||||
|
"various", "vast", "vault", "vehicle", "velvet", "vendor",
|
||||||
|
"venture", "venue", "verb", "verify", "version", "very",
|
||||||
|
"vessel", "veteran", "viable", "vibrant", "vicious", "victory",
|
||||||
|
"video", "view", "village", "vintage", "violin", "virtual",
|
||||||
|
"virus", "visa", "visit", "visual", "vital", "vivid",
|
||||||
|
"vocal", "voice", "void", "volcano", "volume", "vote",
|
||||||
|
"voyage", "wage", "wagon", "wait", "walk", "wall",
|
||||||
|
"walnut", "want", "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"}};
|
|
@ -0,0 +1,222 @@
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <random>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "bip39_dictionary.hpp"
|
||||||
|
#include "sha256.h"
|
||||||
|
|
||||||
|
// PoC author: Christian Reitter
|
||||||
|
// Note: experimental code
|
||||||
|
// See local notes and the README for more license and authorship information
|
||||||
|
// Unless noted otherwise, licensed AGPLv3 or later
|
||||||
|
|
||||||
|
// stay close to libbitcoin in type description
|
||||||
|
typedef std::vector<uint8_t> data_chunk;
|
||||||
|
|
||||||
|
// function adapted from
|
||||||
|
// https://stackoverflow.com/questions/26503606/better-way-to-convert-a-vector-of-uint8-to-an-ascii-hexadecimal-string
|
||||||
|
// Licensed under CC BY-SA 3.0
|
||||||
|
// Author https://stackoverflow.com/users/596781/kerrek-sb
|
||||||
|
std::string uint8_vector_to_hex_string(const std::vector<uint8_t> &v) {
|
||||||
|
std::string result;
|
||||||
|
result.reserve(v.size() * 2); // two digits per character
|
||||||
|
|
||||||
|
// adapted to lowercase hex
|
||||||
|
static constexpr char hex[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
for (uint8_t c : v) {
|
||||||
|
result.push_back(hex[c / 16]);
|
||||||
|
result.push_back(hex[c % 16]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sha256 specific container, fixed size
|
||||||
|
typedef std::array<uint8_t, 32> hash_digest_sha256;
|
||||||
|
|
||||||
|
hash_digest_sha256 sha256_hash(data_chunk data) {
|
||||||
|
hash_digest_sha256 hash;
|
||||||
|
SHA256_(data.data(), data.size(), hash.data());
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BIP-39 private constants.
|
||||||
|
static constexpr size_t bits_per_word = 11;
|
||||||
|
static constexpr size_t entropy_bit_divisor = 32;
|
||||||
|
constexpr uint8_t byte_bits = 8;
|
||||||
|
static constexpr size_t mnemonic_seed_multiple = 4;
|
||||||
|
|
||||||
|
// Represents a mnemonic word list.
|
||||||
|
typedef std::vector<std::string> string_list;
|
||||||
|
typedef string_list word_list;
|
||||||
|
|
||||||
|
// function taken from
|
||||||
|
// https://stackoverflow.com/questions/5288396/c-ostream-out-manipulation/5289170#5289170
|
||||||
|
// License should be CC BY-SA 4.0 (edited after 2018-05-02)
|
||||||
|
// Author https://stackoverflow.com/users/85371/sehe
|
||||||
|
//
|
||||||
|
// note: delimiter cannot contain NUL characters
|
||||||
|
template <typename Range, typename Value = typename Range::value_type>
|
||||||
|
std::string Join(Range const &elements, const char *const delimiter) {
|
||||||
|
std::ostringstream os;
|
||||||
|
auto b = begin(elements), e = end(elements);
|
||||||
|
|
||||||
|
if (b != e) {
|
||||||
|
std::copy(b, prev(e), std::ostream_iterator<Value>(os, delimiter));
|
||||||
|
b = prev(e);
|
||||||
|
}
|
||||||
|
if (b != e) {
|
||||||
|
os << *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint8_t bip39_shift(size_t bit) {
|
||||||
|
return (1 << (byte_bits - (bit % byte_bits) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
word_list create_mnemonic(data_chunk entropy, const dictionary &lexicon) {
|
||||||
|
if ((entropy.size() % mnemonic_seed_multiple) != 0)
|
||||||
|
return word_list();
|
||||||
|
|
||||||
|
const size_t entropy_bits = (entropy.size() * 8);
|
||||||
|
const size_t check_bits = (entropy_bits / entropy_bit_divisor);
|
||||||
|
const size_t total_bits = (entropy_bits + check_bits);
|
||||||
|
const size_t word_count = (total_bits / bits_per_word);
|
||||||
|
|
||||||
|
// disabled assert
|
||||||
|
// BITCOIN_ASSERT((total_bits % bits_per_word) == 0);
|
||||||
|
// BITCOIN_ASSERT((word_count % mnemonic_word_multiple) == 0);
|
||||||
|
|
||||||
|
// old code for reference:
|
||||||
|
// const auto data = build_chunk({entropy, sha256_hash(entropy)});
|
||||||
|
|
||||||
|
// this does the chunk building without a detour over other libbitcoin types
|
||||||
|
auto data = entropy;
|
||||||
|
auto checksum_bytes = sha256_hash(entropy);
|
||||||
|
// mechanism based on
|
||||||
|
// https://stackoverflow.com/questions/259297/how-do-you-copy-the-contents-of-an-array-to-a-stdvector-in-c-without-looping
|
||||||
|
// CC BY-SA 2.5, author https://stackoverflow.com/users/7405/mattyt
|
||||||
|
// uint8_t array, omit the /1 division since sizeof(uint8_t) == 1 byte
|
||||||
|
data.insert(data.end(), &checksum_bytes[0],
|
||||||
|
&checksum_bytes[checksum_bytes.size()]);
|
||||||
|
|
||||||
|
size_t bit = 0;
|
||||||
|
word_list words;
|
||||||
|
|
||||||
|
for (size_t word = 0; word < word_count; word++) {
|
||||||
|
size_t position = 0;
|
||||||
|
for (size_t loop = 0; loop < bits_per_word; loop++) {
|
||||||
|
bit = (word * bits_per_word + loop);
|
||||||
|
position <<= 1;
|
||||||
|
|
||||||
|
const auto byte = bit / 8;
|
||||||
|
|
||||||
|
if ((data[byte] & bip39_shift(bit)) > 0)
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disabled assert
|
||||||
|
// BITCOIN_ASSERT(position < dictionary_size);
|
||||||
|
words.push_back(lexicon[position]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// disabled assert
|
||||||
|
// BITCOIN_ASSERT(words.size() == ((bit + 1) / bits_per_word));
|
||||||
|
return words;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main_wallet_generation_loop(size_t bit_length,
|
||||||
|
uint32_t rng_target_index_start,
|
||||||
|
uint32_t rng_target_index_end) {
|
||||||
|
|
||||||
|
uint32_t rng_target_index = rng_target_index_start;
|
||||||
|
|
||||||
|
// the distribution is static
|
||||||
|
std::uniform_int_distribution<uint16_t> distribution(0, 255);
|
||||||
|
// this gets re-used during computation, initialized with 0 as dummy
|
||||||
|
std::mt19937 twister(0);
|
||||||
|
|
||||||
|
// as defined in libbitcoin
|
||||||
|
size_t fill_seed_size = bit_length / 8;
|
||||||
|
data_chunk seed(fill_seed_size);
|
||||||
|
|
||||||
|
// hot loop
|
||||||
|
while (true) {
|
||||||
|
// simulate the `bx seed` output for the index in question
|
||||||
|
// one index step represents one nanosecond in the time based PRNG seeding
|
||||||
|
|
||||||
|
// Context: former pseudo_random_fill() start
|
||||||
|
twister.seed(rng_target_index);
|
||||||
|
|
||||||
|
const auto fill = [&distribution, &twister](uint8_t byte) {
|
||||||
|
return static_cast<uint8_t>((distribution)(twister));
|
||||||
|
};
|
||||||
|
|
||||||
|
std::transform(seed.begin(), seed.end(), seed.begin(), fill);
|
||||||
|
// Context: former pseudo_random_fill() end
|
||||||
|
|
||||||
|
// weak "entropy" data used by BIP39
|
||||||
|
// print basic index,entropy CSV to stdout
|
||||||
|
// std::cout << rng_target_index << "," << uint8_vector_to_hex_string(seed)
|
||||||
|
// << "\n";
|
||||||
|
|
||||||
|
// Optimization potential, the Join() is likely too expensive
|
||||||
|
// print basic CSV to stdout:
|
||||||
|
// index,bip39 mnemonic (with spaces)
|
||||||
|
std::cout << rng_target_index << "," << Join(create_mnemonic(seed, en), " ")
|
||||||
|
<< "\n";
|
||||||
|
|
||||||
|
// stop looping if we've hit the goal
|
||||||
|
// reminder: be careful with unsigned integer overflow
|
||||||
|
if (rng_target_index >= rng_target_index_end) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rng_target_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// Note hardcoded English BIP39 wordlist choice
|
||||||
|
// other BIP39 wordlist languages require code changes
|
||||||
|
|
||||||
|
// context:
|
||||||
|
// size_t bit_length = 128; // lowest allowed
|
||||||
|
// size_t bit_length = 192; // bx seed default on 3.2.0
|
||||||
|
// other bit lengths possible but unusual
|
||||||
|
#ifndef BIT_LENGTH
|
||||||
|
#define BIT_LENGTH 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// minimum value 0
|
||||||
|
#ifndef RNG_TARGET_INDEX_START
|
||||||
|
#define RNG_TARGET_INDEX_START 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// maximum value 4294967295
|
||||||
|
#ifndef RNG_TARGET_INDEX_END
|
||||||
|
#define RNG_TARGET_INDEX_END 4294967295
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t bit_length = BIT_LENGTH;
|
||||||
|
uint32_t rng_target_index_start = RNG_TARGET_INDEX_START;
|
||||||
|
uint32_t rng_target_index_end = RNG_TARGET_INDEX_END;
|
||||||
|
|
||||||
|
// print stderr to avoid tainting the main output
|
||||||
|
std::cerr << " Running generation with the following parameters: \n";
|
||||||
|
std::cerr << " bit_length " << bit_length << "\n";
|
||||||
|
std::cerr << " rng_target_index_start " << rng_target_index_start << "\n";
|
||||||
|
std::cerr << " rng_target_index_end " << rng_target_index_end << "\n";
|
||||||
|
|
||||||
|
main_wallet_generation_loop(bit_length, rng_target_index_start,
|
||||||
|
rng_target_index_end);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,281 @@
|
||||||
|
/* libsodium: hash_sha256.c, v0.4.5 2014/04/16 */
|
||||||
|
/**
|
||||||
|
* Copyright 2005,2007,2009 Colin Percival. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#include "sha256.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
// #include "zeroize.h"
|
||||||
|
|
||||||
|
// dummy
|
||||||
|
static void zeroize(void* dummy, size_t dummysize) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t be32dec(const void* pp)
|
||||||
|
{
|
||||||
|
const uint8_t* p = (uint8_t const*)pp;
|
||||||
|
|
||||||
|
return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
|
||||||
|
((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void be32enc(void* pp, uint32_t x)
|
||||||
|
{
|
||||||
|
uint8_t* p = (uint8_t*)pp;
|
||||||
|
|
||||||
|
p[3] = x & 0xff;
|
||||||
|
p[2] = (x >> 8) & 0xff;
|
||||||
|
p[1] = (x >> 16) & 0xff;
|
||||||
|
p[0] = (x >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void be32enc_vect(uint8_t* dst, const uint32_t* src, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < len / 4; i++)
|
||||||
|
{
|
||||||
|
be32enc(dst + i * 4, src[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void be32dec_vect(uint32_t* dst, const uint8_t* src, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < len / 4; i++)
|
||||||
|
{
|
||||||
|
dst[i] = be32dec(src + i * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
|
||||||
|
#define Maj(x, y, z) ((x & (y | z)) | (y & z))
|
||||||
|
#define SHR(x, n) (x >> n)
|
||||||
|
#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
|
||||||
|
#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||||
|
#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||||
|
#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
|
||||||
|
#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
|
||||||
|
|
||||||
|
#define RND(a, b, c, d, e, f, g, h, k) \
|
||||||
|
t0 = h + S1(e) + Ch(e, f, g) + k; \
|
||||||
|
t1 = S0(a) + Maj(a, b, c); \
|
||||||
|
d += t0; \
|
||||||
|
h = t0 + t1;
|
||||||
|
|
||||||
|
#define RNDr(S, W, i, k) \
|
||||||
|
RND(S[(64 - i) % 8], S[(65 - i) % 8], \
|
||||||
|
S[(66 - i) % 8], S[(67 - i) % 8], \
|
||||||
|
S[(68 - i) % 8], S[(69 - i) % 8], \
|
||||||
|
S[(70 - i) % 8], S[(71 - i) % 8], \
|
||||||
|
W[i] + k)
|
||||||
|
|
||||||
|
static unsigned char PAD[SHA256_BLOCK_LENGTH] =
|
||||||
|
{
|
||||||
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
void SHA256Pad(SHA256CTX* context);
|
||||||
|
void SHA256Transform(uint32_t state[SHA256_STATE_LENGTH],
|
||||||
|
const uint8_t block[SHA256_BLOCK_LENGTH]);
|
||||||
|
|
||||||
|
void SHA256_(const uint8_t* input, size_t length,
|
||||||
|
uint8_t digest[SHA256_DIGEST_LENGTH])
|
||||||
|
{
|
||||||
|
SHA256CTX context;
|
||||||
|
SHA256Init(&context);
|
||||||
|
SHA256Update(&context, input, length);
|
||||||
|
SHA256Final(&context, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA256Init(SHA256CTX* context)
|
||||||
|
{
|
||||||
|
context->count[0] = context->count[1] = 0;
|
||||||
|
|
||||||
|
context->state[0] = 0x6A09E667;
|
||||||
|
context->state[1] = 0xBB67AE85;
|
||||||
|
context->state[2] = 0x3C6EF372;
|
||||||
|
context->state[3] = 0xA54FF53A;
|
||||||
|
context->state[4] = 0x510E527F;
|
||||||
|
context->state[5] = 0x9B05688C;
|
||||||
|
context->state[6] = 0x1F83D9AB;
|
||||||
|
context->state[7] = 0x5BE0CD19;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA256Update(SHA256CTX* context, const uint8_t* input, size_t length)
|
||||||
|
{
|
||||||
|
uint32_t bitlen[2];
|
||||||
|
uint32_t r = (context->count[1] >> 3) & 0x3f;
|
||||||
|
|
||||||
|
bitlen[1] = ((uint32_t)length) << 3;
|
||||||
|
bitlen[0] = (uint32_t)(length >> 29);
|
||||||
|
|
||||||
|
if ((context->count[1] += bitlen[1]) < bitlen[1])
|
||||||
|
{
|
||||||
|
context->count[0]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->count[0] += bitlen[0];
|
||||||
|
|
||||||
|
if (length < 64 - r)
|
||||||
|
{
|
||||||
|
memcpy(&context->buf[r], input, length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&context->buf[r], input, 64 - r);
|
||||||
|
SHA256Transform(context->state, context->buf);
|
||||||
|
|
||||||
|
input += 64 - r;
|
||||||
|
length -= 64 - r;
|
||||||
|
|
||||||
|
while (length >= 64)
|
||||||
|
{
|
||||||
|
SHA256Transform(context->state, input);
|
||||||
|
input += 64;
|
||||||
|
length -= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(context->buf, input, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA256Final(SHA256CTX* context, uint8_t digest[SHA256_DIGEST_LENGTH])
|
||||||
|
{
|
||||||
|
SHA256Pad(context);
|
||||||
|
be32enc_vect(digest, context->state, SHA256_DIGEST_LENGTH);
|
||||||
|
zeroize((void*)context, sizeof *context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Local */
|
||||||
|
|
||||||
|
void SHA256Pad(SHA256CTX* context)
|
||||||
|
{
|
||||||
|
uint8_t len[8];
|
||||||
|
uint32_t r, plen;
|
||||||
|
|
||||||
|
be32enc_vect(len, context->count, 8);
|
||||||
|
|
||||||
|
r = (context->count[1] >> 3) & 0x3f;
|
||||||
|
plen = (r < 56) ? (56 - r) : (120 - r);
|
||||||
|
|
||||||
|
SHA256Update(context, PAD, plen);
|
||||||
|
SHA256Update(context, len, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHA256Transform(uint32_t state[SHA256_STATE_LENGTH],
|
||||||
|
const uint8_t block[SHA256_BLOCK_LENGTH])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t W[64];
|
||||||
|
uint32_t S[8];
|
||||||
|
uint32_t t0, t1;
|
||||||
|
|
||||||
|
be32dec_vect(W, block, SHA256_BLOCK_LENGTH);
|
||||||
|
|
||||||
|
for (i = 16; i < 64; i++)
|
||||||
|
{
|
||||||
|
W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(S, state, 32);
|
||||||
|
|
||||||
|
RNDr(S, W, 0, 0x428a2f98);
|
||||||
|
RNDr(S, W, 1, 0x71374491);
|
||||||
|
RNDr(S, W, 2, 0xb5c0fbcf);
|
||||||
|
RNDr(S, W, 3, 0xe9b5dba5);
|
||||||
|
RNDr(S, W, 4, 0x3956c25b);
|
||||||
|
RNDr(S, W, 5, 0x59f111f1);
|
||||||
|
RNDr(S, W, 6, 0x923f82a4);
|
||||||
|
RNDr(S, W, 7, 0xab1c5ed5);
|
||||||
|
RNDr(S, W, 8, 0xd807aa98);
|
||||||
|
RNDr(S, W, 9, 0x12835b01);
|
||||||
|
RNDr(S, W, 10, 0x243185be);
|
||||||
|
RNDr(S, W, 11, 0x550c7dc3);
|
||||||
|
RNDr(S, W, 12, 0x72be5d74);
|
||||||
|
RNDr(S, W, 13, 0x80deb1fe);
|
||||||
|
RNDr(S, W, 14, 0x9bdc06a7);
|
||||||
|
RNDr(S, W, 15, 0xc19bf174);
|
||||||
|
RNDr(S, W, 16, 0xe49b69c1);
|
||||||
|
RNDr(S, W, 17, 0xefbe4786);
|
||||||
|
RNDr(S, W, 18, 0x0fc19dc6);
|
||||||
|
RNDr(S, W, 19, 0x240ca1cc);
|
||||||
|
RNDr(S, W, 20, 0x2de92c6f);
|
||||||
|
RNDr(S, W, 21, 0x4a7484aa);
|
||||||
|
RNDr(S, W, 22, 0x5cb0a9dc);
|
||||||
|
RNDr(S, W, 23, 0x76f988da);
|
||||||
|
RNDr(S, W, 24, 0x983e5152);
|
||||||
|
RNDr(S, W, 25, 0xa831c66d);
|
||||||
|
RNDr(S, W, 26, 0xb00327c8);
|
||||||
|
RNDr(S, W, 27, 0xbf597fc7);
|
||||||
|
RNDr(S, W, 28, 0xc6e00bf3);
|
||||||
|
RNDr(S, W, 29, 0xd5a79147);
|
||||||
|
RNDr(S, W, 30, 0x06ca6351);
|
||||||
|
RNDr(S, W, 31, 0x14292967);
|
||||||
|
RNDr(S, W, 32, 0x27b70a85);
|
||||||
|
RNDr(S, W, 33, 0x2e1b2138);
|
||||||
|
RNDr(S, W, 34, 0x4d2c6dfc);
|
||||||
|
RNDr(S, W, 35, 0x53380d13);
|
||||||
|
RNDr(S, W, 36, 0x650a7354);
|
||||||
|
RNDr(S, W, 37, 0x766a0abb);
|
||||||
|
RNDr(S, W, 38, 0x81c2c92e);
|
||||||
|
RNDr(S, W, 39, 0x92722c85);
|
||||||
|
RNDr(S, W, 40, 0xa2bfe8a1);
|
||||||
|
RNDr(S, W, 41, 0xa81a664b);
|
||||||
|
RNDr(S, W, 42, 0xc24b8b70);
|
||||||
|
RNDr(S, W, 43, 0xc76c51a3);
|
||||||
|
RNDr(S, W, 44, 0xd192e819);
|
||||||
|
RNDr(S, W, 45, 0xd6990624);
|
||||||
|
RNDr(S, W, 46, 0xf40e3585);
|
||||||
|
RNDr(S, W, 47, 0x106aa070);
|
||||||
|
RNDr(S, W, 48, 0x19a4c116);
|
||||||
|
RNDr(S, W, 49, 0x1e376c08);
|
||||||
|
RNDr(S, W, 50, 0x2748774c);
|
||||||
|
RNDr(S, W, 51, 0x34b0bcb5);
|
||||||
|
RNDr(S, W, 52, 0x391c0cb3);
|
||||||
|
RNDr(S, W, 53, 0x4ed8aa4a);
|
||||||
|
RNDr(S, W, 54, 0x5b9cca4f);
|
||||||
|
RNDr(S, W, 55, 0x682e6ff3);
|
||||||
|
RNDr(S, W, 56, 0x748f82ee);
|
||||||
|
RNDr(S, W, 57, 0x78a5636f);
|
||||||
|
RNDr(S, W, 58, 0x84c87814);
|
||||||
|
RNDr(S, W, 59, 0x8cc70208);
|
||||||
|
RNDr(S, W, 60, 0x90befffa);
|
||||||
|
RNDr(S, W, 61, 0xa4506ceb);
|
||||||
|
RNDr(S, W, 62, 0xbef9a3f7);
|
||||||
|
RNDr(S, W, 63, 0xc67178f2);
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
state[i] += S[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
zeroize((void*)W, sizeof W);
|
||||||
|
zeroize((void*)S, sizeof S);
|
||||||
|
zeroize((void*)&t0, sizeof t0);
|
||||||
|
zeroize((void*)&t1, sizeof t1);
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/* libsodium: crypto_hash_sha256.h, v0.4.5 2014/04/16 */
|
||||||
|
/**
|
||||||
|
* Copyright 2005,2007,2009 Colin Percival. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
#ifndef LIBBITCOIN_SHA256_H
|
||||||
|
#define LIBBITCOIN_SHA256_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define SHA256_STATE_LENGTH 8U
|
||||||
|
#define SHA256_COUNT_LENGTH 2U
|
||||||
|
#define SHA256_BLOCK_LENGTH 64U
|
||||||
|
#define SHA256_DIGEST_LENGTH 32U
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct SHA256CTX
|
||||||
|
{
|
||||||
|
uint32_t state[SHA256_STATE_LENGTH];
|
||||||
|
uint32_t count[SHA256_COUNT_LENGTH];
|
||||||
|
uint8_t buf[SHA256_BLOCK_LENGTH];
|
||||||
|
} SHA256CTX;
|
||||||
|
|
||||||
|
void SHA256_(const uint8_t* input, size_t length,
|
||||||
|
uint8_t digest[SHA256_DIGEST_LENGTH]);
|
||||||
|
|
||||||
|
void SHA256Init(SHA256CTX* context);
|
||||||
|
void SHA256Update(SHA256CTX* context, const uint8_t* input, size_t length);
|
||||||
|
void SHA256Final(SHA256CTX* context, uint8_t digest[SHA256_DIGEST_LENGTH]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue