{"version":3,"sources":["jsdelivr-header.js","/npm/altcha-lib@1.4.1/dist/index.js"],"names":[],"mappings":"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","file":"/npm/altcha-lib@1.4.1/dist/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/altcha-lib@1.4.1/dist/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","import { ab2hex, hash, hashHex, hmacHex, randomBytes, randomInt, } from './helpers.js';\nconst DEFAULT_MAX_NUMBER = 1e6;\nconst DEFAULT_SALT_LEN = 12;\nconst DEFAULT_ALG = 'SHA-256';\n/**\n * Creates a challenge for the client to solve.\n *\n * @param {ChallengeOptions} options - Options for creating the challenge.\n * @returns {Promise<Challenge>} The created challenge.\n */\nexport async function createChallenge(options) {\n    const algorithm = options.algorithm || DEFAULT_ALG;\n    const maxnumber = options.maxnumber || options.maxNumber || DEFAULT_MAX_NUMBER;\n    const saltLength = options.saltLength || DEFAULT_SALT_LEN;\n    const params = new URLSearchParams(options.params);\n    if (options.expires) {\n        params.set('expires', String(Math.floor(options.expires.getTime() / 1000)));\n    }\n    let salt = options.salt || ab2hex(randomBytes(saltLength));\n    // params.size doesn't work with Node 16\n    if (Object.keys(Object.fromEntries(params)).length) {\n        salt = salt + '?' + params.toString();\n    }\n    // Add a delimiter to prevent parameter splicing\n    if (!salt.endsWith('&')) {\n        salt = salt + '&';\n    }\n    const number = options.number === undefined ? randomInt(maxnumber) : options.number;\n    const challenge = await hashHex(algorithm, salt + number);\n    return {\n        algorithm,\n        challenge,\n        maxnumber,\n        salt,\n        signature: await hmacHex(algorithm, challenge, options.hmacKey),\n    };\n}\n/**\n * Extracts parameters from the payload.\n *\n * @param {string | Payload | Challenge} payload - The payload from which to extract parameters.\n * @returns {Record<string, string>} The extracted parameters.\n */\nexport function extractParams(payload) {\n    if (typeof payload === 'string') {\n        payload = JSON.parse(atob(payload));\n    }\n    return Object.fromEntries(new URLSearchParams(payload?.salt?.split('?')?.[1] || ''));\n}\n/**\n * Verifies the solution provided by the client.\n *\n * @param {string | Payload} payload - The payload to verify.\n * @param {string} hmacKey - The HMAC key used for verification.\n * @param {boolean} [checkExpires=true] - Whether to check if the challenge has expired.\n * @returns {Promise<boolean>} Whether the solution is valid.\n */\nexport async function verifySolution(payload, hmacKey, checkExpires = true) {\n    if (typeof payload === 'string') {\n        try {\n            payload = JSON.parse(atob(payload));\n        }\n        catch {\n            return false;\n        }\n    }\n    const params = extractParams(payload);\n    const expires = params.expires || params.expire;\n    if (checkExpires && expires) {\n        const date = new Date(parseInt(expires, 10) * 1000);\n        if (Number.isNaN(date.getTime()) || date.getTime() < Date.now()) {\n            return false;\n        }\n    }\n    const check = await createChallenge({\n        algorithm: payload.algorithm,\n        hmacKey,\n        number: payload.number,\n        salt: payload.salt,\n    });\n    return (check.challenge === payload.challenge &&\n        check.signature === payload.signature);\n}\n/**\n * Verifies the hash of form fields.\n *\n * @param {FormData | Record<string, unknown>} formData - The form data to verify.\n * @param {string[]} fields - The fields to include in the hash.\n * @param {string} fieldsHash - The expected hash of the fields.\n * @param {string} [algorithm=DEFAULT_ALG] - The hash algorithm to use.\n * @returns {Promise<boolean>} Whether the fields hash is valid.\n */\nexport async function verifyFieldsHash(formData, fields, fieldsHash, algorithm = DEFAULT_ALG) {\n    const data = formData instanceof FormData ? Object.fromEntries(formData) : formData;\n    const lines = [];\n    for (const field of fields) {\n        lines.push(String(data[field] || ''));\n    }\n    return (await hashHex(algorithm, lines.join('\\n'))) === fieldsHash;\n}\n/**\n * Verifies the server's signature.\n *\n * @param {string | ServerSignaturePayload} payload - The payload to verify.\n * @param {string} hmacKey - The HMAC key used for verification.\n * @returns {Promise<{verificationData: ServerSignatureVerificationData | null, verified: boolean}>} The verification result.\n */\nexport async function verifyServerSignature(payload, hmacKey) {\n    if (typeof payload === 'string') {\n        try {\n            payload = JSON.parse(atob(payload));\n        }\n        catch {\n            return {\n                verificationData: null,\n                verified: false,\n            };\n        }\n    }\n    const signature = await hmacHex(payload.algorithm, await hash(payload.algorithm, payload.verificationData), hmacKey);\n    let verificationData = null;\n    try {\n        const params = new URLSearchParams(payload.verificationData);\n        verificationData = {\n            ...Object.fromEntries(params),\n            expire: parseInt(params.get('expire') || '0', 10),\n            fields: params.get('fields')?.split(','),\n            reasons: params.get('reasons')?.split(','),\n            score: params.get('score')\n                ? parseFloat(params.get('score') || '0')\n                : undefined,\n            time: parseInt(params.get('time') || '0', 10),\n            verified: params.get('verified') === 'true',\n        };\n    }\n    catch {\n        // noop\n    }\n    return {\n        verificationData,\n        verified: payload.verified === true &&\n            verificationData?.verified === true &&\n            verificationData.expire > Math.floor(Date.now() / 1000) &&\n            payload.signature === signature,\n    };\n}\n/**\n * Solves a challenge by brute force.\n *\n * @param {string} challenge - The challenge to solve.\n * @param {string} salt - The salt used in the challenge.\n * @param {string} [algorithm='SHA-256'] - The hash algorithm used.\n * @param {number} [max=1e6] - The maximum number to try.\n * @param {number} [start=0] - The starting number.\n * @returns {{promise: Promise<Solution | null>, controller: AbortController}} The solution promise and abort controller.\n */\nexport function solveChallenge(challenge, salt, algorithm = 'SHA-256', max = 1e6, start = 0) {\n    const controller = new AbortController();\n    const startTime = Date.now();\n    const fn = async () => {\n        for (let n = start; n <= max; n += 1) {\n            if (controller.signal.aborted) {\n                return null;\n            }\n            const t = await hashHex(algorithm, salt + n);\n            if (t === challenge) {\n                return {\n                    number: n,\n                    took: Date.now() - startTime,\n                };\n            }\n        }\n        return null;\n    };\n    return {\n        promise: fn(),\n        controller,\n    };\n}\n/**\n * Solves a challenge using web workers for parallel computation.\n *\n * @param {string | URL | (() => Worker)} workerScript - The worker script or function to create a worker.\n * @param {number} concurrency - The number of workers to use.\n * @param {string} challenge - The challenge to solve.\n * @param {string} salt - The salt used in the challenge.\n * @param {string} [algorithm='SHA-256'] - The hash algorithm used.\n * @param {number} [max=1e6] - The maximum number to try.\n * @param {number} [startNumber=0] - The starting number.\n * @returns {Promise<Solution | null>} The solution, or null if not found.\n */\nexport async function solveChallengeWorkers(workerScript, concurrency, challenge, salt, algorithm = 'SHA-256', max = 1e6, startNumber = 0) {\n    const workers = [];\n    concurrency = Math.max(1, Math.min(16, concurrency));\n    for (let i = 0; i < concurrency; i++) {\n        if (typeof workerScript === 'function') {\n            workers.push(workerScript());\n        }\n        else {\n            workers.push(new Worker(workerScript, {\n                type: 'module',\n            }));\n        }\n    }\n    const step = Math.ceil(max / concurrency);\n    const solutions = await Promise.all(workers.map((worker, i) => {\n        const start = startNumber + i * step;\n        return new Promise((resolve) => {\n            worker.addEventListener('message', (message) => {\n                if (message.data) {\n                    for (const w of workers) {\n                        if (w !== worker) {\n                            w.postMessage({ type: 'abort' });\n                        }\n                    }\n                }\n                resolve(message.data);\n            });\n            worker.postMessage({\n                payload: {\n                    algorithm,\n                    challenge,\n                    max: start + step,\n                    salt,\n                    start,\n                },\n                type: 'work',\n            });\n        });\n    }));\n    for (const worker of workers) {\n        worker.terminate();\n    }\n    return solutions.find((solution) => !!solution) || null;\n}\nexport default {\n    createChallenge,\n    extractParams,\n    solveChallenge,\n    solveChallengeWorkers,\n    verifyFieldsHash,\n    verifyServerSignature,\n    verifySolution,\n};\n"]}