@csrf-armor/core
Version:
Framework-agnostic CSRF protection core functionality
159 lines (157 loc) • 5.83 kB
TypeScript
import { TokenPayload } from "./types.js";
//#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;
//# sourceMappingURL=crypto.d.ts.map
//#endregion
export { generateNonce, generateSecureSecret, generateSignedToken, parseSignedToken, signUnsignedToken, timingSafeEqual, verifySignedToken };
//# sourceMappingURL=crypto.d.ts.map