UNPKG

xypriss-security

Version:

Advanced High-Performance Security Framework. Military-grade encryption, post-quantum resilience, and fortified data structures.

202 lines 8.78 kB
"use strict"; /*************************************************************************** * XyPriss Security - Advanced Hyper-Modular Security Framework * * @author NEHONIX (Nehonix-Team - https://github.com/Nehonix-Team) * @license Nehonix Open Source License (NOSL) * * Copyright (c) 2025 NEHONIX. All rights reserved. ****************************************************************************/ Object.defineProperty(exports, "__esModule", { value: true }); exports.EFF_FILENAMES = exports.MAX_GENERATE_LENGTH = exports.MIN_GENERATE_LENGTH = exports.CHARSETS = void 0; exports.loadEFFWordlist = loadEFFWordlist; exports.getWordlist = getWordlist; const fs_1 = require("fs"); const path_1 = require("path"); const constants_1 = require("../utils/constants"); const FALLBACK_WORDLIST_1 = require("./FALLBACK_WORDLIST"); // ─── Character Sets ─────────────────────────────────────────────────────────── exports.CHARSETS = { uppercase: constants_1.CHAR_SETS.UPPERCASE, lowercase: constants_1.CHAR_SETS.LOWERCASE, numbers: constants_1.CHAR_SETS.NUMBERS, symbols: constants_1.CHAR_SETS.SYMBOLS, similarChars: constants_1.CHAR_SETS.RSIMILAR_CHARS, }; /** Minimum length enforced on every `generate()` call. */ exports.MIN_GENERATE_LENGTH = 8; /** Maximum length enforced on every `generate()` call. */ exports.MAX_GENERATE_LENGTH = 512; /** * Canonical filenames used by the EFF for each wordlist variant. * Match the files available at: * https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt * https://www.eff.org/files/2016/09/08/eff_short_wordlist_1.txt * https://www.eff.org/files/2016/09/08/eff_short_wordlist_2_0.txt */ exports.EFF_FILENAMES = { large: "eff_large_wordlist.txt", short1: "eff_short_wordlist_1.txt", short2: "eff_short_wordlist_2_0.txt", }; /** * Parses a raw EFF `.txt` wordlist file and returns a deduplicated, * validated `readonly string[]` ready for use in `generatePassphrase()`. * * **Supported line formats (both are handled automatically):** * ``` * # Numbered (dice-index prefix, tab-separated): * 11111\tabacus * 11112\tabrupt * * # Plain (one word per line): * abacus * abrupt * ``` * * Lines that are empty, start with `#`, or produce a word of length < 2 * after stripping are silently ignored. * * @param options - File location and variant configuration. * @returns A readonly array of lowercased, trimmed words. * @throws `Error` if the file cannot be read or yields fewer than 10 words. * * @example * // Load from ./wordlists/eff_large_wordlist.txt * const words = loadEFFWordlist({ dir: "./wordlists", variant: "large" }); * * @example * // Load a custom EFF-format file * const words = loadEFFWordlist({ filePath: "/opt/security/my_words.txt" }); */ function loadEFFWordlist(options = {}) { const { dir, variant = "large", filePath } = options; // ── Resolve path ──────────────────────────────────────────────────────────── let absolutePath; if (filePath) { absolutePath = (0, path_1.resolve)(filePath); } else if (dir) { absolutePath = (0, path_1.resolve)(dir, exports.EFF_FILENAMES[variant]); } else { const fs = require("fs"); const targetFile = exports.EFF_FILENAMES[variant]; const possiblePaths = [ // 1. Direct sibling (production: dist/src/mods or dev: src/mods) (0, path_1.resolve)(__dirname, targetFile), // 2. process.cwd() fallback (0, path_1.resolve)(process.cwd(), "src", "mods", targetFile), (0, path_1.resolve)(process.cwd(), "dist", "src", "mods", targetFile), // 3. node_modules lookup (0, path_1.resolve)(process.cwd(), "node_modules", "xypriss-security", "dist", "src", "mods", targetFile), ]; for (const p of possiblePaths) { try { if (fs.existsSync(p)) { const stats = fs.statSync(p); if (stats.isFile()) { absolutePath = p; break; } } } catch (e) { // Ignore errors for specific path checks } } if (!absolutePath) { // Final fallback (will trigger caught exception in the read step) absolutePath = (0, path_1.resolve)(__dirname, targetFile); } } // ── Read file ─────────────────────────────────────────────────────────────── let raw; try { raw = (0, fs_1.readFileSync)(absolutePath, "utf-8"); } catch (err) { const msg = err instanceof Error ? err.message : String(err); throw new Error(`loadEFFWordlist: could not read wordlist file at "${absolutePath}". ` + `Ensure the EFF .txt file is present in the specified directory.\n` + `Original error: ${msg}`); } // ── Parse lines ───────────────────────────────────────────────────────────── const seen = new Set(); const words = []; for (const rawLine of raw.split(/\r?\n/)) { const line = rawLine.trim(); // Skip blank lines and comments if (line.length === 0 || line.startsWith("#")) continue; // Numbered format: "11111\tword" or "1-1-1-1-1\tword" // Plain format: "word" const word = line.includes("\t") ? line.split("\t")[1]?.trim().toLowerCase() : line.toLowerCase(); if (!word || word.length < 2) continue; // Deduplicate (paranoid guard — EFF lists should already be unique) if (!seen.has(word)) { seen.add(word); words.push(word); } } const WMLIMIT = 10; // ── Validate result ───────────────────────────────────────────────────────── if (words.length < WMLIMIT) { throw new Error(`loadEFFWordlist: file "${absolutePath}" yielded only ${words.length} valid word(s). ` + `Expected an EFF wordlist with at least ${WMLIMIT} entries.`); } return Object.freeze(words); } /** * Unified wordlist accessor: tries to load an EFF file, falls back to the * built-in list according to `allowFallback`. * * Use this function in `PasswordManager.generatePassphrase()` to stay * decoupled from both the file system and the hardcoded list. * * @param options - File location, variant, and fallback policy. * @returns A readonly array of words suitable for passphrase generation. * * @example * // Prefer the large EFF list; warn & fall back if absent * const words = getWordlist({ dir: "./assets/wordlists", variant: "large" }); * * @example * // Never fall back — throw if the file is missing * const words = getWordlist({ filePath: "./eff_large_wordlist.txt", allowFallback: false }); * * @example * // Only use the built-in list (no file needed) * const words = getWordlist({ allowFallback: "silent" }); * // → returns FALLBACK_WORDLIST without attempting any file read */ function getWordlist(options = {}) { const { allowFallback = "warn", ...loadOptions } = options; // If no file location is specified and fallback is allowed, skip the I/O // entirely and return the built-in list immediately. const hasFileHint = Boolean(loadOptions.filePath ?? loadOptions.dir); if (!hasFileHint && allowFallback !== false) { if (allowFallback === "warn") { console.warn("[PasswordMDict] No EFF wordlist path provided. " + "Using built-in 256-word fallback list. " + "For production use, supply `dir` or `filePath` pointing to an EFF .txt file."); } return FALLBACK_WORDLIST_1.FALLBACK_WORDLIST; } try { return loadEFFWordlist(loadOptions); } catch (err) { if (allowFallback === false) throw err; if (allowFallback === "warn") { console.warn(`[PasswordMDict] Failed to load EFF wordlist: ${err.message}\n` + `Falling back to built-in 256-word list.`); } return FALLBACK_WORDLIST_1.FALLBACK_WORDLIST; } } //# sourceMappingURL=PasswordMDict.js.map