UNPKG

@opendatalabs/vana-sdk

Version:

A TypeScript library for interacting with Vana Network smart contracts.

71 lines 2.64 kB
const PKCE_VERIFIER_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"; const PKCE_VERIFIER_MIN_LENGTH = 43; const PKCE_VERIFIER_MAX_LENGTH = 128; const PKCE_VERIFIER_DEFAULT_LENGTH = 64; const PKCE_VERIFIER_PATTERN = /^[A-Za-z0-9._~-]{43,128}$/; const PKCE_CHALLENGE_PATTERN = /^[A-Za-z0-9_-]{43}$/; function assertValidPkceVerifier(verifier) { if (!PKCE_VERIFIER_PATTERN.test(verifier)) { throw new RangeError( `PKCE verifier must match RFC 7636 \xA74.1: ${PKCE_VERIFIER_MIN_LENGTH}-${PKCE_VERIFIER_MAX_LENGTH} unreserved chars [A-Za-z0-9._~-]` ); } } function generatePkceVerifier(length = PKCE_VERIFIER_DEFAULT_LENGTH) { if (!Number.isInteger(length) || length < PKCE_VERIFIER_MIN_LENGTH || length > PKCE_VERIFIER_MAX_LENGTH) { throw new RangeError( `PKCE verifier length must be an integer between ${PKCE_VERIFIER_MIN_LENGTH} and ${PKCE_VERIFIER_MAX_LENGTH}` ); } const alphabetLen = PKCE_VERIFIER_ALPHABET.length; const acceptCutoff = Math.floor(256 / alphabetLen) * alphabetLen; const out = new Array(length); let filled = 0; const buffer = new Uint8Array(length * 2); while (filled < length) { crypto.getRandomValues(buffer); for (let i = 0; i < buffer.length && filled < length; i++) { const byte = buffer[i]; if (byte < acceptCutoff) { out[filled++] = PKCE_VERIFIER_ALPHABET[byte % alphabetLen]; } } } return out.join(""); } async function computePkceChallenge(verifier) { assertValidPkceVerifier(verifier); const bytes = new TextEncoder().encode(verifier); const digest = await crypto.subtle.digest("SHA-256", bytes); return base64UrlEncode(new Uint8Array(digest)); } async function verifyPkceChallenge(verifier, challenge) { if (!PKCE_VERIFIER_PATTERN.test(verifier)) return false; if (!PKCE_CHALLENGE_PATTERN.test(challenge)) return false; const computed = await computePkceChallenge(verifier); return constantTimeEqualString(computed, challenge); } function base64UrlEncode(bytes) { let binary = ""; for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); } function constantTimeEqualString(a, b) { if (a.length !== b.length) return false; let result = 0; for (let i = 0; i < a.length; i++) { result |= a.charCodeAt(i) ^ b.charCodeAt(i); } return result === 0; } export { PKCE_CHALLENGE_PATTERN, PKCE_VERIFIER_PATTERN, assertValidPkceVerifier, computePkceChallenge, generatePkceVerifier, verifyPkceChallenge }; //# sourceMappingURL=pkce.js.map