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.

340 lines (336 loc) 11.5 kB
'use strict'; var crypto = require('crypto'); var randomGenerators = require('./random-generators.js'); var Uint8Array = require('../../helpers/Uint8Array.js'); /** * Random crypto - Cryptographic utilities (IV, keys, nonces) */ class RandomCrypto { /** * Generate secure nonce/IV for encryption * @param algorithm - Algorithm requiring the nonce * @param options - Generation options * @returns Nonce as Uint8Array */ static generateNonce(algorithm, options = {}) { let length; switch (algorithm) { case "aes-gcm": length = 12; // 96 bits recommended for AES-GCM break; case "chacha20-poly1305": length = 12; // 96 bits for ChaCha20-Poly1305 break; case "aes-cbc": length = 16; // 128 bits for AES-CBC break; case "custom": length = options.customLength || 16; break; default: throw new Error(`Unsupported algorithm: ${algorithm}`); } return randomGenerators.RandomGenerators.getRandomBytes(length, options); } /** * Generate a secure Initialization Vector (IV) for encryption algorithms * @param length - Length of the IV in bytes * @param options - Generation options including algorithm * @returns Secure IV as EnhancedUint8Array */ static generateSecureIV(length, options = {}) { const { algorithm, quantumSafe = false, useEntropyPool = true, validateSize = true, } = options; if (length <= 0) { throw new Error("IV length must be positive"); } // If algorithm is specified, validate the length matches expected size if (algorithm && validateSize) { const expectedSizes = { "aes-128-cbc": 16, "aes-192-cbc": 16, "aes-256-cbc": 16, "aes-128-ctr": 16, "aes-192-ctr": 16, "aes-256-ctr": 16, "aes-128-gcm": 12, "aes-192-gcm": 12, "aes-256-gcm": 12, chacha20: 12, "chacha20-poly1305": 12, "des-ede3-cbc": 8, "blowfish-cbc": 8, }; const expectedSize = expectedSizes[algorithm]; if (expectedSize && length !== expectedSize) { console.warn(`Warning: IV length ${length} bytes does not match recommended ${expectedSize} bytes for ${algorithm}`); } } // Generate secure random bytes for IV const iv = randomGenerators.RandomGenerators.getRandomBytes(length, { quantumSafe, useEntropyPool, }); return new Uint8Array.EnhancedUint8Array(iv); } /** * Generate multiple IVs efficiently * @param count - Number of IVs to generate * @param length - Length of each IV * @param options - Generation options * @returns Array of IVs */ static generateSecureIVBatch(count, length, options = {}) { if (count <= 0 || count > 1000) { throw new Error("Count must be between 1 and 1000"); } const ivs = []; // Generate all random bytes at once for efficiency const allBytes = randomGenerators.RandomGenerators.getRandomBytes(length * count, options); for (let i = 0; i < count; i++) { const offset = i * length; const ivBytes = allBytes.slice(offset, offset + length); ivs.push(new Uint8Array.EnhancedUint8Array(ivBytes)); } return ivs; } /** * Generate IV for specific algorithm * @param algorithm - Encryption algorithm * @param options - Generation options * @returns Algorithm-specific IV */ static generateSecureIVForAlgorithm(algorithm, options = {}) { const algorithmSizes = { "aes-128-cbc": 16, "aes-192-cbc": 16, "aes-256-cbc": 16, "aes-128-ctr": 16, "aes-192-ctr": 16, "aes-256-ctr": 16, "aes-128-gcm": 12, "aes-192-gcm": 12, "aes-256-gcm": 12, chacha20: 12, "chacha20-poly1305": 12, "des-ede3-cbc": 8, "blowfish-cbc": 8, }; const length = algorithmSizes[algorithm.toLowerCase()]; if (!length) { throw new Error(`Unsupported algorithm: ${algorithm}`); } return RandomCrypto.generateSecureIV(length, { ...options, algorithm: algorithm, }); } /** * Generate multiple IVs for specific algorithm * @param count - Number of IVs to generate * @param algorithm - Encryption algorithm * @param options - Generation options * @returns Array of algorithm-specific IVs */ static generateSecureIVBatchForAlgorithm(count, algorithm, options = {}) { const algorithmSizes = { "aes-128-cbc": 16, "aes-192-cbc": 16, "aes-256-cbc": 16, "aes-128-ctr": 16, "aes-192-ctr": 16, "aes-256-ctr": 16, "aes-128-gcm": 12, "aes-192-gcm": 12, "aes-256-gcm": 12, chacha20: 12, "chacha20-poly1305": 12, "des-ede3-cbc": 8, "blowfish-cbc": 8, }; const length = algorithmSizes[algorithm.toLowerCase()]; if (!length) { throw new Error(`Unsupported algorithm: ${algorithm}`); } return RandomCrypto.generateSecureIVBatch(count, length, { ...options, algorithm: algorithm, }); } /** * Validate IV for algorithm * @param iv - IV to validate * @param algorithm - Target algorithm * @returns Validation result */ static validateIV(iv, algorithm) { const algorithmSizes = { "aes-128-cbc": 16, "aes-192-cbc": 16, "aes-256-cbc": 16, "aes-128-ctr": 16, "aes-192-ctr": 16, "aes-256-ctr": 16, "aes-128-gcm": 12, "aes-192-gcm": 12, "aes-256-gcm": 12, chacha20: 12, "chacha20-poly1305": 12, "des-ede3-cbc": 8, "blowfish-cbc": 8, }; const expectedLength = algorithmSizes[algorithm.toLowerCase()]; const actualLength = iv.length; if (!expectedLength) { return { valid: false, actualLength, message: `Unknown algorithm: ${algorithm}`, }; } if (actualLength !== expectedLength) { return { valid: false, expectedLength, actualLength, message: `IV length mismatch: expected ${expectedLength} bytes, got ${actualLength} bytes`, }; } // Check for all zeros (weak IV) const isAllZeros = Array.from(iv).every((byte) => byte === 0); if (isAllZeros) { return { valid: false, expectedLength, actualLength, message: "IV is all zeros (weak)", }; } return { valid: true, expectedLength, actualLength, message: "IV is valid", }; } /** * Create secure cipher with auto-generated IV * @param algorithm - Cipher algorithm * @param key - Encryption key * @param options - Cipher options * @returns Cipher and IV */ static createSecureCipheriv(algorithm, key, options = {}) { const ivOptions = { quantumSafe: options.quantumSafe, useEntropyPool: options.useHardwareEntropy, validateSize: options.validateStrength, }; const iv = RandomCrypto.generateSecureIVForAlgorithm(algorithm, ivOptions); const cipher = crypto.createCipheriv(algorithm, key, Buffer.from(iv)); return { cipher, iv: Buffer.from(iv) }; } /** * Create secure decipher * @param algorithm - Cipher algorithm * @param key - Decryption key * @param iv - Initialization vector * @returns Decipher */ static createSecureDecipheriv(algorithm, key, iv) { return crypto.createDecipheriv(algorithm, key, iv); } /** * Generate cryptographic key * @param length - Key length in bytes * @param options - Generation options * @returns Cryptographic key */ static generateCryptoKey(length, options = {}) { const { quantumSafe = false, useHardwareEntropy = true, validateStrength = true, } = options; const keyBytes = randomGenerators.RandomGenerators.getRandomBytes(length, { quantumSafe, useEntropyPool: useHardwareEntropy, }); const key = Buffer.from(keyBytes); if (validateStrength) { RandomCrypto.validateKeyStrength(key); } return key; } /** * Validate key strength * @param key - Key to validate * @returns Validation result */ static validateKeyStrength(key) { const issues = []; let strength = "strong"; // Check for all zeros if (key.every((byte) => byte === 0)) { issues.push("Key is all zeros"); strength = "weak"; } // Check for all same value const firstByte = key[0]; if (key.every((byte) => byte === firstByte)) { issues.push("Key has no entropy"); strength = "weak"; } // Check entropy const uniqueBytes = new Set(key); const entropyRatio = uniqueBytes.size / key.length; if (entropyRatio < 0.1) { issues.push("Very low entropy"); strength = "weak"; } else if (entropyRatio < 0.3) { issues.push("Low entropy"); strength = "fair"; } else if (entropyRatio < 0.6) { strength = "good"; } // Check length if (key.length < 16) { issues.push("Key too short"); strength = "weak"; } else if (key.length < 32) { if (strength === "strong") strength = "good"; } return { valid: issues.length === 0, strength, issues, }; } /** * Generate key derivation salt * @param length - Salt length * @param options - Generation options * @returns KDF salt */ static generateKDFSalt(length = 32, options = {}) { return randomGenerators.RandomGenerators.generateSalt(length, options); } /** * Generate HMAC key * @param algorithm - HMAC algorithm * @param options - Generation options * @returns HMAC key */ static generateHMACKey(algorithm = "sha256", options = {}) { // Recommended key sizes for HMAC const keySizes = { sha1: 20, sha256: 32, sha384: 48, sha512: 64, }; const keySize = keySizes[algorithm.toLowerCase()] || 32; return RandomCrypto.generateCryptoKey(keySize, options); } } exports.RandomCrypto = RandomCrypto; //# sourceMappingURL=random-crypto.js.map