import { timingSafeEqual } from "./crypto.js";
//#region src/tokens.ts
/**
* `@platform-modules/util/tokens` — opaque CSPRNG tokens (store the hash, never the token).
*/
function bytesToBase64Url(bytes) {
	let binary = "";
	for (const b of bytes) binary += String.fromCharCode(b);
	return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
/** N cryptographically-random bytes (default 32), base64url-encoded (no padding). */
function generateOpaqueToken(bytes = 32) {
	return bytesToBase64Url(crypto.getRandomValues(new Uint8Array(bytes)));
}
/** SHA-256 hex digest of `token` — the value stored in the DB. */
async function hashToken(token) {
	const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(token));
	return Array.from(new Uint8Array(digest)).map((b) => b.toString(16).padStart(2, "0")).join("");
}
/** True when `token` hashes to `hash`. Timing-safe — never `===`. */
async function verifyToken(token, hash) {
	const computed = await hashToken(token);
	return timingSafeEqual(computed, hash);
}
//#endregion
export { generateOpaqueToken, hashToken, verifyToken };
