@dimzxzzx07/file-watcher 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.env +13 -0
  2. package/.eslintrc.json +128 -0
  3. package/.prettierrc +18 -0
  4. package/Dimzxzzx07.png +0 -0
  5. package/README.md +1024 -0
  6. package/dist/core/BackupManager.d.ts +25 -0
  7. package/dist/core/BackupManager.d.ts.map +1 -0
  8. package/dist/core/BackupManager.js +290 -0
  9. package/dist/core/BackupManager.js.map +1 -0
  10. package/dist/core/IntegrityValidator.d.ts +18 -0
  11. package/dist/core/IntegrityValidator.d.ts.map +1 -0
  12. package/dist/core/IntegrityValidator.js +212 -0
  13. package/dist/core/IntegrityValidator.js.map +1 -0
  14. package/dist/core/SecurityManager.d.ts +40 -0
  15. package/dist/core/SecurityManager.d.ts.map +1 -0
  16. package/dist/core/SecurityManager.js +320 -0
  17. package/dist/core/SecurityManager.js.map +1 -0
  18. package/dist/core/WatcherEngine.d.ts +44 -0
  19. package/dist/core/WatcherEngine.d.ts.map +1 -0
  20. package/dist/core/WatcherEngine.js +470 -0
  21. package/dist/core/WatcherEngine.js.map +1 -0
  22. package/dist/crypto/HashGenerator.d.ts +26 -0
  23. package/dist/crypto/HashGenerator.d.ts.map +1 -0
  24. package/dist/crypto/HashGenerator.js +220 -0
  25. package/dist/crypto/HashGenerator.js.map +1 -0
  26. package/dist/crypto/KeyManager.d.ts +30 -0
  27. package/dist/crypto/KeyManager.d.ts.map +1 -0
  28. package/dist/crypto/KeyManager.js +235 -0
  29. package/dist/crypto/KeyManager.js.map +1 -0
  30. package/dist/crypto/SignatureValidator.d.ts +11 -0
  31. package/dist/crypto/SignatureValidator.d.ts.map +1 -0
  32. package/dist/crypto/SignatureValidator.js +102 -0
  33. package/dist/crypto/SignatureValidator.js.map +1 -0
  34. package/dist/detectors/AnomalyDetector.d.ts +24 -0
  35. package/dist/detectors/AnomalyDetector.d.ts.map +1 -0
  36. package/dist/detectors/AnomalyDetector.js +209 -0
  37. package/dist/detectors/AnomalyDetector.js.map +1 -0
  38. package/dist/detectors/InjectionDetector.d.ts +14 -0
  39. package/dist/detectors/InjectionDetector.d.ts.map +1 -0
  40. package/dist/detectors/InjectionDetector.js +204 -0
  41. package/dist/detectors/InjectionDetector.js.map +1 -0
  42. package/dist/detectors/PatternMatcher.d.ts +28 -0
  43. package/dist/detectors/PatternMatcher.d.ts.map +1 -0
  44. package/dist/detectors/PatternMatcher.js +283 -0
  45. package/dist/detectors/PatternMatcher.js.map +1 -0
  46. package/dist/guards/FileGuard.d.ts +35 -0
  47. package/dist/guards/FileGuard.d.ts.map +1 -0
  48. package/dist/guards/FileGuard.js +357 -0
  49. package/dist/guards/FileGuard.js.map +1 -0
  50. package/dist/guards/MemoryGuard.d.ts +28 -0
  51. package/dist/guards/MemoryGuard.d.ts.map +1 -0
  52. package/dist/guards/MemoryGuard.js +256 -0
  53. package/dist/guards/MemoryGuard.js.map +1 -0
  54. package/dist/guards/ProcessGuard.d.ts +25 -0
  55. package/dist/guards/ProcessGuard.d.ts.map +1 -0
  56. package/dist/guards/ProcessGuard.js +221 -0
  57. package/dist/guards/ProcessGuard.js.map +1 -0
  58. package/dist/index.d.ts +19 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +186 -0
  61. package/dist/index.js.map +1 -0
  62. package/dist/types/index.d.ts +69 -0
  63. package/dist/types/index.d.ts.map +1 -0
  64. package/dist/types/index.js +3 -0
  65. package/dist/types/index.js.map +1 -0
  66. package/dist/utils/Constants.d.ts +407 -0
  67. package/dist/utils/Constants.d.ts.map +1 -0
  68. package/dist/utils/Constants.js +505 -0
  69. package/dist/utils/Constants.js.map +1 -0
  70. package/dist/utils/Logger.d.ts +45 -0
  71. package/dist/utils/Logger.d.ts.map +1 -0
  72. package/dist/utils/Logger.js +285 -0
  73. package/dist/utils/Logger.js.map +1 -0
  74. package/dist/utils/Validator.d.ts +27 -0
  75. package/dist/utils/Validator.d.ts.map +1 -0
  76. package/dist/utils/Validator.js +245 -0
  77. package/dist/utils/Validator.js.map +1 -0
  78. package/favicon.png +0 -0
  79. package/jest.config.js +69 -0
  80. package/package.json +69 -0
  81. package/src/core/BackupManager.ts +305 -0
  82. package/src/core/IntegrityValidator.ts +200 -0
  83. package/src/core/SecurityManager.ts +348 -0
  84. package/src/core/WatcherEngine.ts +537 -0
  85. package/src/crypto/HashGenerator.ts +234 -0
  86. package/src/crypto/KeyManager.ts +249 -0
  87. package/src/crypto/SignatureValidator.ts +76 -0
  88. package/src/detectors/AnomalyDetector.ts +247 -0
  89. package/src/detectors/InjectionDetector.ts +233 -0
  90. package/src/detectors/PatternMatcher.ts +319 -0
  91. package/src/guards/FileGuard.ts +385 -0
  92. package/src/guards/MemoryGuard.ts +263 -0
  93. package/src/guards/ProcessGuard.ts +219 -0
  94. package/src/index.ts +189 -0
  95. package/src/types/index.ts +72 -0
  96. package/src/utils/Constants.ts +532 -0
  97. package/src/utils/Logger.ts +279 -0
  98. package/src/utils/Validator.ts +248 -0
  99. package/tests/setup.ts +80 -0
  100. package/tsconfig.json +42 -0
