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.

377 lines (371 loc) 15.1 kB
'use strict'; var constants = require('../../utils/constants.js'); var randomCore = require('../random/random-core.js'); require('../random/random-types.js'); var crypto = require('crypto'); require('../random/random-sources.js'); require('nehonix-uri-processor'); require('../../utils/memory/index.js'); require('../../types.js'); var hashTypes = require('./hash-types.js'); var hashUtils = require('./hash-utils.js'); var hashValidator = require('./hash-validator.js'); var hashAlgorithms = require('../../algorithms/hash-algorithms.js'); var hashSecurity = require('./hash-security.js'); var hashAdvanced = require('./hash-advanced.js'); var hashEntropy = require('./hash-entropy.js'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto); /* --------------------------------------------------------------------------------------------- * Copyright (c) NEHONIX INC. All rights reserved. * Licensed under the MIT License. See LICENSE in the project root for license information. * ------------------------------------------------------------------------------------------- */ /** * Military-grade hashing functionality with enhanced security features * Modular architecture for maintainable and scalable hash operations */ class Hash { // ============================================================================ // PUBLIC API - Main hash functions // ============================================================================ /** * Create secure hash with military-grade security options * * IMPORTANT: This method automatically generates a random salt * when no salt is provided, resulting in different hashes for the same input. * This is designed for password hashing where randomness enhances security. * * For consistent hashes, either: * - Provide a fixed salt parameter, or * - Use Hash.create() method instead * * @param input - The input to hash * @param salt - Salt for the hash (if not provided, random salt is auto-generated) * @param options - Enhanced hashing options * @returns The hash in the specified format */ static createSecureHash(input, salt, options = {}) { const { strength = hashTypes.HashStrength.GOOD, memoryHard = false, quantumResistant = false, timingSafe = false, validateInput = true, secureWipe = true, algorithm = "sha256", iterations = constants.HASH_SECURITY_CONSTANTS.RECOMMENDED_ITERATIONS, pepper, outputFormat = "hex", } = options; // Validate input if requested if (validateInput) { hashValidator.HashValidator.validateHashInput(input, options); } // Generate salt if not provided let finalSalt = salt; if (!finalSalt) { const strengthConfig = hashUtils.HashUtils.getStrengthConfiguration(strength); finalSalt = randomCore.SecureRandom.getRandomBytes(strengthConfig.saltLength); } // Prepare enhanced options const enhancedOptions = { ...options, algorithm, iterations, salt: finalSalt, pepper, outputFormat, }; // Route to appropriate implementation based on options if (memoryHard) { return hashSecurity.HashSecurity.memoryHardHash(input, { ...enhancedOptions, outputFormat: outputFormat === "buffer" ? "buffer" : "hex", }).then((result) => { Hash.handleSecureWipe(input, finalSalt, pepper, secureWipe, result); return typeof result === "string" ? result : result.toString("hex"); }); } if (quantumResistant) { const result = hashSecurity.HashSecurity.quantumResistantHash(input, { ...enhancedOptions, outputFormat: outputFormat, }); return Hash.handleSecureWipe(input, finalSalt, pepper, secureWipe, result); } if (timingSafe) { const result = hashSecurity.HashSecurity.timingSafeHash(input, { ...enhancedOptions, outputFormat: outputFormat, }); return Hash.handleSecureWipe(input, finalSalt, pepper, secureWipe, result); } // Standard secure hash const result = hashAlgorithms.HashAlgorithms.secureHash(input, { ...enhancedOptions, outputFormat: outputFormat, }); return Hash.handleSecureWipe(input, finalSalt, pepper, secureWipe, result); } /** * Verify hash with secure comparison * @param input - Input to verify * @param expectedHash - Expected hash value * @param salt - Salt used in original hash * @param options - Verification options * @returns True if hash matches */ static verifyHash(input, expectedHash, salt, options = {}) { // For async operations, we need to handle them differently // Force synchronous verification by disabling async features const syncOptions = { ...options, memoryHard: false, timingSafe: false, // Disable timing-safe for verification to avoid async }; // Generate hash using the same method as createSecureHash const computedHash = Hash.createSecureHash(input, salt, syncOptions); // Convert both hashes to the same format for comparison const expectedStr = typeof expectedHash === "string" ? expectedHash : expectedHash.toString("hex"); const computedStr = typeof computedHash === "string" ? computedHash : computedHash.toString(); // Use timing-safe comparison return hashValidator.HashValidator.timingSafeEqual(computedStr, expectedStr); } /** * Async verify hash with secure comparison * @param input - Input to verify * @param expectedHash - Expected hash value * @param salt - Salt used in original hash * @param options - Verification options * @returns Promise resolving to true if hash matches */ static async verifyHashAsync(input, expectedHash, salt, options = {}) { // Generate hash using the same method as createSecureHash const computedHash = await Hash.createSecureHash(input, salt, options); // Convert both hashes to the same format for comparison const expectedStr = typeof expectedHash === "string" ? expectedHash : expectedHash.toString("hex"); const computedStr = typeof computedHash === "string" ? computedHash : computedHash.toString("hex"); // Use timing-safe comparison return hashValidator.HashValidator.timingSafeEqual(computedStr, expectedStr); } /** * Enhanced scrypt key derivation */ static deriveKeyScrypt(password, salt, keyLength = 32, options = {}) { const { N = 32768, r = 8, p = 1, encoding = "hex", validateStrength = true, } = options; // Validate password strength if requested if (validateStrength && typeof password === "string") { const strength = hashValidator.HashValidator.validatePasswordStrength(password); if (!strength.isSecure) { console.warn("Weak password detected:", strength.issues); } } const passwordBuffer = hashUtils.HashUtils.toBuffer(password); const saltBuffer = hashUtils.HashUtils.toBuffer(salt); // Use Node.js scrypt const crypto = require("crypto"); const derivedKey = crypto.scryptSync(passwordBuffer, saltBuffer, keyLength, { N, r, p, }); return hashUtils.HashUtils.formatOutput(derivedKey, encoding); } /** * Standard PBKDF2 key derivation * * BEHAVIOR: Uses Node.js crypto.pbkdf2Sync for reliable, standard PBKDF2 implementation. * Produces consistent results and is widely compatible. * With crypto: * @example * crypto.pbkdf2Sync( password, salt, iterations, keyLength, hashFunction ); * * @param password - Password to derive key from * @param salt - Salt for the derivation * @param iterations - Number of iterations (default: 100000) * @param keyLength - Desired key length in bytes (default: 32) * @param hashFunction - Hash function to use (default: "sha256") * @param outputFormat - Output format (default: "hex") * @returns PBKDF2 derived key */ static pbkdf2(password, salt, iterations = 100000, keyLength = 32, hashFunction = "sha256", outputFormat = "hex") { // const crypto = require("crypto"); const result = crypto__namespace.pbkdf2Sync(password, salt, iterations, keyLength, hashFunction); switch (outputFormat) { case "hex": return result.toString("hex"); case "base64": return result.toString("base64"); case "buffer": return result; default: return result.toString("hex"); } } // ============================================================================ // PRIVATE HELPER METHODS // ============================================================================ /** * Handle secure wipe if requested * IMPORTANT: Only wipe copies, not the original salt/pepper that might be needed for verification */ static handleSecureWipe(input, salt, pepper, secureWipe, result) { if (secureWipe) { // Create copies for wiping to avoid destroying original data let inputCopy = input; let saltCopy = undefined; let pepperCopy = undefined; // Only create copies for buffers (strings are immutable anyway) if (Buffer.isBuffer(salt) || salt instanceof Uint8Array) { saltCopy = Buffer.from(salt); } if (pepper && (Buffer.isBuffer(pepper) || pepper instanceof Uint8Array)) { pepperCopy = Buffer.from(pepper); } if (Buffer.isBuffer(input) || input instanceof Uint8Array) { inputCopy = Buffer.from(input); } // Wipe the copies, not the originals hashUtils.HashUtils.performSecureWipe(inputCopy, saltCopy, pepperCopy); } return result; } } // ============================================================================ // KEY DERIVATION FUNCTIONS // ============================================================================ /** * Enhanced PBKDF2 key derivation */ Hash.deriveKeyPBKDF2 = hashSecurity.HashSecurity.memoryHardHash; /** * Enhanced Argon2 key derivation */ Hash.deriveKeyArgon2 = hashSecurity.HashSecurity.memoryHardHash; // ============================================================================ // ADVANCED SECURITY FEATURES // ============================================================================ /** * Hardware Security Module (HSM) compatible hashing */ Hash.hsmCompatibleHash = hashSecurity.HashSecurity.hsmCompatibleHash; /** * Cryptographic agility hash */ Hash.agilityHash = hashAdvanced.HashAdvanced.agilityHash; /** * Side-channel attack resistant hashing */ Hash.sideChannelResistantHash = hashAdvanced.HashAdvanced.sideChannelResistantHash; /** * Real-time security monitoring */ Hash.monitorHashSecurity = hashSecurity.HashSecurity.monitorHashSecurity; // ============================================================================ // ENTROPY AND ANALYSIS // ============================================================================ /** * Analyze hash entropy */ Hash.analyzeHashEntropy = hashEntropy.HashEntropy.analyzeHashEntropy; /** * Generate entropy report */ Hash.generateEntropyReport = hashEntropy.HashEntropy.generateEntropyReport; /** * Perform randomness tests */ Hash.performRandomnessTests = hashEntropy.HashEntropy.performRandomnessTests; // ============================================================================ // VALIDATION AND UTILITIES // ============================================================================ /** * Validate password strength */ Hash.validatePasswordStrength = hashValidator.HashValidator.validatePasswordStrength; /** * Timing-safe string comparison */ Hash.timingSafeEqual = hashValidator.HashValidator.timingSafeEqual; /** * Validate salt quality */ Hash.validateSalt = hashValidator.HashValidator.validateSalt; // ============================================================================ // ADVANCED ALGORITHMS // ============================================================================ /** * Parallel hash processing */ Hash.parallelHash = hashAdvanced.HashAdvanced.parallelHash; /** * Streaming hash for large data */ Hash.createStreamingHash = hashAdvanced.HashAdvanced.createStreamingHash; /** * Merkle tree hash */ Hash.merkleTreeHash = hashAdvanced.HashAdvanced.merkleTreeHash; /** * Incremental hash */ Hash.incrementalHash = hashAdvanced.HashAdvanced.incrementalHash; /** * Hash chain */ Hash.hashChain = hashAdvanced.HashAdvanced.hashChain; // ============================================================================ // UTILITY FUNCTIONS // ============================================================================ /** * Format hash output */ Hash.formatOutput = hashUtils.HashUtils.formatOutput; /** * Get strength configuration */ Hash.getStrengthConfiguration = hashUtils.HashUtils.getStrengthConfiguration; /** * Get algorithm security level */ Hash.getAlgorithmSecurityLevel = hashUtils.HashUtils.getAlgorithmSecurityLevel; // ============================================================================ // LEGACY COMPATIBILITY (for backward compatibility) // ============================================================================ /** * Legacy secure hash method (for backward compatibility) * * BEHAVIOR: Produces consistent hashes for the same input (like CryptoJS). * This method does NOT auto-generate random salts, ensuring deterministic results. * * For password hashing with auto-salt generation, use Hash.createSecureHash() instead. */ Hash.create = hashAlgorithms.HashAlgorithms.secureHash; /** * Legacy HMAC creation (for backward compatibility) */ Hash.createSecureHMAC = hashAlgorithms.HashAlgorithms.createSecureHMAC; exports.Hash = Hash; //# sourceMappingURL=hash-core.js.map