0f3f0e36bc4a

replace the word list that duplicated abandon at index 1 with the browser's canonical 2048, so the same vault stops printing different recovery words on each platform, and decode old phrases through a legacy fallback (v2.4.13)

time
2026-07-26 14:22 UTC · 3 months ago
machine
koh2
agent
claude-opus-5
session
recovery word divergence
parent
8d5c5d9501a7
6 files VERSION+1 −1app/build.gradle+2 −2app/src/main/java/com/peachpasswords/vault/RecoveryWordList.kt+534 −2049app/src/main/java/com/peachpasswords/vault/RecoveryWords.kt+30 −22app/src/test/java/com/peachpasswords/vault/CrossPlatformRecoveryWordsTest.kt+87 −0app/src/test/java/com/peachpasswords/vault/RecoveryEscrowTest.kt+9 −2
VERSION+1 −1
@@ -1 +1 @@1-2.4.121+2.4.13

view file

app/build.gradle+2 −2
@@ -16,8 +16,8 @@1616         applicationId "com.peachpasswords"1717         minSdk 261818         targetSdk 3519-        versionCode 24001220-        versionName "2.4.12"19+        versionCode 24001320+        versionName "2.4.13"2121 2222         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"2323         vectorDrawables {

view file

app/src/main/java/com/peachpasswords/vault/RecoveryWordList.kt+534 −2049
@@ -1,2053 +1,538 @@11 package com.peachpasswords.vault22 3-val WORD_LIST: List<String> = listOf(4-    "abandon",5-    "abandon",6-    "ability",7-    "able",8-    "about",9-    "above",10-    "absent",11-    "absorb",12-    "abstract",13-    "absurd",14-    "abuse",15-    "access",16-    "accident",17-    "account",18-    "accuse",19-    "achieve",20-    "acid",21-    "acoustic",22-    "acquire",23-    "across",24-    "act",25-    "action",26-    "actor",27-    "actress",28-    "actual",29-    "adapt",30-    "add",31-    "addict",32-    "address",33-    "adjust",34-    "admit",35-    "adult",36-    "advance",37-    "advice",38-    "aerobic",39-    "affair",40-    "afford",41-    "afraid",42-    "again",43-    "age",44-    "agent",45-    "agree",46-    "ahead",47-    "aim",48-    "air",49-    "airport",50-    "aisle",51-    "alarm",52-    "album",53-    "alcohol",54-    "alert",55-    "alien",56-    "all",57-    "alley",58-    "allow",59-    "almost",60-    "alone",61-    "alpha",62-    "already",63-    "also",64-    "alter",65-    "always",66-    "amateur",67-    "amazing",68-    "among",69-    "amount",70-    "amused",71-    "analyst",72-    "anchor",73-    "ancient",74-    "anger",75-    "angle",76-    "angry",77-    "animal",78-    "ankle",79-    "announce",80-    "annual",81-    "another",82-    "answer",83-    "antenna",84-    "antique",85-    "anxiety",86-    "any",87-    "apart",88-    "apology",89-    "appear",90-    "apple",91-    "approve",92-    "april",93-    "arch",94-    "arctic",95-    "area",96-    "arena",97-    "argue",98-    "arm",99-    "armed",100-    "armor",101-    "army",102-    "around",103-    "arrange",104-    "arrest",105-    "arrive",106-    "arrow",107-    "art",108-    "artefact",109-    "artist",110-    "artwork",111-    "ask",112-    "aspect",113-    "assault",114-    "asset",115-    "assist",116-    "assume",117-    "asthma",118-    "athlete",119-    "atom",120-    "attack",121-    "attend",122-    "attitude",123-    "attract",124-    "auction",125-    "audit",126-    "august",127-    "aunt",128-    "author",129-    "auto",130-    "autumn",131-    "average",132-    "avocado",133-    "avoid",134-    "awake",135-    "aware",136-    "away",137-    "awesome",138-    "awful",139-    "awkward",140-    "axis",141-    "baby",142-    "bachelor",143-    "bacon",144-    "badge",145-    "bag",146-    "balance",147-    "balcony",148-    "ball",149-    "bamboo",150-    "banana",151-    "banner",152-    "bar",153-    "barely",154-    "bargain",155-    "barrel",156-    "base",157-    "basic",158-    "basket",159-    "battle",160-    "beach",161-    "bean",162-    "beauty",163-    "because",164-    "become",165-    "beef",166-    "before",167-    "begin",168-    "behave",169-    "behind",170-    "believe",171-    "below",172-    "belt",173-    "bench",174-    "benefit",175-    "best",176-    "betray",177-    "better",178-    "between",179-    "beyond",180-    "bicycle",181-    "bid",182-    "bike",183-    "bind",184-    "biology",185-    "bird",186-    "birth",187-    "bitter",188-    "black",189-    "blade",190-    "blame",191-    "blanket",192-    "blast",193-    "bleak",194-    "bless",195-    "blind",196-    "blood",197-    "blossom",198-    "blouse",199-    "blue",200-    "blur",201-    "blush",202-    "board",203-    "boat",204-    "body",205-    "boil",206-    "bomb",207-    "bone",208-    "bonus",209-    "book",210-    "boost",211-    "border",212-    "boring",213-    "borrow",214-    "boss",215-    "bottom",216-    "bounce",217-    "box",218-    "boy",219-    "bracket",220-    "brain",221-    "brand",222-    "brass",223-    "brave",224-    "bread",225-    "breeze",226-    "brick",227-    "bridge",228-    "brief",229-    "bright",230-    "bring",231-    "brisk",232-    "broccoli",233-    "broken",234-    "bronze",235-    "broom",236-    "brother",237-    "brown",238-    "brush",239-    "bubble",240-    "buddy",241-    "budget",242-    "buffalo",243-    "build",244-    "bulb",245-    "bulk",246-    "bullet",247-    "bundle",248-    "bunker",249-    "burden",250-    "burger",251-    "burst",252-    "bus",253-    "business",254-    "busy",255-    "butter",256-    "buyer",257-    "buzz",258-    "cabbage",259-    "cabin",260-    "cable",261-    "cactus",262-    "cage",263-    "cake",264-    "call",265-    "calm",266-    "camera",267-    "camp",268-    "can",269-    "canal",270-    "cancel",271-    "candy",272-    "cannon",273-    "canoe",274-    "canvas",275-    "canyon",276-    "capable",277-    "capital",278-    "captain",279-    "car",280-    "carbon",281-    "card",282-    "cargo",283-    "carpet",284-    "carry",285-    "cart",286-    "case",287-    "cash",288-    "casino",289-    "castle",290-    "casual",291-    "cat",292-    "catalog",293-    "catch",294-    "category",295-    "cattle",296-    "caught",297-    "cause",298-    "caution",299-    "cave",300-    "ceiling",301-    "celery",302-    "cement",303-    "census",304-    "century",305-    "cereal",306-    "certain",307-    "chair",308-    "chalk",309-    "champion",310-    "change",311-    "chaos",312-    "chapter",313-    "charge",314-    "chase",315-    "chat",316-    "cheap",317-    "check",318-    "cheese",319-    "chef",320-    "cherry",321-    "chest",322-    "chicken",323-    "chief",324-    "child",325-    "chimney",326-    "choice",327-    "choose",328-    "chronic",329-    "chuckle",330-    "chunk",331-    "churn",332-    "cigar",333-    "cinnamon",334-    "circle",335-    "citizen",336-    "city",337-    "civil",338-    "claim",339-    "clap",340-    "clarify",341-    "claw",342-    "clay",343-    "clean",344-    "clerk",345-    "clever",346-    "click",347-    "client",348-    "cliff",349-    "climb",350-    "clinic",351-    "clip",352-    "clock",353-    "clog",354-    "close",355-    "cloth",356-    "cloud",357-    "clown",358-    "club",359-    "clump",360-    "cluster",361-    "clutch",362-    "coach",363-    "coast",364-    "coconut",365-    "code",366-    "coffee",367-    "coil",368-    "coin",369-    "collect",370-    "color",371-    "column",372-    "combine",373-    "come",374-    "comfort",375-    "comic",376-    "common",377-    "company",378-    "concert",379-    "conduct",380-    "confirm",381-    "congress",382-    "connect",383-    "consider",384-    "control",385-    "convince",386-    "cook",387-    "cool",388-    "copper",389-    "copy",390-    "coral",391-    "core",392-    "corn",393-    "correct",394-    "cost",395-    "cotton",396-    "couch",397-    "country",398-    "couple",399-    "course",400-    "cousin",401-    "cover",402-    "coyote",403-    "crack",404-    "cradle",405-    "craft",406-    "cram",407-    "crane",408-    "crash",409-    "crater",410-    "crawl",411-    "crazy",412-    "cream",413-    "credit",414-    "creek",415-    "crew",416-    "cricket",417-    "crime",418-    "crisp",419-    "critic",420-    "crop",421-    "cross",422-    "crouch",423-    "crowd",424-    "crucial",425-    "cruel",426-    "cruise",427-    "crumble",428-    "crunch",429-    "crush",430-    "cry",431-    "crystal",432-    "cube",433-    "culture",434-    "cup",435-    "cupboard",436-    "curious",437-    "current",438-    "curtain",439-    "curve",440-    "cushion",441-    "custom",442-    "cute",443-    "cycle",444-    "dad",445-    "damage",446-    "damp",447-    "dance",448-    "danger",449-    "daring",450-    "dash",451-    "daughter",452-    "dawn",453-    "day",454-    "deal",455-    "debate",456-    "debris",457-    "decade",458-    "december",459-    "decide",460-    "decline",461-    "decorate",462-    "decrease",463-    "deer",464-    "defense",465-    "define",466-    "defy",467-    "degree",468-    "delay",469-    "deliver",470-    "demand",471-    "demise",472-    "denial",473-    "dentist",474-    "deny",475-    "depart",476-    "depend",477-    "deposit",478-    "depth",479-    "deputy",480-    "derive",481-    "describe",482-    "desert",483-    "design",484-    "desk",485-    "despair",486-    "destroy",487-    "detail",488-    "detect",489-    "develop",490-    "device",491-    "devote",492-    "diagram",493-    "dial",494-    "diamond",495-    "diary",496-    "dice",497-    "diesel",498-    "diet",499-    "differ",500-    "digital",501-    "dignity",502-    "dilemma",503-    "dinner",504-    "dinosaur",505-    "direct",506-    "dirt",507-    "disagree",508-    "discover",509-    "disease",510-    "dish",511-    "dismiss",512-    "disorder",513-    "display",514-    "distance",515-    "divert",516-    "divide",517-    "divorce",518-    "dizzy",519-    "doctor",520-    "document",521-    "dog",522-    "doll",523-    "dolphin",524-    "domain",525-    "donate",526-    "donkey",527-    "donor",528-    "door",529-    "dose",530-    "double",531-    "dove",532-    "draft",533-    "dragon",534-    "drama",535-    "drastic",536-    "draw",537-    "dream",538-    "dress",539-    "drift",540-    "drill",541-    "drink",542-    "drip",543-    "drive",544-    "drop",545-    "drum",546-    "dry",547-    "duck",548-    "dumb",549-    "dune",550-    "during",551-    "dust",552-    "dutch",553-    "duty",554-    "dwarf",555-    "dynamic",556-    "eager",557-    "eagle",558-    "early",559-    "earn",560-    "earth",561-    "easily",562-    "east",563-    "easy",564-    "echo",565-    "ecology",566-    "economy",567-    "edge",568-    "edit",569-    "educate",570-    "effort",571-    "egg",572-    "eight",573-    "either",574-    "elbow",575-    "elder",576-    "electric",577-    "elegant",578-    "element",579-    "elephant",580-    "elevator",581-    "elite",582-    "else",583-    "embark",584-    "embody",585-    "embrace",586-    "emerge",587-    "emotion",588-    "employ",589-    "empower",590-    "empty",591-    "enable",592-    "enact",593-    "end",594-    "endless",595-    "endorse",596-    "enemy",597-    "energy",598-    "enforce",599-    "engage",600-    "engine",601-    "enhance",602-    "enjoy",603-    "enlist",604-    "enough",605-    "enrich",606-    "enroll",607-    "ensure",608-    "enter",609-    "entire",610-    "entry",611-    "envelope",612-    "episode",613-    "equal",614-    "equip",615-    "era",616-    "erase",617-    "erode",618-    "erosion",619-    "error",620-    "erupt",621-    "escape",622-    "essay",623-    "essence",624-    "estate",625-    "eternal",626-    "ethics",627-    "evidence",628-    "evil",629-    "evoke",630-    "evolve",631-    "exact",632-    "example",633-    "excess",634-    "exchange",635-    "excite",636-    "exclude",637-    "excuse",638-    "execute",639-    "exercise",640-    "exhaust",641-    "exhibit",642-    "exile",643-    "exist",644-    "exit",645-    "exotic",646-    "expand",647-    "expect",648-    "expire",649-    "explain",650-    "expose",651-    "express",652-    "extend",653-    "extra",654-    "eye",655-    "eyebrow",656-    "fabric",657-    "face",658-    "faculty",659-    "fade",660-    "faint",661-    "faith",662-    "fall",663-    "false",664-    "fame",665-    "family",666-    "famous",667-    "fan",668-    "fancy",669-    "fantasy",670-    "farm",671-    "fashion",672-    "fat",673-    "fatal",674-    "father",675-    "fatigue",676-    "fault",677-    "favorite",678-    "feature",679-    "february",680-    "federal",681-    "fee",682-    "feed",683-    "feel",684-    "female",685-    "fence",686-    "festival",687-    "fetch",688-    "fever",689-    "few",690-    "fiber",691-    "fiction",692-    "field",693-    "figure",694-    "file",695-    "film",696-    "filter",697-    "final",698-    "find",699-    "fine",700-    "finger",701-    "finish",702-    "fire",703-    "firm",704-    "first",705-    "fiscal",706-    "fish",707-    "fit",708-    "fitness",709-    "fix",710-    "flag",711-    "flame",712-    "flash",713-    "flat",714-    "flavor",715-    "flee",716-    "flight",717-    "flip",718-    "float",719-    "flock",720-    "floor",721-    "flower",722-    "fluid",723-    "flush",724-    "fly",725-    "foam",726-    "focus",727-    "fog",728-    "foil",729-    "fold",730-    "follow",731-    "food",732-    "foot",733-    "force",734-    "forest",735-    "forget",736-    "fork",737-    "fortune",738-    "forum",739-    "forward",740-    "fossil",741-    "foster",742-    "found",743-    "fox",744-    "fragile",745-    "frame",746-    "frequent",747-    "fresh",748-    "friend",749-    "fringe",750-    "frog",751-    "front",752-    "frost",753-    "frown",754-    "frozen",755-    "fruit",756-    "fuel",757-    "fun",758-    "funny",759-    "furnace",760-    "fury",761-    "future",762-    "gadget",763-    "gain",764-    "galaxy",765-    "gallery",766-    "game",767-    "gap",768-    "garage",769-    "garbage",770-    "garden",771-    "garlic",772-    "garment",773-    "gas",774-    "gasp",775-    "gate",776-    "gather",777-    "gauge",778-    "gaze",779-    "general",780-    "genius",781-    "genre",782-    "gentle",783-    "genuine",784-    "gesture",785-    "ghost",786-    "giant",787-    "gift",788-    "giggle",789-    "ginger",790-    "giraffe",791-    "girl",792-    "give",793-    "glad",794-    "glance",795-    "glare",796-    "glass",797-    "glide",798-    "glimpse",799-    "globe",800-    "gloom",801-    "glory",802-    "glove",803-    "glow",804-    "glue",805-    "goat",806-    "goddess",807-    "gold",808-    "good",809-    "goose",810-    "gorilla",811-    "gospel",812-    "gossip",813-    "govern",814-    "gown",815-    "grab",816-    "grace",817-    "grain",818-    "grant",819-    "grape",820-    "grass",821-    "gravity",822-    "great",823-    "green",824-    "grid",825-    "grief",826-    "grit",827-    "grocery",828-    "group",829-    "grow",830-    "grunt",831-    "guard",832-    "guess",833-    "guide",834-    "guilt",835-    "guitar",836-    "gun",837-    "gym",838-    "habit",839-    "hair",840-    "half",841-    "hammer",842-    "hamster",843-    "hand",844-    "happy",845-    "harbor",846-    "hard",847-    "harsh",848-    "harvest",849-    "hat",850-    "have",851-    "hawk",852-    "hazard",853-    "head",854-    "health",855-    "heart",856-    "heavy",857-    "hedgehog",858-    "height",859-    "hello",860-    "helmet",861-    "help",862-    "hen",863-    "hero",864-    "hidden",865-    "high",866-    "hill",867-    "hint",868-    "hip",869-    "hire",870-    "history",871-    "hobby",872-    "hockey",873-    "hold",874-    "hole",875-    "holiday",876-    "hollow",877-    "home",878-    "honey",879-    "hood",880-    "hope",881-    "horn",882-    "horror",883-    "horse",884-    "hospital",885-    "host",886-    "hotel",887-    "hour",888-    "hover",889-    "hub",890-    "huge",891-    "human",892-    "humble",893-    "humor",894-    "hundred",895-    "hungry",896-    "hunt",897-    "hurdle",898-    "hurry",899-    "hurt",900-    "husband",901-    "hybrid",902-    "ice",903-    "icon",904-    "idea",905-    "identify",906-    "idle",907-    "ignore",908-    "ill",909-    "illegal",910-    "illness",911-    "image",912-    "imitate",913-    "immense",914-    "immune",915-    "impact",916-    "impose",917-    "improve",918-    "impulse",919-    "inch",920-    "include",921-    "income",922-    "increase",923-    "index",924-    "indicate",925-    "indoor",926-    "industry",927-    "infant",928-    "inflict",929-    "inform",930-    "inhale",931-    "inherit",932-    "initial",933-    "inject",934-    "injury",935-    "inmate",936-    "inner",937-    "innocent",938-    "input",939-    "inquiry",940-    "insane",941-    "insect",942-    "inside",943-    "inspire",944-    "install",945-    "intact",946-    "interest",947-    "into",948-    "invest",949-    "invite",950-    "involve",951-    "iron",952-    "island",953-    "isolate",954-    "issue",955-    "item",956-    "ivory",957-    "jacket",958-    "jaguar",959-    "jar",960-    "jazz",961-    "jealous",962-    "jeans",963-    "jelly",964-    "jewel",965-    "job",966-    "join",967-    "joke",968-    "journey",969-    "joy",970-    "judge",971-    "juice",972-    "jump",973-    "jungle",974-    "junior",975-    "junk",976-    "just",977-    "kangaroo",978-    "keen",979-    "keep",980-    "ketchup",981-    "key",982-    "kick",983-    "kid",984-    "kidney",985-    "kind",986-    "kingdom",987-    "kiss",988-    "kit",989-    "kitchen",990-    "kite",991-    "kitten",992-    "kiwi",993-    "knee",994-    "knife",995-    "knock",996-    "know",997-    "lab",998-    "label",999-    "labor",1000-    "ladder",1001-    "lady",1002-    "lake",1003-    "lamp",1004-    "language",1005-    "laptop",1006-    "large",1007-    "later",1008-    "latin",1009-    "laugh",1010-    "laundry",1011-    "lava",1012-    "law",1013-    "lawn",1014-    "lawsuit",1015-    "layer",1016-    "lazy",1017-    "leader",1018-    "leaf",1019-    "learn",1020-    "leave",1021-    "lecture",1022-    "left",1023-    "leg",1024-    "legal",1025-    "legend",1026-    "leisure",1027-    "lemon",1028-    "lend",1029-    "length",1030-    "lens",1031-    "leopard",1032-    "lesson",1033-    "letter",1034-    "level",1035-    "liar",1036-    "liberty",1037-    "library",1038-    "license",1039-    "life",1040-    "lift",1041-    "light",1042-    "like",1043-    "limb",1044-    "limit",1045-    "link",1046-    "lion",1047-    "liquid",1048-    "list",1049-    "little",1050-    "live",1051-    "lizard",1052-    "load",1053-    "loan",1054-    "lobster",1055-    "local",1056-    "lock",1057-    "logic",1058-    "lonely",1059-    "long",1060-    "loop",1061-    "lottery",1062-    "loud",1063-    "lounge",1064-    "love",1065-    "loyal",1066-    "lucky",1067-    "luggage",1068-    "lumber",1069-    "lunar",1070-    "lunch",1071-    "luxury",1072-    "lyrics",1073-    "machine",1074-    "mad",1075-    "magic",1076-    "magnet",1077-    "maid",1078-    "mail",1079-    "main",1080-    "major",1081-    "make",1082-    "mammal",1083-    "man",1084-    "manage",1085-    "mandate",1086-    "mango",1087-    "mansion",1088-    "manual",1089-    "maple",1090-    "marble",1091-    "march",1092-    "margin",1093-    "marine",1094-    "market",1095-    "marriage",1096-    "mask",1097-    "mass",1098-    "master",1099-    "match",1100-    "material",1101-    "math",1102-    "matrix",1103-    "matter",1104-    "maximum",1105-    "maze",1106-    "meadow",1107-    "mean",1108-    "measure",1109-    "meat",1110-    "mechanic",1111-    "medal",1112-    "media",1113-    "melody",1114-    "melt",1115-    "member",1116-    "memory",1117-    "mention",1118-    "menu",1119-    "mercy",1120-    "merge",1121-    "merit",1122-    "merry",1123-    "mesh",1124-    "message",1125-    "metal",1126-    "method",1127-    "middle",1128-    "midnight",1129-    "milk",1130-    "million",1131-    "mimic",1132-    "mind",1133-    "minimum",1134-    "minor",1135-    "minute",1136-    "miracle",1137-    "mirror",1138-    "misery",1139-    "miss",1140-    "mistake",1141-    "mix",1142-    "mixed",1143-    "mixture",1144-    "mobile",1145-    "model",1146-    "modify",1147-    "mom",1148-    "moment",1149-    "monitor",1150-    "monkey",1151-    "monster",1152-    "month",1153-    "moon",1154-    "moral",1155-    "more",1156-    "morning",1157-    "mosquito",1158-    "mother",1159-    "motion",1160-    "motor",1161-    "mountain",1162-    "mouse",1163-    "move",1164-    "movie",1165-    "much",1166-    "muffin",1167-    "mule",1168-    "multiply",1169-    "muscle",1170-    "museum",1171-    "mushroom",1172-    "music",1173-    "must",1174-    "mutual",1175-    "myself",1176-    "mystery",1177-    "myth",1178-    "naive",1179-    "name",1180-    "napkin",1181-    "narrow",1182-    "nasty",1183-    "nation",1184-    "nature",1185-    "near",1186-    "neck",1187-    "need",1188-    "negative",1189-    "neglect",1190-    "neither",1191-    "nephew",1192-    "nerve",1193-    "nest",1194-    "net",1195-    "network",1196-    "neutral",1197-    "never",1198-    "news",1199-    "next",1200-    "nice",1201-    "night",1202-    "noble",1203-    "noise",1204-    "nominee",1205-    "noodle",1206-    "normal",1207-    "north",1208-    "nose",1209-    "notable",1210-    "note",1211-    "nothing",1212-    "notice",1213-    "novel",1214-    "now",1215-    "nuclear",1216-    "number",1217-    "nurse",1218-    "nut",1219-    "oak",1220-    "obey",1221-    "object",1222-    "oblige",1223-    "obscure",1224-    "observe",1225-    "obtain",1226-    "obvious",1227-    "occur",1228-    "ocean",1229-    "october",1230-    "odor",1231-    "off",1232-    "offer",1233-    "office",1234-    "often",1235-    "oil",1236-    "okay",1237-    "old",1238-    "olive",1239-    "olympic",1240-    "omit",1241-    "once",1242-    "one",1243-    "onion",1244-    "online",1245-    "only",1246-    "open",1247-    "opera",1248-    "opinion",1249-    "oppose",1250-    "option",1251-    "orange",1252-    "orbit",1253-    "orchard",1254-    "order",1255-    "ordinary",1256-    "organ",1257-    "orient",1258-    "original",1259-    "orphan",1260-    "ostrich",1261-    "other",1262-    "outdoor",1263-    "outer",1264-    "output",1265-    "outside",1266-    "oval",1267-    "oven",1268-    "over",1269-    "own",1270-    "owner",1271-    "oxygen",1272-    "oyster",1273-    "ozone",1274-    "pact",1275-    "paddle",1276-    "page",1277-    "pair",1278-    "palace",1279-    "palm",1280-    "panda",1281-    "panel",1282-    "panic",1283-    "panther",1284-    "paper",1285-    "parade",1286-    "parent",1287-    "park",1288-    "parrot",1289-    "party",1290-    "pass",1291-    "patch",1292-    "path",1293-    "patient",1294-    "patrol",1295-    "pattern",1296-    "pause",1297-    "pave",1298-    "payment",1299-    "peace",1300-    "peanut",1301-    "pear",1302-    "peasant",1303-    "pelican",1304-    "pen",1305-    "penalty",1306-    "pencil",1307-    "people",1308-    "pepper",1309-    "perfect",1310-    "permit",1311-    "person",1312-    "pet",1313-    "phone",1314-    "photo",1315-    "phrase",1316-    "physical",1317-    "piano",1318-    "picnic",1319-    "picture",1320-    "piece",1321-    "pig",1322-    "pigeon",1323-    "pill",1324-    "pilot",1325-    "pink",1326-    "pioneer",1327-    "pipe",1328-    "pistol",1329-    "pitch",1330-    "pizza",1331-    "place",1332-    "planet",1333-    "plastic",1334-    "plate",1335-    "play",1336-    "please",1337-    "pledge",1338-    "pluck",1339-    "plug",1340-    "plunge",1341-    "poem",1342-    "poet",1343-    "point",1344-    "polar",1345-    "pole",1346-    "police",1347-    "pond",1348-    "pony",1349-    "pool",1350-    "popular",1351-    "portion",1352-    "position",1353-    "possible",1354-    "post",1355-    "potato",1356-    "pottery",1357-    "poverty",1358-    "powder",1359-    "power",1360-    "practice",1361-    "praise",1362-    "predict",1363-    "prefer",1364-    "prepare",1365-    "present",1366-    "pretty",1367-    "prevent",1368-    "price",1369-    "pride",1370-    "primary",1371-    "print",1372-    "priority",1373-    "prison",1374-    "private",1375-    "prize",1376-    "problem",1377-    "process",1378-    "produce",1379-    "profit",1380-    "program",1381-    "project",1382-    "promote",1383-    "proof",1384-    "property",1385-    "prosper",1386-    "protect",1387-    "proud",1388-    "provide",1389-    "public",1390-    "pudding",1391-    "pull",1392-    "pulp",1393-    "pulse",1394-    "pumpkin",1395-    "punch",1396-    "pupil",1397-    "puppy",1398-    "purchase",1399-    "purity",1400-    "purpose",1401-    "purse",1402-    "push",1403-    "put",1404-    "puzzle",1405-    "pyramid",1406-    "quality",1407-    "quantum",1408-    "quarter",1409-    "question",1410-    "quick",1411-    "quit",1412-    "quiz",1413-    "quote",1414-    "rabbit",1415-    "raccoon",1416-    "race",1417-    "rack",1418-    "radar",1419-    "radio",1420-    "rail",1421-    "rain",1422-    "raise",1423-    "rally",1424-    "ramp",1425-    "ranch",1426-    "random",1427-    "range",1428-    "rapid",1429-    "rare",1430-    "rate",1431-    "rather",1432-    "raven",1433-    "raw",1434-    "razor",1435-    "ready",1436-    "real",1437-    "reason",1438-    "rebel",1439-    "rebuild",1440-    "recall",1441-    "receive",1442-    "recipe",1443-    "record",1444-    "recycle",1445-    "reduce",1446-    "reflect",1447-    "reform",1448-    "refuse",1449-    "region",1450-    "regret",1451-    "regular",1452-    "reject",1453-    "relax",1454-    "release",1455-    "relief",1456-    "rely",1457-    "remain",1458-    "remember",1459-    "remind",1460-    "remove",1461-    "render",1462-    "renew",1463-    "rent",1464-    "reopen",1465-    "repair",1466-    "repeat",1467-    "replace",1468-    "report",1469-    "require",1470-    "rescue",1471-    "resemble",1472-    "resist",1473-    "resource",1474-    "response",1475-    "result",1476-    "retire",1477-    "retreat",1478-    "return",1479-    "reunion",1480-    "reveal",1481-    "review",1482-    "reward",1483-    "rhythm",1484-    "rib",1485-    "ribbon",1486-    "rice",1487-    "rich",1488-    "ride",1489-    "ridge",1490-    "rifle",1491-    "right",1492-    "rigid",1493-    "ring",1494-    "riot",1495-    "ripple",1496-    "risk",1497-    "ritual",1498-    "rival",1499-    "river",1500-    "road",1501-    "roast",1502-    "robot",1503-    "robust",1504-    "rocket",1505-    "romance",1506-    "roof",1507-    "rookie",1508-    "room",1509-    "rose",1510-    "rotate",1511-    "rough",1512-    "round",1513-    "route",1514-    "royal",1515-    "rubber",1516-    "rude",1517-    "rug",1518-    "rule",1519-    "run",1520-    "runway",1521-    "rural",1522-    "sad",1523-    "saddle",1524-    "sadness",1525-    "safe",1526-    "sail",1527-    "salad",1528-    "salmon",1529-    "salon",1530-    "salt",1531-    "salute",1532-    "same",1533-    "sample",1534-    "sand",1535-    "satisfy",1536-    "satoshi",1537-    "sauce",1538-    "sausage",1539-    "save",1540-    "say",1541-    "scale",1542-    "scan",1543-    "scare",1544-    "scatter",1545-    "scene",1546-    "scheme",1547-    "school",1548-    "science",1549-    "scissors",1550-    "scorpion",1551-    "scout",1552-    "scrap",1553-    "screen",1554-    "script",1555-    "scrub",1556-    "sea",1557-    "search",1558-    "season",1559-    "seat",1560-    "second",1561-    "secret",1562-    "section",1563-    "security",1564-    "seed",1565-    "seek",1566-    "segment",1567-    "select",1568-    "sell",1569-    "seminar",1570-    "senior",1571-    "sense",1572-    "sentence",1573-    "series",1574-    "service",1575-    "session",1576-    "settle",1577-    "setup",1578-    "seven",1579-    "shadow",1580-    "shaft",1581-    "shallow",1582-    "share",1583-    "shed",1584-    "shell",1585-    "sheriff",1586-    "shield",1587-    "shift",1588-    "shine",1589-    "ship",1590-    "shiver",1591-    "shock",1592-    "shoe",1593-    "shoot",1594-    "shop",1595-    "short",1596-    "shoulder",1597-    "shove",1598-    "shrimp",1599-    "shrug",1600-    "shuffle",1601-    "shy",1602-    "sibling",1603-    "sick",1604-    "side",1605-    "siege",1606-    "sight",1607-    "sign",1608-    "silent",1609-    "silk",1610-    "silly",1611-    "silver",1612-    "similar",1613-    "simple",1614-    "since",1615-    "sing",1616-    "siren",1617-    "sister",1618-    "situate",1619-    "six",1620-    "size",1621-    "skate",1622-    "sketch",1623-    "ski",1624-    "skill",1625-    "skin",1626-    "skirt",1627-    "skull",1628-    "slab",1629-    "slam",1630-    "sleep",1631-    "slender",1632-    "slice",1633-    "slide",1634-    "slight",1635-    "slim",1636-    "slogan",1637-    "slot",1638-    "slow",1639-    "slush",1640-    "small",1641-    "smart",1642-    "smile",1643-    "smoke",1644-    "smooth",1645-    "snack",1646-    "snake",1647-    "snap",1648-    "sniff",1649-    "snow",1650-    "soap",1651-    "soccer",1652-    "social",1653-    "sock",1654-    "soda",1655-    "soft",1656-    "solar",1657-    "soldier",1658-    "solid",1659-    "solution",1660-    "solve",1661-    "someone",1662-    "song",1663-    "soon",1664-    "sorry",1665-    "sort",1666-    "soul",1667-    "sound",1668-    "soup",1669-    "source",1670-    "south",1671-    "space",1672-    "spare",1673-    "spatial",1674-    "spawn",1675-    "speak",1676-    "special",1677-    "speed",1678-    "spell",1679-    "spend",1680-    "sphere",1681-    "spice",1682-    "spider",1683-    "spike",1684-    "spin",1685-    "spirit",1686-    "split",1687-    "spoil",1688-    "sponsor",1689-    "spoon",1690-    "sport",1691-    "spot",1692-    "spray",1693-    "spread",1694-    "spring",1695-    "spy",1696-    "square",1697-    "squeeze",1698-    "squirrel",1699-    "stable",1700-    "stadium",1701-    "staff",1702-    "stage",1703-    "stairs",1704-    "stamp",1705-    "stand",1706-    "start",1707-    "state",1708-    "stay",1709-    "steak",1710-    "steel",1711-    "stem",1712-    "step",1713-    "stereo",1714-    "stick",1715-    "still",1716-    "sting",1717-    "stock",1718-    "stomach",1719-    "stone",1720-    "stool",1721-    "story",1722-    "stove",1723-    "strategy",1724-    "street",1725-    "strike",1726-    "strong",1727-    "struggle",1728-    "student",1729-    "stuff",1730-    "stumble",1731-    "style",1732-    "subject",1733-    "submit",1734-    "subway",1735-    "success",1736-    "such",1737-    "sudden",1738-    "suffer",1739-    "sugar",1740-    "suggest",1741-    "suit",1742-    "summer",1743-    "sun",1744-    "sunny",1745-    "sunset",1746-    "super",1747-    "supply",1748-    "supreme",1749-    "sure",1750-    "surface",1751-    "surge",1752-    "surprise",1753-    "surround",1754-    "survey",1755-    "suspect",1756-    "sustain",1757-    "swallow",1758-    "swamp",1759-    "swap",1760-    "swarm",1761-    "swear",1762-    "sweet",1763-    "swift",1764-    "swim",1765-    "swing",1766-    "switch",1767-    "sword",1768-    "symbol",1769-    "symptom",1770-    "syrup",1771-    "system",1772-    "table",1773-    "tackle",1774-    "tag",1775-    "tail",1776-    "talent",1777-    "talk",1778-    "tank",1779-    "tape",1780-    "target",1781-    "task",1782-    "taste",1783-    "tattoo",1784-    "taxi",1785-    "teach",1786-    "team",1787-    "tell",1788-    "ten",1789-    "tenant",1790-    "tennis",1791-    "tent",1792-    "term",1793-    "test",1794-    "text",1795-    "thank",1796-    "that",1797-    "theme",1798-    "then",1799-    "theory",1800-    "there",1801-    "they",1802-    "thing",1803-    "this",1804-    "thought",1805-    "three",1806-    "thrive",1807-    "throw",1808-    "thumb",1809-    "thunder",1810-    "ticket",1811-    "tide",1812-    "tiger",1813-    "tilt",1814-    "timber",1815-    "time",1816-    "tiny",1817-    "tip",1818-    "tired",1819-    "tissue",1820-    "title",1821-    "toast",1822-    "tobacco",1823-    "today",1824-    "toddler",1825-    "toe",1826-    "together",1827-    "toilet",1828-    "token",1829-    "tomato",1830-    "tomorrow",1831-    "tone",1832-    "tongue",1833-    "tonight",1834-    "tool",1835-    "tooth",1836-    "top",1837-    "topic",1838-    "topple",1839-    "torch",1840-    "tornado",1841-    "tortoise",1842-    "toss",1843-    "total",1844-    "tourist",1845-    "toward",1846-    "tower",1847-    "town",1848-    "toy",1849-    "track",1850-    "trade",1851-    "traffic",1852-    "tragic",1853-    "train",1854-    "transfer",1855-    "trap",1856-    "trash",1857-    "travel",1858-    "tray",1859-    "treat",1860-    "tree",1861-    "trend",1862-    "trial",1863-    "tribe",1864-    "trick",1865-    "trigger",1866-    "trim",1867-    "trip",1868-    "trophy",1869-    "trouble",1870-    "truck",1871-    "true",1872-    "truly",1873-    "trumpet",1874-    "trust",1875-    "truth",1876-    "try",1877-    "tube",1878-    "tuition",1879-    "tumble",1880-    "tuna",1881-    "tunnel",1882-    "turkey",1883-    "turn",1884-    "turtle",1885-    "twelve",1886-    "twenty",1887-    "twice",1888-    "twin",1889-    "twist",1890-    "two",1891-    "type",1892-    "typical",1893-    "ugly",1894-    "umbrella",1895-    "unable",1896-    "unaware",1897-    "uncle",1898-    "uncover",1899-    "under",1900-    "undo",1901-    "unfair",1902-    "unfold",1903-    "unhappy",1904-    "uniform",1905-    "unique",1906-    "unit",1907-    "universe",1908-    "unknown",1909-    "unlock",1910-    "until",1911-    "unusual",1912-    "unveil",1913-    "update",1914-    "upgrade",1915-    "uphold",1916-    "upon",1917-    "upper",1918-    "upset",1919-    "urban",1920-    "urge",1921-    "usage",1922-    "use",1923-    "used",1924-    "useful",1925-    "useless",1926-    "usual",1927-    "utility",1928-    "vacant",1929-    "vacuum",1930-    "vague",1931-    "valid",1932-    "valley",1933-    "valve",1934-    "van",1935-    "vanish",1936-    "vapor",1937-    "various",1938-    "vast",1939-    "vault",1940-    "vehicle",1941-    "velvet",1942-    "vendor",1943-    "venture",1944-    "venue",1945-    "verb",1946-    "verify",1947-    "version",1948-    "very",1949-    "vessel",1950-    "veteran",1951-    "viable",1952-    "vibrant",1953-    "vicious",1954-    "victory",1955-    "video",1956-    "view",1957-    "village",1958-    "vintage",1959-    "violin",1960-    "virtual",1961-    "virus",1962-    "visa",1963-    "visit",1964-    "visual",1965-    "vital",1966-    "vivid",1967-    "vocal",1968-    "voice",1969-    "void",1970-    "volcano",1971-    "volume",1972-    "vote",1973-    "voyage",1974-    "wage",1975-    "wagon",1976-    "wait",1977-    "walk",1978-    "wall",1979-    "walnut",1980-    "want",1981-    "warfare",1982-    "warm",1983-    "warrior",1984-    "wash",1985-    "wasp",1986-    "waste",1987-    "water",1988-    "wave",1989-    "way",1990-    "wealth",1991-    "weapon",1992-    "wear",1993-    "weasel",1994-    "weather",1995-    "web",1996-    "wedding",1997-    "weekend",1998-    "weird",1999-    "welcome",2000-    "west",2001-    "wet",2002-    "whale",2003-    "what",2004-    "wheat",2005-    "wheel",2006-    "when",2007-    "where",2008-    "whip",2009-    "whisper",2010-    "wide",2011-    "width",2012-    "wife",2013-    "wild",2014-    "will",2015-    "win",2016-    "window",2017-    "wine",2018-    "wing",2019-    "wink",2020-    "winner",2021-    "winter",2022-    "wire",2023-    "wisdom",2024-    "wise",2025-    "wish",2026-    "witness",2027-    "wolf",2028-    "woman",2029-    "wonder",2030-    "wood",2031-    "wool",2032-    "word",2033-    "work",2034-    "world",2035-    "worry",2036-    "worth",2037-    "wrap",2038-    "wreck",2039-    "wrestle",2040-    "wrist",2041-    "write",2042-    "wrong",2043-    "yard",2044-    "year",2045-    "yellow",2046-    "you",2047-    "young",2048-    "youth",2049-    "zebra",2050-    "zero",2051-    "zone",3+/**4+ * Recovery word list — byte-identical to the browser's5+ * `src/shared/recovery-word-list.ts`: the canonical 2048-word BIP39 English6+ * list, 0-indexed, no duplicates.7+ *8+ * This MUST stay identical to the browser's list. Words are only a human9+ * readable encoding of the root key's first 16 bytes, so any divergence in10+ * ordering means the same vault prints different words on each platform and a11+ * phrase written down on one device restores nothing on the other.12+ * `CrossPlatformRecoveryWordsTest` pins that with a shared vector.13+ */14+val WORD_LIST: List<String> = listOf(15+    "abandon", "ability", "able", "about", "above", "absent", "absorb", "abstract",16+    "absurd", "abuse", "access", "accident", "account", "accuse", "achieve", "acid",17+    "acoustic", "acquire", "across", "act", "action", "actor", "actress", "actual",18+    "adapt", "add", "addict", "address", "adjust", "admit", "adult", "advance",19+    "advice", "aerobic", "affair", "afford", "afraid", "again", "age", "agent",20+    "agree", "ahead", "aim", "air", "airport", "aisle", "alarm", "album",21+    "alcohol", "alert", "alien", "all", "alley", "allow", "almost", "alone",22+    "alpha", "already", "also", "alter", "always", "amateur", "amazing", "among",23+    "amount", "amused", "analyst", "anchor", "ancient", "anger", "angle", "angry",24+    "animal", "ankle", "announce", "annual", "another", "answer", "antenna", "antique",25+    "anxiety", "any", "apart", "apology", "appear", "apple", "approve", "april",26+    "arch", "arctic", "area", "arena", "argue", "arm", "armed", "armor",27+    "army", "around", "arrange", "arrest", "arrive", "arrow", "art", "artefact",28+    "artist", "artwork", "ask", "aspect", "assault", "asset", "assist", "assume",29+    "asthma", "athlete", "atom", "attack", "attend", "attitude", "attract", "auction",30+    "audit", "august", "aunt", "author", "auto", "autumn", "average", "avocado",31+    "avoid", "awake", "aware", "away", "awesome", "awful", "awkward", "axis",32+    "baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony", "ball",33+    "bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel", "base",34+    "basic", "basket", "battle", "beach", "bean", "beauty", "because", "become",35+    "beef", "before", "begin", "behave", "behind", "believe", "below", "belt",36+    "bench", "benefit", "best", "betray", "better", "between", "beyond", "bicycle",37+    "bid", "bike", "bind", "biology", "bird", "birth", "bitter", "black",38+    "blade", "blame", "blanket", "blast", "bleak", "bless", "blind", "blood",39+    "blossom", "blouse", "blue", "blur", "blush", "board", "boat", "body",40+    "boil", "bomb", "bone", "bonus", "book", "boost", "border", "boring",41+    "borrow", "boss", "bottom", "bounce", "box", "boy", "bracket", "brain",42+    "brand", "brass", "brave", "bread", "breeze", "brick", "bridge", "brief",43+    "bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom", "brother",44+    "brown", "brush", "bubble", "buddy", "budget", "buffalo", "build", "bulb",45+    "bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst", "bus",46+    "business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin", "cable",47+    "cactus", "cage", "cake", "call", "calm", "camera", "camp", "can",48+    "canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon", "capable",49+    "capital", "captain", "car", "carbon", "card", "cargo", "carpet", "carry",50+    "cart", "case", "cash", "casino", "castle", "casual", "cat", "catalog",51+    "catch", "category", "cattle", "caught", "cause", "caution", "cave", "ceiling",52+    "celery", "cement", "census", "century", "cereal", "certain", "chair", "chalk",53+    "champion", "change", "chaos", "chapter", "charge", "chase", "chat", "cheap",54+    "check", "cheese", "chef", "cherry", "chest", "chicken", "chief", "child",55+    "chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn", "cigar",56+    "cinnamon", "circle", "citizen", "city", "civil", "claim", "clap", "clarify",57+    "claw", "clay", "clean", "clerk", "clever", "click", "client", "cliff",58+    "climb", "clinic", "clip", "clock", "clog", "close", "cloth", "cloud",59+    "clown", "club", "clump", "cluster", "clutch", "coach", "coast", "coconut",60+    "code", "coffee", "coil", "coin", "collect", "color", "column", "combine",61+    "come", "comfort", "comic", "common", "company", "concert", "conduct", "confirm",62+    "congress", "connect", "consider", "control", "convince", "cook", "cool", "copper",63+    "copy", "coral", "core", "corn", "correct", "cost", "cotton", "couch",64+    "country", "couple", "course", "cousin", "cover", "coyote", "crack", "cradle",65+    "craft", "cram", "crane", "crash", "crater", "crawl", "crazy", "cream",66+    "credit", "creek", "crew", "cricket", "crime", "crisp", "critic", "crop",67+    "cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble", "crunch",68+    "crush", "cry", "crystal", "cube", "culture", "cup", "cupboard", "curious",69+    "current", "curtain", "curve", "cushion", "custom", "cute", "cycle", "dad",70+    "damage", "damp", "dance", "danger", "daring", "dash", "daughter", "dawn",71+    "day", "deal", "debate", "debris", "decade", "december", "decide", "decline",72+    "decorate", "decrease", "deer", "defense", "define", "defy", "degree", "delay",73+    "deliver", "demand", "demise", "denial", "dentist", "deny", "depart", "depend",74+    "deposit", "depth", "deputy", "derive", "describe", "desert", "design", "desk",75+    "despair", "destroy", "detail", "detect", "develop", "device", "devote", "diagram",76+    "dial", "diamond", "diary", "dice", "diesel", "diet", "differ", "digital",77+    "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt", "disagree", "discover",78+    "disease", "dish", "dismiss", "disorder", "display", "distance", "divert", "divide",79+    "divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin", "domain",80+    "donate", "donkey", "donor", "door", "dose", "double", "dove", "draft",81+    "dragon", "drama", "drastic", "draw", "dream", "dress", "drift", "drill",82+    "drink", "drip", "drive", "drop", "drum", "dry", "duck", "dumb",83+    "dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic", "eager",84+    "eagle", "early", "earn", "earth", "easily", "east", "easy", "echo",85+    "ecology", "economy", "edge", "edit", "educate", "effort", "egg", "eight",86+    "either", "elbow", "elder", "electric", "elegant", "element", "elephant", "elevator",87+    "elite", "else", "embark", "embody", "embrace", "emerge", "emotion", "employ",88+    "empower", "empty", "enable", "enact", "end", "endless", "endorse", "enemy",89+    "energy", "enforce", "engage", "engine", "enhance", "enjoy", "enlist", "enough",90+    "enrich", "enroll", "ensure", "enter", "entire", "entry", "envelope", "episode",91+    "equal", "equip", "era", "erase", "erode", "erosion", "error", "erupt",92+    "escape", "essay", "essence", "estate", "eternal", "ethics", "evidence", "evil",93+    "evoke", "evolve", "exact", "example", "excess", "exchange", "excite", "exclude",94+    "excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist", "exit",95+    "exotic", "expand", "expect", "expire", "explain", "expose", "express", "extend",96+    "extra", "eye", "eyebrow", "fabric", "face", "faculty", "fade", "faint",97+    "faith", "fall", "false", "fame", "family", "famous", "fan", "fancy",98+    "fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue", "fault",99+    "favorite", "feature", "february", "federal", "fee", "feed", "feel", "female",100+    "fence", "festival", "fetch", "fever", "few", "fiber", "fiction", "field",101+    "figure", "file", "film", "filter", "final", "find", "fine", "finger",102+    "finish", "fire", "firm", "first", "fiscal", "fish", "fit", "fitness",103+    "fix", "flag", "flame", "flash", "flat", "flavor", "flee", "flight",104+    "flip", "float", "flock", "floor", "flower", "fluid", "flush", "fly",105+    "foam", "focus", "fog", "foil", "fold", "follow", "food", "foot",106+    "force", "forest", "forget", "fork", "fortune", "forum", "forward", "fossil",107+    "foster", "found", "fox", "fragile", "frame", "frequent", "fresh", "friend",108+    "fringe", "frog", "front", "frost", "frown", "frozen", "fruit", "fuel",109+    "fun", "funny", "furnace", "fury", "future", "gadget", "gain", "galaxy",110+    "gallery", "game", "gap", "garage", "garbage", "garden", "garlic", "garment",111+    "gas", "gasp", "gate", "gather", "gauge", "gaze", "general", "genius",112+    "genre", "gentle", "genuine", "gesture", "ghost", "giant", "gift", "giggle",113+    "ginger", "giraffe", "girl", "give", "glad", "glance", "glare", "glass",114+    "glide", "glimpse", "globe", "gloom", "glory", "glove", "glow", "glue",115+    "goat", "goddess", "gold", "good", "goose", "gorilla", "gospel", "gossip",116+    "govern", "gown", "grab", "grace", "grain", "grant", "grape", "grass",117+    "gravity", "great", "green", "grid", "grief", "grit", "grocery", "group",118+    "grow", "grunt", "guard", "guess", "guide", "guilt", "guitar", "gun",119+    "gym", "habit", "hair", "half", "hammer", "hamster", "hand", "happy",120+    "harbor", "hard", "harsh", "harvest", "hat", "have", "hawk", "hazard",121+    "head", "health", "heart", "heavy", "hedgehog", "height", "hello", "helmet",122+    "help", "hen", "hero", "hidden", "high", "hill", "hint", "hip",123+    "hire", "history", "hobby", "hockey", "hold", "hole", "holiday", "hollow",124+    "home", "honey", "hood", "hope", "horn", "horror", "horse", "hospital",125+    "host", "hotel", "hour", "hover", "hub", "huge", "human", "humble",126+    "humor", "hundred", "hungry", "hunt", "hurdle", "hurry", "hurt", "husband",127+    "hybrid", "ice", "icon", "idea", "identify", "idle", "ignore", "ill",128+    "illegal", "illness", "image", "imitate", "immense", "immune", "impact", "impose",129+    "improve", "impulse", "inch", "include", "income", "increase", "index", "indicate",130+    "indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit", "initial",131+    "inject", "injury", "inmate", "inner", "innocent", "input", "inquiry", "insane",132+    "insect", "inside", "inspire", "install", "intact", "interest", "into", "invest",133+    "invite", "involve", "iron", "island", "isolate", "issue", "item", "ivory",134+    "jacket", "jaguar", "jar", "jazz", "jealous", "jeans", "jelly", "jewel",135+    "job", "join", "joke", "journey", "joy", "judge", "juice", "jump",136+    "jungle", "junior", "junk", "just", "kangaroo", "keen", "keep", "ketchup",137+    "key", "kick", "kid", "kidney", "kind", "kingdom", "kiss", "kit",138+    "kitchen", "kite", "kitten", "kiwi", "knee", "knife", "knock", "know",139+    "lab", "label", "labor", "ladder", "lady", "lake", "lamp", "language",140+    "laptop", "large", "later", "latin", "laugh", "laundry", "lava", "law",141+    "lawn", "lawsuit", "layer", "lazy", "leader", "leaf", "learn", "leave",142+    "lecture", "left", "leg", "legal", "legend", "leisure", "lemon", "lend",143+    "length", "lens", "leopard", "lesson", "letter", "level", "liar", "liberty",144+    "library", "license", "life", "lift", "light", "like", "limb", "limit",145+    "link", "lion", "liquid", "list", "little", "live", "lizard", "load",146+    "loan", "lobster", "local", "lock", "logic", "lonely", "long", "loop",147+    "lottery", "loud", "lounge", "love", "loyal", "lucky", "luggage", "lumber",148+    "lunar", "lunch", "luxury", "lyrics", "machine", "mad", "magic", "magnet",149+    "maid", "mail", "main", "major", "make", "mammal", "man", "manage",150+    "mandate", "mango", "mansion", "manual", "maple", "marble", "march", "margin",151+    "marine", "market", "marriage", "mask", "mass", "master", "match", "material",152+    "math", "matrix", "matter", "maximum", "maze", "meadow", "mean", "measure",153+    "meat", "mechanic", "medal", "media", "melody", "melt", "member", "memory",154+    "mention", "menu", "mercy", "merge", "merit", "merry", "mesh", "message",155+    "metal", "method", "middle", "midnight", "milk", "million", "mimic", "mind",156+    "minimum", "minor", "minute", "miracle", "mirror", "misery", "miss", "mistake",157+    "mix", "mixed", "mixture", "mobile", "model", "modify", "mom", "moment",158+    "monitor", "monkey", "monster", "month", "moon", "moral", "more", "morning",159+    "mosquito", "mother", "motion", "motor", "mountain", "mouse", "move", "movie",160+    "much", "muffin", "mule", "multiply", "muscle", "museum", "mushroom", "music",161+    "must", "mutual", "myself", "mystery", "myth", "naive", "name", "napkin",162+    "narrow", "nasty", "nation", "nature", "near", "neck", "need", "negative",163+    "neglect", "neither", "nephew", "nerve", "nest", "net", "network", "neutral",164+    "never", "news", "next", "nice", "night", "noble", "noise", "nominee",165+    "noodle", "normal", "north", "nose", "notable", "note", "nothing", "notice",166+    "novel", "now", "nuclear", "number", "nurse", "nut", "oak", "obey",167+    "object", "oblige", "obscure", "observe", "obtain", "obvious", "occur", "ocean",168+    "october", "odor", "off", "offer", "office", "often", "oil", "okay",169+    "old", "olive", "olympic", "omit", "once", "one", "onion", "online",170+    "only", "open", "opera", "opinion", "oppose", "option", "orange", "orbit",171+    "orchard", "order", "ordinary", "organ", "orient", "original", "orphan", "ostrich",172+    "other", "outdoor", "outer", "output", "outside", "oval", "oven", "over",173+    "own", "owner", "oxygen", "oyster", "ozone", "pact", "paddle", "page",174+    "pair", "palace", "palm", "panda", "panel", "panic", "panther", "paper",175+    "parade", "parent", "park", "parrot", "party", "pass", "patch", "path",176+    "patient", "patrol", "pattern", "pause", "pave", "payment", "peace", "peanut",177+    "pear", "peasant", "pelican", "pen", "penalty", "pencil", "people", "pepper",178+    "perfect", "permit", "person", "pet", "phone", "photo", "phrase", "physical",179+    "piano", "picnic", "picture", "piece", "pig", "pigeon", "pill", "pilot",180+    "pink", "pioneer", "pipe", "pistol", "pitch", "pizza", "place", "planet",181+    "plastic", "plate", "play", "please", "pledge", "pluck", "plug", "plunge",182+    "poem", "poet", "point", "polar", "pole", "police", "pond", "pony",183+    "pool", "popular", "portion", "position", "possible", "post", "potato", "pottery",184+    "poverty", "powder", "power", "practice", "praise", "predict", "prefer", "prepare",185+    "present", "pretty", "prevent", "price", "pride", "primary", "print", "priority",186+    "prison", "private", "prize", "problem", "process", "produce", "profit", "program",187+    "project", "promote", "proof", "property", "prosper", "protect", "proud", "provide",188+    "public", "pudding", "pull", "pulp", "pulse", "pumpkin", "punch", "pupil",189+    "puppy", "purchase", "purity", "purpose", "purse", "push", "put", "puzzle",190+    "pyramid", "quality", "quantum", "quarter", "question", "quick", "quit", "quiz",191+    "quote", "rabbit", "raccoon", "race", "rack", "radar", "radio", "rail",192+    "rain", "raise", "rally", "ramp", "ranch", "random", "range", "rapid",193+    "rare", "rate", "rather", "raven", "raw", "razor", "ready", "real",194+    "reason", "rebel", "rebuild", "recall", "receive", "recipe", "record", "recycle",195+    "reduce", "reflect", "reform", "refuse", "region", "regret", "regular", "reject",196+    "relax", "release", "relief", "rely", "remain", "remember", "remind", "remove",197+    "render", "renew", "rent", "reopen", "repair", "repeat", "replace", "report",198+    "require", "rescue", "resemble", "resist", "resource", "response", "result", "retire",199+    "retreat", "return", "reunion", "reveal", "review", "reward", "rhythm", "rib",200+    "ribbon", "rice", "rich", "ride", "ridge", "rifle", "right", "rigid",201+    "ring", "riot", "ripple", "risk", "ritual", "rival", "river", "road",202+    "roast", "robot", "robust", "rocket", "romance", "roof", "rookie", "room",203+    "rose", "rotate", "rough", "round", "route", "royal", "rubber", "rude",204+    "rug", "rule", "run", "runway", "rural", "sad", "saddle", "sadness",205+    "safe", "sail", "salad", "salmon", "salon", "salt", "salute", "same",206+    "sample", "sand", "satisfy", "satoshi", "sauce", "sausage", "save", "say",207+    "scale", "scan", "scare", "scatter", "scene", "scheme", "school", "science",208+    "scissors", "scorpion", "scout", "scrap", "screen", "script", "scrub", "sea",209+    "search", "season", "seat", "second", "secret", "section", "security", "seed",210+    "seek", "segment", "select", "sell", "seminar", "senior", "sense", "sentence",211+    "series", "service", "session", "settle", "setup", "seven", "shadow", "shaft",212+    "shallow", "share", "shed", "shell", "sheriff", "shield", "shift", "shine",213+    "ship", "shiver", "shock", "shoe", "shoot", "shop", "short", "shoulder",214+    "shove", "shrimp", "shrug", "shuffle", "shy", "sibling", "sick", "side",215+    "siege", "sight", "sign", "silent", "silk", "silly", "silver", "similar",216+    "simple", "since", "sing", "siren", "sister", "situate", "six", "size",217+    "skate", "sketch", "ski", "skill", "skin", "skirt", "skull", "slab",218+    "slam", "sleep", "slender", "slice", "slide", "slight", "slim", "slogan",219+    "slot", "slow", "slush", "small", "smart", "smile", "smoke", "smooth",220+    "snack", "snake", "snap", "sniff", "snow", "soap", "soccer", "social",221+    "sock", "soda", "soft", "solar", "soldier", "solid", "solution", "solve",222+    "someone", "song", "soon", "sorry", "sort", "soul", "sound", "soup",223+    "source", "south", "space", "spare", "spatial", "spawn", "speak", "special",224+    "speed", "spell", "spend", "sphere", "spice", "spider", "spike", "spin",225+    "spirit", "split", "spoil", "sponsor", "spoon", "sport", "spot", "spray",226+    "spread", "spring", "spy", "square", "squeeze", "squirrel", "stable", "stadium",227+    "staff", "stage", "stairs", "stamp", "stand", "start", "state", "stay",228+    "steak", "steel", "stem", "step", "stereo", "stick", "still", "sting",229+    "stock", "stomach", "stone", "stool", "story", "stove", "strategy", "street",230+    "strike", "strong", "struggle", "student", "stuff", "stumble", "style", "subject",231+    "submit", "subway", "success", "such", "sudden", "suffer", "sugar", "suggest",232+    "suit", "summer", "sun", "sunny", "sunset", "super", "supply", "supreme",233+    "sure", "surface", "surge", "surprise", "surround", "survey", "suspect", "sustain",234+    "swallow", "swamp", "swap", "swarm", "swear", "sweet", "swift", "swim",235+    "swing", "switch", "sword", "symbol", "symptom", "syrup", "system", "table",236+    "tackle", "tag", "tail", "talent", "talk", "tank", "tape", "target",237+    "task", "taste", "tattoo", "taxi", "teach", "team", "tell", "ten",238+    "tenant", "tennis", "tent", "term", "test", "text", "thank", "that",239+    "theme", "then", "theory", "there", "they", "thing", "this", "thought",240+    "three", "thrive", "throw", "thumb", "thunder", "ticket", "tide", "tiger",241+    "tilt", "timber", "time", "tiny", "tip", "tired", "tissue", "title",242+    "toast", "tobacco", "today", "toddler", "toe", "together", "toilet", "token",243+    "tomato", "tomorrow", "tone", "tongue", "tonight", "tool", "tooth", "top",244+    "topic", "topple", "torch", "tornado", "tortoise", "toss", "total", "tourist",245+    "toward", "tower", "town", "toy", "track", "trade", "traffic", "tragic",246+    "train", "transfer", "trap", "trash", "travel", "tray", "treat", "tree",247+    "trend", "trial", "tribe", "trick", "trigger", "trim", "trip", "trophy",248+    "trouble", "truck", "true", "truly", "trumpet", "trust", "truth", "try",249+    "tube", "tuition", "tumble", "tuna", "tunnel", "turkey", "turn", "turtle",250+    "twelve", "twenty", "twice", "twin", "twist", "two", "type", "typical",251+    "ugly", "umbrella", "unable", "unaware", "uncle", "uncover", "under", "undo",252+    "unfair", "unfold", "unhappy", "uniform", "unique", "unit", "universe", "unknown",253+    "unlock", "until", "unusual", "unveil", "update", "upgrade", "uphold", "upon",254+    "upper", "upset", "urban", "urge", "usage", "use", "used", "useful",255+    "useless", "usual", "utility", "vacant", "vacuum", "vague", "valid", "valley",256+    "valve", "van", "vanish", "vapor", "various", "vast", "vault", "vehicle",257+    "velvet", "vendor", "venture", "venue", "verb", "verify", "version", "very",258+    "vessel", "veteran", "viable", "vibrant", "vicious", "victory", "video", "view",259+    "village", "vintage", "violin", "virtual", "virus", "visa", "visit", "visual",260+    "vital", "vivid", "vocal", "voice", "void", "volcano", "volume", "vote",261+    "voyage", "wage", "wagon", "wait", "walk", "wall", "walnut", "want",262+    "warfare", "warm", "warrior", "wash", "wasp", "waste", "water", "wave",263+    "way", "wealth", "weapon", "wear", "weasel", "weather", "web", "wedding",264+    "weekend", "weird", "welcome", "west", "wet", "whale", "what", "wheat",265+    "wheel", "when", "where", "whip", "whisper", "wide", "width", "wife",266+    "wild", "will", "win", "window", "wine", "wing", "wink", "winner",267+    "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf", "woman",268+    "wonder", "wood", "wool", "word", "work", "world", "worry", "worth",269+    "wrap", "wreck", "wrestle", "wrist", "write", "wrong", "yard", "year",270+    "yellow", "you", "young", "youth", "zebra", "zero", "zone", "zoo",271+)272+273+/**274+ * The list shipped up to v2.4.12, which carried a duplicate "abandon" at index275+ * 1 and so was the canonical list shifted by one from index 1 onward. Phrases276+ * written down from those builds decode only under this ordering, so277+ * [wordsToRootKeyMaterial] falls back to it. Never used for display or for new278+ * vaults — decode only, and it will be removed once no such phrase can remain.279+ */280+val LEGACY_WORD_LIST: List<String> = listOf(281+    "abandon", "abandon", "ability", "able", "about", "above", "absent", "absorb",282+    "abstract", "absurd", "abuse", "access", "accident", "account", "accuse", "achieve",283+    "acid", "acoustic", "acquire", "across", "act", "action", "actor", "actress",284+    "actual", "adapt", "add", "addict", "address", "adjust", "admit", "adult",285+    "advance", "advice", "aerobic", "affair", "afford", "afraid", "again", "age",286+    "agent", "agree", "ahead", "aim", "air", "airport", "aisle", "alarm",287+    "album", "alcohol", "alert", "alien", "all", "alley", "allow", "almost",288+    "alone", "alpha", "already", "also", "alter", "always", "amateur", "amazing",289+    "among", "amount", "amused", "analyst", "anchor", "ancient", "anger", "angle",290+    "angry", "animal", "ankle", "announce", "annual", "another", "answer", "antenna",291+    "antique", "anxiety", "any", "apart", "apology", "appear", "apple", "approve",292+    "april", "arch", "arctic", "area", "arena", "argue", "arm", "armed",293+    "armor", "army", "around", "arrange", "arrest", "arrive", "arrow", "art",294+    "artefact", "artist", "artwork", "ask", "aspect", "assault", "asset", "assist",295+    "assume", "asthma", "athlete", "atom", "attack", "attend", "attitude", "attract",296+    "auction", "audit", "august", "aunt", "author", "auto", "autumn", "average",297+    "avocado", "avoid", "awake", "aware", "away", "awesome", "awful", "awkward",298+    "axis", "baby", "bachelor", "bacon", "badge", "bag", "balance", "balcony",299+    "ball", "bamboo", "banana", "banner", "bar", "barely", "bargain", "barrel",300+    "base", "basic", "basket", "battle", "beach", "bean", "beauty", "because",301+    "become", "beef", "before", "begin", "behave", "behind", "believe", "below",302+    "belt", "bench", "benefit", "best", "betray", "better", "between", "beyond",303+    "bicycle", "bid", "bike", "bind", "biology", "bird", "birth", "bitter",304+    "black", "blade", "blame", "blanket", "blast", "bleak", "bless", "blind",305+    "blood", "blossom", "blouse", "blue", "blur", "blush", "board", "boat",306+    "body", "boil", "bomb", "bone", "bonus", "book", "boost", "border",307+    "boring", "borrow", "boss", "bottom", "bounce", "box", "boy", "bracket",308+    "brain", "brand", "brass", "brave", "bread", "breeze", "brick", "bridge",309+    "brief", "bright", "bring", "brisk", "broccoli", "broken", "bronze", "broom",310+    "brother", "brown", "brush", "bubble", "buddy", "budget", "buffalo", "build",311+    "bulb", "bulk", "bullet", "bundle", "bunker", "burden", "burger", "burst",312+    "bus", "business", "busy", "butter", "buyer", "buzz", "cabbage", "cabin",313+    "cable", "cactus", "cage", "cake", "call", "calm", "camera", "camp",314+    "can", "canal", "cancel", "candy", "cannon", "canoe", "canvas", "canyon",315+    "capable", "capital", "captain", "car", "carbon", "card", "cargo", "carpet",316+    "carry", "cart", "case", "cash", "casino", "castle", "casual", "cat",317+    "catalog", "catch", "category", "cattle", "caught", "cause", "caution", "cave",318+    "ceiling", "celery", "cement", "census", "century", "cereal", "certain", "chair",319+    "chalk", "champion", "change", "chaos", "chapter", "charge", "chase", "chat",320+    "cheap", "check", "cheese", "chef", "cherry", "chest", "chicken", "chief",321+    "child", "chimney", "choice", "choose", "chronic", "chuckle", "chunk", "churn",322+    "cigar", "cinnamon", "circle", "citizen", "city", "civil", "claim", "clap",323+    "clarify", "claw", "clay", "clean", "clerk", "clever", "click", "client",324+    "cliff", "climb", "clinic", "clip", "clock", "clog", "close", "cloth",325+    "cloud", "clown", "club", "clump", "cluster", "clutch", "coach", "coast",326+    "coconut", "code", "coffee", "coil", "coin", "collect", "color", "column",327+    "combine", "come", "comfort", "comic", "common", "company", "concert", "conduct",328+    "confirm", "congress", "connect", "consider", "control", "convince", "cook", "cool",329+    "copper", "copy", "coral", "core", "corn", "correct", "cost", "cotton",330+    "couch", "country", "couple", "course", "cousin", "cover", "coyote", "crack",331+    "cradle", "craft", "cram", "crane", "crash", "crater", "crawl", "crazy",332+    "cream", "credit", "creek", "crew", "cricket", "crime", "crisp", "critic",333+    "crop", "cross", "crouch", "crowd", "crucial", "cruel", "cruise", "crumble",334+    "crunch", "crush", "cry", "crystal", "cube", "culture", "cup", "cupboard",335+    "curious", "current", "curtain", "curve", "cushion", "custom", "cute", "cycle",336+    "dad", "damage", "damp", "dance", "danger", "daring", "dash", "daughter",337+    "dawn", "day", "deal", "debate", "debris", "decade", "december", "decide",338+    "decline", "decorate", "decrease", "deer", "defense", "define", "defy", "degree",339+    "delay", "deliver", "demand", "demise", "denial", "dentist", "deny", "depart",340+    "depend", "deposit", "depth", "deputy", "derive", "describe", "desert", "design",341+    "desk", "despair", "destroy", "detail", "detect", "develop", "device", "devote",342+    "diagram", "dial", "diamond", "diary", "dice", "diesel", "diet", "differ",343+    "digital", "dignity", "dilemma", "dinner", "dinosaur", "direct", "dirt", "disagree",344+    "discover", "disease", "dish", "dismiss", "disorder", "display", "distance", "divert",345+    "divide", "divorce", "dizzy", "doctor", "document", "dog", "doll", "dolphin",346+    "domain", "donate", "donkey", "donor", "door", "dose", "double", "dove",347+    "draft", "dragon", "drama", "drastic", "draw", "dream", "dress", "drift",348+    "drill", "drink", "drip", "drive", "drop", "drum", "dry", "duck",349+    "dumb", "dune", "during", "dust", "dutch", "duty", "dwarf", "dynamic",350+    "eager", "eagle", "early", "earn", "earth", "easily", "east", "easy",351+    "echo", "ecology", "economy", "edge", "edit", "educate", "effort", "egg",352+    "eight", "either", "elbow", "elder", "electric", "elegant", "element", "elephant",353+    "elevator", "elite", "else", "embark", "embody", "embrace", "emerge", "emotion",354+    "employ", "empower", "empty", "enable", "enact", "end", "endless", "endorse",355+    "enemy", "energy", "enforce", "engage", "engine", "enhance", "enjoy", "enlist",356+    "enough", "enrich", "enroll", "ensure", "enter", "entire", "entry", "envelope",357+    "episode", "equal", "equip", "era", "erase", "erode", "erosion", "error",358+    "erupt", "escape", "essay", "essence", "estate", "eternal", "ethics", "evidence",359+    "evil", "evoke", "evolve", "exact", "example", "excess", "exchange", "excite",360+    "exclude", "excuse", "execute", "exercise", "exhaust", "exhibit", "exile", "exist",361+    "exit", "exotic", "expand", "expect", "expire", "explain", "expose", "express",362+    "extend", "extra", "eye", "eyebrow", "fabric", "face", "faculty", "fade",363+    "faint", "faith", "fall", "false", "fame", "family", "famous", "fan",364+    "fancy", "fantasy", "farm", "fashion", "fat", "fatal", "father", "fatigue",365+    "fault", "favorite", "feature", "february", "federal", "fee", "feed", "feel",366+    "female", "fence", "festival", "fetch", "fever", "few", "fiber", "fiction",367+    "field", "figure", "file", "film", "filter", "final", "find", "fine",368+    "finger", "finish", "fire", "firm", "first", "fiscal", "fish", "fit",369+    "fitness", "fix", "flag", "flame", "flash", "flat", "flavor", "flee",370+    "flight", "flip", "float", "flock", "floor", "flower", "fluid", "flush",371+    "fly", "foam", "focus", "fog", "foil", "fold", "follow", "food",372+    "foot", "force", "forest", "forget", "fork", "fortune", "forum", "forward",373+    "fossil", "foster", "found", "fox", "fragile", "frame", "frequent", "fresh",374+    "friend", "fringe", "frog", "front", "frost", "frown", "frozen", "fruit",375+    "fuel", "fun", "funny", "furnace", "fury", "future", "gadget", "gain",376+    "galaxy", "gallery", "game", "gap", "garage", "garbage", "garden", "garlic",377+    "garment", "gas", "gasp", "gate", "gather", "gauge", "gaze", "general",378+    "genius", "genre", "gentle", "genuine", "gesture", "ghost", "giant", "gift",379+    "giggle", "ginger", "giraffe", "girl", "give", "glad", "glance", "glare",380+    "glass", "glide", "glimpse", "globe", "gloom", "glory", "glove", "glow",381+    "glue", "goat", "goddess", "gold", "good", "goose", "gorilla", "gospel",382+    "gossip", "govern", "gown", "grab", "grace", "grain", "grant", "grape",383+    "grass", "gravity", "great", "green", "grid", "grief", "grit", "grocery",384+    "group", "grow", "grunt", "guard", "guess", "guide", "guilt", "guitar",385+    "gun", "gym", "habit", "hair", "half", "hammer", "hamster", "hand",386+    "happy", "harbor", "hard", "harsh", "harvest", "hat", "have", "hawk",387+    "hazard", "head", "health", "heart", "heavy", "hedgehog", "height", "hello",388+    "helmet", "help", "hen", "hero", "hidden", "high", "hill", "hint",389+    "hip", "hire", "history", "hobby", "hockey", "hold", "hole", "holiday",390+    "hollow", "home", "honey", "hood", "hope", "horn", "horror", "horse",391+    "hospital", "host", "hotel", "hour", "hover", "hub", "huge", "human",392+    "humble", "humor", "hundred", "hungry", "hunt", "hurdle", "hurry", "hurt",393+    "husband", "hybrid", "ice", "icon", "idea", "identify", "idle", "ignore",394+    "ill", "illegal", "illness", "image", "imitate", "immense", "immune", "impact",395+    "impose", "improve", "impulse", "inch", "include", "income", "increase", "index",396+    "indicate", "indoor", "industry", "infant", "inflict", "inform", "inhale", "inherit",397+    "initial", "inject", "injury", "inmate", "inner", "innocent", "input", "inquiry",398+    "insane", "insect", "inside", "inspire", "install", "intact", "interest", "into",399+    "invest", "invite", "involve", "iron", "island", "isolate", "issue", "item",400+    "ivory", "jacket", "jaguar", "jar", "jazz", "jealous", "jeans", "jelly",401+    "jewel", "job", "join", "joke", "journey", "joy", "judge", "juice",402+    "jump", "jungle", "junior", "junk", "just", "kangaroo", "keen", "keep",403+    "ketchup", "key", "kick", "kid", "kidney", "kind", "kingdom", "kiss",404+    "kit", "kitchen", "kite", "kitten", "kiwi", "knee", "knife", "knock",405+    "know", "lab", "label", "labor", "ladder", "lady", "lake", "lamp",406+    "language", "laptop", "large", "later", "latin", "laugh", "laundry", "lava",407+    "law", "lawn", "lawsuit", "layer", "lazy", "leader", "leaf", "learn",408+    "leave", "lecture", "left", "leg", "legal", "legend", "leisure", "lemon",409+    "lend", "length", "lens", "leopard", "lesson", "letter", "level", "liar",410+    "liberty", "library", "license", "life", "lift", "light", "like", "limb",411+    "limit", "link", "lion", "liquid", "list", "little", "live", "lizard",412+    "load", "loan", "lobster", "local", "lock", "logic", "lonely", "long",413+    "loop", "lottery", "loud", "lounge", "love", "loyal", "lucky", "luggage",414+    "lumber", "lunar", "lunch", "luxury", "lyrics", "machine", "mad", "magic",415+    "magnet", "maid", "mail", "main", "major", "make", "mammal", "man",416+    "manage", "mandate", "mango", "mansion", "manual", "maple", "marble", "march",417+    "margin", "marine", "market", "marriage", "mask", "mass", "master", "match",418+    "material", "math", "matrix", "matter", "maximum", "maze", "meadow", "mean",419+    "measure", "meat", "mechanic", "medal", "media", "melody", "melt", "member",420+    "memory", "mention", "menu", "mercy", "merge", "merit", "merry", "mesh",421+    "message", "metal", "method", "middle", "midnight", "milk", "million", "mimic",422+    "mind", "minimum", "minor", "minute", "miracle", "mirror", "misery", "miss",423+    "mistake", "mix", "mixed", "mixture", "mobile", "model", "modify", "mom",424+    "moment", "monitor", "monkey", "monster", "month", "moon", "moral", "more",425+    "morning", "mosquito", "mother", "motion", "motor", "mountain", "mouse", "move",426+    "movie", "much", "muffin", "mule", "multiply", "muscle", "museum", "mushroom",427+    "music", "must", "mutual", "myself", "mystery", "myth", "naive", "name",428+    "napkin", "narrow", "nasty", "nation", "nature", "near", "neck", "need",429+    "negative", "neglect", "neither", "nephew", "nerve", "nest", "net", "network",430+    "neutral", "never", "news", "next", "nice", "night", "noble", "noise",431+    "nominee", "noodle", "normal", "north", "nose", "notable", "note", "nothing",432+    "notice", "novel", "now", "nuclear", "number", "nurse", "nut", "oak",433+    "obey", "object", "oblige", "obscure", "observe", "obtain", "obvious", "occur",434+    "ocean", "october", "odor", "off", "offer", "office", "often", "oil",435+    "okay", "old", "olive", "olympic", "omit", "once", "one", "onion",436+    "online", "only", "open", "opera", "opinion", "oppose", "option", "orange",437+    "orbit", "orchard", "order", "ordinary", "organ", "orient", "original", "orphan",438+    "ostrich", "other", "outdoor", "outer", "output", "outside", "oval", "oven",439+    "over", "own", "owner", "oxygen", "oyster", "ozone", "pact", "paddle",440+    "page", "pair", "palace", "palm", "panda", "panel", "panic", "panther",441+    "paper", "parade", "parent", "park", "parrot", "party", "pass", "patch",442+    "path", "patient", "patrol", "pattern", "pause", "pave", "payment", "peace",443+    "peanut", "pear", "peasant", "pelican", "pen", "penalty", "pencil", "people",444+    "pepper", "perfect", "permit", "person", "pet", "phone", "photo", "phrase",445+    "physical", "piano", "picnic", "picture", "piece", "pig", "pigeon", "pill",446+    "pilot", "pink", "pioneer", "pipe", "pistol", "pitch", "pizza", "place",447+    "planet", "plastic", "plate", "play", "please", "pledge", "pluck", "plug",448+    "plunge", "poem", "poet", "point", "polar", "pole", "police", "pond",449+    "pony", "pool", "popular", "portion", "position", "possible", "post", "potato",450+    "pottery", "poverty", "powder", "power", "practice", "praise", "predict", "prefer",451+    "prepare", "present", "pretty", "prevent", "price", "pride", "primary", "print",452+    "priority", "prison", "private", "prize", "problem", "process", "produce", "profit",453+    "program", "project", "promote", "proof", "property", "prosper", "protect", "proud",454+    "provide", "public", "pudding", "pull", "pulp", "pulse", "pumpkin", "punch",455+    "pupil", "puppy", "purchase", "purity", "purpose", "purse", "push", "put",456+    "puzzle", "pyramid", "quality", "quantum", "quarter", "question", "quick", "quit",457+    "quiz", "quote", "rabbit", "raccoon", "race", "rack", "radar", "radio",458+    "rail", "rain", "raise", "rally", "ramp", "ranch", "random", "range",459+    "rapid", "rare", "rate", "rather", "raven", "raw", "razor", "ready",460+    "real", "reason", "rebel", "rebuild", "recall", "receive", "recipe", "record",461+    "recycle", "reduce", "reflect", "reform", "refuse", "region", "regret", "regular",462+    "reject", "relax", "release", "relief", "rely", "remain", "remember", "remind",463+    "remove", "render", "renew", "rent", "reopen", "repair", "repeat", "replace",464+    "report", "require", "rescue", "resemble", "resist", "resource", "response", "result",465+    "retire", "retreat", "return", "reunion", "reveal", "review", "reward", "rhythm",466+    "rib", "ribbon", "rice", "rich", "ride", "ridge", "rifle", "right",467+    "rigid", "ring", "riot", "ripple", "risk", "ritual", "rival", "river",468+    "road", "roast", "robot", "robust", "rocket", "romance", "roof", "rookie",469+    "room", "rose", "rotate", "rough", "round", "route", "royal", "rubber",470+    "rude", "rug", "rule", "run", "runway", "rural", "sad", "saddle",471+    "sadness", "safe", "sail", "salad", "salmon", "salon", "salt", "salute",472+    "same", "sample", "sand", "satisfy", "satoshi", "sauce", "sausage", "save",473+    "say", "scale", "scan", "scare", "scatter", "scene", "scheme", "school",474+    "science", "scissors", "scorpion", "scout", "scrap", "screen", "script", "scrub",475+    "sea", "search", "season", "seat", "second", "secret", "section", "security",476+    "seed", "seek", "segment", "select", "sell", "seminar", "senior", "sense",477+    "sentence", "series", "service", "session", "settle", "setup", "seven", "shadow",478+    "shaft", "shallow", "share", "shed", "shell", "sheriff", "shield", "shift",479+    "shine", "ship", "shiver", "shock", "shoe", "shoot", "shop", "short",480+    "shoulder", "shove", "shrimp", "shrug", "shuffle", "shy", "sibling", "sick",481+    "side", "siege", "sight", "sign", "silent", "silk", "silly", "silver",482+    "similar", "simple", "since", "sing", "siren", "sister", "situate", "six",483+    "size", "skate", "sketch", "ski", "skill", "skin", "skirt", "skull",484+    "slab", "slam", "sleep", "slender", "slice", "slide", "slight", "slim",485+    "slogan", "slot", "slow", "slush", "small", "smart", "smile", "smoke",486+    "smooth", "snack", "snake", "snap", "sniff", "snow", "soap", "soccer",487+    "social", "sock", "soda", "soft", "solar", "soldier", "solid", "solution",488+    "solve", "someone", "song", "soon", "sorry", "sort", "soul", "sound",489+    "soup", "source", "south", "space", "spare", "spatial", "spawn", "speak",490+    "special", "speed", "spell", "spend", "sphere", "spice", "spider", "spike",491+    "spin", "spirit", "split", "spoil", "sponsor", "spoon", "sport", "spot",492+    "spray", "spread", "spring", "spy", "square", "squeeze", "squirrel", "stable",493+    "stadium", "staff", "stage", "stairs", "stamp", "stand", "start", "state",494+    "stay", "steak", "steel", "stem", "step", "stereo", "stick", "still",495+    "sting", "stock", "stomach", "stone", "stool", "story", "stove", "strategy",496+    "street", "strike", "strong", "struggle", "student", "stuff", "stumble", "style",497+    "subject", "submit", "subway", "success", "such", "sudden", "suffer", "sugar",498+    "suggest", "suit", "summer", "sun", "sunny", "sunset", "super", "supply",499+    "supreme", "sure", "surface", "surge", "surprise", "surround", "survey", "suspect",500+    "sustain", "swallow", "swamp", "swap", "swarm", "swear", "sweet", "swift",501+    "swim", "swing", "switch", "sword", "symbol", "symptom", "syrup", "system",502+    "table", "tackle", "tag", "tail", "talent", "talk", "tank", "tape",503+    "target", "task", "taste", "tattoo", "taxi", "teach", "team", "tell",504+    "ten", "tenant", "tennis", "tent", "term", "test", "text", "thank",505+    "that", "theme", "then", "theory", "there", "they", "thing", "this",506+    "thought", "three", "thrive", "throw", "thumb", "thunder", "ticket", "tide",507+    "tiger", "tilt", "timber", "time", "tiny", "tip", "tired", "tissue",508+    "title", "toast", "tobacco", "today", "toddler", "toe", "together", "toilet",509+    "token", "tomato", "tomorrow", "tone", "tongue", "tonight", "tool", "tooth",510+    "top", "topic", "topple", "torch", "tornado", "tortoise", "toss", "total",511+    "tourist", "toward", "tower", "town", "toy", "track", "trade", "traffic",512+    "tragic", "train", "transfer", "trap", "trash", "travel", "tray", "treat",513+    "tree", "trend", "trial", "tribe", "trick", "trigger", "trim", "trip",514+    "trophy", "trouble", "truck", "true", "truly", "trumpet", "trust", "truth",515+    "try", "tube", "tuition", "tumble", "tuna", "tunnel", "turkey", "turn",516+    "turtle", "twelve", "twenty", "twice", "twin", "twist", "two", "type",517+    "typical", "ugly", "umbrella", "unable", "unaware", "uncle", "uncover", "under",518+    "undo", "unfair", "unfold", "unhappy", "uniform", "unique", "unit", "universe",519+    "unknown", "unlock", "until", "unusual", "unveil", "update", "upgrade", "uphold",520+    "upon", "upper", "upset", "urban", "urge", "usage", "use", "used",521+    "useful", "useless", "usual", "utility", "vacant", "vacuum", "vague", "valid",522+    "valley", "valve", "van", "vanish", "vapor", "various", "vast", "vault",523+    "vehicle", "velvet", "vendor", "venture", "venue", "verb", "verify", "version",524+    "very", "vessel", "veteran", "viable", "vibrant", "vicious", "victory", "video",525+    "view", "village", "vintage", "violin", "virtual", "virus", "visa", "visit",526+    "visual", "vital", "vivid", "vocal", "voice", "void", "volcano", "volume",527+    "vote", "voyage", "wage", "wagon", "wait", "walk", "wall", "walnut",528+    "want", "warfare", "warm", "warrior", "wash", "wasp", "waste", "water",529+    "wave", "way", "wealth", "weapon", "wear", "weasel", "weather", "web",530+    "wedding", "weekend", "weird", "welcome", "west", "wet", "whale", "what",531+    "wheat", "wheel", "when", "where", "whip", "whisper", "wide", "width",532+    "wife", "wild", "will", "win", "window", "wine", "wing", "wink",533+    "winner", "winter", "wire", "wisdom", "wise", "wish", "witness", "wolf",534+    "woman", "wonder", "wood", "wool", "word", "work", "world", "worry",535+    "worth", "wrap", "wreck", "wrestle", "wrist", "write", "wrong", "yard",536+    "year", "yellow", "you", "young", "youth", "zebra", "zero", "zone",2052537     "zoo",2053538 )

view file

app/src/main/java/com/peachpasswords/vault/RecoveryWords.kt+30 −22
@@ -35,13 +35,30 @@3535     return words3636 }3737 38-fun wordsToRootKeyMaterial(words: List<String>): ByteArray {38+/**39+ * Decode a phrase to its 16 bytes of word material.40+ *41+ * Tries the canonical list first, then [LEGACY_WORD_LIST] so a phrase written42+ * down from a build that shipped the duplicated-"abandon" ordering still43+ * recovers. Both orderings are checksum-verified, and the escrow this material44+ * unwraps is authenticated, so a phrase that decodes under the wrong ordering45+ * cannot silently yield the wrong vault.46+ */47+fun wordsToRootKeyMaterial(words: List<String>): ByteArray =48+    runCatching { decodeWith(words, WORD_LIST) }49+        .recoverCatching { canonicalFailure ->50+            runCatching { decodeWith(words, LEGACY_WORD_LIST) }51+                .getOrElse { throw canonicalFailure }52+        }53+        .getOrThrow()54+55+private fun decodeWith(words: List<String>, list: List<String>): ByteArray {3956     require(words.size == TOTAL_WORDS) { "exactly $TOTAL_WORDS words required" }4057 4158     val indices = IntArray(words.size)4259     for (i in words.indices) {4360         val word = words[i].trim().lowercase()44-        val index = WORD_LIST.indexOf(word)61+        val index = list.indexOf(word)4562         require(index >= 0) { "unknown word at position ${i + 1}: \"${words[i]}\"" }4663         indices[i] = index4764     }@@ -67,29 +84,20 @@6784 }6885 6986 /**70- * Generate a random 32-byte root key whose recovery words round-trip cleanly.87+ * Generate a random 32-byte root key and prove its words round-trip.7188  *72- * WORD_LIST carries "abandon" at both index 0 and 1 (a byte-identical parity copy73- * of the browser list), so `wordsToRootKeyMaterial` — which reconstructs entropy74- * via `indexOf` — cannot invert any phrase that `rootKeyToWords` emitted from75- * index 1; it throws on the checksum. The browser's `createVault` (`vault.ts:947`)76- * does NOT retry and therefore throws for those ~0.6% of root keys (a latent77- * reference bug). We deviate deliberately and safely: regenerate until the words78- * round-trip, yielding a strict, fully cross-compatible SUBSET of root keys. Any79- * vault created this way is recoverable by the browser too.89+ * The retry loop this used to carry existed only because the shipped word list90+ * duplicated "abandon" at index 1, which made ~0.6% of keys undecodable. The91+ * list is now the canonical 2048, so every key round-trips; the check stays as92+ * an assertion because shipping a key whose words cannot be typed back is the93+ * one failure this code must never allow.8094  */81-fun generateRecoverableRootKey(maxAttempts: Int = 64): ByteArray {82-    val rng = java.security.SecureRandom()83-    repeat(maxAttempts) {84-        val candidate = ByteArray(32).also(rng::nextBytes)85-        val words = rootKeyToWords(candidate)86-        val roundTrips = runCatching { wordsToRootKeyMaterial(words) }.isSuccess87-        if (roundTrips) return candidate88-        candidate.fill(0)95+fun generateRecoverableRootKey(): ByteArray {96+    val candidate = ByteArray(32).also(java.security.SecureRandom()::nextBytes)97+    check(runCatching { wordsToRootKeyMaterial(rootKeyToWords(candidate)) }.isSuccess) {98+        "generated a root key whose recovery words do not round-trip"8999     }90-    // Astronomically unlikely (P(fail)^64 with P(fail)≈0.006). Surface rather than91-    // ship a root key whose displayed words cannot be entered back.92-    throw IllegalStateException("could not generate a round-tripping root key")100+    return candidate93101 }94102 95103 /** Lowercase, unseparated hex of [bytes] — the exact ASCII the browser wraps in the escrow. */

view file

app/src/test/java/com/peachpasswords/vault/CrossPlatformRecoveryWordsTest.kt+87 −0
@@ -0,0 +1,87 @@1+package com.peachpasswords.vault2+3+import org.junit.Assert.assertEquals4+import org.junit.Assert.assertNotEquals5+import org.junit.Assert.assertTrue6+import org.junit.Test7+8+/**9+ * Recovery words are only a human-readable encoding of the root key's first 1610+ * bytes, so the two platforms MUST agree on the word list byte for byte. They11+ * did not: Android shipped a list with "abandon" duplicated at index 1, making12+ * it the canonical list shifted by one from index 1 on. The same vault printed13+ * different words on each platform, so a phrase written down on the phone14+ * restored nothing in the extension.15+ *16+ * The vector below is computed from the browser's canonical list17+ * (`src/shared/recovery-word-list.ts`) and is pinned identically in18+ * `src/background/recovery-words.test.ts`.19+ */20+class CrossPlatformRecoveryWordsTest {21+22+    private val vectorRootKey =23+        "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"24+25+    private val vectorWords = listOf(26+        "abandon", "math", "mimic", "master", "filter", "design",27+        "carbon", "crystal", "rookie", "group", "knife", "young",28+    )29+30+    @Test fun word_list_is_the_canonical_2048_with_no_duplicates() {31+        assertEquals(2048, WORD_LIST.size)32+        assertEquals(2048, WORD_LIST.toSet().size)33+        assertEquals("abandon", WORD_LIST.first())34+        assertEquals("ability", WORD_LIST[1])35+        assertEquals("zoo", WORD_LIST.last())36+    }37+38+    @Test fun words_match_the_browser_for_the_shared_vector() {39+        assertEquals(vectorWords, rootKeyToWords(hexToRootKey(vectorRootKey)))40+    }41+42+    @Test fun every_reachable_index_round_trips() {43+        // The old list failed exactly here: index 1 encoded to "abandon" and44+        // decoded back to 0. An 11-bit index reaches 0..2047, so all of it must.45+        for (index in 0 until 2048) {46+            assertEquals(47+                "index $index does not round-trip",48+                index,49+                WORD_LIST.indexOf(WORD_LIST[index]),50+            )51+        }52+    }53+54+    @Test fun random_root_keys_always_round_trip() {55+        val rng = java.util.Random(20260726)56+        repeat(20_000) {57+            val key = ByteArray(32).also(rng::nextBytes)58+            val material = wordsToRootKeyMaterial(rootKeyToWords(key))59+            assertTrue(material.copyOfRange(0, 16).contentEquals(key.copyOfRange(0, 16)))60+        }61+    }62+63+    @Test fun a_phrase_written_under_the_legacy_ordering_still_recovers() {64+        // What an affected phone displayed for the same root key. It must keep65+        // working: someone has this on paper.66+        val legacyWords = LEGACY_WORD_LIST.let { legacy ->67+            val key = hexToRootKey(vectorRootKey)68+            val canonical = rootKeyToWords(key)69+            // Same indices, rendered through the legacy ordering: the extra70+            // "abandon" at index 1 means legacy[i] is canonical[i - 1].71+            canonical.map { legacy[WORD_LIST.indexOf(it)] }72+        }73+        assertNotEquals(vectorWords, legacyWords)74+75+        val expected = hexToRootKey(vectorRootKey).copyOfRange(0, 16)76+        assertTrue(77+            wordsToRootKeyMaterial(legacyWords).copyOfRange(0, 16).contentEquals(expected),78+        )79+    }80+81+    @Test fun canonical_phrases_are_not_misread_as_legacy() {82+        val expected = hexToRootKey(vectorRootKey).copyOfRange(0, 16)83+        assertTrue(84+            wordsToRootKeyMaterial(vectorWords).copyOfRange(0, 16).contentEquals(expected),85+        )86+    }87+}

view file

app/src/test/java/com/peachpasswords/vault/RecoveryEscrowTest.kt+9 −2
@@ -136,9 +136,16 @@136136     // root key on both platforms.137137     @Test fun kat_matches_browser_algorithm() {138138         val rootKeyHex = "bfb2d5731a470e1b1a0ae9521f501ac5edad8b4ce8e064b76da4cb3cdf00b937"139+        // Corrected in v2.4.13. These were previously this platform's own140+        // output under a word list that duplicated "abandon" at index 1, so the141+        // vector was one position off the browser at every index >= 1 — this142+        // test asserted browser parity while pinning the divergence. Recomputed143+        // against the browser's canonical list; the material/HKDF/ciphertext144+        // vectors below are unchanged because they key off the root key bytes,145+        // not the word ordering.139146         val expectedWords = listOf(140-            "sauce", "notable", "frequent", "crucial", "ignore", "aspect",141-            "gym", "fringe", "faint", "whip", "alley", "merge",147+            "sausage", "note", "fresh", "cruel", "ill", "assault",148+            "habit", "frog", "faith", "whisper", "allow", "merit",142149         )143150         val wordMaterialHex = "bfb2d5731a470e1b1a0ae9521f501ac500000000000000000000000000000000"144151         val recoveryKeyHex = "06880fb677e5b1cd1a65de6340a605681a55c86268885d644117401a9effd990"

view file