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.
389 lines (386 loc) • 13.6 kB
JavaScript
import { bufferToBase64, base64ToBuffer } from '../../../utils/encoding.js';
import { Hash } from '../../../core/hash/hash-core.js';
import '../../../core/hash/hash-types.js';
import 'crypto';
import '../../../core/hash/hash-security.js';
import '../../../core/hash/hash-advanced.js';
import '../../../algorithms/hash-algorithms.js';
/***************************************************************************
* FortifyJS - Secure Array Serialization Handler
*
* This file contains the serialization operations for SecureArray
*
* @author Nehonix
* @version 2.0.0
* @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.
***************************************************************************** */
/**
* Serialization handler for SecureArray operations
*/
class ArraySerializationHandler {
constructor(crypto, metadata) {
this.crypto = crypto;
this.metadata = metadata;
this.version = "2.0.0";
this.format = "FortifyJS-SecureArray";
}
/**
* Serializes SecureArray data to a secure format
*/
serialize(elements, options = {}) {
try {
const { includeMetadata = true, encryptSensitive = true, compression = false, format = "json", includeChecksum = true, } = options;
// Create serialization package
const package_ = {
version: this.version,
format: this.format,
timestamp: Date.now(),
elements: this.serializeElements(elements, encryptSensitive),
metadata: includeMetadata ? this.serializeMetadata() : null,
checksum: null,
compression: compression,
elementCount: elements.length,
};
// Generate checksum if requested
if (includeChecksum) {
package_.checksum = this.generateChecksum(package_);
}
// Convert to string based on format
let serialized;
switch (format) {
case "json":
serialized = JSON.stringify(package_, null, 0);
break;
case "compact":
serialized = JSON.stringify(package_);
break;
case "base64":
serialized = bufferToBase64(new TextEncoder().encode(JSON.stringify(package_)));
break;
default:
serialized = JSON.stringify(package_);
}
// Apply compression if requested
if (compression) {
serialized = this.compressData(serialized);
}
return serialized;
}
catch (error) {
console.error("Serialization failed:", error);
throw new Error(`Serialization failed: ${error.message}`);
}
}
/**
* Deserializes SecureArray data from a secure format
*/
deserialize(serializedData) {
try {
// Detect and handle compression
let data = serializedData;
if (this.isCompressed(data)) {
data = this.decompressData(data);
}
// Parse the package
let package_;
try {
// Try base64 decode first
if (this.isBase64Format(data)) {
const decoded = base64ToBuffer(data);
package_ = JSON.parse(new TextDecoder().decode(decoded));
}
else {
package_ = JSON.parse(data);
}
}
catch {
throw new Error("Invalid serialization format");
}
// Validate package structure
this.validatePackage(package_);
// Verify checksum if present
if (package_.checksum) {
const originalChecksum = package_.checksum;
package_.checksum = null;
const computedChecksum = this.generateChecksum(package_);
if (originalChecksum !== computedChecksum) {
throw new Error("Checksum verification failed - data may be corrupted");
}
}
// Deserialize elements
const elements = this.deserializeElements(package_.elements);
// Deserialize metadata
const metadata = package_.metadata
? this.deserializeMetadata(package_.metadata)
: new Map();
return {
elements,
metadata,
version: package_.version,
timestamp: package_.timestamp,
};
}
catch (error) {
console.error("Deserialization failed:", error);
throw new Error(`Deserialization failed: ${error.message}`);
}
}
/**
* Serializes array elements with optional encryption
*/
serializeElements(elements, encryptSensitive) {
return elements.map((element, index) => {
const metadata = this.metadata.get(index);
const isSecure = metadata?.isSecure || false;
if (encryptSensitive && isSecure && typeof element === "string") {
// Encrypt sensitive string data
return {
type: "encrypted",
value: this.crypto.encryptValue(element),
originalType: metadata?.type || "string",
};
}
else {
// Store non-sensitive data as-is
return {
type: "plain",
value: element,
originalType: metadata?.type || typeof element,
};
}
});
}
/**
* Deserializes array elements with decryption
*/
deserializeElements(serializedElements) {
return serializedElements.map((item) => {
if (item.type === "encrypted") {
// Decrypt encrypted data
return this.crypto.decryptValue(item.value);
}
else {
// Return plain data
return item.value;
}
});
}
/**
* Serializes metadata
*/
serializeMetadata() {
const metadataObj = {};
// Convert Map to object for serialization
for (const [index, metadata] of this.metadata.getAll()) {
metadataObj[index] = {
type: metadata.type,
isSecure: metadata.isSecure,
lastAccessed: metadata.lastAccessed,
accessCount: metadata.accessCount,
};
}
return metadataObj;
}
/**
* Deserializes metadata
*/
deserializeMetadata(serializedMetadata) {
const metadata = new Map();
for (const [indexStr, data] of Object.entries(serializedMetadata)) {
const index = parseInt(indexStr, 10);
metadata.set(index, data);
}
return metadata;
}
/**
* Generates a checksum for data integrity
*/
generateChecksum(package_) {
// Create a deterministic string representation
const dataStr = JSON.stringify(package_, Object.keys(package_).sort());
// Generate SHA-256 hash
const hash = Hash.create(dataStr, {
algorithm: "sha256",
outputFormat: "hex",
});
return hash;
}
/**
* Validates package structure
*/
validatePackage(package_) {
if (!package_ || typeof package_ !== "object") {
throw new Error("Invalid package structure");
}
const requiredFields = ["version", "format", "timestamp", "elements"];
for (const field of requiredFields) {
if (!(field in package_)) {
throw new Error(`Missing required field: ${field}`);
}
}
if (package_.format !== this.format) {
throw new Error(`Unsupported format: ${package_.format}`);
}
if (!Array.isArray(package_.elements)) {
throw new Error("Elements must be an array");
}
}
/**
* Compresses data using a simple compression algorithm
*/
compressData(data) {
// Simple compression using base64 encoding with compression marker
const compressed = bufferToBase64(new TextEncoder().encode(data));
return `[COMPRESSED:${compressed}]`;
}
/**
* Decompresses data
*/
decompressData(data) {
if (!this.isCompressed(data)) {
return data;
}
// Extract compressed data
const compressedData = data.slice(12, -1); // Remove [COMPRESSED: and ]
const decompressed = base64ToBuffer(compressedData);
return new TextDecoder().decode(decompressed);
}
/**
* Checks if data is compressed
*/
isCompressed(data) {
return data.startsWith("[COMPRESSED:") && data.endsWith("]");
}
/**
* Checks if data is in base64 format
*/
isBase64Format(data) {
try {
// Simple base64 detection
return /^[A-Za-z0-9+/]*={0,2}$/.test(data) && data.length % 4 === 0;
}
catch {
return false;
}
}
/**
* Exports array data in various formats
*/
exportData(elements, format = "json") {
try {
switch (format) {
case "json":
return JSON.stringify(elements, null, 2);
case "csv":
return this.exportToCSV(elements);
case "xml":
return this.exportToXML(elements);
case "yaml":
return this.exportToYAML(elements);
default:
throw new Error(`Unsupported export format: ${format}`);
}
}
catch (error) {
console.error("Export failed:", error);
throw new Error(`Export failed: ${error.message}`);
}
}
/**
* Exports to CSV format
*/
exportToCSV(elements) {
if (elements.length === 0) {
return "";
}
// Simple CSV export
const rows = [];
// Header
rows.push("Index,Value,Type");
// Data rows
elements.forEach((element, index) => {
const value = typeof element === "string"
? `"${element.replace(/"/g, '""')}"`
: String(element);
const type = typeof element;
rows.push(`${index},${value},${type}`);
});
return rows.join("\n");
}
/**
* Exports to XML format
*/
exportToXML(elements) {
const xmlElements = elements
.map((element, index) => {
const value = String(element)
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
const type = typeof element;
return ` <element index="${index}" type="${type}">${value}</element>`;
})
.join("\n");
return `<?xml version="1.0" encoding="UTF-8"?>\n<secureArray>\n${xmlElements}\n</secureArray>`;
}
/**
* Exports to YAML format
*/
exportToYAML(elements) {
const yamlElements = elements
.map((element, index) => {
const value = typeof element === "string"
? `"${element.replace(/"/g, '\\"')}"`
: String(element);
return ` - index: ${index}\n value: ${value}\n type: ${typeof element}`;
})
.join("\n");
return `secureArray:\n${yamlElements}`;
}
/**
* Gets serialization statistics
*/
getSerializationStats() {
return {
version: this.version,
format: this.format,
supportedFormats: ["json", "compact", "base64"],
features: [
"Encryption",
"Compression",
"Checksum verification",
"Metadata preservation",
"Multiple export formats",
],
};
}
/**
* Securely destroys the serialization handler
*/
destroy() {
// Clear any cached data
// The crypto and metadata handlers will be destroyed by their owners
}
}
export { ArraySerializationHandler };
//# sourceMappingURL=ArraySerializationHandler.js.map