Skip to main content

max / makenotwork

19.4 KB · 237 lines History Blame Raw
1 //! Curated wordlist for license key generation.
2 //!
3 //! 2048 short common English words (3-6 letters), no offensive or confusable terms.
4 //! Each key picks 6 random words from this list (~66 bits of entropy), see
5 //! the birthday-collision rationale in `crypto.rs`.
6
7 pub static WORDLIST: [&str; 2048] = [
8 "ace", "acid", "acme", "acorn", "acre", "act", "add", "adept", "admit", "adopt", "adult",
9 "afar", "aged", "agent", "agile", "aging", "agree", "ahead", "aid", "aim", "air", "aisle",
10 "alarm", "album", "alert", "algae", "align", "alive", "alley", "allot", "allow", "alloy",
11 "aloft", "along", "aloof", "alpha", "alter", "amaze", "amber", "ample", "amuse", "angel",
12 "anger", "angle", "ankle", "annex", "anvil", "apart", "apex", "apple", "apply", "apron",
13 "aqua", "arbor", "arch", "arena", "argue", "arise", "armor", "aroma", "array", "arrow", "art",
14 "ash", "aside", "ask", "asset", "atom", "attic", "audio", "audit", "auto", "avid", "avoid",
15 "await", "awake", "award", "aware", "axis", "azure", "bacon", "badge", "badly", "bagel",
16 "bake", "baker", "balm", "ban", "band", "banjo", "bank", "barn", "baron", "base", "basic",
17 "basin", "basis", "batch", "bath", "bay", "beach", "bead", "beam", "bean", "bear", "beard",
18 "beast", "beat", "bed", "beech", "beef", "beer", "begin", "being", "bell", "belly", "below",
19 "belt", "bench", "bend", "bent", "berry", "best", "bid", "bike", "bill", "bind", "birch",
20 "bird", "birth", "bit", "bite", "black", "blade", "blame", "bland", "blank", "blast", "blaze",
21 "bleak", "bleed", "blend", "bless", "blind", "blink", "bliss", "block", "blond", "bloom",
22 "blown", "blue", "bluff", "blunt", "blur", "blurt", "blush", "board", "boat", "body", "bold",
23 "bolt", "bond", "bone", "bonus", "book", "boost", "boot", "booth", "born", "bound", "bow",
24 "bowl", "box", "brace", "braid", "brain", "brake", "brand", "brass", "brave", "bread", "break",
25 "bred", "breed", "brick", "bride", "brief", "brim", "bring", "brink", "brisk", "broad",
26 "broil", "broke", "brook", "broth", "brown", "brush", "buck", "buddy", "budge", "bug", "build",
27 "built", "bulge", "bulk", "bunch", "buoy", "burn", "burst", "bus", "bush", "busy", "buyer",
28 "cabin", "cable", "cache", "cadet", "cafe", "cage", "cake", "calm", "camel", "camp", "canal",
29 "candy", "cane", "canon", "cape", "car", "card", "cargo", "carry", "cart", "carve", "case",
30 "cash", "cast", "catch", "cater", "cause", "cave", "cease", "cedar", "cell", "cent", "chain",
31 "chair", "chalk", "champ", "chant", "chaos", "charm", "chart", "chase", "cheap", "check",
32 "cheek", "cheer", "chess", "chest", "chew", "chief", "child", "chill", "chime", "chin", "chip",
33 "choir", "chop", "chord", "chore", "chunk", "churn", "cider", "cigar", "cinch", "circa",
34 "cite", "city", "civic", "civil", "claim", "clam", "clamp", "clap", "clash", "clasp", "class",
35 "claw", "clay", "clean", "clear", "clerk", "click", "cliff", "climb", "cling", "clip", "cloak",
36 "clock", "clone", "close", "cloth", "cloud", "clout", "club", "clue", "clump", "coach", "coal",
37 "coast", "coat", "cocoa", "code", "coil", "coin", "cold", "comet", "comic", "comma", "cone",
38 "cook", "cool", "cope", "copy", "coral", "cord", "core", "cork", "corn", "cosy", "couch",
39 "count", "court", "cover", "cozy", "craft", "crane", "crash", "crate", "crawl", "crazy",
40 "creak", "cream", "creek", "creep", "crew", "crisp", "crop", "cross", "crowd", "crown",
41 "crude", "crush", "crust", "cube", "cup", "curb", "cure", "curl", "curve", "cycle", "daily",
42 "dairy", "daisy", "dance", "dare", "dark", "darts", "dash", "data", "date", "dawn", "deal",
43 "dear", "decay", "deck", "decor", "decoy", "deed", "deep", "deer", "delay", "delta", "delve",
44 "demon", "den", "denim", "dense", "deny", "depot", "depth", "derby", "desk", "deter", "detox",
45 "deuce", "dew", "dial", "diary", "dice", "dig", "dim", "dine", "dip", "dirt", "disc", "dish",
46 "ditch", "dive", "dizzy", "dock", "dodge", "doe", "dome", "donor", "donut", "door", "dose",
47 "dot", "doubt", "dough", "dove", "down", "dozen", "draft", "drain", "drake", "drama", "drape",
48 "draw", "drawn", "dream", "dress", "dried", "drift", "drill", "drink", "drive", "drone",
49 "drop", "drove", "drum", "dry", "dual", "duck", "duet", "duke", "dull", "dune", "duo", "dusk",
50 "dust", "dusty", "duty", "dwell", "dyer", "eager", "eagle", "ear", "early", "earn", "earth",
51 "ease", "east", "eaten", "eater", "eave", "ebony", "echo", "edge", "edit", "eel", "eight",
52 "elect", "elite", "elm", "ember", "emit", "empty", "end", "endow", "enemy", "enjoy", "enter",
53 "entry", "envoy", "epic", "equal", "equip", "era", "erase", "error", "erupt", "essay", "ethic",
54 "euro", "eve", "even", "event", "ever", "evict", "evoke", "exact", "exam", "exalt", "excel",
55 "exile", "exist", "exit", "extra", "exult", "eye", "fable", "face", "facet", "fact", "fade",
56 "faint", "fair", "fairy", "faith", "fake", "fall", "fame", "fan", "fancy", "fang", "far",
57 "farm", "fast", "fate", "fauna", "favor", "feast", "feat", "feed", "feel", "fence", "fend",
58 "fern", "ferry", "fest", "fetch", "fever", "few", "fiber", "field", "fig", "file", "fill",
59 "film", "final", "finch", "find", "fine", "fire", "firm", "first", "fish", "fit", "five",
60 "fix", "flag", "flail", "flair", "flake", "flame", "flank", "flap", "flare", "flash", "flask",
61 "flat", "flaw", "flax", "fled", "flee", "fleet", "flesh", "flex", "flick", "fling", "flint",
62 "flip", "float", "flock", "flood", "floor", "flora", "flour", "flow", "flown", "fluff",
63 "fluid", "fluke", "flunk", "flush", "flute", "fly", "foam", "focal", "focus", "fog", "foil",
64 "fold", "folk", "fond", "font", "food", "foot", "forge", "fork", "form", "fort", "forth",
65 "forum", "found", "four", "fowl", "fox", "foyer", "frame", "frank", "freed", "fresh", "frog",
66 "front", "frost", "froze", "fruit", "fuel", "full", "fully", "fun", "fund", "fungi", "funny",
67 "fur", "fury", "fuse", "fussy", "fuzzy", "gain", "gala", "gale", "game", "gamma", "gap",
68 "gape", "gas", "gate", "gauge", "gave", "gavel", "gaze", "gear", "gem", "gene", "genre",
69 "gift", "gild", "gin", "given", "glad", "gland", "glare", "glass", "glaze", "gleam", "glee",
70 "glide", "globe", "gloom", "glory", "gloss", "glove", "glow", "glue", "goat", "gold", "golf",
71 "goose", "gorge", "gown", "grab", "grace", "grade", "grain", "grand", "grant", "grape",
72 "graph", "grasp", "grass", "grave", "gravy", "gray", "graze", "great", "greed", "green",
73 "greet", "grew", "grey", "grief", "grill", "grim", "grin", "grind", "grip", "groan", "groom",
74 "grove", "grow", "grown", "guard", "guess", "guest", "guide", "guild", "guilt", "guise",
75 "gulp", "gum", "guru", "gust", "gut", "gym", "habit", "half", "hall", "halt", "hand", "handy",
76 "hang", "happy", "hard", "harm", "harp", "harsh", "haste", "hasty", "hat", "hatch", "haunt",
77 "haven", "hawk", "hay", "hazel", "head", "heal", "heap", "heart", "heat", "heavy", "hedge",
78 "heel", "held", "helm", "help", "hence", "herb", "herd", "hero", "heron", "hide", "high",
79 "hike", "hill", "hilly", "hinge", "hint", "hip", "hire", "hive", "hobby", "hoist", "hold",
80 "hole", "holly", "home", "honey", "hood", "hook", "hope", "horn", "horse", "host", "hotel",
81 "hound", "hour", "house", "hover", "hub", "huge", "hull", "human", "humid", "humor", "hunt",
82 "hurry", "hut", "hymn", "ice", "icing", "icon", "idea", "ideal", "idiom", "idle", "idly",
83 "image", "imp", "imply", "inbox", "inch", "index", "indie", "infer", "ink", "inlet", "inn",
84 "inner", "input", "ion", "iris", "iron", "isle", "issue", "item", "ivory", "ivy", "jab",
85 "jack", "jade", "jam", "jar", "jaw", "jazz", "jean", "jelly", "jet", "jewel", "jig", "job",
86 "jog", "join", "joint", "joke", "jolly", "jolt", "joy", "judge", "jug", "juice", "juicy",
87 "jump", "karma", "kayak", "keen", "keep", "kept", "key", "kick", "kid", "kind", "king",
88 "kiosk", "kit", "kite", "knack", "knead", "knee", "kneel", "knelt", "knife", "knit", "knob",
89 "knock", "knoll", "knot", "known", "koala", "lace", "lack", "lad", "laden", "lake", "lamb",
90 "lamp", "land", "lane", "lap", "lapse", "large", "laser", "lash", "last", "latch", "late",
91 "later", "lathe", "latte", "laugh", "lava", "lawn", "lay", "layer", "lead", "leaf", "leak",
92 "lean", "leap", "learn", "lease", "least", "ledge", "left", "legal", "lemon", "lend", "lens",
93 "lent", "level", "lever", "lid", "life", "lift", "light", "lilac", "lily", "limb", "lime",
94 "limit", "limp", "line", "linen", "liner", "link", "lint", "lion", "lip", "list", "liter",
95 "live", "liver", "llama", "load", "loaf", "loan", "lobby", "local", "lock", "lodge", "loft",
96 "lofty", "log", "logic", "logo", "lone", "long", "look", "loom", "loop", "loose", "lord",
97 "loss", "lost", "lot", "loud", "love", "lover", "low", "lower", "loyal", "luck", "lucky",
98 "lug", "lunar", "lunch", "lure", "lurk", "lush", "lyric", "mace", "macro", "made", "magic",
99 "maid", "mail", "main", "major", "maker", "malt", "mane", "mango", "manor", "map", "maple",
100 "march", "mare", "mark", "marsh", "mask", "mason", "mass", "mast", "match", "mate", "math",
101 "mayor", "maze", "mead", "meal", "mean", "meant", "media", "medic", "meet", "melon", "melt",
102 "memo", "mend", "menu", "mercy", "merge", "merit", "merry", "mesh", "messy", "metal", "meter",
103 "mice", "mid", "might", "mild", "mile", "milk", "mill", "mimic", "mind", "mine", "miner",
104 "minor", "mint", "minus", "mist", "misty", "mite", "mix", "mixer", "moan", "moat", "mock",
105 "model", "moist", "mold", "mole", "money", "month", "mood", "moon", "moose", "mop", "moral",
106 "moss", "motel", "moth", "motor", "motto", "mound", "mount", "mouse", "mouth", "move", "movie",
107 "mud", "muddy", "mug", "mulch", "mule", "mural", "murky", "music", "mute", "myth", "nail",
108 "name", "nap", "nasal", "naval", "near", "neat", "neck", "need", "nerve", "nest", "net",
109 "never", "new", "newly", "next", "nice", "niche", "night", "nine", "noble", "nod", "noise",
110 "nook", "noon", "norm", "north", "nose", "notch", "note", "noun", "novel", "nudge", "nurse",
111 "nut", "nylon", "oak", "oar", "oasis", "oat", "ocean", "odd", "odds", "offer", "oil", "oily",
112 "old", "olive", "omega", "omen", "once", "onset", "ooze", "open", "opera", "optic", "orbit",
113 "order", "ore", "organ", "other", "otter", "ought", "ounce", "outer", "oval", "oven", "over",
114 "own", "owner", "oxide", "ozone", "pace", "pack", "pad", "page", "paid", "pail", "pain",
115 "paint", "pair", "palm", "pan", "panda", "panel", "panic", "paper", "park", "party", "pass",
116 "past", "paste", "patch", "path", "patio", "pause", "pave", "paw", "pay", "peace", "peach",
117 "peak", "pear", "pearl", "pecan", "pedal", "peek", "peel", "pen", "penny", "perch", "peril",
118 "perk", "perky", "petal", "phase", "phone", "photo", "piano", "pick", "pie", "piece", "pier",
119 "pig", "pike", "pile", "pilot", "pin", "pine", "pink", "pinky", "pint", "pipe", "pit", "pitch",
120 "pixel", "pizza", "place", "plaid", "plain", "plan", "plane", "plank", "plant", "plate",
121 "plaza", "plead", "pleat", "plier", "plot", "ploy", "pluck", "plug", "plum", "plumb", "plume",
122 "plump", "plunk", "plus", "plush", "pod", "poem", "poet", "point", "poise", "poker", "polar",
123 "pole", "poll", "polo", "pond", "pool", "pop", "poppy", "porch", "pork", "port", "pose",
124 "poser", "post", "pouch", "pound", "pour", "power", "pray", "press", "prey", "price", "pride",
125 "prime", "print", "prior", "prism", "privy", "prize", "probe", "prong", "proof", "prop",
126 "prose", "proud", "prove", "prowl", "prune", "pub", "pull", "pulp", "pulse", "pump", "punch",
127 "pupil", "puppy", "pure", "purge", "purse", "push", "putty", "quack", "quad", "quake", "qualm",
128 "queen", "query", "quest", "queue", "quick", "quiet", "quill", "quilt", "quirk", "quit",
129 "quite", "quiz", "quota", "quote", "race", "rack", "radar", "radio", "raft", "rage", "raid",
130 "rail", "rain", "rainy", "raise", "rally", "ramp", "ranch", "range", "rank", "rapid", "rare",
131 "rate", "ratio", "raven", "raw", "ray", "razor", "reach", "react", "read", "ready", "real",
132 "realm", "reap", "rear", "rebel", "recap", "red", "reed", "reef", "reel", "reign", "relay",
133 "relic", "rely", "renew", "rent", "repay", "reply", "reset", "resin", "rest", "retro", "reuse",
134 "revel", "rhyme", "rib", "rice", "rich", "ride", "rider", "ridge", "rifle", "right", "rigid",
135 "rim", "rinse", "riot", "ripe", "rise", "risen", "risk", "risky", "rival", "river", "rivet",
136 "road", "roam", "roar", "roast", "robe", "robin", "robot", "rock", "rocky", "rod", "rode",
137 "rogue", "role", "roll", "roof", "room", "roomy", "root", "rope", "rose", "rosy", "round",
138 "route", "rover", "row", "royal", "ruby", "rug", "ruin", "rule", "ruler", "run", "rung",
139 "rural", "rush", "rust", "rut", "sack", "sad", "sadly", "safe", "sage", "sail", "saint",
140 "sake", "salad", "sale", "salon", "salt", "salty", "salve", "sand", "sandy", "sane", "sap",
141 "sash", "sauna", "save", "savor", "saw", "say", "scale", "scan", "scar", "scare", "scarf",
142 "scene", "scent", "scope", "score", "scout", "scowl", "sea", "seal", "seam", "seat", "seed",
143 "self", "sell", "send", "sense", "sent", "serve", "set", "seven", "shade", "shady", "shaft",
144 "shake", "shame", "shape", "shard", "share", "shark", "sharp", "shave", "shawl", "shed",
145 "sheen", "sheep", "sheer", "sheet", "shelf", "shell", "shift", "shine", "shiny", "ship",
146 "shirt", "shock", "shoe", "shook", "shoot", "shop", "shore", "short", "shot", "shout", "shove",
147 "show", "shown", "shrub", "shrug", "shut", "shy", "side", "siege", "sift", "sigh", "sight",
148 "sigma", "sign", "silk", "silky", "silo", "sing", "sink", "sip", "siren", "sit", "site",
149 "sixth", "sixty", "size", "skate", "ski", "skill", "skin", "skip", "skirt", "skull", "sky",
150 "slab", "slam", "slant", "slap", "slash", "slate", "sled", "sleek", "sleep", "sleet", "slept",
151 "slice", "slide", "slim", "slime", "sling", "slip", "slit", "slope", "slot", "slow", "slug",
152 "slump", "small", "smart", "smash", "smell", "smile", "smirk", "smith", "smog", "smoke",
153 "smoky", "snack", "snag", "snail", "snake", "snap", "snare", "sneak", "snow", "snowy", "snug",
154 "soak", "soap", "soar", "sober", "sock", "soda", "sofa", "soft", "soil", "solar", "sold",
155 "sole", "solid", "solo", "solve", "song", "soon", "sort", "soul", "sound", "soup", "sour",
156 "south", "sow", "space", "spade", "span", "spare", "spark", "speak", "spear", "spec", "speed",
157 "spell", "spend", "spent", "spice", "spicy", "spike", "spill", "spin", "spine", "spoke",
158 "spoon", "sport", "spot", "spray", "spree", "spy", "squad", "squid", "stack", "staff", "stage",
159 "stain", "stair", "stake", "stale", "stalk", "stall", "stamp", "stand", "star", "stare",
160 "start", "state", "stay", "steak", "steal", "steam", "steel", "steep", "steer", "stem", "step",
161 "stern", "stew", "stick", "stiff", "still", "sting", "stint", "stir", "stock", "stoke",
162 "stole", "stomp", "stone", "stool", "stop", "store", "stork", "storm", "story", "stout",
163 "stove", "stow", "strap", "straw", "stray", "strip", "strum", "strut", "stub", "stuck",
164 "study", "stuff", "stump", "stun", "stung", "stunt", "style", "sugar", "suit", "suite", "sulk",
165 "sum", "sunny", "super", "surf", "surge", "swamp", "swan", "swap", "swarm", "sway", "swear",
166 "sweat", "sweep", "sweet", "swell", "swept", "swift", "swim", "swing", "swipe", "swirl",
167 "sword", "syrup", "table", "tack", "tag", "tail", "take", "taken", "tale", "talk", "tall",
168 "tally", "talon", "tank", "tap", "tape", "tart", "task", "taste", "tasty", "tax", "tea",
169 "teach", "teal", "team", "tear", "teen", "tell", "tempo", "tend", "tense", "tent", "tenth",
170 "term", "test", "text", "thank", "thick", "thief", "thigh", "thin", "thing", "think", "third",
171 "thorn", "three", "threw", "throw", "thud", "thumb", "tide", "tidy", "tie", "tied", "tiger",
172 "tight", "tile", "till", "tilt", "time", "timer", "timid", "tin", "tiny", "tip", "tire",
173 "tired", "title", "toad", "toast", "today", "toe", "token", "toll", "tone", "tonic", "tool",
174 "tooth", "top", "topic", "torch", "torn", "total", "touch", "tough", "tour", "towel", "tower",
175 "town", "toxic", "trace", "track", "trade", "trail", "train", "trait", "trap", "trash", "tray",
176 "treat", "tree", "trend", "trial", "tribe", "trick", "tried", "trim", "trio", "trip", "troll",
177 "troop", "trot", "trout", "truck", "true", "truly", "trunk", "trust", "truth", "try", "tub",
178 "tube", "tuck", "tulip", "tuna", "tune", "turf", "turn", "tutor", "twig", "twin", "twirl",
179 "twist", "type", "ultra", "uncle", "under", "unfit", "union", "unite", "unity", "until",
180 "upper", "upset", "urban", "urge", "usage", "use", "user", "usual", "utter", "vague", "vain",
181 "valid", "value", "valve", "van", "vapor", "vast", "vault", "vegan", "veil", "vein", "verse",
182 "vest", "veto", "video", "view", "vigor", "vine", "vinyl", "viola", "viral", "visit", "visor",
183 "vista", "vital", "vivid", "vocal", "vodka", "voice", "void", "volt", "voter", "vouch", "vow",
184 "vowel", "wade", "wag", "wage", "wagon", "waist", "wait", "wake", "walk", "wall", "wand",
185 "want", "ward", "warm", "warn", "warp", "wash", "wasp", "waste", "watch", "water", "wave",
186 "wavy", "wax", "way", "weak", "wear", "weary", "weave", "web", "wed", "wedge", "weed", "week",
187 "weigh", "weird", "well", "west", "wet", "whale", "wheat", "wheel", "whim", "whip", "whirl",
188 "white", "whole", "wide", "widen", "width", "wield", "wild", "win", "wind", "wine", "wing",
189 "wink", "wire", "wired", "wise", "wish", "wit", "witch", "wolf", "won", "wood", "woody",
190 "wool", "word", "work", "world", "worm", "worry", "worth", "wound", "woven", "wrap", "wren",
191 "wrist", "write", "wrong", "yacht", "yard", "yarn", "year", "yeast", "yield", "yoga", "young",
192 "youth", "zeal", "zebra", "zen", "zero", "zest", "zinc", "zone", "zoom", "afoot", "aglow",
193 "amble", "antic", "balmy", "blimp", "burly", "caulk", "chasm", "crypt", "ditto", "dwarf",
194 "elfin", "feint", "filth", "fjord", "glyph", "grimy", "hyper", "jiffy", "nifty", "rowdy",
195 "terse", "topaz", "agave", "bijou", "coypu", "dryly", "ether", "gauze", "husky", "ingot",
196 "jaunt", "kefir", "lemur", "pixie",
197 ];
198
199 #[cfg(test)]
200 mod tests {
201 use super::WORDLIST;
202 use std::collections::HashSet;
203
204 /// The ~66-bit entropy claim (6 words from 2048 => 2048^6 == 2^66) holds
205 /// only if the words are distinct: a duplicate shrinks the effective pool
206 /// and biases key generation. Pin uniqueness so an accidental copy-paste
207 /// during a future edit fails the build rather than silently weakening keys.
208 #[test]
209 fn wordlist_entries_are_unique() {
210 let mut seen = HashSet::with_capacity(WORDLIST.len());
211 for w in WORDLIST {
212 assert!(seen.insert(w), "duplicate word in WORDLIST: {w:?}");
213 }
214 assert_eq!(seen.len(), WORDLIST.len());
215 }
216
217 /// Guard the pool size the entropy math depends on. A power of two also
218 /// keeps index selection unbiased (2048 divides the u16 space evenly).
219 #[test]
220 fn wordlist_is_exactly_2048_words() {
221 assert_eq!(WORDLIST.len(), 2048);
222 }
223
224 /// Words must be lowercase ASCII with no whitespace/punctuation so keys are
225 /// unambiguous to read back and type. Also rejects the empty string.
226 #[test]
227 fn wordlist_entries_are_lowercase_ascii() {
228 for w in WORDLIST {
229 assert!(!w.is_empty(), "empty word in WORDLIST");
230 assert!(
231 w.chars().all(|c| c.is_ascii_lowercase()),
232 "non-lowercase-ascii word in WORDLIST: {w:?}"
233 );
234 }
235 }
236 }
237