@@ -0,0 +1,25 @@
1
+ import { SecurityConfig, FileMetadata, BackupEntry } from '../types';
2
+ export declare class BackupManager {
3
+ private readonly config;
4
+ private readonly logger;
5
+ private readonly backups;
6
+ private readonly maxBackupsPerFile;
7
+ constructor(config: SecurityConfig);
8
+ private initializeBackupDirectory;
9
+ private loadExistingBackups;
10
+ private readBackupFile;
11
+ createBackup(filePath: string, metadata: FileMetadata): Promise<string>;
12
+ rollbackFile(filePath: string, version?: number): Promise<boolean>;
13
+ updateBackup(filePath: string, metadata: FileMetadata): Promise<void>;
14
+ restoreFile(filePath: string): Promise<boolean>;
15
+ performFinalBackup(): Promise<void>;
16
+ private verifyBackup;
17
+ private deleteBackup;
18
+ private encryptBackup;
19
+ private decryptBackup;
20
+ private getNextVersion;
21
+ private fileExists;
22
+ getBackups(filePath: string): BackupEntry[];
23
+ getStatus(): any;
24
+ }
25
+ //# sourceMappingURL=BackupManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackupManager.d.ts","sourceRoot":"","sources":["../../src/core/BackupManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAGrE,qBAAa,aAAa;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAc;gBAEpC,MAAM,EAAE,cAAc;YAQpB,yBAAyB;YASzB,mBAAmB;YAuBnB,cAAc;IASf,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAoDvE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA0DlE,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBrE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI/C,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;YAmBlC,YAAY;YAsBZ,YAAY;YAgBZ,aAAa;YAUb,aAAa;IAU3B,OAAO,CAAC,cAAc;YAQR,UAAU;IASjB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE;IAI3C,SAAS,IAAI,GAAG;CAS1B"}
@@ -0,0 +1,290 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.BackupManager = void 0;
37
+ const fs = __importStar(require("fs/promises"));
38
+ const path = __importStar(require("path"));
39
+ const crypto = __importStar(require("crypto"));
40
+ const Logger_1 = require("../utils/Logger");
41
+ class BackupManager {
42
+ config;
43
+ logger;
44
+ backups;
45
+ maxBackupsPerFile = 10;
46
+ constructor(config) {
47
+ this.config = config;
48
+ this.logger = Logger_1.Logger.getInstance();
49
+ this.backups = new Map();
50
+ this.initializeBackupDirectory();
51
+ }
52
+ async initializeBackupDirectory() {
53
+ try {
54
+ await fs.mkdir(this.config.backupDir, { recursive: true, mode: 0o700 });
55
+ await this.loadExistingBackups();
56
+ }
57
+ catch (error) {
58
+ this.logger.error('Failed to initialize backup directory', { error });
59
+ }
60
+ }
61
+ async loadExistingBackups() {
62
+ try {
63
+ const files = await fs.readdir(this.config.backupDir);
64
+ for (const file of files) {
65
+ if (file.endsWith('.backup')) {
66
+ const backupPath = path.join(this.config.backupDir, file);
67
+ const backupData = await this.readBackupFile(backupPath);
68
+ if (backupData) {
69
+ const backups = this.backups.get(backupData.originalPath) || [];
70
+ backups.push(backupData);
71
+ this.backups.set(backupData.originalPath, backups);
72
+ }
73
+ }
74
+ }
75
+ this.logger.info(`Loaded ${this.backups.size} backup entries`);
76
+ }
77
+ catch (error) {
78
+ this.logger.error('Failed to load existing backups', { error });
79
+ }
80
+ }
81
+ async readBackupFile(backupPath) {
82
+ try {
83
+ const content = await fs.readFile(backupPath, 'utf8');
84
+ return JSON.parse(content);
85
+ }
86
+ catch {
87
+ return null;
88
+ }
89
+ }
90
+ async createBackup(filePath, metadata) {
91
+ try {
92
+ const backupId = crypto.randomUUID();
93
+ const backupFileName = `${path.basename(filePath)}.${backupId}.backup`;
94
+ const backupPath = path.join(this.config.backupDir, backupFileName);
95
+ const content = await fs.readFile(filePath);
96
+ const backupEntry = {
97
+ id: backupId,
98
+ originalPath: filePath,
99
+ backupPath,
100
+ timestamp: new Date(),
101
+ hash: metadata.hash,
102
+ encrypted: this.config.signatureVerification,
103
+ size: metadata.size,
104
+ metadata,
105
+ version: this.getNextVersion(filePath)
106
+ };
107
+ let backupContent = content;
108
+ if (this.config.signatureVerification) {
109
+ backupContent = Buffer.from(await this.encryptBackup(content));
110
+ }
111
+ await fs.writeFile(backupPath, backupContent);
112
+ const metadataPath = backupPath + '.meta';
113
+ await fs.writeFile(metadataPath, JSON.stringify(backupEntry, null, 2));
114
+ const backups = this.backups.get(filePath) || [];
115
+ backups.push(backupEntry);
116
+ backups.sort((a, b) => b.version - a.version);
117
+ while (backups.length > this.maxBackupsPerFile) {
118
+ const oldBackup = backups.pop();
119
+ if (oldBackup) {
120
+ await this.deleteBackup(oldBackup);
121
+ }
122
+ }
123
+ this.backups.set(filePath, backups);
124
+ this.logger.debug(`Backup created: ${filePath} -> ${backupPath}`);
125
+ return backupPath;
126
+ }
127
+ catch (error) {
128
+ this.logger.error(`Failed to create backup for ${filePath}`, { error });
129
+ throw error;
130
+ }
131
+ }
132
+ async rollbackFile(filePath, version) {
133
+ try {
134
+ const backups = this.backups.get(filePath);
135
+ if (!backups || backups.length === 0) {
136
+ this.logger.warning(`No backups found for ${filePath}`);
137
+ return false;
138
+ }
139
+ let targetBackup;
140
+ if (version) {
141
+ targetBackup = backups.find(b => b.version === version);
142
+ }
143
+ else {
144
+ targetBackup = backups[0];
145
+ }
146
+ if (!targetBackup) {
147
+ this.logger.warning(`Backup version ${version} not found for ${filePath}`);
148
+ return false;
149
+ }
150
+ if (!await this.verifyBackup(targetBackup)) {
151
+ this.logger.error(`Backup integrity check failed for ${targetBackup.id}`);
152
+ return false;
153
+ }
154
+ let backupContent = await fs.readFile(targetBackup.backupPath);
155
+ if (targetBackup.encrypted) {
156
+ backupContent = Buffer.from(await this.decryptBackup(backupContent));
157
+ }
158
+ const hash = crypto.createHash(this.config.hashAlgorithm)
159
+ .update(backupContent)
160
+ .digest('hex');
161
+ if (hash !== targetBackup.hash) {
162
+ this.logger.error('Backup hash mismatch');
163
+ return false;
164
+ }
165
+ if (await this.fileExists(filePath)) {
166
+ const currentContent = await fs.readFile(filePath);
167
+ const tempBackup = path.join(this.config.backupDir, 'pre_rollback_' + path.basename(filePath));
168
+ await fs.writeFile(tempBackup, currentContent);
169
+ }
170
+ await fs.writeFile(filePath, backupContent);
171
+ this.logger.info(`File rolled back: ${filePath} (version ${targetBackup.version})`);
172
+ return true;
173
+ }
174
+ catch (error) {
175
+ this.logger.error(`Failed to rollback ${filePath}`, { error });
176
+ return false;
177
+ }
178
+ }
179
+ async updateBackup(filePath, metadata) {
180
+ try {
181
+ const backups = this.backups.get(filePath);
182
+ if (!backups || backups.length === 0) {
183
+ await this.createBackup(filePath, metadata);
184
+ return;
185
+ }
186
+ if (backups[0] && backups[0].hash === metadata.hash) {
187
+ backups[0].timestamp = new Date();
188
+ const metadataPath = backups[0].backupPath + '.meta';
189
+ await fs.writeFile(metadataPath, JSON.stringify(backups[0], null, 2));
190
+ }
191
+ else {
192
+ await this.createBackup(filePath, metadata);
193
+ }
194
+ }
195
+ catch (error) {
196
+ this.logger.error(`Failed to update backup for ${filePath}`, { error });
197
+ }
198
+ }
199
+ async restoreFile(filePath) {
200
+ return this.rollbackFile(filePath);
201
+ }
202
+ async performFinalBackup() {
203
+ this.logger.info('Performing final backup...');
204
+ const entries = Array.from(this.backups.entries());
205
+ for (const [filePath, backups] of entries) {
206
+ if (backups.length > 0 && await this.fileExists(filePath)) {
207
+ const currentContent = await fs.readFile(filePath);
208
+ const finalBackupPath = path.join(this.config.backupDir, 'final_' + path.basename(filePath));
209
+ await fs.writeFile(finalBackupPath, currentContent);
210
+ }
211
+ }
212
+ this.logger.info('Final backup completed');
213
+ }
214
+ async verifyBackup(backup) {
215
+ try {
216
+ if (!await this.fileExists(backup.backupPath)) {
217
+ return false;
218
+ }
219
+ const metadataPath = backup.backupPath + '.meta';
220
+ if (!await this.fileExists(metadataPath)) {
221
+ return false;
222
+ }
223
+ const stats = await fs.stat(backup.backupPath);
224
+ if (stats.size !== backup.size) {
225
+ return false;
226
+ }
227
+ return true;
228
+ }
229
+ catch {
230
+ return false;
231
+ }
232
+ }
233
+ async deleteBackup(backup) {
234
+ try {
235
+ await fs.unlink(backup.backupPath);
236
+ const metadataPath = backup.backupPath + '.meta';
237
+ try {
238
+ await fs.unlink(metadataPath);
239
+ }
240
+ catch {
241
+ }
242
+ this.logger.debug(`Deleted old backup: ${backup.id}`);
243
+ }
244
+ catch (error) {
245
+ this.logger.error(`Failed to delete backup ${backup.id}`, { error });
246
+ }
247
+ }
248
+ async encryptBackup(data) {
249
+ const key = crypto.randomBytes(32);
250
+ const iv = crypto.randomBytes(16);
251
+ const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
252
+ const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
253
+ return Buffer.concat([iv, encrypted]);
254
+ }
255
+ async decryptBackup(data) {
256
+ const iv = data.subarray(0, 16);
257
+ const encrypted = data.subarray(16);
258
+ const key = crypto.randomBytes(32);
259
+ const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
260
+ return Buffer.concat([decipher.update(encrypted), decipher.final()]);
261
+ }
262
+ getNextVersion(filePath) {
263
+ const backups = this.backups.get(filePath) || [];
264
+ if (backups.length === 0)
265
+ return 1;
266
+ const maxVersion = Math.max(...backups.map(b => b.version));
267
+ return maxVersion + 1;
268
+ }
269
+ async fileExists(filePath) {
270
+ try {
271
+ await fs.access(filePath);
272
+ return true;
273
+ }
274
+ catch {
275
+ return false;
276
+ }
277
+ }
278
+ getBackups(filePath) {
279
+ return this.backups.get(filePath) || [];
280
+ }
281
+ getStatus() {
282
+ return {
283
+ totalBackups: Array.from(this.backups.values()).reduce((sum, backups) => sum + backups.length, 0),
284
+ filesWithBackups: this.backups.size,
285
+ backupDir: this.config.backupDir
286
+ };
287
+ }
288
+ }
289
+ exports.BackupManager = BackupManager;
290
+ //# sourceMappingURL=BackupManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackupManager.js","sourceRoot":"","sources":["../../src/core/BackupManager.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs/promises';\nimport * as path from 'path';\nimport * as crypto from 'crypto';\nimport { SecurityConfig, FileMetadata, BackupEntry } from '../types';\nimport { Logger } from '../utils/Logger';\n\nexport class BackupManager {\n private readonly config: SecurityConfig;\n private readonly logger: Logger;\n private readonly backups: Map<string, BackupEntry[]>;\n private readonly maxBackupsPerFile: number = 10;\n\n constructor(config: SecurityConfig) {\n this.config = config;\n this.logger = Logger.getInstance();\n this.backups = new Map();\n \n this.initializeBackupDirectory();\n }\n\n private async initializeBackupDirectory(): Promise<void> {\n try {\n await fs.mkdir(this.config.backupDir, { recursive: true, mode: 0o700 });\n await this.loadExistingBackups();\n } catch (error) {\n this.logger.error('Failed to initialize backup directory', { error });\n }\n }\n\n private async loadExistingBackups(): Promise<void> {\n try {\n const files = await fs.readdir(this.config.backupDir);\n \n for (const file of files) {\n if (file.endsWith('.backup')) {\n const backupPath = path.join(this.config.backupDir, file);\n const backupData = await this.readBackupFile(backupPath);\n \n if (backupData) {\n const backups = this.backups.get(backupData.originalPath) || [];\n backups.push(backupData);\n this.backups.set(backupData.originalPath, backups);\n }\n }\n }\n \n this.logger.info(`Loaded ${this.backups.size} backup entries`);\n } catch (error) {\n this.logger.error('Failed to load existing backups', { error });\n }\n }\n\n private async readBackupFile(backupPath: string): Promise<BackupEntry | null> {\n try {\n const content = await fs.readFile(backupPath, 'utf8');\n return JSON.parse(content) as BackupEntry;\n } catch {\n return null;\n }\n }\n\n public async createBackup(filePath: string, metadata: FileMetadata): Promise<string> {\n try {\n const backupId = crypto.randomUUID();\n const backupFileName = `${path.basename(filePath)}.${backupId}.backup`;\n const backupPath = path.join(this.config.backupDir, backupFileName);\n \n const content = await fs.readFile(filePath);\n \n const backupEntry: BackupEntry = {\n id: backupId,\n originalPath: filePath,\n backupPath,\n timestamp: new Date(),\n hash: metadata.hash,\n encrypted: this.config.signatureVerification,\n size: metadata.size,\n metadata,\n version: this.getNextVersion(filePath)\n };\n\n let backupContent: Buffer | Uint8Array = content;\n if (this.config.signatureVerification) {\n backupContent = Buffer.from(await this.encryptBackup(content));\n }\n\n await fs.writeFile(backupPath, backupContent);\n \n const metadataPath = backupPath + '.meta';\n await fs.writeFile(metadataPath, JSON.stringify(backupEntry, null, 2));\n \n const backups = this.backups.get(filePath) || [];\n backups.push(backupEntry);\n \n backups.sort((a, b) => b.version - a.version);\n while (backups.length > this.maxBackupsPerFile) {\n const oldBackup = backups.pop();\n if (oldBackup) {\n await this.deleteBackup(oldBackup);\n }\n }\n \n this.backups.set(filePath, backups);\n \n this.logger.debug(`Backup created: ${filePath} -> ${backupPath}`);\n return backupPath;\n \n } catch (error) {\n this.logger.error(`Failed to create backup for ${filePath}`, { error });\n throw error;\n }\n }\n\n public async rollbackFile(filePath: string, version?: number): Promise<boolean> {\n try {\n const backups = this.backups.get(filePath);\n if (!backups || backups.length === 0) {\n this.logger.warning(`No backups found for ${filePath}`);\n return false;\n }\n\n let targetBackup: BackupEntry | undefined;\n \n if (version) {\n targetBackup = backups.find(b => b.version === version);\n } else {\n targetBackup = backups[0];\n }\n\n if (!targetBackup) {\n this.logger.warning(`Backup version ${version} not found for ${filePath}`);\n return false;\n }\n\n if (!await this.verifyBackup(targetBackup)) {\n this.logger.error(`Backup integrity check failed for ${targetBackup.id}`);\n return false;\n }\n\n let backupContent = await fs.readFile(targetBackup.backupPath);\n \n if (targetBackup.encrypted) {\n backupContent = Buffer.from(await this.decryptBackup(backupContent));\n }\n\n const hash = crypto.createHash(this.config.hashAlgorithm)\n .update(backupContent)\n .digest('hex');\n \n if (hash !== targetBackup.hash) {\n this.logger.error('Backup hash mismatch');\n return false;\n }\n\n if (await this.fileExists(filePath)) {\n const currentContent = await fs.readFile(filePath);\n const tempBackup = path.join(this.config.backupDir, 'pre_rollback_' + path.basename(filePath));\n await fs.writeFile(tempBackup, currentContent);\n }\n\n await fs.writeFile(filePath, backupContent);\n \n this.logger.info(`File rolled back: ${filePath} (version ${targetBackup.version})`);\n return true;\n \n } catch (error) {\n this.logger.error(`Failed to rollback ${filePath}`, { error });\n return false;\n }\n }\n\n public async updateBackup(filePath: string, metadata: FileMetadata): Promise<void> {\n try {\n const backups = this.backups.get(filePath);\n if (!backups || backups.length === 0) {\n await this.createBackup(filePath, metadata);\n return;\n }\n\n if (backups[0] && backups[0].hash === metadata.hash) {\n backups[0].timestamp = new Date();\n \n const metadataPath = backups[0].backupPath + '.meta';\n await fs.writeFile(metadataPath, JSON.stringify(backups[0], null, 2));\n } else {\n await this.createBackup(filePath, metadata);\n }\n \n } catch (error) {\n this.logger.error(`Failed to update backup for ${filePath}`, { error });\n }\n }\n\n public async restoreFile(filePath: string): Promise<boolean> {\n return this.rollbackFile(filePath);\n }\n\n public async performFinalBackup(): Promise<void> {\n this.logger.info('Performing final backup...');\n \n const entries = Array.from(this.backups.entries());\n \n for (const [filePath, backups] of entries) {\n if (backups.length > 0 && await this.fileExists(filePath)) {\n const currentContent = await fs.readFile(filePath);\n const finalBackupPath = path.join(\n this.config.backupDir,\n 'final_' + path.basename(filePath)\n );\n await fs.writeFile(finalBackupPath, currentContent);\n }\n }\n \n this.logger.info('Final backup completed');\n }\n\n private async verifyBackup(backup: BackupEntry): Promise<boolean> {\n try {\n if (!await this.fileExists(backup.backupPath)) {\n return false;\n }\n\n const metadataPath = backup.backupPath + '.meta';\n if (!await this.fileExists(metadataPath)) {\n return false;\n }\n\n const stats = await fs.stat(backup.backupPath);\n if (stats.size !== backup.size) {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n }\n\n private async deleteBackup(backup: BackupEntry): Promise<void> {\n try {\n await fs.unlink(backup.backupPath);\n \n const metadataPath = backup.backupPath + '.meta';\n try {\n await fs.unlink(metadataPath);\n } catch {\n }\n \n this.logger.debug(`Deleted old backup: ${backup.id}`);\n } catch (error) {\n this.logger.error(`Failed to delete backup ${backup.id}`, { error });\n }\n }\n\n private async encryptBackup(data: Buffer): Promise<Uint8Array> {\n const key = crypto.randomBytes(32);\n const iv = crypto.randomBytes(16);\n \n const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);\n const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);\n \n return Buffer.concat([iv, encrypted]);\n }\n\n private async decryptBackup(data: Buffer): Promise<Uint8Array> {\n const iv = data.subarray(0, 16);\n const encrypted = data.subarray(16);\n \n const key = crypto.randomBytes(32);\n \n const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);\n return Buffer.concat([decipher.update(encrypted), decipher.final()]);\n }\n\n private getNextVersion(filePath: string): number {\n const backups = this.backups.get(filePath) || [];\n if (backups.length === 0) return 1;\n \n const maxVersion = Math.max(...backups.map(b => b.version));\n return maxVersion + 1;\n }\n\n private async fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n public getBackups(filePath: string): BackupEntry[] {\n return this.backups.get(filePath) || [];\n }\n\n public getStatus(): any {\n return {\n totalBackups: Array.from(this.backups.values()).reduce(\n (sum, backups) => sum + backups.length, 0\n ),\n filesWithBackups: this.backups.size,\n backupDir: this.config.backupDir\n };\n }\n}"]}
@@ -0,0 +1,18 @@
1
+ import { SecurityConfig, FileMetadata } from '../types';
2
+ export declare class IntegrityValidator {
3
+ private readonly hashGenerator;
4
+ private readonly signatureValidator;
5
+ private readonly injectionDetector;
6
+ private readonly logger;
7
+ private readonly config;
8
+ constructor(config: SecurityConfig);
9
+ generateFileMetadata(filePath: string): Promise<FileMetadata>;
10
+ validateFile(filePath: string, metadata: FileMetadata): Promise<boolean>;
11
+ verifySignature(filePath: string, metadata: FileMetadata): Promise<boolean>;
12
+ private calculateEntropy;
13
+ private getMagicBytes;
14
+ private generateChecksum;
15
+ private fileExists;
16
+ private isTextFile;
17
+ }
18
+ //# sourceMappingURL=IntegrityValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrityValidator.d.ts","sourceRoot":"","sources":["../../src/core/IntegrityValidator.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMxD,qBAAa,kBAAkB;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoB;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;gBAE5B,MAAM,EAAE,cAAc;IAQrB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAsC7D,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IA0ExE,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC;IAcxF,OAAO,CAAC,gBAAgB;YAkBV,aAAa;IAa3B,OAAO,CAAC,gBAAgB;YAIV,UAAU;IASxB,OAAO,CAAC,UAAU;CAKrB"}
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.IntegrityValidator = void 0;
37
+ const crypto = __importStar(require("crypto"));
38
+ const fs = __importStar(require("fs/promises"));
39
+ const path = __importStar(require("path"));
40
+ const HashGenerator_1 = require("../crypto/HashGenerator");
41
+ const SignatureValidator_1 = require("../crypto/SignatureValidator");
42
+ const InjectionDetector_1 = require("../detectors/InjectionDetector");
43
+ const Logger_1 = require("../utils/Logger");
44
+ class IntegrityValidator {
45
+ hashGenerator;
46
+ signatureValidator;
47
+ injectionDetector;
48
+ logger;
49
+ config;
50
+ constructor(config) {
51
+ this.config = config;
52
+ this.logger = Logger_1.Logger.getInstance();
53
+ this.hashGenerator = new HashGenerator_1.HashGenerator(config);
54
+ this.signatureValidator = new SignatureValidator_1.SignatureValidator();
55
+ this.injectionDetector = new InjectionDetector_1.InjectionDetector();
56
+ }
57
+ async generateFileMetadata(filePath) {
58
+ try {
59
+ const stats = await fs.stat(filePath);
60
+ const content = await fs.readFile(filePath);
61
+ const hash = this.hashGenerator.generateHash(content);
62
+ const encryptedHash = this.hashGenerator.generateEncryptedHash(content);
63
+ const entropy = this.calculateEntropy(content);
64
+ const magicBytes = await this.getMagicBytes(filePath);
65
+ let signature;
66
+ if (this.config.signatureVerification) {
67
+ signature = await this.signatureValidator.generateSignature(content);
68
+ }
69
+ return {
70
+ path: filePath,
71
+ hash,
72
+ signature,
73
+ size: stats.size,
74
+ created: stats.birthtime,
75
+ modified: stats.mtime,
76
+ accessed: stats.atime,
77
+ permissions: stats.mode,
78
+ owner: stats.uid.toString(),
79
+ group: stats.gid.toString(),
80
+ inode: stats.ino,
81
+ checksum: this.generateChecksum(content),
82
+ version: 1,
83
+ encryptedHash,
84
+ entropy,
85
+ magicBytes
86
+ };
87
+ }
88
+ catch (error) {
89
+ this.logger.error(`Failed to generate metadata for ${filePath}`, { error });
90
+ throw error;
91
+ }
92
+ }
93
+ async validateFile(filePath, metadata) {
94
+ try {
95
+ if (!await this.fileExists(filePath)) {
96
+ return false;
97
+ }
98
+ const stats = await fs.stat(filePath);
99
+ const content = await fs.readFile(filePath);
100
+ const currentHash = this.hashGenerator.generateHash(content);
101
+ if (currentHash !== metadata.hash) {
102
+ this.logger.warning(`Hash mismatch for ${filePath}`, {
103
+ expected: metadata.hash,
104
+ actual: currentHash
105
+ });
106
+ return false;
107
+ }
108
+ if (stats.size !== metadata.size) {
109
+ this.logger.warning(`Size mismatch for ${filePath}`, {
110
+ expected: metadata.size,
111
+ actual: stats.size
112
+ });
113
+ return false;
114
+ }
115
+ if (stats.ino !== metadata.inode) {
116
+ this.logger.warning(`Inode mismatch for ${filePath}`, {
117
+ expected: metadata.inode,
118
+ actual: stats.ino
119
+ });
120
+ return false;
121
+ }
122
+ if (this.isTextFile(filePath)) {
123
+ const textContent = content.toString('utf8');
124
+ if (await this.injectionDetector.detectInjection(textContent)) {
125
+ this.logger.warning(`Injection detected in ${filePath}`);
126
+ return false;
127
+ }
128
+ }
129
+ if (this.config.signatureVerification && metadata.signature) {
130
+ const isValidSignature = await this.signatureValidator.validateSignature(content, metadata.signature);
131
+ if (!isValidSignature) {
132
+ this.logger.warning(`Invalid signature for ${filePath}`);
133
+ return false;
134
+ }
135
+ }
136
+ if (this.config.integrityLevel === 'paranoid') {
137
+ const currentEntropy = this.calculateEntropy(content);
138
+ if (Math.abs(currentEntropy - metadata.entropy) > 0.1) {
139
+ this.logger.warning(`Entropy changed for ${filePath}`);
140
+ return false;
141
+ }
142
+ const currentMagic = await this.getMagicBytes(filePath);
143
+ if (currentMagic !== metadata.magicBytes) {
144
+ this.logger.warning(`Magic bytes changed for ${filePath}`);
145
+ return false;
146
+ }
147
+ }
148
+ return true;
149
+ }
150
+ catch (error) {
151
+ this.logger.error(`Validation error for ${filePath}`, { error });
152
+ return false;
153
+ }
154
+ }
155
+ async verifySignature(filePath, metadata) {
156
+ if (!metadata.signature) {
157
+ return false;
158
+ }
159
+ try {
160
+ const content = await fs.readFile(filePath);
161
+ return await this.signatureValidator.validateSignature(content, metadata.signature);
162
+ }
163
+ catch (error) {
164
+ this.logger.error(`Signature verification failed for ${filePath}`, { error });
165
+ return false;
166
+ }
167
+ }
168
+ calculateEntropy(data) {
169
+ const frequencies = {};
170
+ for (const byte of data) {
171
+ frequencies[byte] = (frequencies[byte] || 0) + 1;
172
+ }
173
+ let entropy = 0;
174
+ const length = data.length;
175
+ for (const freq of Object.values(frequencies)) {
176
+ const probability = freq / length;
177
+ entropy -= probability * Math.log2(probability);
178
+ }
179
+ return entropy;
180
+ }
181
+ async getMagicBytes(filePath) {
182
+ try {
183
+ const buffer = Buffer.alloc(8);
184
+ const fd = await fs.open(filePath, 'r');
185
+ await fd.read(buffer, 0, 8, 0);
186
+ await fd.close();
187
+ return buffer.toString('hex').substring(0, 8);
188
+ }
189
+ catch {
190
+ return undefined;
191
+ }
192
+ }
193
+ generateChecksum(data) {
194
+ return crypto.createHash('md5').update(data).digest('hex');
195
+ }
196
+ async fileExists(filePath) {
197
+ try {
198
+ await fs.access(filePath);
199
+ return true;
200
+ }
201
+ catch {
202
+ return false;
203
+ }
204
+ }
205
+ isTextFile(filePath) {
206
+ const textExtensions = ['.js', '.ts', '.json', '.txt', '.md', '.html', '.css', '.xml'];
207
+ const ext = path.extname(filePath).toLowerCase();
208
+ return textExtensions.includes(ext);
209
+ }
210
+ }
211
+ exports.IntegrityValidator = IntegrityValidator;
212
+ //# sourceMappingURL=IntegrityValidator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntegrityValidator.js","sourceRoot":"","sources":["../../src/core/IntegrityValidator.ts"],"names":[],"mappings":"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","sourcesContent":["import * as crypto from 'crypto';\nimport * as fs from 'fs/promises';\nimport * as path from 'path';\nimport { SecurityConfig, FileMetadata } from '../types';\nimport { HashGenerator } from '../crypto/HashGenerator';\nimport { SignatureValidator } from '../crypto/SignatureValidator';\nimport { InjectionDetector } from '../detectors/InjectionDetector';\nimport { Logger } from '../utils/Logger';\n\nexport class IntegrityValidator {\n private readonly hashGenerator: HashGenerator;\n private readonly signatureValidator: SignatureValidator;\n private readonly injectionDetector: InjectionDetector;\n private readonly logger: Logger;\n private readonly config: SecurityConfig;\n\n constructor(config: SecurityConfig) {\n this.config = config;\n this.logger = Logger.getInstance();\n this.hashGenerator = new HashGenerator(config);\n this.signatureValidator = new SignatureValidator();\n this.injectionDetector = new InjectionDetector();\n }\n\n public async generateFileMetadata(filePath: string): Promise<FileMetadata> {\n try {\n const stats = await fs.stat(filePath);\n const content = await fs.readFile(filePath);\n const hash = this.hashGenerator.generateHash(content);\n const encryptedHash = this.hashGenerator.generateEncryptedHash(content);\n const entropy = this.calculateEntropy(content);\n const magicBytes = await this.getMagicBytes(filePath);\n \n let signature: string | undefined;\n if (this.config.signatureVerification) {\n signature = await this.signatureValidator.generateSignature(content);\n }\n\n return {\n path: filePath,\n hash,\n signature,\n size: stats.size,\n created: stats.birthtime,\n modified: stats.mtime,\n accessed: stats.atime,\n permissions: stats.mode,\n owner: stats.uid.toString(),\n group: stats.gid.toString(),\n inode: stats.ino,\n checksum: this.generateChecksum(content),\n version: 1,\n encryptedHash,\n entropy,\n magicBytes\n };\n } catch (error) {\n this.logger.error(`Failed to generate metadata for ${filePath}`, { error });\n throw error;\n }\n }\n\n public async validateFile(filePath: string, metadata: FileMetadata): Promise<boolean> {\n try {\n if (!await this.fileExists(filePath)) {\n return false;\n }\n\n const stats = await fs.stat(filePath);\n const content = await fs.readFile(filePath);\n const currentHash = this.hashGenerator.generateHash(content);\n\n if (currentHash !== metadata.hash) {\n this.logger.warning(`Hash mismatch for ${filePath}`, {\n expected: metadata.hash,\n actual: currentHash\n });\n return false;\n }\n\n if (stats.size !== metadata.size) {\n this.logger.warning(`Size mismatch for ${filePath}`, {\n expected: metadata.size,\n actual: stats.size\n });\n return false;\n }\n\n if (stats.ino !== metadata.inode) {\n this.logger.warning(`Inode mismatch for ${filePath}`, {\n expected: metadata.inode,\n actual: stats.ino\n });\n return false;\n }\n\n if (this.isTextFile(filePath)) {\n const textContent = content.toString('utf8');\n if (await this.injectionDetector.detectInjection(textContent)) {\n this.logger.warning(`Injection detected in ${filePath}`);\n return false;\n }\n }\n\n if (this.config.signatureVerification && metadata.signature) {\n const isValidSignature = await this.signatureValidator.validateSignature(\n content,\n metadata.signature\n );\n if (!isValidSignature) {\n this.logger.warning(`Invalid signature for ${filePath}`);\n return false;\n }\n }\n\n if (this.config.integrityLevel === 'paranoid') {\n const currentEntropy = this.calculateEntropy(content);\n if (Math.abs(currentEntropy - metadata.entropy) > 0.1) {\n this.logger.warning(`Entropy changed for ${filePath}`);\n return false;\n }\n\n const currentMagic = await this.getMagicBytes(filePath);\n if (currentMagic !== metadata.magicBytes) {\n this.logger.warning(`Magic bytes changed for ${filePath}`);\n return false;\n }\n }\n\n return true;\n } catch (error) {\n this.logger.error(`Validation error for ${filePath}`, { error });\n return false;\n }\n }\n\n public async verifySignature(filePath: string, metadata: FileMetadata): Promise<boolean> {\n if (!metadata.signature) {\n return false;\n }\n\n try {\n const content = await fs.readFile(filePath);\n return await this.signatureValidator.validateSignature(content, metadata.signature);\n } catch (error) {\n this.logger.error(`Signature verification failed for ${filePath}`, { error });\n return false;\n }\n }\n\n private calculateEntropy(data: Buffer): number {\n const frequencies: { [key: number]: number } = {};\n \n for (const byte of data) {\n frequencies[byte] = (frequencies[byte] || 0) + 1;\n }\n \n let entropy = 0;\n const length = data.length;\n \n for (const freq of Object.values(frequencies)) {\n const probability = freq / length;\n entropy -= probability * Math.log2(probability);\n }\n \n return entropy;\n }\n\n private async getMagicBytes(filePath: string): Promise<string | undefined> {\n try {\n const buffer = Buffer.alloc(8);\n const fd = await fs.open(filePath, 'r');\n await fd.read(buffer, 0, 8, 0);\n await fd.close();\n \n return buffer.toString('hex').substring(0, 8);\n } catch {\n return undefined;\n }\n }\n\n private generateChecksum(data: Buffer): string {\n return crypto.createHash('md5').update(data).digest('hex');\n }\n\n private async fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n }\n\n private isTextFile(filePath: string): boolean {\n const textExtensions = ['.js', '.ts', '.json', '.txt', '.md', '.html', '.css', '.xml'];\n const ext = path.extname(filePath).toLowerCase();\n return textExtensions.includes(ext);\n }\n}"]}