UNPKG

xypriss-security

Version:

XyPriss Security is an advanced JavaScript security library designed for enterprise applications. It provides military-grade encryption, secure data structures, quantum-resistant cryptography, and comprehensive security utilities for modern web applicatio

357 lines (354 loc) 14.1 kB
import { HASH_SECURITY_CONSTANTS } from '../../utils/constants.js'; import { SecureRandom } from '../random/random-core.js'; import '../random/random-types.js'; import * as crypto from 'crypto'; import '../random/random-sources.js'; import 'nehonix-uri-processor'; import '../../utils/memory/index.js'; import '../../types.js'; import '../random/random-security.js'; import { HashStrength } from './hash-types.js'; import { HashUtils } from './hash-utils.js'; import { HashValidator } from './hash-validator.js'; import { HashAlgorithms } from '../../algorithms/hash-algorithms.js'; import { HashSecurity } from './hash-security.js'; import { HashAdvanced } from './hash-advanced.js'; import { HashEntropy } from './hash-entropy.js'; /* --------------------------------------------------------------------------------------------- * 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 = HashStrength.GOOD, memoryHard = false, quantumResistant = false, timingSafe = false, validateInput = true, secureWipe = true, algorithm = "sha256", iterations = HASH_SECURITY_CONSTANTS.RECOMMENDED_ITERATIONS, pepper, outputFormat = "hex", } = options; // Validate input if requested if (validateInput) { HashValidator.validateHashInput(input, options); } // Generate salt if not provided let finalSalt = salt; if (!finalSalt) { const strengthConfig = HashUtils.getStrengthConfiguration(strength); finalSalt = 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.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.quantumResistantHash(input, { ...enhancedOptions, outputFormat: outputFormat, }); return Hash.handleSecureWipe(input, finalSalt, pepper, secureWipe, result); } if (timingSafe) { const result = HashSecurity.timingSafeHash(input, { ...enhancedOptions, outputFormat: outputFormat, }); return Hash.handleSecureWipe(input, finalSalt, pepper, secureWipe, result); } // Standard secure hash const result = 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.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.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.validatePasswordStrength(password); if (!strength.isSecure) { console.warn("Weak password detected:", strength.issues); } } const passwordBuffer = HashUtils.toBuffer(password); const saltBuffer = HashUtils.toBuffer(salt); // Use Node.js scrypt const crypto = require("crypto"); const derivedKey = crypto.scryptSync(passwordBuffer, saltBuffer, keyLength, { N, r, p, }); return 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.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.performSecureWipe(inputCopy, saltCopy, pepperCopy); } return result; } } // ============================================================================ // KEY DERIVATION FUNCTIONS // ============================================================================ /** * Enhanced PBKDF2 key derivation */ Hash.deriveKeyPBKDF2 = HashSecurity.memoryHardHash; /** * Enhanced Argon2 key derivation */ Hash.deriveKeyArgon2 = HashSecurity.memoryHardHash; // ============================================================================ // ADVANCED SECURITY FEATURES // ============================================================================ /** * Hardware Security Module (HSM) compatible hashing */ Hash.hsmCompatibleHash = HashSecurity.hsmCompatibleHash; /** * Cryptographic agility hash */ Hash.agilityHash = HashAdvanced.agilityHash; /** * Side-channel attack resistant hashing */ Hash.sideChannelResistantHash = HashAdvanced.sideChannelResistantHash; /** * Real-time security monitoring */ Hash.monitorHashSecurity = HashSecurity.monitorHashSecurity; // ============================================================================ // ENTROPY AND ANALYSIS // ============================================================================ /** * Analyze hash entropy */ Hash.analyzeHashEntropy = HashEntropy.analyzeHashEntropy; /** * Generate entropy report */ Hash.generateEntropyReport = HashEntropy.generateEntropyReport; /** * Perform randomness tests */ Hash.performRandomnessTests = HashEntropy.performRandomnessTests; // ============================================================================ // VALIDATION AND UTILITIES // ============================================================================ /** * Validate password strength */ Hash.validatePasswordStrength = HashValidator.validatePasswordStrength; /** * Timing-safe string comparison */ Hash.timingSafeEqual = HashValidator.timingSafeEqual; /** * Validate salt quality */ Hash.validateSalt = HashValidator.validateSalt; // ============================================================================ // ADVANCED ALGORITHMS // ============================================================================ /** * Parallel hash processing */ Hash.parallelHash = HashAdvanced.parallelHash; /** * Streaming hash for large data */ Hash.createStreamingHash = HashAdvanced.createStreamingHash; /** * Merkle tree hash */ Hash.merkleTreeHash = HashAdvanced.merkleTreeHash; /** * Incremental hash */ Hash.incrementalHash = HashAdvanced.incrementalHash; /** * Hash chain */ Hash.hashChain = HashAdvanced.hashChain; // ============================================================================ // UTILITY FUNCTIONS // ============================================================================ /** * Format hash output */ Hash.formatOutput = HashUtils.formatOutput; /** * Get strength configuration */ Hash.getStrengthConfiguration = HashUtils.getStrengthConfiguration; /** * Get algorithm security level */ Hash.getAlgorithmSecurityLevel = 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.secureHash; /** * Legacy HMAC creation (for backward compatibility) */ Hash.createSecureHMAC = HashAlgorithms.createSecureHMAC; export { Hash }; //# sourceMappingURL=hash-core.js.map