UNPKG

fortify2-js

Version:

MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.

721 lines (718 loc) 25.6 kB
import { SecurityLevel, HashAlgorithm } from '../types.js'; import { SECURITY_DEFAULTS } from '../utils/constants.js'; import { stringToBuffer, bufferToBase32 } from '../utils/encoding.js'; import { StatsTracker } from '../utils/stats.js'; import { Hash } from './hash/hash-core.js'; import './hash/hash-types.js'; import 'crypto'; import './hash/hash-security.js'; import './hash/hash-advanced.js'; import '../algorithms/hash-algorithms.js'; import { Keys } from './keys.js'; import { SecureRandom } from './random/random-core.js'; import './random/random-types.js'; import './random/random-sources.js'; import 'nehonix-uri-processor'; import '../utils/memory/index.js'; import { RandomTokens } from './random/random-tokens.js'; import { Validators } from './validators.js'; import { constantTimeEqual, secureModPow, faultResistantEqual } from '../components/side-channel.js'; import { argon2Derive, balloonDerive } from '../components/memory-hard.js'; import { lamportGenerateKeypair, lamportSign, lamportVerify, ringLweGenerateKeypair, ringLweEncrypt, ringLweDecrypt } from '../components/post-quantum.js'; import { SecureBuffer, secureWipe } from '../components/secure-memory.js'; import { EntropyPool } from '../components/entropy-augmentation.js'; import { createCanary, createCanaryObject, createCanaryFunction, triggerCanary } from '../components/canary-tokens.js'; import { createAttestation, verifyAttestation, createLibraryAttestation, verifyLibraryAttestation } from '../components/attestation.js'; import { verifyRuntimeSecurity } from '../components/runtime-verification.js'; import { secureSerialize, secureDeserialize } from '../components/secure-serialization.js'; import { TamperEvidentLogger, LogLevel } from '../components/tamper-evident-logging.js'; import { bufferDataConverter } from '../utils/dataConverter.js'; import { SecureString } from '../components/secure-string/core/secure-string-core.js'; import '../components/secure-string/advanced/entropy-analyzer.js'; import '../components/secure-string/advanced/quantum-safe.js'; import '../components/secure-string/advanced/performance-monitor.js'; import { SecureObject } from '../components/secure-object/core/secure-object-core.js'; import 'nehoid'; /*************************************************************************** * FortifyJS - Secure Array Types * * This file contains type definitions for the SecureArray modular architecture * * @author Nehonix * * @license MIT * * Copyright (c) 2025 Nehonix. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ***************************************************************************** */ /** * Main class for the FortifyJS library */ class FortifyJS { /** * Generate a secure token with customizable options * @param options - Token generation options * @returns Secure random token */ static generateSecureToken(options = { entropy: "high", }) { const { length = SECURITY_DEFAULTS.TOKEN_LENGTH, includeUppercase = true, includeLowercase = true, includeNumbers = true, includeSymbols = false, maxValidityLength = 1024, excludeSimilarCharacters = false, entropy, } = options; // Validate inputs Validators.validateLength(length, 1, maxValidityLength); Validators.validateEntropyLevel(entropy); // Map entropy string to SecurityLevel enum const securityLevel = { standard: SecurityLevel.STANDARD, high: SecurityLevel.HIGH, maximum: SecurityLevel.MAXIMUM, }; return RandomTokens.generateSecureToken(length, { includeUppercase, includeLowercase, includeNumbers, includeSymbols, excludeSimilarCharacters, entropyLevel: securityLevel[entropy], }); } // PIN GENERATOR /** * Generate secure PIN * @param length - PIN length * @param options - Generation options * @returns Secure numeric PIN */ static generateSecurePIN(...args) { return RandomTokens.generateSecurePIN(...args); } /** * Generate recovery codes * @param count - Number of codes to generate * @param codeLength - Length of each code * @param options - Generation options * @returns Array of recovery codes */ static generateRecoveryCodes(...args) { return RandomTokens.generateRecoveryCodes(...args); } /** * Generate an API key with prefix and timestamp * @param options - API key generation options * @returns API key */ static generateAPIKey(options = {}) { // Handle string input (prefix) if (typeof options === "string") { options = { prefix: options }; } const { prefix = "", includeTimestamp = true, randomPartLength = SECURITY_DEFAULTS.API_KEY_RANDOM_LENGTH, separator = "_", } = options; // Validate inputs Validators.validateLength(randomPartLength, 16, 64); // Generate timestamp part (8 hex characters) const timestamp = includeTimestamp ? Math.floor(Date.now() / 1000) .toString(16) .padStart(8, "0") : ""; // Generate random part const randomPart = RandomTokens.generateSecureToken(randomPartLength, { includeUppercase: true, includeLowercase: true, includeNumbers: true, includeSymbols: false, entropyLevel: SecurityLevel.MAXIMUM, }); // Combine parts let apiKey = ""; if (prefix) { apiKey += prefix + separator; } if (includeTimestamp) { apiKey += timestamp + separator; } apiKey += randomPart; if (options.encoding) { let result = apiKey; const e = bufferDataConverter(stringToBuffer(randomPart), options.encoding, { onResult: (r) => (result = r), onBuffer: (b) => (result = b), }); if (e) return e; return result; } return apiKey; } /** * Generate a JWT secret with high entropy * @param length - Length of the secret * @returns High-entropy JWT secret */ static generateJWTSecret(length = 32, encoding) { // Validate inputs Validators.validateLength(length, 32, 128); // Generate a high-entropy secret const secr = RandomTokens.generateSecureToken(length, { includeUppercase: true, includeLowercase: true, includeNumbers: true, includeSymbols: true, entropyLevel: SecurityLevel.MAXIMUM, }); if (encoding) { let result = secr; // Initialize with default value const e = bufferDataConverter(stringToBuffer(secr), encoding, { onResult: (r) => (result = r), onBuffer: (b) => (result = b), }); if (e) return e; return result; } return secr; } /** * Generate a session token with built-in signature * @param options - Session token options * @returns Session token */ static generateSessionToken(options = {}) { const { userId, ipAddress, userAgent, expiresIn = SECURITY_DEFAULTS.SESSION_EXPIRATION, } = options; // Generate timestamp (seconds since epoch) const timestamp = Math.floor(Date.now() / 1000); // Calculate expiration const expiration = timestamp + expiresIn; // Generate nonce const nonce = RandomTokens.generateSecureToken(16, { includeUppercase: false, includeLowercase: true, includeNumbers: true, includeSymbols: false, }); // Build data part let data = `exp=${expiration}`; if (userId) { data += `,uid=${userId}`; } if (ipAddress) { data += `,ip=${ipAddress}`; } if (userAgent) { // Hash the user agent to keep the token size reasonable const uaHash = Hash.createSecureHash(userAgent, SecureRandom.generateSalt(), { algorithm: "sha256", outputFormat: "hex", }).substring(0, 16); data += `,ua=${uaHash}`; } // Generate signature const signatureInput = `${timestamp}.${nonce}.${data}`; const signature = Hash.createSecureHash(signatureInput, SecureRandom.generateSalt(), { algorithm: HashAlgorithm.SHA256, iterations: 1, outputFormat: "base64", }); // Combine all parts return `${timestamp}.${nonce}.${data}.${signature}`; } /** * Generate a TOTP secret for two-factor authentication * @returns Base32 encoded TOTP secret */ static generateTOTPSecret() { // Generate 20 bytes of random data (160 bits) const secretBytes = SecureRandom.getRandomBytes(20); // Encode as Base32 (standard for TOTP) return bufferToBase32(secretBytes).replace(/=/g, ""); } /** * Create a secure hash with configurable options * @param input - The input to hash * @param options - Hashing options * @returns The hash in the specified format */ static secureHash(...p) { return Hash.createSecureHash(...p); } /** * Verify that a hash matches the expected input * @param input - The input to verify * @param hash - The hash to verify against * @param options - Hashing options (must match those used to create the hash) * @returns True if the hash matches the input */ static verifyHash(...p) { return Hash.verifyHash(...p); } /** * Derive a key from a password or other input * @param input - The input to derive a key from * @param options - Key derivation options * @returns The derived key as a hex string */ static deriveKey(input, options = {}) { return Keys.deriveKey(input, options); } /** * Calculate password strength with detailed analysis * @param password - The password to analyze * @returns Password strength analysis */ static calculatePasswordStrength(password) { if (!password) { return { score: 0, feedback: ["Password is empty"], estimatedCrackTime: "Instant", analysis: { length: 0, entropy: 0, variety: 0, patterns: 100, }, }; } // Calculate basic metrics const length = password.length; const hasUppercase = /[A-Z]/.test(password); const hasLowercase = /[a-z]/.test(password); const hasNumbers = /[0-9]/.test(password); const hasSymbols = /[^A-Za-z0-9]/.test(password); // Calculate character variety score (0-25) let varietyScore = 0; if (hasUppercase) varietyScore += 6.25; if (hasLowercase) varietyScore += 6.25; if (hasNumbers) varietyScore += 6.25; if (hasSymbols) varietyScore += 6.25; // Calculate length score (0-40) const lengthScore = Math.min(40, length * 2); // Check for common patterns const patterns = [ /^[0-9]+$/, // All numbers /^[a-zA-Z]+$/, // All letters /^[a-z]+$/, // All lowercase /^[A-Z]+$/, // All uppercase /^(qwerty|asdfgh|zxcvbn)/i, // Keyboard patterns /^(password|admin|user)/i, // Common words /^(123|abc|xyz)/i, // Simple sequences /(.)\1{2,}/, // Repeated characters ]; // Calculate pattern penalty (0-35) let patternPenalty = 0; for (const pattern of patterns) { if (pattern.test(password)) { patternPenalty += 5; } } // Calculate entropy (0-35) let charsetSize = 0; if (hasUppercase) charsetSize += 26; if (hasLowercase) charsetSize += 26; if (hasNumbers) charsetSize += 10; if (hasSymbols) charsetSize += 33; const entropy = Math.log2(Math.pow(charsetSize, length)); const entropyScore = Math.min(35, entropy / 8); // Calculate final score (0-100) const rawScore = lengthScore + entropyScore + varietyScore - patternPenalty; const finalScore = Math.max(0, Math.min(100, rawScore)); // Generate feedback const feedback = []; if (length < 8) { feedback.push("Password is too short"); } if (!hasUppercase) { feedback.push("Add uppercase letters"); } if (!hasLowercase) { feedback.push("Add lowercase letters"); } if (!hasNumbers) { feedback.push("Add numbers"); } if (!hasSymbols) { feedback.push("Add symbols"); } if (patternPenalty > 10) { feedback.push("Avoid common patterns and sequences"); } // Estimate crack time let estimatedCrackTime = "Instant"; if (finalScore > 90) { estimatedCrackTime = "Centuries"; } else if (finalScore > 80) { estimatedCrackTime = "Decades"; } else if (finalScore > 70) { estimatedCrackTime = "Years"; } else if (finalScore > 60) { estimatedCrackTime = "Months"; } else if (finalScore > 50) { estimatedCrackTime = "Weeks"; } else if (finalScore > 40) { estimatedCrackTime = "Days"; } else if (finalScore > 30) { estimatedCrackTime = "Hours"; } else if (finalScore > 20) { estimatedCrackTime = "Minutes"; } else if (finalScore > 10) { estimatedCrackTime = "Seconds"; } return { score: Math.round(finalScore), feedback: feedback.length > 0 ? feedback : ["Password is strong"], estimatedCrackTime, analysis: { length: lengthScore, entropy: entropyScore, variety: varietyScore, patterns: patternPenalty, }, }; } /** * Run security tests to validate the library's functionality * @returns Security test results */ // public static runSecurityTests(sampleSize?: number) { // return runSecurityTests({ // generateToken: () => FortifyJS.generateSecureToken(), // hashFunction: (input: string) => FortifyJS.secureHash(input), // sampleSize, // }); // } /** * Get cryptographic operation statistics * @returns Current statistics */ static getStats() { return StatsTracker.getInstance().getStats(); } /** * Reset statistics */ static resetStats() { StatsTracker.getInstance().resetStats(); } // ===== ADVANCED SECURITY FEATURES ===== /** * Perform a constant-time comparison of two strings or arrays * This prevents timing attacks by ensuring the comparison takes the same * amount of time regardless of how many characters match * * @param a - First string or array to compare * @param b - Second string or array to compare * @returns True if the inputs are equal, false otherwise */ static constantTimeEqual(a, b) { return constantTimeEqual(a, b); } /** * Derive a key using memory-hard Argon2 algorithm * This is more resistant to hardware-based attacks than standard PBKDF2 * * @param password - Password to derive key from * @param options - Derivation options * @returns Derived key and metadata */ static deriveKeyMemoryHard(password, options = {}) { return argon2Derive(password, options); } /** * Derive a key using memory-hard Balloon algorithm * An alternative memory-hard algorithm with different security properties * * @param password - Password to derive key from * @param options - Derivation options * @returns Derived key and metadata */ static deriveKeyBalloon(password, options = {}) { return balloonDerive(password, options); } /** * Generate a post-quantum secure key pair using Lamport one-time signatures * This is resistant to attacks by quantum computers * * @returns Public and private key pair */ static generateQuantumResistantKeypair() { return lamportGenerateKeypair(); } /** * Sign a message using quantum-resistant Lamport signatures * * @param message - Message to sign * @param privateKey - Private key * @returns Signature */ static quantumResistantSign(message, privateKey) { return lamportSign(message, privateKey); } /** * Verify a quantum-resistant signature * * @param message - Message that was signed * @param signature - Signature to verify * @param publicKey - Public key * @returns True if the signature is valid */ static quantumResistantVerify(message, signature, publicKey) { return lamportVerify(message, signature, publicKey); } /** * Create a secure buffer that automatically zeros its contents when destroyed * * @param size - Size of the buffer in bytes * @param fill - Optional value to fill the buffer with * @returns Secure buffer */ static createSecureBuffer(size, fill) { return new SecureBuffer(size, fill); } /** * Create a secure string that can be explicitly cleared from memory * * @param value - Initial string value * @returns Secure string */ static createSecureString(value = "") { return new SecureString(value); } /** * Create a secure object that can store sensitive data and be explicitly cleared * * @param initialData - Initial data * @returns Secure object */ static createSecureObject(initialData) { return new SecureObject(initialData); } /** * Securely wipe a section of memory * * @param buffer - Buffer to wipe * @param start - Start position * @param end - End position */ static secureWipe(buffer, start = 0, end = buffer.length) { secureWipe(buffer, start, end); } /** * Get an enhanced entropy source that collects entropy from multiple sources * * @param poolSize - Size of the entropy pool in bytes * @param options - Entropy collection options * @returns Entropy pool instance */ static getEnhancedEntropySource(poolSize, options) { return EntropyPool.getInstance(poolSize, options); } /** * Create a canary token that can detect unauthorized access * * @param options - Canary options * @returns Canary token */ static createCanaryToken(options = {}) { return createCanary(options); } /** * Create a canary object that triggers when accessed * * @param target - Object to wrap with a canary * @param options - Canary options * @returns Proxy object that triggers the canary when accessed */ static createCanaryObject(target, options = {}) { return createCanaryObject(target, options); } /** * Create a canary function that triggers when called * * @param fn - Function to wrap with a canary * @param options - Canary options * @returns Function that triggers the canary when called */ static createCanaryFunction(fn, options = {}) { return createCanaryFunction(fn, options); } /** * Create a cryptographic attestation for data * * @param data - Data to attest * @param options - Attestation options * @returns Attestation string */ static createAttestation(data, options = {}) { return createAttestation(data, options); } /** * Verify a cryptographic attestation * * @param attestation - Attestation to verify * @param options - Verification options * @returns Verification result */ static verifyAttestation(attestation, options) { return verifyAttestation(attestation, options); } /** * Create an attestation for the library itself * * @param options - Attestation options * @returns Attestation string */ static createLibraryAttestation(options = {}) { return createLibraryAttestation(options); } /** * Verify a library attestation * * @param attestation - Attestation to verify * @param options - Verification options * @returns Verification result */ static verifyLibraryAttestation(attestation, options) { return verifyLibraryAttestation(attestation, options); } /** * Verify the security of the runtime environment * * @param options - Verification options * @returns Verification result */ static verifyRuntimeSecurity(options = {}) { return verifyRuntimeSecurity(options); } /** * Securely serialize data with protection against various attacks * * @param data - Data to serialize * @param options - Serialization options * @returns Serialization result */ static secureSerialize(data, options = {}) { return secureSerialize(data, options); } /** * Securely deserialize data * * @param serialized - Serialized data * @param options - Deserialization options * @returns Deserialization result */ static secureDeserialize(serialized, options = {}) { return secureDeserialize(serialized, options); } /** * Create a tamper-evident logger * * @param key - Secret key for hashing * @param storageKey - Key for storing logs in localStorage * @returns Tamper-evident logger */ static createTamperEvidentLogger(key, storageKey) { return new TamperEvidentLogger(key, storageKey); } /** * Get log level enum for tamper-evident logging * @returns Log level enum */ static getLogLevel() { return LogLevel; } /** * Perform secure modular exponentiation resistant to timing attacks * * @param base - Base value * @param exponent - Exponent value * @param modulus - Modulus value * @returns (base^exponent) mod modulus */ static secureModPow(base, exponent, modulus) { return secureModPow(base, exponent, modulus); } /** * Perform a fault-resistant comparison of two buffers * This is resistant to fault injection attacks * * @param a - First buffer to compare * @param b - Second buffer to compare * @returns True if the buffers are equal */ static faultResistantEqual(a, b) { return faultResistantEqual(a, b); } /** * Generate a Ring-LWE key pair for post-quantum encryption * * @returns Public and private key pair */ static generateRingLweKeypair() { return ringLweGenerateKeypair(); } /** * Encrypt data using Ring-LWE post-quantum encryption * * @param message - Message to encrypt * @param publicKey - Public key * @returns Encrypted message */ static ringLweEncrypt(message, publicKey) { return ringLweEncrypt(message, publicKey); } /** * Decrypt data using Ring-LWE post-quantum encryption * * @param ciphertext - Encrypted message * @param privateKey - Private key * @returns Decrypted message */ static ringLweDecrypt(ciphertext, privateKey) { return ringLweDecrypt(ciphertext, privateKey); } /** * Trigger a canary token * * @param token - Canary token to trigger * @param triggerContext - Additional context for the trigger * @returns True if the canary was triggered */ static triggerCanaryToken(token, triggerContext) { return triggerCanary(token, triggerContext); } } export { FortifyJS }; //# sourceMappingURL=crypto.js.map