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.

723 lines (719 loc) 26 kB
'use strict'; var types = require('../types.js'); var constants = require('../utils/constants.js'); var encoding = require('../utils/encoding.js'); var stats = require('../utils/stats.js'); var hashCore = require('./hash/hash-core.js'); require('./hash/hash-types.js'); require('crypto'); require('./hash/hash-security.js'); require('./hash/hash-advanced.js'); require('../algorithms/hash-algorithms.js'); var keys = require('./keys.js'); var randomCore = require('./random/random-core.js'); require('./random/random-types.js'); require('./random/random-sources.js'); require('nehonix-uri-processor'); require('../utils/memory/index.js'); var randomTokens = require('./random/random-tokens.js'); var validators = require('./validators.js'); var sideChannel = require('../components/side-channel.js'); var memoryHard = require('../components/memory-hard.js'); var postQuantum = require('../components/post-quantum.js'); var secureMemory = require('../components/secure-memory.js'); var entropyAugmentation = require('../components/entropy-augmentation.js'); var canaryTokens = require('../components/canary-tokens.js'); var attestation = require('../components/attestation.js'); var runtimeVerification = require('../components/runtime-verification.js'); var secureSerialization = require('../components/secure-serialization.js'); var tamperEvidentLogging = require('../components/tamper-evident-logging.js'); var dataConverter = require('../utils/dataConverter.js'); var secureStringCore = require('../components/secure-string/core/secure-string-core.js'); require('../components/secure-string/advanced/entropy-analyzer.js'); require('../components/secure-string/advanced/quantum-safe.js'); require('../components/secure-string/advanced/performance-monitor.js'); var secureObjectCore = require('../components/secure-object/core/secure-object-core.js'); require('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 = constants.SECURITY_DEFAULTS.TOKEN_LENGTH, includeUppercase = true, includeLowercase = true, includeNumbers = true, includeSymbols = false, maxValidityLength = 1024, excludeSimilarCharacters = false, entropy, } = options; // Validate inputs validators.Validators.validateLength(length, 1, maxValidityLength); validators.Validators.validateEntropyLevel(entropy); // Map entropy string to SecurityLevel enum const securityLevel = { standard: types.SecurityLevel.STANDARD, high: types.SecurityLevel.HIGH, maximum: types.SecurityLevel.MAXIMUM, }; return randomTokens.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.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.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 = constants.SECURITY_DEFAULTS.API_KEY_RANDOM_LENGTH, separator = "_", } = options; // Validate inputs validators.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.RandomTokens.generateSecureToken(randomPartLength, { includeUppercase: true, includeLowercase: true, includeNumbers: true, includeSymbols: false, entropyLevel: types.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 = dataConverter.bufferDataConverter(encoding.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$1) { // Validate inputs validators.Validators.validateLength(length, 32, 128); // Generate a high-entropy secret const secr = randomTokens.RandomTokens.generateSecureToken(length, { includeUppercase: true, includeLowercase: true, includeNumbers: true, includeSymbols: true, entropyLevel: types.SecurityLevel.MAXIMUM, }); if (encoding$1) { let result = secr; // Initialize with default value const e = dataConverter.bufferDataConverter(encoding.stringToBuffer(secr), encoding$1, { 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 = constants.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.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 = hashCore.Hash.createSecureHash(userAgent, randomCore.SecureRandom.generateSalt(), { algorithm: "sha256", outputFormat: "hex", }).substring(0, 16); data += `,ua=${uaHash}`; } // Generate signature const signatureInput = `${timestamp}.${nonce}.${data}`; const signature = hashCore.Hash.createSecureHash(signatureInput, randomCore.SecureRandom.generateSalt(), { algorithm: types.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 = randomCore.SecureRandom.getRandomBytes(20); // Encode as Base32 (standard for TOTP) return encoding.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 hashCore.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 hashCore.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.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 stats.StatsTracker.getInstance().getStats(); } /** * Reset statistics */ static resetStats() { stats.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 sideChannel.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 memoryHard.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 memoryHard.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 postQuantum.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 postQuantum.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 postQuantum.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 secureMemory.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 secureStringCore.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 secureObjectCore.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) { secureMemory.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 entropyAugmentation.EntropyPool.getInstance(poolSize, options); } /** * Create a canary token that can detect unauthorized access * * @param options - Canary options * @returns Canary token */ static createCanaryToken(options = {}) { return canaryTokens.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 canaryTokens.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 canaryTokens.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 attestation.createAttestation(data, options); } /** * Verify a cryptographic attestation * * @param attestation - Attestation to verify * @param options - Verification options * @returns Verification result */ static verifyAttestation(attestation$1, options) { return attestation.verifyAttestation(attestation$1, options); } /** * Create an attestation for the library itself * * @param options - Attestation options * @returns Attestation string */ static createLibraryAttestation(options = {}) { return attestation.createLibraryAttestation(options); } /** * Verify a library attestation * * @param attestation - Attestation to verify * @param options - Verification options * @returns Verification result */ static verifyLibraryAttestation(attestation$1, options) { return attestation.verifyLibraryAttestation(attestation$1, options); } /** * Verify the security of the runtime environment * * @param options - Verification options * @returns Verification result */ static verifyRuntimeSecurity(options = {}) { return runtimeVerification.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 secureSerialization.secureSerialize(data, options); } /** * Securely deserialize data * * @param serialized - Serialized data * @param options - Deserialization options * @returns Deserialization result */ static secureDeserialize(serialized, options = {}) { return secureSerialization.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 tamperEvidentLogging.TamperEvidentLogger(key, storageKey); } /** * Get log level enum for tamper-evident logging * @returns Log level enum */ static getLogLevel() { return tamperEvidentLogging.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 sideChannel.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 sideChannel.faultResistantEqual(a, b); } /** * Generate a Ring-LWE key pair for post-quantum encryption * * @returns Public and private key pair */ static generateRingLweKeypair() { return postQuantum.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 postQuantum.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 postQuantum.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 canaryTokens.triggerCanary(token, triggerContext); } } exports.FortifyJS = FortifyJS; //# sourceMappingURL=crypto.js.map