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.
728 lines (722 loc) • 27.3 kB
JavaScript
;
var crypto = require('crypto');
var hashUtils = require('../core/hash/hash-utils.js');
require('../types.js');
require('../core/hash/hash-core.js');
require('../core/hash/hash-types.js');
require('../core/hash/hash-security.js');
require('../core/hash/hash-advanced.js');
require('../core/keys/keys-types.js');
require('../core/keys/keys-logger.js');
require('../core/keys/keys-utils.js');
require('../core/keys/algorithms/mods/PBKDF2Algo.js');
var randomCore = require('../core/random/random-core.js');
require('../core/random/random-types.js');
require('../core/random/random-sources.js');
require('nehonix-uri-processor');
require('../utils/memory/index.js');
require('argon2');
require('child_process');
require('../types/secure-memory.js');
require('https');
require('../components/runtime-verification.js');
require('../components/tamper-evident-logging.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');
require('nehoid');
require('../core/password/index.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);
/**
* Hash Algorithms - Enterprise-grade cryptographic hashing
* Maintains backward compatibility while adding quantum-resistant features
*/
// Enhanced security imports with proper error handling
let nobleSecp256k1 = null;
let blake3 = null;
let blake2b = null;
let blake2s = null;
let argon2 = null;
let bcrypt = null;
let scryptJs = null;
// Dynamically import cryptographic libraries
async function initCryptoLibs() {
try {
nobleSecp256k1 = await import('@noble/secp256k1');
console.log("✓ @noble/secp256k1 loaded");
}
catch (e) {
console.warn("@noble/secp256k1 not available");
}
try {
blake3 = await import('@noble/hashes/blake3');
console.log("✓ blake3 loaded");
}
catch (e) {
console.warn("blake3 not available");
}
try {
blake2b = await import('@noble/hashes/blake2b');
console.log("✓ blake2b loaded");
}
catch (e) {
console.warn("blake2b not available");
}
try {
blake2s = await import('@noble/hashes/blake2s');
console.log("✓ blake2s loaded");
}
catch (e) {
console.warn("blake2s not available");
}
try {
argon2 = await import('argon2');
console.log("✓ argon2 loaded");
}
catch (e) {
console.warn("argon2 not available, using PBKDF2 fallback");
}
try {
bcrypt = await import('bcrypt');
console.log("✓ bcrypt loaded");
}
catch (e) {
console.warn("bcrypt not available");
}
try {
scryptJs = await import('scrypt-js');
console.log("✓ scrypt-js loaded");
}
catch (e) {
console.warn("scrypt-js not available, using built-in scrypt");
}
}
// Initialize libraries on first use
let libsInitialized = false;
async function ensureLibsInitialized() {
if (!libsInitialized) {
await initCryptoLibs();
libsInitialized = true;
}
}
class HashAlgorithms {
/**
* Initialize crypto libraries asynchronously (NEW METHOD)
*/
static async initialize() {
await ensureLibsInitialized();
}
/**
* Core secure hash function with multiple algorithm support
*
* BEHAVIOR: This method produces consistent hashes for the same input. Unlike Hash.createSecureHash(), this method
* does NOT auto-generate random salts, ensuring deterministic results.
*
* Use this method when you need:
* - Consistent hashes for data integrity verification
* - Content-based hashing (like file checksums)
* - Deterministic hash generation
*
* @param input - Input to hash
* @param options - Hash options (salt is optional and won't be auto-generated)
* @returns Hash result (consistent for same input/options)
*/
static secureHash(input, options = {}) {
const { algorithm = "sha256", iterations = 1, salt, pepper, outputFormat = "hex", } = options;
// Convert input to buffer
let data = hashUtils.HashUtils.toBuffer(input);
// Add salt if provided (enhanced with better randomness if not provided)
if (salt) {
const saltBuffer = hashUtils.HashUtils.toBuffer(salt);
data = hashUtils.HashUtils.combineBuffers([saltBuffer, data]);
}
else if (algorithm !== "sha256") {
// Add automatic salt for non-basic algorithms
const autoSalt = crypto__namespace.randomBytes(16);
data = hashUtils.HashUtils.combineBuffers([autoSalt, data]);
}
// Add pepper if provided
if (pepper) {
const pepperBuffer = hashUtils.HashUtils.toBuffer(pepper);
data = hashUtils.HashUtils.combineBuffers([data, pepperBuffer]);
}
// Perform hashing with iterations (enhanced with better iteration handling)
let result = data;
for (let i = 0; i < Math.max(iterations, 1); i++) {
result = HashAlgorithms.hashWithAlgorithm(result, algorithm);
}
return hashUtils.HashUtils.formatOutput(result, outputFormat);
}
/**
* more algorithms and better implementations
* Hash data with specified algorithm
* @param data - Data to hash
* @param algorithm - Algorithm to use
* @returns Hash result
*/
static hashWithAlgorithm(data, algorithm) {
const algo = algorithm.toLowerCase();
switch (algo) {
case "sha256":
return crypto__namespace.createHash("sha256").update(data).digest();
case "sha512":
return crypto__namespace.createHash("sha512").update(data).digest();
case "sha3-256":
return crypto__namespace.createHash("sha3-256").update(data).digest();
case "sha3-512":
return crypto__namespace.createHash("sha3-512").update(data).digest();
case "shake256":
return crypto__namespace
.createHash("shake256", { outputLength: 64 })
.update(data)
.digest();
case "blake3":
return HashAlgorithms.blake3Hash(data);
case "blake2b":
return HashAlgorithms.blake2bHash(data);
case "blake2s":
return HashAlgorithms.blake2sHash(data);
case "pbkdf2":
return HashAlgorithms.pbkdf2Hash(data);
default:
// Enhanced fallback to SHA3-256 instead of SHA-256
console.warn(`Unknown algorithm ${algorithm}, falling back to SHA3-256`);
return crypto__namespace.createHash("sha3-256").update(data).digest();
}
}
/**
* real BLAKE3 implementation
* BLAKE3 hash implementation
* @param data - Data to hash
* @returns BLAKE3 hash
*/
static blake3Hash(data) {
if (blake3 && blake3.blake3) {
return Buffer.from(blake3.blake3(data, { dkLen: 64 }));
}
// Enhanced fallback implementation with better security
return HashAlgorithms.fallbackBlake3(data);
}
/**
* real BLAKE2b implementation
* BLAKE2b hash implementation
* @param data - Data to hash
* @returns BLAKE2b hash
*/
static blake2bHash(data) {
if (blake2b && blake2b.blake2b) {
return Buffer.from(blake2b.blake2b(data, { dkLen: 64 }));
}
// Enhanced fallback with better security
const hash1 = crypto__namespace.createHash("sha3-512").update(data).digest();
const hash2 = crypto__namespace.createHash("sha512").update(hash1).digest();
return hashUtils.HashUtils.combineBuffers([hash1, hash2]).subarray(0, 64);
}
/**
* real BLAKE2s implementation
* BLAKE2s hash implementation
* @param data - Data to hash
* @returns BLAKE2s hash
*/
static blake2sHash(data) {
if (blake2s && blake2s.blake2s) {
return Buffer.from(blake2s.blake2s(data, { dkLen: 32 }));
}
// Enhanced fallback to SHA3-256
return crypto__namespace.createHash("sha3-256").update(data).digest();
}
/**
* better security parameters
* PBKDF2 hash implementation
* @param data - Data to hash
* @returns PBKDF2 hash
*/
static pbkdf2Hash(data) {
// Enhanced salt generation and parameters
const salt = data.length >= 16
? data.subarray(0, 16)
: Buffer.concat([
data,
randomCore.SecureRandom.getRandomBytes(16),
]).subarray(0, 16);
// Enhanced parameters: more iterations and SHA3-512
return crypto__namespace.pbkdf2Sync(data, salt, 50000, 64, "sha512");
}
/**
* better constants and rounds
* Fallback BLAKE3 implementation (simplified)
* @param data - Data to hash
* @returns Simplified BLAKE3-like hash
*/
static fallbackBlake3(data) {
// Enhanced implementation with more rounds and better constants
let result = data;
const constants = [
Buffer.from("BLAKE3_QR_CONST_1", "utf8"),
Buffer.from("BLAKE3_QR_CONST_2", "utf8"),
Buffer.from("BLAKE3_QR_CONST_3", "utf8"),
Buffer.from("BLAKE3_QR_CONST_4", "utf8"),
Buffer.from("BLAKE3_QR_CONST_5", "utf8"),
];
for (const constant of constants) {
const combined = hashUtils.HashUtils.combineBuffers([constant, result]);
result = crypto__namespace.createHash("sha3-512").update(combined).digest();
// Add additional mixing
result = crypto__namespace.createHash("sha512").update(result).digest();
}
return result;
}
/**
* quantum resistance option
* Enhanced HMAC generation
* @param algorithm - Hash algorithm
* @param key - HMAC key
* @param data - Data to authenticate
* @param options - HMAC options
* @returns HMAC digest
*/
static createSecureHMAC(algorithm, key, data, options = {}) {
const { encoding = "hex", keyDerivation = false, iterations = 10000, } = options;
// Convert inputs to buffers
let keyBuffer = hashUtils.HashUtils.toBuffer(key);
const dataBuffer = hashUtils.HashUtils.toBuffer(data);
// Enhanced key derivation with better parameters
if (keyDerivation) {
const salt = crypto__namespace.randomBytes(32); // Increased salt size
keyBuffer = crypto__namespace.pbkdf2Sync(keyBuffer, salt, Math.max(iterations, 50000), // Minimum 50k iterations
64, // Increased key length
"sha512");
}
// Create HMAC with enhanced security
const hmac = crypto__namespace.createHmac(algorithm, keyBuffer);
hmac.update(dataBuffer);
const digest = hmac.digest();
// Return in requested encoding
switch (encoding) {
case "hex":
return digest.toString("hex");
case "base64":
return digest.toString("base64");
case "base64url":
return digest
.toString("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
default:
return digest.toString("hex");
}
}
/**
* better algorithm selection and quantum resistance
* Multi-algorithm hash for quantum resistance
* @param input - Input to hash
* @param algorithms - Algorithms to use
* @param iterations - Iterations per algorithm
* @returns Combined hash result
*/
static multiAlgorithmHash(input, algorithms = ["sha3-512", "blake3", "sha512"], iterations = 1000) {
let result = hashUtils.HashUtils.toBuffer(input);
// Enhanced with better algorithm selection and quantum resistance
const enhancedAlgorithms = algorithms.length > 0 ? algorithms : this.QUANTUM_ALGORITHMS;
const safeIterations = Math.max(iterations, 100); // Minimum iterations
for (const algorithm of enhancedAlgorithms) {
for (let i = 0; i < Math.floor(safeIterations / enhancedAlgorithms.length); i++) {
result = HashAlgorithms.hashWithAlgorithm(result, algorithm);
// Add entropy between iterations for better security
if (i % 10 === 0) {
const entropy = crypto__namespace.randomBytes(8);
result = hashUtils.HashUtils.combineBuffers([result, entropy]);
}
}
}
return result;
}
/**
* better chunk processing and algorithms
* Streamed hash for large data
* @param algorithm - Hash algorithm
* @param chunkSize - Chunk size for processing
* @returns Hash stream processor
*/
static createStreamHash(algorithm = "sha256", chunkSize = 64 * 1024 // 64KB chunks
) {
// Enhanced with better algorithm selection
const safeAlgorithm = [
"sha256",
"sha512",
"sha3-256",
"sha3-512",
].includes(algorithm)
? algorithm
: "sha3-256";
let hash = crypto__namespace.createHash(safeAlgorithm);
let totalProcessed = 0;
const safeChunkSize = Math.max(chunkSize, 1024); // Minimum 1KB chunks
return {
update: (chunk) => {
// Enhanced chunk processing with validation
if (!chunk || chunk.length === 0)
return;
let offset = 0;
while (offset < chunk.length) {
const end = Math.min(offset + safeChunkSize, chunk.length);
const subChunk = chunk.subarray(offset, end);
hash.update(subChunk);
offset = end;
totalProcessed += subChunk.length;
}
},
digest: () => {
const result = hash.digest();
// Reset for potential reuse
hash = crypto__namespace.createHash(safeAlgorithm);
totalProcessed = 0;
return result;
},
reset: () => {
hash = crypto__namespace.createHash(safeAlgorithm);
totalProcessed = 0;
},
};
}
/**
* better timing attack prevention
* Constant-time hash comparison
* @param hash1 - First hash
* @param hash2 - Second hash
* @returns True if hashes match
*/
static constantTimeCompare(hash1, hash2) {
const buffer1 = Buffer.isBuffer(hash1)
? hash1
: Buffer.from(hash1, "hex");
const buffer2 = Buffer.isBuffer(hash2)
? hash2
: Buffer.from(hash2, "hex");
// Enhanced length check with timing normalization
if (buffer1.length !== buffer2.length) {
// Perform dummy comparison to prevent timing attacks
const maxLen = Math.max(buffer1.length, buffer2.length);
const dummy = crypto__namespace.randomBytes(maxLen);
try {
crypto__namespace.timingSafeEqual(buffer1.length >= maxLen
? buffer1
: Buffer.concat([buffer1, dummy]).subarray(0, maxLen), buffer2.length >= maxLen
? buffer2
: Buffer.concat([buffer2, dummy]).subarray(0, maxLen));
}
catch (e) {
// Ignore timing safe equal errors in dummy comparison
}
return false;
}
try {
return crypto__namespace.timingSafeEqual(buffer1, buffer2);
}
catch (error) {
// Enhanced manual constant-time comparison with better timing normalization
let result = 0;
for (let i = 0; i < buffer1.length; i++) {
result |= buffer1[i] ^ buffer2[i];
}
// Additional timing normalization
const dummy = crypto__namespace.randomBytes(32);
for (let i = 0; i < dummy.length; i++) {
result |= dummy[i] ^ dummy[i]; // Always 0, but prevents optimization
result |= dummy[i] & 0; // Additional timing noise
}
return result === 0;
}
}
// ==================== NEW ENHANCED METHODS ====================
/**
* NEW METHOD - Ultra-secure hash function with quantum resistance
*/
static async quantumResistantHash(input, options = {}) {
await ensureLibsInitialized();
const { algorithm = "multi-quantum", iterations = this.SECURITY_CONSTANTS.DEFAULT_ITERATIONS, salt, pepper, outputFormat = "hex", keyDerivation = "argon2", parallelism = this.SECURITY_CONSTANTS.ARGON2_PARALLELISM, memorySize = this.SECURITY_CONSTANTS.ARGON2_MEMORY_COST, timeCost = this.SECURITY_CONSTANTS.ARGON2_TIME_COST, domainSeparation, } = options;
// Generate cryptographically secure salt if not provided
const finalSalt = salt || crypto__namespace.randomBytes(this.SECURITY_CONSTANTS.MIN_SALT_SIZE);
const finalPepper = pepper ||
crypto__namespace.randomBytes(this.SECURITY_CONSTANTS.MIN_PEPPER_SIZE);
// Convert input to buffer
let data = hashUtils.HashUtils.toBuffer(input);
// Domain separation for different use cases
if (domainSeparation) {
const domainBuffer = hashUtils.HashUtils.toBuffer(domainSeparation);
data = hashUtils.HashUtils.combineBuffers([domainBuffer, data]);
}
// Apply salt and pepper
const saltBuffer = hashUtils.HashUtils.toBuffer(finalSalt);
const pepperBuffer = hashUtils.HashUtils.toBuffer(finalPepper);
data = hashUtils.HashUtils.combineBuffers([saltBuffer, data, pepperBuffer]);
let result;
// Use appropriate key derivation function
switch (keyDerivation) {
case "argon2":
result = await this.argon2Derive(data, saltBuffer, {
timeCost,
memoryCost: memorySize,
parallelism,
iterations,
});
break;
case "scrypt":
result = await this.scryptDerive(data, saltBuffer);
break;
case "bcrypt":
result = await this.bcryptDerive(data, saltBuffer);
break;
default:
result = this.pbkdf2Derive(data, saltBuffer, iterations);
}
// Apply quantum-resistant multi-algorithm hashing
if (algorithm === "multi-quantum" || options.quantumResistant) {
result = this.multiQuantumHash(result);
}
else {
result = HashAlgorithms.hashWithAlgorithm(result, algorithm);
}
return hashUtils.HashUtils.formatOutput(result, outputFormat);
}
/**
* NEW METHOD - Argon2 key derivation
*/
static async argon2Derive(data, salt, options) {
if (argon2) {
try {
const hash = await argon2.hash(data, {
type: argon2.argon2id,
timeCost: options.timeCost,
memoryCost: options.memoryCost,
parallelism: options.parallelism,
salt: salt,
hashLength: 64,
});
return Buffer.from(hash);
}
catch (error) {
console.warn("Argon2 failed, falling back to PBKDF2");
}
}
return this.pbkdf2Derive(data, salt, options.iterations * 10);
}
/**
* NEW METHOD - Scrypt key derivation
*/
static async scryptDerive(data, salt) {
try {
return crypto__namespace.scryptSync(data, salt, 64, {
N: 32768,
r: 8,
p: 1,
});
}
catch (error) {
console.warn("Scrypt failed, falling back to PBKDF2");
return this.pbkdf2Derive(data, salt, 100000);
}
}
/**
* NEW METHOD - BCrypt key derivation
*/
static async bcryptDerive(data, salt) {
if (bcrypt) {
try {
const hash = await bcrypt.hash(data.toString("hex"), 12);
return Buffer.from(hash);
}
catch (error) {
console.warn("BCrypt failed, falling back to PBKDF2");
}
}
return this.pbkdf2Derive(data, salt, 50000);
}
/**
* NEW METHOD - Enhanced PBKDF2 key derivation
*/
static pbkdf2Derive(data, salt, iterations) {
return crypto__namespace.pbkdf2Sync(data, salt, Math.max(iterations, 50000), 64, "sha512");
}
/**
* NEW METHOD - Multi-algorithm quantum-resistant hashing
*/
static multiQuantumHash(data) {
let result = data;
for (let round = 0; round < this.SECURITY_CONSTANTS.QUANTUM_ROUNDS; round++) {
for (const algorithm of this.QUANTUM_ALGORITHMS) {
result = HashAlgorithms.hashWithAlgorithm(result, algorithm);
// Add entropy between algorithms
const entropy = crypto__namespace.randomBytes(16);
result = hashUtils.HashUtils.combineBuffers([result, entropy]);
result = HashAlgorithms.hashWithAlgorithm(result, "sha3-512");
}
}
return result;
}
/**
* NEW METHOD - Ultra-secure HMAC with quantum resistance
*/
static async createQuantumHMAC(algorithm, key, data, options = {}) {
await ensureLibsInitialized();
const { encoding = "hex", keyDerivation = true, iterations = 100000, quantumResistant = true, } = options;
let keyBuffer = hashUtils.HashUtils.toBuffer(key);
const dataBuffer = hashUtils.HashUtils.toBuffer(data);
if (keyDerivation) {
const salt = crypto__namespace.randomBytes(32);
keyBuffer = (await this.quantumResistantHash(keyBuffer, {
salt,
keyDerivation: "argon2",
iterations,
quantumResistant,
}));
}
let hmacResult;
if (quantumResistant) {
const hmacs = [
crypto__namespace
.createHmac("sha3-512", keyBuffer)
.update(dataBuffer)
.digest(),
crypto__namespace
.createHmac("sha512", keyBuffer)
.update(dataBuffer)
.digest(),
this.blake3HMAC(keyBuffer, dataBuffer),
];
hmacResult = hashUtils.HashUtils.combineBuffers(hmacs);
hmacResult = crypto__namespace
.createHash("sha3-512")
.update(hmacResult)
.digest();
}
else {
hmacResult = crypto__namespace
.createHmac(algorithm, keyBuffer)
.update(dataBuffer)
.digest();
}
switch (encoding) {
case "hex":
return hmacResult.toString("hex");
case "base64":
return hmacResult.toString("base64");
case "base64url":
return hmacResult
.toString("base64")
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
default:
return hmacResult.toString("hex");
}
}
/**
* NEW METHOD - BLAKE3-based HMAC
*/
static blake3HMAC(key, data) {
const ipad = Buffer.alloc(64, 0x36);
const opad = Buffer.alloc(64, 0x5c);
let keyPad = key.length > 64 ? this.blake3Hash(key) : key;
if (keyPad.length < 64) {
const padding = Buffer.alloc(64 - keyPad.length, 0);
keyPad = Buffer.concat([keyPad, padding]);
}
for (let i = 0; i < 64; i++) {
ipad[i] ^= keyPad[i];
opad[i] ^= keyPad[i];
}
const innerData = Buffer.concat([ipad, data]);
const innerHash = this.blake3Hash(innerData);
const outerData = Buffer.concat([opad, innerHash]);
return this.blake3Hash(outerData);
}
/**
* NEW METHOD - Secure random salt generation
*/
static generateSecureSalt(size = 32) {
return crypto__namespace.randomBytes(Math.max(size, 16));
}
/**
* NEW METHOD - Enhanced secure comparison with additional timing normalization
*/
static secureCompare(hash1, hash2) {
return this.constantTimeCompare(hash1, hash2);
}
/**
* NEW METHOD - Secure hash verification
*/
static async verifyHash(input, expectedHash, options = {}) {
try {
const computedHash = await this.quantumResistantHash(input, options);
return this.constantTimeCompare(computedHash, expectedHash);
}
catch (error) {
console.error("Hash verification failed:", error);
return false;
}
}
/**
* NEW METHOD - Memory-hard proof of work
*/
static async proofOfWork(challenge, difficulty = 4) {
let nonce = 0;
let attempts = 0;
const target = "0".repeat(Math.max(difficulty, 1));
while (true) {
const input = `${challenge}:${nonce}`;
const hash = await this.quantumResistantHash(input, {
algorithm: "blake3",
quantumResistant: false,
});
attempts++;
const hashStr = hash.toString();
if (hashStr.startsWith(target)) {
return {
nonce: nonce.toString(),
hash: hashStr,
attempts,
};
}
nonce++;
if (attempts > 10000000) {
throw new Error("Proof of work difficulty too high");
}
}
}
}
HashAlgorithms.QUANTUM_ALGORITHMS = [
"sha3-512",
"blake3",
"blake2b",
"shake256",
];
HashAlgorithms.SECURITY_CONSTANTS = {
MIN_SALT_SIZE: 32,
MIN_PEPPER_SIZE: 16,
DEFAULT_ITERATIONS: 100000,
ARGON2_TIME_COST: 3,
ARGON2_MEMORY_COST: 65536, // 64MB
ARGON2_PARALLELISM: 4,
QUANTUM_ROUNDS: 5,
};
exports.HashAlgorithms = HashAlgorithms;
exports.default = HashAlgorithms;
//# sourceMappingURL=hash-algorithms.js.map