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.
723 lines (719 loc) • 26 kB
JavaScript
;
var types = require('../types.js');
var constants = require('../utils/constants.js');
var encoding = require('../utils/encoding.js');
var stats = require('../utils/stats.js');
var hashCore = require('./hash/hash-core.js');
require('./hash/hash-types.js');
require('crypto');
require('./hash/hash-security.js');
require('./hash/hash-advanced.js');
require('../algorithms/hash-algorithms.js');
var keys = require('./keys.js');
var randomCore = require('./random/random-core.js');
require('./random/random-types.js');
require('./random/random-sources.js');
require('nehonix-uri-processor');
require('../utils/memory/index.js');
var randomTokens = require('./random/random-tokens.js');
var validators = require('./validators.js');
var sideChannel = require('../components/side-channel.js');
var memoryHard = require('../components/memory-hard.js');
var postQuantum = require('../components/post-quantum.js');
var secureMemory = require('../components/secure-memory.js');
var entropyAugmentation = require('../components/entropy-augmentation.js');
var canaryTokens = require('../components/canary-tokens.js');
var attestation = require('../components/attestation.js');
var runtimeVerification = require('../components/runtime-verification.js');
var secureSerialization = require('../components/secure-serialization.js');
var tamperEvidentLogging = require('../components/tamper-evident-logging.js');
var dataConverter = require('../utils/dataConverter.js');
var secureStringCore = require('../components/secure-string/core/secure-string-core.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');
var secureObjectCore = require('../components/secure-object/core/secure-object-core.js');
require('nehoid');
/***************************************************************************
* FortifyJS - Secure Array Types
*
* This file contains type definitions for the SecureArray modular architecture
*
* @author Nehonix
*
* @license MIT
*
* Copyright (c) 2025 Nehonix. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***************************************************************************** */
/**
* Main class for the FortifyJS library
*/
class FortifyJS {
/**
* Generate a secure token with customizable options
* @param options - Token generation options
* @returns Secure random token
*/
static generateSecureToken(options = {
entropy: "high",
}) {
const { length = constants.SECURITY_DEFAULTS.TOKEN_LENGTH, includeUppercase = true, includeLowercase = true, includeNumbers = true, includeSymbols = false, maxValidityLength = 1024, excludeSimilarCharacters = false, entropy, } = options;
// Validate inputs
validators.Validators.validateLength(length, 1, maxValidityLength);
validators.Validators.validateEntropyLevel(entropy);
// Map entropy string to SecurityLevel enum
const securityLevel = {
standard: types.SecurityLevel.STANDARD,
high: types.SecurityLevel.HIGH,
maximum: types.SecurityLevel.MAXIMUM,
};
return randomTokens.RandomTokens.generateSecureToken(length, {
includeUppercase,
includeLowercase,
includeNumbers,
includeSymbols,
excludeSimilarCharacters,
entropyLevel: securityLevel[entropy],
});
}
// PIN GENERATOR
/**
* Generate secure PIN
* @param length - PIN length
* @param options - Generation options
* @returns Secure numeric PIN
*/
static generateSecurePIN(...args) {
return randomTokens.RandomTokens.generateSecurePIN(...args);
}
/**
* Generate recovery codes
* @param count - Number of codes to generate
* @param codeLength - Length of each code
* @param options - Generation options
* @returns Array of recovery codes
*/
static generateRecoveryCodes(...args) {
return randomTokens.RandomTokens.generateRecoveryCodes(...args);
}
/**
* Generate an API key with prefix and timestamp
* @param options - API key generation options
* @returns API key
*/
static generateAPIKey(options = {}) {
// Handle string input (prefix)
if (typeof options === "string") {
options = { prefix: options };
}
const { prefix = "", includeTimestamp = true, randomPartLength = constants.SECURITY_DEFAULTS.API_KEY_RANDOM_LENGTH, separator = "_", } = options;
// Validate inputs
validators.Validators.validateLength(randomPartLength, 16, 64);
// Generate timestamp part (8 hex characters)
const timestamp = includeTimestamp
? Math.floor(Date.now() / 1000)
.toString(16)
.padStart(8, "0")
: "";
// Generate random part
const randomPart = randomTokens.RandomTokens.generateSecureToken(randomPartLength, {
includeUppercase: true,
includeLowercase: true,
includeNumbers: true,
includeSymbols: false,
entropyLevel: types.SecurityLevel.MAXIMUM,
});
// Combine parts
let apiKey = "";
if (prefix) {
apiKey += prefix + separator;
}
if (includeTimestamp) {
apiKey += timestamp + separator;
}
apiKey += randomPart;
if (options.encoding) {
let result = apiKey;
const e = dataConverter.bufferDataConverter(encoding.stringToBuffer(randomPart), options.encoding, {
onResult: (r) => (result = r),
onBuffer: (b) => (result = b),
});
if (e)
return e;
return result;
}
return apiKey;
}
/**
* Generate a JWT secret with high entropy
* @param length - Length of the secret
* @returns High-entropy JWT secret
*/
static generateJWTSecret(length = 32, encoding$1) {
// Validate inputs
validators.Validators.validateLength(length, 32, 128);
// Generate a high-entropy secret
const secr = randomTokens.RandomTokens.generateSecureToken(length, {
includeUppercase: true,
includeLowercase: true,
includeNumbers: true,
includeSymbols: true,
entropyLevel: types.SecurityLevel.MAXIMUM,
});
if (encoding$1) {
let result = secr; // Initialize with default value
const e = dataConverter.bufferDataConverter(encoding.stringToBuffer(secr), encoding$1, {
onResult: (r) => (result = r),
onBuffer: (b) => (result = b),
});
if (e)
return e;
return result;
}
return secr;
}
/**
* Generate a session token with built-in signature
* @param options - Session token options
* @returns Session token
*/
static generateSessionToken(options = {}) {
const { userId, ipAddress, userAgent, expiresIn = constants.SECURITY_DEFAULTS.SESSION_EXPIRATION, } = options;
// Generate timestamp (seconds since epoch)
const timestamp = Math.floor(Date.now() / 1000);
// Calculate expiration
const expiration = timestamp + expiresIn;
// Generate nonce
const nonce = randomTokens.RandomTokens.generateSecureToken(16, {
includeUppercase: false,
includeLowercase: true,
includeNumbers: true,
includeSymbols: false,
});
// Build data part
let data = `exp=${expiration}`;
if (userId) {
data += `,uid=${userId}`;
}
if (ipAddress) {
data += `,ip=${ipAddress}`;
}
if (userAgent) {
// Hash the user agent to keep the token size reasonable
const uaHash = hashCore.Hash.createSecureHash(userAgent, randomCore.SecureRandom.generateSalt(), {
algorithm: "sha256",
outputFormat: "hex",
}).substring(0, 16);
data += `,ua=${uaHash}`;
}
// Generate signature
const signatureInput = `${timestamp}.${nonce}.${data}`;
const signature = hashCore.Hash.createSecureHash(signatureInput, randomCore.SecureRandom.generateSalt(), {
algorithm: types.HashAlgorithm.SHA256,
iterations: 1,
outputFormat: "base64",
});
// Combine all parts
return `${timestamp}.${nonce}.${data}.${signature}`;
}
/**
* Generate a TOTP secret for two-factor authentication
* @returns Base32 encoded TOTP secret
*/
static generateTOTPSecret() {
// Generate 20 bytes of random data (160 bits)
const secretBytes = randomCore.SecureRandom.getRandomBytes(20);
// Encode as Base32 (standard for TOTP)
return encoding.bufferToBase32(secretBytes).replace(/=/g, "");
}
/**
* Create a secure hash with configurable options
* @param input - The input to hash
* @param options - Hashing options
* @returns The hash in the specified format
*/
static secureHash(...p) {
return hashCore.Hash.createSecureHash(...p);
}
/**
* Verify that a hash matches the expected input
* @param input - The input to verify
* @param hash - The hash to verify against
* @param options - Hashing options (must match those used to create the hash)
* @returns True if the hash matches the input
*/
static verifyHash(...p) {
return hashCore.Hash.verifyHash(...p);
}
/**
* Derive a key from a password or other input
* @param input - The input to derive a key from
* @param options - Key derivation options
* @returns The derived key as a hex string
*/
static deriveKey(input, options = {}) {
return keys.Keys.deriveKey(input, options);
}
/**
* Calculate password strength with detailed analysis
* @param password - The password to analyze
* @returns Password strength analysis
*/
static calculatePasswordStrength(password) {
if (!password) {
return {
score: 0,
feedback: ["Password is empty"],
estimatedCrackTime: "Instant",
analysis: {
length: 0,
entropy: 0,
variety: 0,
patterns: 100,
},
};
}
// Calculate basic metrics
const length = password.length;
const hasUppercase = /[A-Z]/.test(password);
const hasLowercase = /[a-z]/.test(password);
const hasNumbers = /[0-9]/.test(password);
const hasSymbols = /[^A-Za-z0-9]/.test(password);
// Calculate character variety score (0-25)
let varietyScore = 0;
if (hasUppercase)
varietyScore += 6.25;
if (hasLowercase)
varietyScore += 6.25;
if (hasNumbers)
varietyScore += 6.25;
if (hasSymbols)
varietyScore += 6.25;
// Calculate length score (0-40)
const lengthScore = Math.min(40, length * 2);
// Check for common patterns
const patterns = [
/^[0-9]+$/, // All numbers
/^[a-zA-Z]+$/, // All letters
/^[a-z]+$/, // All lowercase
/^[A-Z]+$/, // All uppercase
/^(qwerty|asdfgh|zxcvbn)/i, // Keyboard patterns
/^(password|admin|user)/i, // Common words
/^(123|abc|xyz)/i, // Simple sequences
/(.)\1{2,}/, // Repeated characters
];
// Calculate pattern penalty (0-35)
let patternPenalty = 0;
for (const pattern of patterns) {
if (pattern.test(password)) {
patternPenalty += 5;
}
}
// Calculate entropy (0-35)
let charsetSize = 0;
if (hasUppercase)
charsetSize += 26;
if (hasLowercase)
charsetSize += 26;
if (hasNumbers)
charsetSize += 10;
if (hasSymbols)
charsetSize += 33;
const entropy = Math.log2(Math.pow(charsetSize, length));
const entropyScore = Math.min(35, entropy / 8);
// Calculate final score (0-100)
const rawScore = lengthScore + entropyScore + varietyScore - patternPenalty;
const finalScore = Math.max(0, Math.min(100, rawScore));
// Generate feedback
const feedback = [];
if (length < 8) {
feedback.push("Password is too short");
}
if (!hasUppercase) {
feedback.push("Add uppercase letters");
}
if (!hasLowercase) {
feedback.push("Add lowercase letters");
}
if (!hasNumbers) {
feedback.push("Add numbers");
}
if (!hasSymbols) {
feedback.push("Add symbols");
}
if (patternPenalty > 10) {
feedback.push("Avoid common patterns and sequences");
}
// Estimate crack time
let estimatedCrackTime = "Instant";
if (finalScore > 90) {
estimatedCrackTime = "Centuries";
}
else if (finalScore > 80) {
estimatedCrackTime = "Decades";
}
else if (finalScore > 70) {
estimatedCrackTime = "Years";
}
else if (finalScore > 60) {
estimatedCrackTime = "Months";
}
else if (finalScore > 50) {
estimatedCrackTime = "Weeks";
}
else if (finalScore > 40) {
estimatedCrackTime = "Days";
}
else if (finalScore > 30) {
estimatedCrackTime = "Hours";
}
else if (finalScore > 20) {
estimatedCrackTime = "Minutes";
}
else if (finalScore > 10) {
estimatedCrackTime = "Seconds";
}
return {
score: Math.round(finalScore),
feedback: feedback.length > 0 ? feedback : ["Password is strong"],
estimatedCrackTime,
analysis: {
length: lengthScore,
entropy: entropyScore,
variety: varietyScore,
patterns: patternPenalty,
},
};
}
/**
* Run security tests to validate the library's functionality
* @returns Security test results
*/
// public static runSecurityTests(sampleSize?: number) {
// return runSecurityTests({
// generateToken: () => FortifyJS.generateSecureToken(),
// hashFunction: (input: string) => FortifyJS.secureHash(input),
// sampleSize,
// });
// }
/**
* Get cryptographic operation statistics
* @returns Current statistics
*/
static getStats() {
return stats.StatsTracker.getInstance().getStats();
}
/**
* Reset statistics
*/
static resetStats() {
stats.StatsTracker.getInstance().resetStats();
}
// ===== ADVANCED SECURITY FEATURES =====
/**
* Perform a constant-time comparison of two strings or arrays
* This prevents timing attacks by ensuring the comparison takes the same
* amount of time regardless of how many characters match
*
* @param a - First string or array to compare
* @param b - Second string or array to compare
* @returns True if the inputs are equal, false otherwise
*/
static constantTimeEqual(a, b) {
return sideChannel.constantTimeEqual(a, b);
}
/**
* Derive a key using memory-hard Argon2 algorithm
* This is more resistant to hardware-based attacks than standard PBKDF2
*
* @param password - Password to derive key from
* @param options - Derivation options
* @returns Derived key and metadata
*/
static deriveKeyMemoryHard(password, options = {}) {
return memoryHard.argon2Derive(password, options);
}
/**
* Derive a key using memory-hard Balloon algorithm
* An alternative memory-hard algorithm with different security properties
*
* @param password - Password to derive key from
* @param options - Derivation options
* @returns Derived key and metadata
*/
static deriveKeyBalloon(password, options = {}) {
return memoryHard.balloonDerive(password, options);
}
/**
* Generate a post-quantum secure key pair using Lamport one-time signatures
* This is resistant to attacks by quantum computers
*
* @returns Public and private key pair
*/
static generateQuantumResistantKeypair() {
return postQuantum.lamportGenerateKeypair();
}
/**
* Sign a message using quantum-resistant Lamport signatures
*
* @param message - Message to sign
* @param privateKey - Private key
* @returns Signature
*/
static quantumResistantSign(message, privateKey) {
return postQuantum.lamportSign(message, privateKey);
}
/**
* Verify a quantum-resistant signature
*
* @param message - Message that was signed
* @param signature - Signature to verify
* @param publicKey - Public key
* @returns True if the signature is valid
*/
static quantumResistantVerify(message, signature, publicKey) {
return postQuantum.lamportVerify(message, signature, publicKey);
}
/**
* Create a secure buffer that automatically zeros its contents when destroyed
*
* @param size - Size of the buffer in bytes
* @param fill - Optional value to fill the buffer with
* @returns Secure buffer
*/
static createSecureBuffer(size, fill) {
return new secureMemory.SecureBuffer(size, fill);
}
/**
* Create a secure string that can be explicitly cleared from memory
*
* @param value - Initial string value
* @returns Secure string
*/
static createSecureString(value = "") {
return new secureStringCore.SecureString(value);
}
/**
* Create a secure object that can store sensitive data and be explicitly cleared
*
* @param initialData - Initial data
* @returns Secure object
*/
static createSecureObject(initialData) {
return new secureObjectCore.SecureObject(initialData);
}
/**
* Securely wipe a section of memory
*
* @param buffer - Buffer to wipe
* @param start - Start position
* @param end - End position
*/
static secureWipe(buffer, start = 0, end = buffer.length) {
secureMemory.secureWipe(buffer, start, end);
}
/**
* Get an enhanced entropy source that collects entropy from multiple sources
*
* @param poolSize - Size of the entropy pool in bytes
* @param options - Entropy collection options
* @returns Entropy pool instance
*/
static getEnhancedEntropySource(poolSize, options) {
return entropyAugmentation.EntropyPool.getInstance(poolSize, options);
}
/**
* Create a canary token that can detect unauthorized access
*
* @param options - Canary options
* @returns Canary token
*/
static createCanaryToken(options = {}) {
return canaryTokens.createCanary(options);
}
/**
* Create a canary object that triggers when accessed
*
* @param target - Object to wrap with a canary
* @param options - Canary options
* @returns Proxy object that triggers the canary when accessed
*/
static createCanaryObject(target, options = {}) {
return canaryTokens.createCanaryObject(target, options);
}
/**
* Create a canary function that triggers when called
*
* @param fn - Function to wrap with a canary
* @param options - Canary options
* @returns Function that triggers the canary when called
*/
static createCanaryFunction(fn, options = {}) {
return canaryTokens.createCanaryFunction(fn, options);
}
/**
* Create a cryptographic attestation for data
*
* @param data - Data to attest
* @param options - Attestation options
* @returns Attestation string
*/
static createAttestation(data, options = {}) {
return attestation.createAttestation(data, options);
}
/**
* Verify a cryptographic attestation
*
* @param attestation - Attestation to verify
* @param options - Verification options
* @returns Verification result
*/
static verifyAttestation(attestation$1, options) {
return attestation.verifyAttestation(attestation$1, options);
}
/**
* Create an attestation for the library itself
*
* @param options - Attestation options
* @returns Attestation string
*/
static createLibraryAttestation(options = {}) {
return attestation.createLibraryAttestation(options);
}
/**
* Verify a library attestation
*
* @param attestation - Attestation to verify
* @param options - Verification options
* @returns Verification result
*/
static verifyLibraryAttestation(attestation$1, options) {
return attestation.verifyLibraryAttestation(attestation$1, options);
}
/**
* Verify the security of the runtime environment
*
* @param options - Verification options
* @returns Verification result
*/
static verifyRuntimeSecurity(options = {}) {
return runtimeVerification.verifyRuntimeSecurity(options);
}
/**
* Securely serialize data with protection against various attacks
*
* @param data - Data to serialize
* @param options - Serialization options
* @returns Serialization result
*/
static secureSerialize(data, options = {}) {
return secureSerialization.secureSerialize(data, options);
}
/**
* Securely deserialize data
*
* @param serialized - Serialized data
* @param options - Deserialization options
* @returns Deserialization result
*/
static secureDeserialize(serialized, options = {}) {
return secureSerialization.secureDeserialize(serialized, options);
}
/**
* Create a tamper-evident logger
*
* @param key - Secret key for hashing
* @param storageKey - Key for storing logs in localStorage
* @returns Tamper-evident logger
*/
static createTamperEvidentLogger(key, storageKey) {
return new tamperEvidentLogging.TamperEvidentLogger(key, storageKey);
}
/**
* Get log level enum for tamper-evident logging
* @returns Log level enum
*/
static getLogLevel() {
return tamperEvidentLogging.LogLevel;
}
/**
* Perform secure modular exponentiation resistant to timing attacks
*
* @param base - Base value
* @param exponent - Exponent value
* @param modulus - Modulus value
* @returns (base^exponent) mod modulus
*/
static secureModPow(base, exponent, modulus) {
return sideChannel.secureModPow(base, exponent, modulus);
}
/**
* Perform a fault-resistant comparison of two buffers
* This is resistant to fault injection attacks
*
* @param a - First buffer to compare
* @param b - Second buffer to compare
* @returns True if the buffers are equal
*/
static faultResistantEqual(a, b) {
return sideChannel.faultResistantEqual(a, b);
}
/**
* Generate a Ring-LWE key pair for post-quantum encryption
*
* @returns Public and private key pair
*/
static generateRingLweKeypair() {
return postQuantum.ringLweGenerateKeypair();
}
/**
* Encrypt data using Ring-LWE post-quantum encryption
*
* @param message - Message to encrypt
* @param publicKey - Public key
* @returns Encrypted message
*/
static ringLweEncrypt(message, publicKey) {
return postQuantum.ringLweEncrypt(message, publicKey);
}
/**
* Decrypt data using Ring-LWE post-quantum encryption
*
* @param ciphertext - Encrypted message
* @param privateKey - Private key
* @returns Decrypted message
*/
static ringLweDecrypt(ciphertext, privateKey) {
return postQuantum.ringLweDecrypt(ciphertext, privateKey);
}
/**
* Trigger a canary token
*
* @param token - Canary token to trigger
* @param triggerContext - Additional context for the trigger
* @returns True if the canary was triggered
*/
static triggerCanaryToken(token, triggerContext) {
return canaryTokens.triggerCanary(token, triggerContext);
}
}
exports.FortifyJS = FortifyJS;
//# sourceMappingURL=crypto.js.map