'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generatePwd = void 0; const node_crypto_1 = __importDefault(require("node:crypto")); const CHARS = `!"#$%&'()*+,-./:;<=>?@[\]^_~{|}~`; const MAX_OFFSET = 20_000; const PWD_CHUNK_SIZE = 4; const normalizeNum = (value = 0, min, max) => { min = min ?? Number.MIN_SAFE_INTEGER; max = max ?? Number.MAX_SAFE_INTEGER; min = Math.min(min, max); max = Math.max(min, max); if (value < min) return min; if (value > max) return max; return value; }; const isBlank = (val) => { return val === undefined || val === null || val === '' || val.trim() === ''; }; const hash = async (data, encoding = 'base64') => { return node_crypto_1.default.createHash('sha512').update(data).digest(encoding); }; const slice = (str, sliceSize) => { sliceSize = normalizeNum(sliceSize, 1); return str.match(new RegExp(`.{1,${sliceSize}}`, 'g')) ?? []; }; const appendWithChar = (str, offset) => { return str + CHARS.charAt(Math.abs(offset) % CHARS.length); }; const generateKeyOffsets = async (key) => { return await hash(key) .then((hash) => slice(hash, 4)) .then((slices) => Promise.all(slices.map((slice) => hash(slice, 'hex')))) .then((hashes) => hashes.map((hash) => Number.parseInt(hash.slice(0, 8), 16))) .then((offsets) => offsets.map((offset) => Math.floor((offset / 0xffffffff) * MAX_OFFSET))); }; const generateSeed = async (phrase, minLength) => { const sliceSize = 4; const seed = await hash(phrase) .then((hash) => slice(hash, sliceSize)) .then((slices) => slices.map(appendWithChar)) .then((slices) => Promise.all(slices.map((slice) => hash(slice)))) .then((hashes) => hashes.flatMap((hash) => slice(hash, sliceSize))) .then((slices) => slices.map(appendWithChar)) .then((slices) => slices.join('')); return seed.length >= minLength ? seed : seed + (await generateSeed(seed, minLength - seed.length)); }; const generatePwd = async (phrase, key, length = 32) => { if (isBlank(phrase)) throw new Error('Phrase is required'); if (isBlank(key)) throw new Error('Key is required'); phrase = phrase.trim(); key = key.trim(); length = normalizeNum(length ?? 32, 16, 64); const offsets = await generateKeyOffsets(key); const lastPwdChunkSize = PWD_CHUNK_SIZE + (length % PWD_CHUNK_SIZE); const minSeedLength = Math.max(...offsets) + lastPwdChunkSize; const seed = await generateSeed(phrase + key, minSeedLength); const lastOffsetIndex = 0; return offsets .map((offset, i) => seed.slice(offset, offset + (i === lastOffsetIndex ? lastPwdChunkSize : PWD_CHUNK_SIZE))) .join('') .slice(0, length); }; exports.generatePwd = generatePwd;