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.
789 lines (785 loc) • 26.9 kB
JavaScript
'use strict';
var index = require('../../../utils/memory/index.js');
var bufferManager = require('../buffer/buffer-manager.js');
var stringOperations = require('../operations/string-operations.js');
var comparisonOperations = require('../operations/comparison-operations.js');
var cryptoOperations = require('../crypto/crypto-operations.js');
var stringValidator = require('../validation/string-validator.js');
var entropyAnalyzer = require('../advanced/entropy-analyzer.js');
var quantumSafe = require('../advanced/quantum-safe.js');
var performanceMonitor = require('../advanced/performance-monitor.js');
var types = require('../../../utils/memory/types.js');
/***************************************************************************
* 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.
***************************************************************************** */
// Import enhanced memory management
/**
* A secure string that can be explicitly cleared from memory with modular architecture
*/
class SecureString {
/**
* Creates a new secure string with enhanced memory management
*/
constructor(value = "", options = {}) {
this.eventListeners = new Map();
this._isDestroyed = false;
this._memoryTracking = false;
this._createdAt = Date.now();
this._id = `secure-string-${Date.now()}-${Math.random()
.toString(36)
.substring(2, 9)}`;
this.bufferManager = new bufferManager.BufferManager(value, options);
// Enable memory tracking by default for security
this._memoryTracking = options.enableMemoryTracking ?? true;
// Register with advanced memory manager
if (this._memoryTracking) {
index.memoryManager.registerObject(this, this._id);
// Listen to memory events for proactive management
index.memoryManager.on(types.MemoryEventType.MEMORY_PRESSURE, (event) => {
if (event.data?.pressure > 0.8) {
this.handleMemoryPressure();
}
});
index.memoryManager.on(types.MemoryEventType.LEAK_DETECTED, (event) => {
if (event.data?.leaks?.includes(this._id)) {
console.warn(`Potential memory leak detected in SecureString ${this._id}`);
}
});
}
// Initialize secure string pool for efficient reuse
this.initializeSecureStringPool();
this.emit("created", {
value: value.length,
id: this._id,
memoryTracking: this._memoryTracking,
});
}
/**
* Creates a SecureString from another SecureString (copy constructor)
*/
static from(other) {
other.ensureNotDestroyed();
const value = other.toString();
const options = other.bufferManager.getOptions();
return new SecureString(value, options);
}
/**
* Creates a SecureString from a buffer
*/
static fromBuffer(buffer, options = {}, encoding = "utf-8") {
const bufferManager$1 = bufferManager.BufferManager.fromUint8Array(buffer, options, encoding);
const secureString = Object.create(SecureString.prototype);
secureString.bufferManager = bufferManager$1;
secureString.eventListeners = new Map();
secureString._isDestroyed = false;
secureString.emit("created", { fromBuffer: true });
return secureString;
}
// ===== PROPERTY ACCESSORS =====
/**
* Gets the string value
*/
toString() {
this.ensureNotDestroyed();
const value = this.bufferManager.getString();
this.emit("accessed", { operation: "toString" });
return value;
}
/**
* Gets the raw buffer (copy)
*/
toBuffer() {
this.ensureNotDestroyed();
const buffer = this.bufferManager.toUint8Array();
this.emit("accessed", { operation: "toBuffer" });
return buffer;
}
/**
* Gets the length of the string
*/
length() {
this.ensureNotDestroyed();
return this.bufferManager.getCharacterLength();
}
/**
* Gets the byte length of the string in UTF-8 encoding
*/
byteLength() {
this.ensureNotDestroyed();
return this.bufferManager.getByteLength();
}
/**
* Checks if the string is empty
*/
isEmpty() {
this.ensureNotDestroyed();
return this.bufferManager.isEmpty();
}
/**
* Checks if the SecureString has been destroyed
*/
isDestroyed() {
return this._isDestroyed;
}
// ===== STRING MANIPULATION METHODS =====
/**
* Appends another string
*/
append(value) {
this.ensureNotDestroyed();
const currentValue = this.toString();
const appendValue = value instanceof SecureString ? value.toString() : value;
const newValue = stringOperations.StringOperations.append(currentValue, appendValue);
this.bufferManager.updateBuffer(newValue);
this.emit("modified", {
operation: "append",
length: appendValue.length,
});
return this;
}
/**
* Prepends another string
*/
prepend(value) {
this.ensureNotDestroyed();
const currentValue = this.toString();
const prependValue = value instanceof SecureString ? value.toString() : value;
const newValue = stringOperations.StringOperations.prepend(currentValue, prependValue);
this.bufferManager.updateBuffer(newValue);
this.emit("modified", {
operation: "prepend",
length: prependValue.length,
});
return this;
}
/**
* Replaces the entire content with a new value
*/
replace(value) {
this.ensureNotDestroyed();
const newValue = value instanceof SecureString ? value.toString() : value;
this.bufferManager.updateBuffer(newValue);
this.emit("modified", {
operation: "replace",
newLength: newValue.length,
});
return this;
}
/**
* Extracts a substring
*/
substring(start, end) {
this.ensureNotDestroyed();
const currentValue = this.toString();
const substr = stringOperations.StringOperations.substring(currentValue, start, end);
return new SecureString(substr, this.bufferManager.getOptions());
}
/**
* Splits the string into an array of SecureStrings
*/
split(separator, options = {}) {
this.ensureNotDestroyed();
const currentValue = this.toString();
const parts = stringOperations.StringOperations.split(currentValue, separator, options);
const stringOptions = this.bufferManager.getOptions();
return parts.map((part) => new SecureString(part, stringOptions));
}
/**
* Trims whitespace from both ends
*/
trim() {
this.ensureNotDestroyed();
const currentValue = this.toString();
const trimmedValue = stringOperations.StringOperations.trim(currentValue);
this.bufferManager.updateBuffer(trimmedValue);
this.emit("modified", { operation: "trim" });
return this;
}
/**
* Converts to uppercase
*/
toUpperCase() {
this.ensureNotDestroyed();
const currentValue = this.toString();
const upperValue = stringOperations.StringOperations.toUpperCase(currentValue);
return new SecureString(upperValue, this.bufferManager.getOptions());
}
/**
* Converts to lowercase
*/
toLowerCase() {
this.ensureNotDestroyed();
const currentValue = this.toString();
const lowerValue = stringOperations.StringOperations.toLowerCase(currentValue);
return new SecureString(lowerValue, this.bufferManager.getOptions());
}
// ===== COMPARISON METHODS =====
/**
* Compares this SecureString with another string (constant-time comparison)
*/
equals(other, constantTime = true) {
this.ensureNotDestroyed();
const thisValue = this.toString();
const otherValue = other instanceof SecureString ? other.toString() : other;
const result = constantTime
? comparisonOperations.ComparisonOperations.constantTimeEquals(thisValue, otherValue)
: comparisonOperations.ComparisonOperations.regularEquals(thisValue, otherValue);
this.emit("compared", {
operation: "equals",
constantTime,
result: result.isEqual,
});
return result.isEqual;
}
/**
* Performs detailed comparison with timing information
*/
compare(other, constantTime = true) {
this.ensureNotDestroyed();
const thisValue = this.toString();
const otherValue = other instanceof SecureString ? other.toString() : other;
const result = constantTime
? comparisonOperations.ComparisonOperations.constantTimeEquals(thisValue, otherValue)
: comparisonOperations.ComparisonOperations.regularEquals(thisValue, otherValue);
this.emit("compared", {
operation: "compare",
constantTime,
result: result.isEqual,
});
return result;
}
// ===== SEARCH METHODS =====
/**
* Checks if the string contains a substring
*/
includes(searchString, options = {}) {
this.ensureNotDestroyed();
const currentValue = this.toString();
const search = searchString instanceof SecureString
? searchString.toString()
: searchString;
return stringOperations.StringOperations.includes(currentValue, search, options);
}
/**
* Checks if the string starts with a prefix
*/
startsWith(searchString, options = {}) {
this.ensureNotDestroyed();
const currentValue = this.toString();
const search = searchString instanceof SecureString
? searchString.toString()
: searchString;
return stringOperations.StringOperations.startsWith(currentValue, search, options);
}
/**
* Checks if the string ends with a suffix
*/
endsWith(searchString, options = {}) {
this.ensureNotDestroyed();
const currentValue = this.toString();
const search = searchString instanceof SecureString
? searchString.toString()
: searchString;
return stringOperations.StringOperations.endsWith(currentValue, search, options);
}
// ===== VALIDATION METHODS =====
/**
* Validates the string as a password
*/
validatePassword(requirements = {}) {
this.ensureNotDestroyed();
const currentValue = this.toString();
return stringValidator.StringValidator.validatePassword(currentValue, requirements);
}
/**
* Validates the string as an email
*/
validateEmail() {
this.ensureNotDestroyed();
const currentValue = this.toString();
return stringValidator.StringValidator.validateEmail(currentValue);
}
/**
* Gets detailed string statistics
*/
getStatistics() {
this.ensureNotDestroyed();
const currentValue = this.toString();
return stringValidator.StringValidator.getStringStatistics(currentValue);
}
// ===== VALIDATION METHODS =====
/**
* Ensures the SecureString hasn't been destroyed
*/
ensureNotDestroyed() {
if (this._isDestroyed) {
throw new Error("String has been destroyed and cannot be used");
}
}
/**
* Emits an event to all registered listeners
*/
emit(event, details) {
const listeners = this.eventListeners.get(event);
if (listeners) {
for (const listener of listeners) {
try {
listener(event, details);
}
catch (error) {
console.error(`Error in SecureString event listener:`, error);
}
}
}
}
// ===== CRYPTOGRAPHIC METHODS =====
/**
* Creates a hash of the string content
*/
async hash(algorithm = "SHA-256", format = "hex") {
this.ensureNotDestroyed();
const content = this.toString();
const result = await cryptoOperations.CryptoOperations.hash(content, algorithm, format);
this.emit("hashed", { algorithm, format });
return result;
}
/**
* Creates an HMAC of the string content
*/
async hmac(options, format = "hex") {
this.ensureNotDestroyed();
const content = this.toString();
const result = await cryptoOperations.CryptoOperations.hmac(content, options, format);
this.emit("hashed", {
type: "hmac",
algorithm: options.algorithm,
format,
});
return result;
}
/**
* Derives a key using PBKDF2
*/
async deriveKeyPBKDF2(options, format = "hex") {
this.ensureNotDestroyed();
const content = this.toString();
const result = await cryptoOperations.CryptoOperations.deriveKeyPBKDF2(content, options, format);
this.emit("hashed", {
type: "pbkdf2",
iterations: options.iterations,
format,
});
return result;
}
// ===== ADVANCED FEATURES =====
/**
* Performs comprehensive entropy analysis
*/
analyzeEntropy() {
this.ensureNotDestroyed();
const content = this.toString();
return entropyAnalyzer.EntropyAnalyzer.analyzeEntropy(content);
}
/**
* Analyzes patterns in the string
*/
analyzePatterns() {
this.ensureNotDestroyed();
const content = this.toString();
return entropyAnalyzer.EntropyAnalyzer.analyzePatterns(content);
}
/**
* Creates a quantum-safe hash
*/
async createQuantumSafeHash(options, format = "hex") {
this.ensureNotDestroyed();
const content = this.toString();
const result = await quantumSafe.QuantumSafeOperations.createQuantumSafeHash(content, options, format);
this.emit("hashed", {
type: "quantum-safe",
algorithm: options.algorithm,
format,
});
return result;
}
/**
* Derives a quantum-safe key
*/
async deriveQuantumSafeKey(options, keyLength = 32, format = "hex") {
this.ensureNotDestroyed();
const content = this.toString();
const result = await quantumSafe.QuantumSafeOperations.deriveQuantumSafeKey(content, options, keyLength, format);
this.emit("hashed", {
type: "quantum-safe-kdf",
algorithm: options.algorithm,
format,
});
return result;
}
/**
* Verifies a quantum-safe hash
*/
async verifyQuantumSafeHash(expectedHash, options, format = "hex") {
this.ensureNotDestroyed();
const content = this.toString();
return quantumSafe.QuantumSafeOperations.verifyQuantumSafeHash(content, expectedHash, options, format);
}
/**
* Starts performance monitoring for this SecureString
*/
startPerformanceMonitoring() {
performanceMonitor.PerformanceMonitor.startMonitoring();
}
/**
* Stops performance monitoring
*/
stopPerformanceMonitoring() {
performanceMonitor.PerformanceMonitor.stopMonitoring();
}
/**
* Gets performance statistics
*/
getPerformanceStats() {
return performanceMonitor.PerformanceMonitor.getStats();
}
/**
* Benchmarks a specific operation on this SecureString
*/
async benchmarkOperation(operation, operationName, iterations = 100) {
return performanceMonitor.PerformanceMonitor.benchmark(operation, operationName, iterations);
}
/**
* Measures an operation with automatic performance recording
*/
async measureOperation(operation, operationType) {
const operationSize = this.length();
return performanceMonitor.PerformanceMonitor.measure(operation, operationType, operationSize);
}
// ===== EVENT MANAGEMENT =====
/**
* Adds an event listener
*/
addEventListener(event, listener) {
if (!this.eventListeners.has(event)) {
this.eventListeners.set(event, new Set());
}
this.eventListeners.get(event).add(listener);
}
/**
* Removes an event listener
*/
removeEventListener(event, listener) {
const listeners = this.eventListeners.get(event);
if (listeners) {
listeners.delete(listener);
if (listeners.size === 0) {
this.eventListeners.delete(event);
}
}
}
/**
* Removes all event listeners
*/
removeAllEventListeners(event) {
if (event) {
this.eventListeners.delete(event);
}
else {
this.eventListeners.clear();
}
}
// ===== UTILITY METHODS =====
/**
* Gets memory usage information
*/
getMemoryUsage() {
this.ensureNotDestroyed();
return this.bufferManager.getMemoryUsage();
}
/**
* Gets the current options
*/
getOptions() {
this.ensureNotDestroyed();
return this.bufferManager.getOptions();
}
/**
* Updates the options (may recreate buffer)
*/
updateOptions(newOptions) {
this.ensureNotDestroyed();
this.bufferManager.updateOptions(newOptions);
this.emit("modified", {
operation: "updateOptions",
options: newOptions,
});
}
/**
* Creates a shallow copy of the SecureString
*/
clone() {
this.ensureNotDestroyed();
return SecureString.from(this);
}
/**
* Executes a function with the string value and optionally clears it afterward
*/
use(fn, autoClear = false) {
this.ensureNotDestroyed();
try {
const value = this.toString();
return fn(value);
}
finally {
if (autoClear) {
this.clear();
}
}
}
// ===== ENHANCED MEMORY MANAGEMENT METHODS =====
/**
* Initialize secure string pool for efficient memory reuse
*/
initializeSecureStringPool() {
if (!this.secureStringPool) {
try {
this.secureStringPool =
index.memoryManager.getPool("secure-string-pool") ||
index.memoryManager.createPool({
name: "secure-string-pool",
factory: () => new Uint8Array(256), // 256 byte buffers for strings
reset: (buffer) => {
// Secure wipe before reuse
this.secureWipe(buffer);
},
capacity: 30,
strategy: types.PoolStrategy.LRU,
validator: (buffer) => buffer instanceof Uint8Array,
});
}
catch (error) {
// Pool might already exist, try to get it
this.secureStringPool =
index.memoryManager.getPool("secure-string-pool");
}
}
}
/**
* Handle memory pressure situations
*/
handleMemoryPressure() {
// Force cleanup of the buffer manager
try {
this.bufferManager.wipe(); // Use wipe() method instead of cleanup()
}
catch (error) {
// Buffer might already be destroyed
}
// Emit event for external handlers
this.emit("destroyed", {
reason: "memory_pressure_cleanup",
timestamp: Date.now(),
objectId: this._id,
});
}
/**
* Secure wipe of buffer memory
*/
secureWipe(buffer) {
if (!buffer || buffer.length === 0)
return;
// Multiple-pass secure wipe
const passes = [0x00, 0xff, 0xaa, 0x55, 0x00];
for (const pattern of passes) {
buffer.fill(pattern);
}
// Final random pass if crypto is available
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
crypto.getRandomValues(buffer);
}
buffer.fill(0x00); // Final zero pass
}
/**
* Get enhanced memory usage statistics
*/
getEnhancedMemoryUsage() {
this.ensureNotDestroyed();
const basicUsage = this.getMemoryUsage();
const now = Date.now();
return {
...basicUsage,
formattedSize: index.MemoryUtils.formatBytes(basicUsage.bufferSize),
age: now - this._createdAt,
poolStats: this.secureStringPool?.getStats(),
};
}
/**
* Force garbage collection for this SecureString
*/
forceGarbageCollection() {
this.ensureNotDestroyed();
if (this._memoryTracking) {
const beforeUsage = this.getEnhancedMemoryUsage();
// Clean up buffer manager
try {
this.bufferManager.wipe(); // Use wipe() method instead of cleanup()
}
catch (error) {
// Buffer might already be cleaned
}
// Trigger global GC
const gcResult = index.memoryManager.forceGC();
const afterUsage = this.getEnhancedMemoryUsage();
const freedMemory = beforeUsage.bufferSize - afterUsage.bufferSize;
this.emit("destroyed", {
operation: "gc",
timestamp: Date.now(),
freedMemory,
gcDuration: gcResult.duration,
gcSuccess: gcResult.success,
beforeUsage: beforeUsage.formattedSize,
afterUsage: afterUsage.formattedSize,
});
}
}
/**
* Enable memory tracking for this SecureString
*/
enableMemoryTracking() {
this.ensureNotDestroyed();
if (!this._memoryTracking) {
this._memoryTracking = true;
index.memoryManager.registerObject(this, this._id);
}
return this;
}
/**
* Disable memory tracking for this SecureString
*/
disableMemoryTracking() {
this.ensureNotDestroyed();
if (this._memoryTracking) {
this._memoryTracking = false;
index.memoryManager.removeReference(this._id);
}
return this;
}
/**
* Clears the string by zeroing its contents and marks as destroyed
*/
clear() {
if (!this._isDestroyed) {
// Clean up memory tracking
if (this._memoryTracking) {
index.memoryManager.removeReference(this._id);
}
this.bufferManager.destroy();
this._isDestroyed = true;
this.emit("destroyed", { operation: "clear" });
this.eventListeners.clear();
}
}
/**
* Alias for clear() - destroys the SecureString
*/
destroy() {
this.clear();
}
/**
* Securely wipes the content without destroying the SecureString
*/
wipe() {
this.ensureNotDestroyed();
this.bufferManager.wipe();
this.emit("modified", { operation: "wipe" });
}
// ===== SERIALIZATION METHODS =====
/**
* Creates a JSON representation (warning: exposes the value)
*/
toJSON() {
this.ensureNotDestroyed();
return {
value: this.toString(),
length: this.length(),
byteLength: this.byteLength(),
};
}
/**
* Custom inspection for debugging (masks the actual value)
*/
[Symbol.for("nodejs.util.inspect.custom")]() {
if (this._isDestroyed) {
return "SecureString [DESTROYED]";
}
const memUsage = this.getMemoryUsage();
return `SecureString [${this.length()} chars, ${memUsage.bufferSize} bytes${memUsage.isEncrypted ? ", encrypted" : ""}]`;
}
// ===== STATIC UTILITY METHODS =====
/**
* Gets information about available algorithms
*/
static getAlgorithmInfo() {
return cryptoOperations.CryptoOperations.getAlgorithmInfo();
}
/**
* Lists all supported hash algorithms
*/
static getSupportedHashAlgorithms() {
return cryptoOperations.CryptoOperations.getSupportedHashAlgorithms();
}
/**
* Lists all supported HMAC algorithms
*/
static getSupportedHMACAlgorithms() {
return cryptoOperations.CryptoOperations.getSupportedHMACAlgorithms();
}
/**
* Generates a cryptographically secure salt
*/
static generateSalt(length = 32, format = "hex") {
if (format === "uint8array") {
return cryptoOperations.CryptoOperations.generateSalt(length);
}
else if (format === "base64") {
return cryptoOperations.CryptoOperations.generateSaltBase64(length);
}
else {
return cryptoOperations.CryptoOperations.generateSaltHex(length);
}
}
/**
* Performs constant-time hash comparison
*/
static constantTimeHashCompare(hash1, hash2) {
return cryptoOperations.CryptoOperations.constantTimeHashCompare(hash1, hash2);
}
}
exports.SecureString = SecureString;
//# sourceMappingURL=secure-string-core.js.map