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
JavaScript
;
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