1import { describe, it, expect } from "vitest";23import { WORD_LIST } from "./recovery-word-list";4import { rootKeyToWords, wordsToRootKeyMaterial } from "./recovery-words";56789101112131415161718describe("recovery words — cross-platform word list", () => {19 const VECTOR_ROOT_KEY =20 "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff";2122 const VECTOR_WORDS = [23 "abandon", "math", "mimic", "master", "filter", "design",24 "carbon", "crystal", "rookie", "group", "knife", "young",25 ];2627 function hexToBytes(hex: string): Uint8Array {28 const out = new Uint8Array(hex.length / 2);29 for (let i = 0; i < out.length; i++) {30 out[i] = Number.parseInt(hex.slice(i * 2, i * 2 + 2), 16);31 }32 return out;33 }3435 it("is the canonical 2048-word list with no duplicates", () => {36 expect(WORD_LIST.length).toBe(2048);37 expect(new Set(WORD_LIST).size).toBe(2048);38 expect(WORD_LIST[0]).toBe("abandon");39 expect(WORD_LIST[1]).toBe("ability");40 expect(WORD_LIST[2047]).toBe("zoo");41 });4243 it("produces the shared vector Android pins", async () => {44 expect(await rootKeyToWords(hexToBytes(VECTOR_ROOT_KEY))).toEqual(VECTOR_WORDS);45 });4647 it("round-trips every reachable 11-bit index", () => {48 49 50 for (let index = 0; index < 2048; index++) {51 expect(WORD_LIST.indexOf(WORD_LIST[index]!)).toBe(index);52 }53 });5455 it("round-trips random root keys without exception", async () => {56 for (let i = 0; i < 500; i++) {57 const key = crypto.getRandomValues(new Uint8Array(32));58 const material = await wordsToRootKeyMaterial(await rootKeyToWords(key));59 expect(material.slice(0, 16)).toEqual(key.slice(0, 16));60 }61 });62});