UNPKG

xypriss-security

Version:

XyPriss Security is an advanced JavaScript security library designed for enterprise applications. It provides military-grade encryption, secure data structures, quantum-resistant cryptography, and comprehensive security utilities for modern web applicatio

393 lines (389 loc) 12 kB
'use strict'; var hashCore = require('../core/hash/hash-core.js'); require('../core/hash/hash-types.js'); require('crypto'); var encoding = require('../utils/encoding.js'); require('../core/hash/hash-security.js'); require('../core/hash/hash-advanced.js'); require('../algorithms/hash-algorithms.js'); var randomCore = require('../core/random/random-core.js'); require('../core/random/random-types.js'); require('../core/random/random-sources.js'); require('nehonix-uri-processor'); require('../utils/memory/index.js'); require('../types.js'); require('../core/random/random-security.js'); /* --------------------------------------------------------------------------------------------- * Copyright (c) NEHONIX INC. All rights reserved. * Licensed under the MIT License. See LICENSE in the project root for license information. * ------------------------------------------------------------------------------------------- */ /** * @author NEHONIX INC. * @version 1.0.0 * @license MIT * @description Tamper-Evident Logging Module * * This module provides secure logging functionality with tamper detection. * It creates a cryptographically linked chain of log entries that can detect * if any entries have been modified, deleted, or inserted. * * This is useful for security-critical applications where log integrity * is important, such as audit logs, security events, or financial transactions. */ /** * Log level */ exports.LogLevel = void 0; (function (LogLevel) { LogLevel["DEBUG"] = "DEBUG"; LogLevel["INFO"] = "INFO"; LogLevel["WARNING"] = "WARNING"; LogLevel["ERROR"] = "ERROR"; LogLevel["CRITICAL"] = "CRITICAL"; })(exports.LogLevel || (exports.LogLevel = {})); /** * Tamper-evident logger */ class TamperEvidentLogger { /** * Creates a new tamper-evident logger * * @param key - Secret key for hashing * @param storageKey - Key for storing logs in localStorage (if available) */ constructor(key, storageKey) { this.entries = []; this.lastHash = ""; this.sequence = 0; this.key = key || encoding.bufferToHex(randomCore.SecureRandom.getRandomBytes(32)); this.storageKey = storageKey; // Initialize with a genesis entry if storage is empty if (this.entries.length === 0) { this.addGenesisEntry(); } // Load from storage if available this.loadFromStorage(); } /** * Adds a genesis entry to the log */ addGenesisEntry() { const timestamp = Date.now(); const id = this.generateId(); const genesisEntry = { id, timestamp, level: exports.LogLevel.INFO, message: "Genesis entry", previousHash: "0000000000000000000000000000000000000000000000000000000000000000", hash: "", sequence: 0, }; // Calculate the hash genesisEntry.hash = this.calculateHash(genesisEntry); // Add to entries this.entries.push(genesisEntry); this.lastHash = genesisEntry.hash; this.sequence = 1; // Save to storage this.saveToStorage(); } /** * Generates a unique ID for a log entry * * @returns Unique ID */ generateId() { return encoding.bufferToHex(randomCore.SecureRandom.getRandomBytes(16)); } /** * Calculates the hash of a log entry * * @param entry - Log entry to hash * @returns Hash of the log entry */ calculateHash(entry) { // Create a string representation of the entry without the hash const entryString = JSON.stringify({ id: entry.id, timestamp: entry.timestamp, level: entry.level, message: entry.message, data: entry.data, previousHash: entry.previousHash, sequence: entry.sequence, }); // Calculate the hash return hashCore.Hash.create(entryString, { salt: this.key, algorithm: "sha256", iterations: 1, outputFormat: "hex", }); } /** * Loads logs from storage */ loadFromStorage() { if (!this.storageKey || typeof localStorage === "undefined") { return; } try { const storedData = localStorage.getItem(this.storageKey); if (storedData) { const parsed = JSON.parse(storedData); if (Array.isArray(parsed)) { this.entries = parsed; if (this.entries.length > 0) { const lastEntry = this.entries[this.entries.length - 1]; this.lastHash = lastEntry.hash; this.sequence = lastEntry.sequence + 1; } else { this.addGenesisEntry(); } } } } catch (e) { console.error("Failed to load logs from storage:", e); this.addGenesisEntry(); } } /** * Saves logs to storage */ saveToStorage() { if (!this.storageKey || typeof localStorage === "undefined") { return; } try { localStorage.setItem(this.storageKey, JSON.stringify(this.entries)); } catch (e) { console.error("Failed to save logs to storage:", e); } } /** * Adds a log entry * * @param level - Log level * @param message - Log message * @param data - Additional data * @returns The created log entry */ log(level, message, data) { const timestamp = Date.now(); const id = this.generateId(); const entry = { id, timestamp, level, message, data, previousHash: this.lastHash, hash: "", sequence: this.sequence, }; // Calculate the hash entry.hash = this.calculateHash(entry); // Add to entries this.entries.push(entry); this.lastHash = entry.hash; this.sequence++; // Save to storage this.saveToStorage(); return entry; } /** * Logs a debug message * * @param message - Log message * @param data - Additional data * @returns The created log entry */ debug(message, data) { return this.log(exports.LogLevel.DEBUG, message, data); } /** * Logs an info message * * @param message - Log message * @param data - Additional data * @returns The created log entry */ info(message, data) { return this.log(exports.LogLevel.INFO, message, data); } /** * Logs a warning message * * @param message - Log message * @param data - Additional data * @returns The created log entry */ warning(message, data) { return this.log(exports.LogLevel.WARNING, message, data); } /** * Logs an error message * * @param message - Log message * @param data - Additional data * @returns The created log entry */ error(message, data) { return this.log(exports.LogLevel.ERROR, message, data); } /** * Logs a critical message * * @param message - Log message * @param data - Additional data * @returns The created log entry */ critical(message, data) { return this.log(exports.LogLevel.CRITICAL, message, data); } /** * Gets all log entries * * @returns All log entries */ getEntries() { return [...this.entries]; } /** * Gets log entries by level * * @param level - Log level * @returns Log entries with the specified level */ getEntriesByLevel(level) { return this.entries.filter((entry) => entry.level === level); } /** * Gets log entries by time range * * @param startTime - Start time * @param endTime - End time * @returns Log entries within the specified time range */ getEntriesByTimeRange(startTime, endTime) { return this.entries.filter((entry) => entry.timestamp >= startTime && entry.timestamp <= endTime); } /** * Verifies the integrity of the log chain * * @returns Verification result */ verify() { const result = { valid: true, invalidEntries: [], missingEntries: [], tamperedEntries: [], }; if (this.entries.length === 0) { return result; } // Check the genesis entry const genesisEntry = this.entries[0]; if (genesisEntry.previousHash !== "0000000000000000000000000000000000000000000000000000000000000000") { result.valid = false; result.tamperedEntries.push(0); } // Verify each entry for (let i = 0; i < this.entries.length; i++) { const entry = this.entries[i]; // Verify the hash const calculatedHash = this.calculateHash(entry); if (calculatedHash !== entry.hash) { result.valid = false; result.tamperedEntries.push(i); } // Verify the previous hash (except for genesis) if (i > 0) { const previousEntry = this.entries[i - 1]; if (entry.previousHash !== previousEntry.hash) { result.valid = false; result.tamperedEntries.push(i); } } // Verify the sequence if (entry.sequence !== i) { result.valid = false; result.invalidEntries.push(i); } } // Check for missing entries for (let i = 1; i < this.entries.length; i++) { const entry = this.entries[i]; const previousEntry = this.entries[i - 1]; if (entry.sequence - previousEntry.sequence > 1) { result.valid = false; for (let j = previousEntry.sequence + 1; j < entry.sequence; j++) { result.missingEntries.push(j); } } } return result; } /** * Exports the logs to a string * * @returns Exported logs */ export() { return JSON.stringify(this.entries); } /** * Imports logs from a string * * @param data - Exported logs * @param verify - Whether to verify the logs after importing * @returns Verification result if verify is true */ import(data, verify = true) { try { const parsed = JSON.parse(data); if (!Array.isArray(parsed)) { throw new Error("Invalid log data"); } this.entries = parsed; if (this.entries.length > 0) { const lastEntry = this.entries[this.entries.length - 1]; this.lastHash = lastEntry.hash; this.sequence = lastEntry.sequence + 1; } else { this.addGenesisEntry(); } // Save to storage this.saveToStorage(); // Verify if requested if (verify) { return this.verify(); } } catch (e) { console.error("Failed to import logs:", e); this.addGenesisEntry(); } return undefined; } /** * Clears all logs */ clear() { this.entries = []; this.lastHash = ""; this.sequence = 0; // Add genesis entry this.addGenesisEntry(); } } exports.TamperEvidentLogger = TamperEvidentLogger; //# sourceMappingURL=tamper-evident-logging.js.map