houser-js-utils
Version:
A comprehensive collection of TypeScript utility functions for common development tasks including array manipulation, string processing, date handling, random number generation, validation, and much more.
1 lines • 10.3 kB
Source Map (JSON)
{"version":3,"file":"SecurityUtils.mjs","sources":["../src/SecurityUtils.ts"],"sourcesContent":["/**\n * @module SecurityUtils\n * @description A collection of utility functions for security operations including hashing, encryption, and validation.\n * @example\n * ```typescript\n * import { SecurityUtils } from 'houser-js-utils';\n *\n * // Generate secure hash\n * const hash = await SecurityUtils.hashString('password123');\n *\n * // Generate random token\n * const token = SecurityUtils.generateRandomToken(32);\n *\n * // Sanitize user input\n * const clean = SecurityUtils.sanitizeInput('<script>alert(\"xss\")</script>');\n * ```\n */\n\nexport const SecurityUtils = {\n /**\n * Decrypts a string using AES-GCM\n * @param encryptedData - Data to decrypt\n * @param key - Decryption key\n * @returns Decrypted data\n */\n async decrypt(encryptedData: string, key: string): Promise<string> {\n const decoder = new TextDecoder();\n const keyBuffer = new TextEncoder().encode(key);\n\n const cryptoKey = await crypto.subtle.importKey(\n \"raw\",\n keyBuffer,\n { name: \"AES-GCM\" },\n false,\n [\"decrypt\"]\n );\n\n const data = Uint8Array.from(atob(encryptedData), (c) => c.charCodeAt(0));\n const iv = data.slice(0, 12);\n const encrypted = data.slice(12);\n\n const decrypted = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv },\n cryptoKey,\n encrypted\n );\n\n return decoder.decode(decrypted);\n },\n\n /**\n * Encrypts a string using AES-GCM\n * @param data - Data to encrypt\n * @param key - Encryption key\n * @returns Encrypted data\n */\n async encrypt(data: string, key: string): Promise<string> {\n const encoder = new TextEncoder();\n const dataBuffer = encoder.encode(data);\n const keyBuffer = encoder.encode(key);\n\n const cryptoKey = await crypto.subtle.importKey(\n \"raw\",\n keyBuffer,\n { name: \"AES-GCM\" },\n false,\n [\"encrypt\"]\n );\n\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const encrypted = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n cryptoKey,\n dataBuffer\n );\n\n const result = new Uint8Array(iv.length + encrypted.byteLength);\n result.set(iv);\n result.set(new Uint8Array(encrypted), iv.length);\n\n return btoa(String.fromCharCode(...result));\n },\n\n /**\n * Generates a CSRF token\n * @returns CSRF token\n */\n async generateCsrfToken(): Promise<string> {\n return this.generateRandomString(32);\n },\n\n /**\n * Generates a random number between min and max\n * @param min - Minimum value (inclusive)\n * @param max - Maximum value (inclusive)\n * @returns Random number\n */\n async generateRandomNumber(min: number, max: number): Promise<number> {\n const range = max - min + 1;\n const bytesNeeded = Math.ceil(Math.log2(range) / 8);\n const maxNum = Math.pow(256, bytesNeeded);\n const maxRange = maxNum - (maxNum % range);\n\n let value;\n do {\n const buffer = new Uint8Array(bytesNeeded);\n crypto.getRandomValues(buffer);\n value = buffer.reduce((acc, byte) => (acc << 8) + byte, 0);\n } while (value >= maxRange);\n\n return min + (value % range);\n },\n\n /**\n * Generates a random string of specified length\n * @param length - Length of the random string\n * @returns Random string\n */\n async generateRandomString(length: number): Promise<string> {\n const chars =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n let result = \"\";\n const array = new Uint32Array(length);\n crypto.getRandomValues(array);\n for (let i = 0; i < length; i++) {\n result += chars[array[i] % chars.length];\n }\n return result;\n },\n\n /**\n * Generates a secure password\n * @param length - Length of the password\n * @returns Generated password\n */\n async generateSecurePassword(length = 16): Promise<string> {\n const upperChars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n const lowerChars = \"abcdefghijklmnopqrstuvwxyz\";\n const numberChars = \"0123456789\";\n const specialChars = '!@#$%^&*(),.?\":{}|<>';\n const allChars = upperChars + lowerChars + numberChars + specialChars;\n\n let password = \"\";\n password +=\n upperChars[await this.generateRandomNumber(0, upperChars.length - 1)];\n password +=\n lowerChars[await this.generateRandomNumber(0, lowerChars.length - 1)];\n password +=\n numberChars[await this.generateRandomNumber(0, numberChars.length - 1)];\n password +=\n specialChars[await this.generateRandomNumber(0, specialChars.length - 1)];\n\n for (let i = password.length; i < length; i++) {\n password +=\n allChars[await this.generateRandomNumber(0, allChars.length - 1)];\n }\n\n return password\n .split(\"\")\n .sort(() => Math.random() - 0.5)\n .join(\"\");\n },\n\n /**\n * Hashes a string using SHA-256\n * @param input - String to hash\n * @returns Hashed string\n */\n async hashString(input: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(input);\n const hash = await crypto.subtle.digest(\"SHA-256\", data);\n return Array.from(new Uint8Array(hash))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n },\n\n /**\n * Sanitizes HTML input to prevent XSS attacks\n * @param input - Input string to sanitize\n * @returns Sanitized string\n */\n sanitizeHtml: (input: string): string => {\n return input\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\"/g, \""\")\n .replace(/'/g, \"'\");\n },\n\n /**\n * Validates a CSRF token\n * @param token - Token to validate\n * @param storedToken - Stored token to compare against\n * @returns True if tokens match\n */\n validateCsrfToken: (token: string, storedToken: string): boolean => {\n return token === storedToken;\n },\n\n /**\n * Checks if a password meets security requirements\n * @param password - Password to check\n * @returns Object containing validation results\n */\n validatePassword: (password: string) => {\n const minLength = 8;\n const hasUpperCase = /[A-Z]/.test(password);\n const hasLowerCase = /[a-z]/.test(password);\n const hasNumbers = /\\d/.test(password);\n const hasSpecialChar = /[!@#$%^&*(),.?\":{}|<>]/.test(password);\n const isLongEnough = password.length >= minLength;\n\n return {\n isValid:\n isLongEnough &&\n hasUpperCase &&\n hasLowerCase &&\n hasNumbers &&\n hasSpecialChar,\n requirements: {\n minLength: isLongEnough,\n hasUpperCase,\n hasLowerCase,\n hasNumbers,\n hasSpecialChar,\n },\n };\n },\n};\n"],"names":[],"mappings":"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"}