UNPKG

@csrf-armor/core

Version:

Framework-agnostic CSRF protection core functionality

157 lines (156 loc) 5.79 kB
import { TokenPayload } from "./types.mjs"; //#region src/crypto.d.ts /** * Generates a cryptographically secure random nonce. * * Creates a random hexadecimal string using the Web Crypto API's secure * random number generator. Used for preventing replay attacks and ensuring * token uniqueness across multiple generations. * * @public * @param length - Length of the nonce in bytes (default: 16 bytes = 32 hex chars) * @returns Hexadecimal string representing the random nonce * * @example * ```typescript * import { generateNonce } from '@csrf-armor/core'; * * // Generate default 32-character nonce * const nonce = generateNonce(); * console.log(nonce); // "a1b2c3d4e5f6789..." * * // Generate custom length nonce * const shortNonce = generateNonce(8); * console.log(shortNonce); // "a1b2c3d4e5f67890" * ``` */ declare function generateNonce(length?: number): string; /** * Generates a cryptographically secure secret key. * * Creates a random secret suitable for HMAC operations. This is used internally * when no secret is provided in the configuration. * * **Security Warning**: Secrets generated by this function will be different * on each application restart, invalidating existing tokens. For production * use, always provide a consistent secret key. * * @internal * @returns Base64-encoded random secret key */ declare function generateSecureSecret(): string; /** * Generates a cryptographically signed CSRF token with expiration. * * Creates a tamper-proof token that includes an expiration timestamp and * a random nonce, secured with an HMAC-SHA256 signature. The token format * is: `{expiration}.{nonce}.{signature}` * * @public * @param secret - Secret key for HMAC signing (must be consistent across requests) * @param expirySeconds - Token validity duration in seconds from now * @returns Promise resolving to the signed token string * * @example * ```typescript * import { generateSignedToken } from '@csrf-armor/core'; * * // Generate token valid for 1 hour * const token = await generateSignedToken('my-secret-key', 3600); * console.log(token); // "1640995200.a1b2c3d4e5f67890.signature..." * * // Generate short-lived token for sensitive operations * const shortToken = await generateSignedToken('my-secret-key', 300); // 5 minutes * ``` * * @throws {Error} If Web Crypto API is not available or signing fails */ declare function generateSignedToken(secret: string, expirySeconds: number): Promise<string>; /** * Parses and validates a signed CSRF token. * * Extracts the expiration timestamp and nonce from a signed token, * verifies the signature, and checks that the token hasn't expired. * Uses timing-safe comparison to prevent timing-based attacks. * * @public * @param token - The signed token string to parse * @param secret - Secret key used for signature verification * @returns Promise resolving to the validated token payload * * @example * ```typescript * import { parseSignedToken } from '@csrf-armor/core'; * * try { * const payload = await parseSignedToken(receivedToken, 'my-secret-key'); * console.log('Token expires at:', new Date(payload.exp * 1000)); * console.log('Token nonce:', payload.nonce); * } catch (error) { * if (error instanceof TokenExpiredError) { * console.log('Token has expired'); * } else if (error instanceof TokenInvalidError) { * console.log('Token is invalid:', error.message); * } * } * ``` * * @throws {TokenInvalidError} If token format is invalid or signature verification fails * @throws {TokenExpiredError} If token has expired based on current time */ declare function parseSignedToken(token: string, secret: string): Promise<TokenPayload>; /** * Signs an existing unsigned token with HMAC-SHA256. * * Takes a plain token string and appends a cryptographic signature, * creating a signed token in the format: `{token}.{signature}` * * @public * @param unsignedToken - The token string to sign * @param secret - Secret key for HMAC signing * @returns Promise resolving to the signed token * * @example * ```typescript * import { signUnsignedToken } from '@csrf-armor/core'; * * const plainToken = generateNonce(32); * const signedToken = await signUnsignedToken(plainToken, 'my-secret-key'); * console.log(signedToken); // "a1b2c3d4e5f67890.signature..." * ``` */ declare function signUnsignedToken(unsignedToken: string, secret: string): Promise<string>; /** * Verifies a signed token and extracts the original unsigned token. * * Validates the HMAC-SHA256 signature of a signed token and returns * the original unsigned token if verification succeeds. Uses timing-safe * comparison to prevent timing-based signature attacks. * * @public * @param signedToken - The signed token to verify (format: `{token}.{signature}`) * @param secret - Secret key used for signature verification * @returns Promise resolving to the original unsigned token * * @example * ```typescript * import { verifySignedToken } from '@csrf-armor/core'; * * try { * const originalToken = await verifySignedToken( * 'a1b2c3d4e5f67890.signature...', * 'my-secret-key' * ); * console.log('Original token:', originalToken); // "a1b2c3d4e5f67890" * } catch (error) { * console.log('Token verification failed:', error.message); * } * ``` * * @throws {TokenInvalidError} If token format is invalid or signature verification fails */ declare function verifySignedToken(signedToken: string, secret: string): Promise<string>; declare function timingSafeEqual(a: string, b: string): boolean; //#endregion export { generateNonce, generateSecureSecret, generateSignedToken, parseSignedToken, signUnsignedToken, timingSafeEqual, verifySignedToken }; //# sourceMappingURL=crypto.d.mts.map