/** * ETH Keystore Guided Bruteforce * * NO IDEA IF THIS SCRIPT STILL WORKS. * I just keep it now because it's a funny story to me. * * @description * A small script I used to bruteforce my ethereum password for a really old * wallet from list of possible passphrase combinations. It did the job at * that time (phew)! Originally built in node.js, I rejiggered to be a deno * app so I wouldn't need to push package.json, and to make importing json * files look cleaner. * * Required Files: * `keystore.json` is the wallet keystore * `template.json`` is nested array of word/phrase combinations * * @example deno run deno run wallet_guided_bruteforce.js */ import { bold, green, red, yellow } from "jsr:@std/fmt/colors"; import keythereum from "npm:keythereum"; import keystore from "./keystore.json" assert { type: "json" }; import passwordTemplate from "./template.json" assert { type: "json" }; const response = getPasswordCombinations(passwordTemplate) .find((password) => Boolean(checkPass(password))); if (!response) console.log(red(bold("Failed to find password"))); function checkPass(password) { try { const privateKey = keythereum.recover(password, keystore).toString("hex"); console.log(`0x${keystore.address}: 0x${privateKey}`); console.log(green(bold("FOUND PASSWORD", password))); return password; } catch (e) { console.log("tried", password); // Expected "bad-pass" error is mismatch. Anything else is sus. if (!(e.message || "").includes("authentication code mismatch")) { console.log( yellow(bold("Unexpected Error, please try previous password")), ); console.log(e); } } } function getPasswordCombinations(arr) { if (arr.length == 1) return arr[0]; const result = []; const allCasesOfRest = getPasswordCombinations(arr.slice(1)); // recur with the rest of array for (let i = 0; i < allCasesOfRest.length; i++) { for (let j = 0; j < arr[0].length; j++) { result.push(arr[0][j] + allCasesOfRest[i]); } } return result; } const exampleKeystoreJsonFile = { "version": 3, "id": "36ff6493-21a5-41f5-998f-ed8e53627ed2", "address": "a9f7d6911a3169289229b761099403db87581640", "crypto": { "ciphertext": "b09e6dfe731c092e4951b861b7c576dcd65834fdbbf3fd5c39e88a5510c2a0b0", "cipherparams": { "iv": "3e125a0889bbac987901b7007f2f571a", }, "cipher": "aes-128-ctr", "kdf": "scrypt", "kdfparams": { "dklen": 32, "salt": "58298ca71cf02f698780a1ba53a3efc1f4162c81296045214cfaecc75ce849e0", "n": 8192, "r": 8, "p": 1, }, "mac": "41f440e55e9da8e5075cb401cf9a66cff34d26eb3ca772a70ed9370c99f697a1", }, }; const exampleTemplateFile = [ ["one", "two", "three"], ["two", "two", "three"], ["one", "two", "three"], ["one", "two", "three"], ["one", "two", "three"], ];