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.
198 lines (194 loc) • 7.18 kB
JavaScript
;
var secureMemory = require('../../secure-memory.js');
var secureStringCore = require('../../secure-string/core/secure-string-core.js');
require('crypto');
require('../../secure-string/advanced/entropy-analyzer.js');
require('../../secure-string/advanced/quantum-safe.js');
require('../../secure-string/advanced/performance-monitor.js');
/**
* Serialization Handler Module
* Handles object serialization and format conversion
*/
/**
* Handles serialization operations for SecureObject
*/
class SerializationHandler {
constructor(cryptoHandler, metadataManager) {
this.cryptoHandler = cryptoHandler;
this.metadataManager = metadataManager;
}
/**
* Converts SecureObject data to a regular object
*/
toObject(data, sensitiveKeys, options = {}) {
const result = {};
for (const [key, value] of data.entries()) {
const metadata = this.metadataManager.get(key);
const isUserDefinedSensitive = typeof sensitiveKeys === "function"
? sensitiveKeys(key)
: sensitiveKeys.has(key);
// Handle sensitive keys
if (isUserDefinedSensitive) {
if (options.encryptSensitive) {
// Encrypt user-defined sensitive data
let valueToEncrypt;
if (value instanceof secureMemory.SecureBuffer) {
const buffer = value.getBuffer();
if (metadata?.type === "Uint8Array") {
valueToEncrypt = Array.from(new Uint8Array(buffer));
}
else {
valueToEncrypt = new TextDecoder().decode(buffer);
}
}
else if (value instanceof secureStringCore.SecureString) {
valueToEncrypt = value.toString();
}
else {
valueToEncrypt = value;
}
result[key] =
this.cryptoHandler.encryptValue(valueToEncrypt);
}
// If encryptSensitive is false, skip sensitive keys (filter them out)
// This is the fix for the nested password filtering bug
}
else {
// Normal processing - show actual values for non-sensitive keys
result[key] = this.processValue(value, metadata, options, sensitiveKeys);
}
}
if (options.includeMetadata) {
result._metadata = this.metadataManager.toObject();
}
return this.applyFormat(result, options);
}
/**
* Processes a single value for serialization
*/
processValue(value, metadata, options, sensitiveKeys) {
if (value instanceof secureMemory.SecureBuffer) {
const buffer = value.getBuffer();
if (metadata?.type === "Uint8Array") {
// Return as Uint8Array for binary data
return new Uint8Array(buffer);
}
else {
// Return as string for text data
return new TextDecoder().decode(buffer);
}
}
else if (value instanceof secureStringCore.SecureString) {
return value.toString();
}
else if (value &&
typeof value === "object" &&
typeof value.toObject === "function") {
// For nested SecureObjects, recursively process with the same options
// Pass through the strictSensitiveKeys option to maintain consistency
return value.toObject(options);
}
else if (typeof value === "object" && value !== null) {
// For regular nested objects, recursively check for sensitive keys
// FIXED: Pass the actual sensitive keys instead of empty Set
return this.cryptoHandler.processNestedObject(value, options, sensitiveKeys);
}
else {
return value;
}
}
/**
* Applies format transformation to the result
*/
applyFormat(result, options) {
if (options.format === "binary") {
// Convert to binary format (Uint8Array)
const jsonString = JSON.stringify(result);
return new TextEncoder().encode(jsonString);
}
else if (options.format === "json") {
// Return as JSON string
return JSON.stringify(result);
}
// Default: return as regular object
return result;
}
/**
* Converts to JSON string
*/
toJSON(data, sensitiveKeys, options = {}) {
const obj = this.toObject(data, sensitiveKeys, options);
return JSON.stringify(obj);
}
/**
* Creates a deterministic representation for hashing
*/
createHashableRepresentation(entries) {
const sortedEntries = entries.sort(([a], [b]) => String(a).localeCompare(String(b)));
return JSON.stringify(sortedEntries.map(([key, value]) => [
String(key),
typeof value === "object" && value instanceof Uint8Array
? Array.from(value)
: value,
]));
}
/**
* Processes nested objects recursively for sensitive key detection
*/
processNestedObject(obj, options, sensitiveKeys) {
return this.cryptoHandler.processNestedObject(obj, options, sensitiveKeys);
}
/**
* Validates serialization options
*/
validateOptions(options) {
if (options.format && !["json", "binary"].includes(options.format)) {
throw new Error(`Invalid format option: ${options.format}. Must be 'json' or 'binary'.`);
}
}
/**
* Gets serialization statistics
*/
getSerializationStats(data) {
let secureBufferCount = 0;
let secureStringCount = 0;
let nestedObjectCount = 0;
let primitiveCount = 0;
for (const value of data.values()) {
if (value instanceof secureMemory.SecureBuffer) {
secureBufferCount++;
}
else if (value instanceof secureStringCore.SecureString) {
secureStringCount++;
}
else if (typeof value === "object" && value !== null) {
nestedObjectCount++;
}
else {
primitiveCount++;
}
}
return {
totalKeys: data.size,
secureBufferCount,
secureStringCount,
nestedObjectCount,
primitiveCount,
};
}
/**
* Estimates serialized size
*/
estimateSerializedSize(data, options = {}) {
try {
const serialized = this.toJSON(data, new Set(), options);
return new TextEncoder().encode(serialized).length;
}
catch (error) {
// Fallback estimation
return data.size * 50; // Rough estimate
}
}
}
exports.SerializationHandler = SerializationHandler;
//# sourceMappingURL=serialization-handler.js.map