stegdoc 4.0.0 → 5.0.1
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.
- package/LICENSE +21 -21
- package/README.md +200 -214
- package/package.json +59 -59
- package/src/commands/decode.js +485 -343
- package/src/commands/encode.js +567 -449
- package/src/commands/info.js +118 -114
- package/src/commands/verify.js +207 -204
- package/src/index.js +89 -87
- package/src/lib/compression.js +177 -115
- package/src/lib/crypto.js +172 -172
- package/src/lib/decoy-generator.js +306 -306
- package/src/lib/docx-handler.js +587 -161
- package/src/lib/docx-templates.js +355 -0
- package/src/lib/file-handler.js +113 -113
- package/src/lib/file-utils.js +160 -150
- package/src/lib/interactive.js +190 -190
- package/src/lib/log-generator.js +764 -0
- package/src/lib/metadata.js +151 -122
- package/src/lib/streams.js +197 -197
- package/src/lib/utils.js +227 -227
- package/src/lib/xlsx-handler.js +597 -416
- package/src/lib/xml-utils.js +115 -115
|
@@ -1,306 +1,306 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decoy Data Generator - Server Metrics Report
|
|
3
|
-
* Generates realistic-looking server monitoring/metrics data
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// Fixed list of servers (small dev team setup - ~10 servers total)
|
|
7
|
-
const SERVERS = [
|
|
8
|
-
'app-prod-01',
|
|
9
|
-
'app-prod-02',
|
|
10
|
-
'api-prod-01',
|
|
11
|
-
'db-prod-01',
|
|
12
|
-
'redis-prod-01',
|
|
13
|
-
'nginx-prod-01',
|
|
14
|
-
'app-dev-01',
|
|
15
|
-
'db-dev-01',
|
|
16
|
-
'jenkins-01',
|
|
17
|
-
'gitlab-01',
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
const STATUS_VALUES = [
|
|
21
|
-
{ status: 'healthy', weight: 85 },
|
|
22
|
-
{ status: 'warning', weight: 10 },
|
|
23
|
-
{ status: 'critical', weight: 3 },
|
|
24
|
-
{ status: 'maintenance', weight: 2 },
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Generate a random float between min and max with specified decimal places
|
|
29
|
-
*/
|
|
30
|
-
function randomFloat(min, max, decimals = 1) {
|
|
31
|
-
const val = Math.random() * (max - min) + min;
|
|
32
|
-
return parseFloat(val.toFixed(decimals));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Generate a random integer between min and max (inclusive)
|
|
37
|
-
*/
|
|
38
|
-
function randomInt(min, max) {
|
|
39
|
-
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Generate a random element from an array
|
|
44
|
-
*/
|
|
45
|
-
function randomElement(arr) {
|
|
46
|
-
return arr[Math.floor(Math.random() * arr.length)];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Generate a weighted random status
|
|
51
|
-
*/
|
|
52
|
-
function generateStatus() {
|
|
53
|
-
const totalWeight = STATUS_VALUES.reduce((sum, s) => sum + s.weight, 0);
|
|
54
|
-
let random = Math.random() * totalWeight;
|
|
55
|
-
|
|
56
|
-
for (const item of STATUS_VALUES) {
|
|
57
|
-
random -= item.weight;
|
|
58
|
-
if (random <= 0) {
|
|
59
|
-
return item.status;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return 'healthy';
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Pick a server from the fixed list
|
|
67
|
-
*/
|
|
68
|
-
function generateServerId() {
|
|
69
|
-
return randomElement(SERVERS);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Time window configuration (last 4 hours of data)
|
|
73
|
-
const HOURS_WINDOW = 4;
|
|
74
|
-
|
|
75
|
-
// Shared time window for multi-part consistency
|
|
76
|
-
let sharedTimeWindow = null;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Initialize or get the shared time window
|
|
80
|
-
* This ensures multi-part files have continuous timestamps
|
|
81
|
-
*/
|
|
82
|
-
function getTimeWindow() {
|
|
83
|
-
if (!sharedTimeWindow) {
|
|
84
|
-
const now = new Date();
|
|
85
|
-
sharedTimeWindow = {
|
|
86
|
-
end: now.getTime(),
|
|
87
|
-
start: now.getTime() - (HOURS_WINDOW * 60 * 60 * 1000),
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
return sharedTimeWindow;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Reset the time window (called between separate encode sessions)
|
|
95
|
-
*/
|
|
96
|
-
function resetTimeWindow() {
|
|
97
|
-
sharedTimeWindow = null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Generate a realistic timestamp within the configured time window
|
|
102
|
-
*/
|
|
103
|
-
function generateTimestamp() {
|
|
104
|
-
const window = getTimeWindow();
|
|
105
|
-
const timestamp = new Date(window.start + Math.random() * (window.end - window.start));
|
|
106
|
-
|
|
107
|
-
// Format: YYYY-MM-DD HH:MM:SS
|
|
108
|
-
const year = timestamp.getFullYear();
|
|
109
|
-
const month = (timestamp.getMonth() + 1).toString().padStart(2, '0');
|
|
110
|
-
const day = timestamp.getDate().toString().padStart(2, '0');
|
|
111
|
-
const hours = timestamp.getHours().toString().padStart(2, '0');
|
|
112
|
-
const minutes = timestamp.getMinutes().toString().padStart(2, '0');
|
|
113
|
-
const seconds = timestamp.getSeconds().toString().padStart(2, '0');
|
|
114
|
-
|
|
115
|
-
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Generate CPU usage based on status
|
|
120
|
-
*/
|
|
121
|
-
function generateCpuUsage(status) {
|
|
122
|
-
switch (status) {
|
|
123
|
-
case 'critical':
|
|
124
|
-
return randomFloat(90, 99);
|
|
125
|
-
case 'warning':
|
|
126
|
-
return randomFloat(70, 89);
|
|
127
|
-
case 'maintenance':
|
|
128
|
-
return randomFloat(0, 10);
|
|
129
|
-
default:
|
|
130
|
-
return randomFloat(15, 69);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Generate memory usage based on status
|
|
136
|
-
*/
|
|
137
|
-
function generateMemoryUsage(status) {
|
|
138
|
-
switch (status) {
|
|
139
|
-
case 'critical':
|
|
140
|
-
return randomFloat(92, 99);
|
|
141
|
-
case 'warning':
|
|
142
|
-
return randomFloat(75, 91);
|
|
143
|
-
case 'maintenance':
|
|
144
|
-
return randomFloat(5, 20);
|
|
145
|
-
default:
|
|
146
|
-
return randomFloat(30, 74);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Generate disk usage (generally more stable than CPU/memory)
|
|
152
|
-
*/
|
|
153
|
-
function generateDiskUsage(status) {
|
|
154
|
-
switch (status) {
|
|
155
|
-
case 'critical':
|
|
156
|
-
return randomFloat(95, 99);
|
|
157
|
-
case 'warning':
|
|
158
|
-
return randomFloat(80, 94);
|
|
159
|
-
default:
|
|
160
|
-
return randomFloat(25, 79);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Generate network I/O in MB/s
|
|
166
|
-
*/
|
|
167
|
-
function generateNetworkIO() {
|
|
168
|
-
return randomFloat(0.5, 150, 2);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Generate request count (for web/api servers)
|
|
173
|
-
*/
|
|
174
|
-
function generateRequestCount(serverId) {
|
|
175
|
-
// Higher for app/api/nginx servers
|
|
176
|
-
if (serverId.match(/^(app|api|nginx)/)) {
|
|
177
|
-
return randomInt(500, 15000);
|
|
178
|
-
}
|
|
179
|
-
// Low for CI/CD servers
|
|
180
|
-
if (serverId.match(/^(jenkins|gitlab)/)) {
|
|
181
|
-
return randomInt(10, 200);
|
|
182
|
-
}
|
|
183
|
-
return randomInt(50, 1000);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Generate response time in ms
|
|
188
|
-
*/
|
|
189
|
-
function generateResponseTime(status) {
|
|
190
|
-
switch (status) {
|
|
191
|
-
case 'critical':
|
|
192
|
-
return randomInt(2000, 10000);
|
|
193
|
-
case 'warning':
|
|
194
|
-
return randomInt(500, 1999);
|
|
195
|
-
default:
|
|
196
|
-
return randomInt(5, 499);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Generate uptime in hours
|
|
202
|
-
*/
|
|
203
|
-
function generateUptime(status) {
|
|
204
|
-
if (status === 'maintenance') {
|
|
205
|
-
return randomFloat(0, 2, 1);
|
|
206
|
-
}
|
|
207
|
-
// Servers typically have long uptimes
|
|
208
|
-
return randomFloat(24, 2160, 1); // Up to 90 days
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Generate column headers
|
|
213
|
-
*/
|
|
214
|
-
function generateDecoyHeaders() {
|
|
215
|
-
return [
|
|
216
|
-
'Timestamp',
|
|
217
|
-
'Server ID',
|
|
218
|
-
'Status',
|
|
219
|
-
'CPU %',
|
|
220
|
-
'Memory %',
|
|
221
|
-
'Disk %',
|
|
222
|
-
'Network (MB/s)',
|
|
223
|
-
'Requests',
|
|
224
|
-
'Resp Time (ms)',
|
|
225
|
-
'Uptime (hrs)',
|
|
226
|
-
];
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Generate a single row of server metrics
|
|
231
|
-
*/
|
|
232
|
-
function generateMetricsRow() {
|
|
233
|
-
const serverId = generateServerId();
|
|
234
|
-
const status = generateStatus();
|
|
235
|
-
|
|
236
|
-
return {
|
|
237
|
-
timestamp: generateTimestamp(),
|
|
238
|
-
serverId,
|
|
239
|
-
status,
|
|
240
|
-
cpu: generateCpuUsage(status),
|
|
241
|
-
memory: generateMemoryUsage(status),
|
|
242
|
-
disk: generateDiskUsage(status),
|
|
243
|
-
network: generateNetworkIO(),
|
|
244
|
-
requests: generateRequestCount(serverId),
|
|
245
|
-
responseTime: generateResponseTime(status),
|
|
246
|
-
uptime: generateUptime(status),
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* Generate decoy data with specified number of rows
|
|
252
|
-
* @param {number} rowCount - Number of rows to generate (default 100)
|
|
253
|
-
* @returns {Array<object>} Array of metrics row objects
|
|
254
|
-
*/
|
|
255
|
-
function generateDecoyData(rowCount = 100) {
|
|
256
|
-
const rows = [];
|
|
257
|
-
for (let i = 0; i < rowCount; i++) {
|
|
258
|
-
rows.push(generateMetricsRow());
|
|
259
|
-
}
|
|
260
|
-
// Sort by timestamp descending (most recent first)
|
|
261
|
-
rows.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
262
|
-
return rows;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Calculate appropriate row count based on payload size
|
|
267
|
-
* @param {number} payloadSizeBytes - Size of encrypted payload
|
|
268
|
-
* @returns {number} Recommended number of decoy rows
|
|
269
|
-
*/
|
|
270
|
-
function calculateDecoyRowCount(payloadSizeBytes) {
|
|
271
|
-
const estimatedBytesPerRow = 150;
|
|
272
|
-
const targetDecoyRatio = 0.4;
|
|
273
|
-
|
|
274
|
-
const minRows = 50;
|
|
275
|
-
const maxRows = 10000;
|
|
276
|
-
|
|
277
|
-
const calculatedRows = Math.floor((payloadSizeBytes * targetDecoyRatio) / estimatedBytesPerRow);
|
|
278
|
-
|
|
279
|
-
return Math.max(minRows, Math.min(maxRows, calculatedRows));
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Convert row object to array of values (for Excel)
|
|
284
|
-
*/
|
|
285
|
-
function rowToArray(row) {
|
|
286
|
-
return [
|
|
287
|
-
row.timestamp,
|
|
288
|
-
row.serverId,
|
|
289
|
-
row.status,
|
|
290
|
-
row.cpu,
|
|
291
|
-
row.memory,
|
|
292
|
-
row.disk,
|
|
293
|
-
row.network,
|
|
294
|
-
row.requests,
|
|
295
|
-
row.responseTime,
|
|
296
|
-
row.uptime,
|
|
297
|
-
];
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
module.exports = {
|
|
301
|
-
generateDecoyHeaders,
|
|
302
|
-
generateDecoyData,
|
|
303
|
-
calculateDecoyRowCount,
|
|
304
|
-
rowToArray,
|
|
305
|
-
resetTimeWindow,
|
|
306
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Decoy Data Generator - Server Metrics Report
|
|
3
|
+
* Generates realistic-looking server monitoring/metrics data
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Fixed list of servers (small dev team setup - ~10 servers total)
|
|
7
|
+
const SERVERS = [
|
|
8
|
+
'app-prod-01',
|
|
9
|
+
'app-prod-02',
|
|
10
|
+
'api-prod-01',
|
|
11
|
+
'db-prod-01',
|
|
12
|
+
'redis-prod-01',
|
|
13
|
+
'nginx-prod-01',
|
|
14
|
+
'app-dev-01',
|
|
15
|
+
'db-dev-01',
|
|
16
|
+
'jenkins-01',
|
|
17
|
+
'gitlab-01',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const STATUS_VALUES = [
|
|
21
|
+
{ status: 'healthy', weight: 85 },
|
|
22
|
+
{ status: 'warning', weight: 10 },
|
|
23
|
+
{ status: 'critical', weight: 3 },
|
|
24
|
+
{ status: 'maintenance', weight: 2 },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Generate a random float between min and max with specified decimal places
|
|
29
|
+
*/
|
|
30
|
+
function randomFloat(min, max, decimals = 1) {
|
|
31
|
+
const val = Math.random() * (max - min) + min;
|
|
32
|
+
return parseFloat(val.toFixed(decimals));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Generate a random integer between min and max (inclusive)
|
|
37
|
+
*/
|
|
38
|
+
function randomInt(min, max) {
|
|
39
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Generate a random element from an array
|
|
44
|
+
*/
|
|
45
|
+
function randomElement(arr) {
|
|
46
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Generate a weighted random status
|
|
51
|
+
*/
|
|
52
|
+
function generateStatus() {
|
|
53
|
+
const totalWeight = STATUS_VALUES.reduce((sum, s) => sum + s.weight, 0);
|
|
54
|
+
let random = Math.random() * totalWeight;
|
|
55
|
+
|
|
56
|
+
for (const item of STATUS_VALUES) {
|
|
57
|
+
random -= item.weight;
|
|
58
|
+
if (random <= 0) {
|
|
59
|
+
return item.status;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return 'healthy';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Pick a server from the fixed list
|
|
67
|
+
*/
|
|
68
|
+
function generateServerId() {
|
|
69
|
+
return randomElement(SERVERS);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Time window configuration (last 4 hours of data)
|
|
73
|
+
const HOURS_WINDOW = 4;
|
|
74
|
+
|
|
75
|
+
// Shared time window for multi-part consistency
|
|
76
|
+
let sharedTimeWindow = null;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Initialize or get the shared time window
|
|
80
|
+
* This ensures multi-part files have continuous timestamps
|
|
81
|
+
*/
|
|
82
|
+
function getTimeWindow() {
|
|
83
|
+
if (!sharedTimeWindow) {
|
|
84
|
+
const now = new Date();
|
|
85
|
+
sharedTimeWindow = {
|
|
86
|
+
end: now.getTime(),
|
|
87
|
+
start: now.getTime() - (HOURS_WINDOW * 60 * 60 * 1000),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return sharedTimeWindow;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Reset the time window (called between separate encode sessions)
|
|
95
|
+
*/
|
|
96
|
+
function resetTimeWindow() {
|
|
97
|
+
sharedTimeWindow = null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Generate a realistic timestamp within the configured time window
|
|
102
|
+
*/
|
|
103
|
+
function generateTimestamp() {
|
|
104
|
+
const window = getTimeWindow();
|
|
105
|
+
const timestamp = new Date(window.start + Math.random() * (window.end - window.start));
|
|
106
|
+
|
|
107
|
+
// Format: YYYY-MM-DD HH:MM:SS
|
|
108
|
+
const year = timestamp.getFullYear();
|
|
109
|
+
const month = (timestamp.getMonth() + 1).toString().padStart(2, '0');
|
|
110
|
+
const day = timestamp.getDate().toString().padStart(2, '0');
|
|
111
|
+
const hours = timestamp.getHours().toString().padStart(2, '0');
|
|
112
|
+
const minutes = timestamp.getMinutes().toString().padStart(2, '0');
|
|
113
|
+
const seconds = timestamp.getSeconds().toString().padStart(2, '0');
|
|
114
|
+
|
|
115
|
+
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Generate CPU usage based on status
|
|
120
|
+
*/
|
|
121
|
+
function generateCpuUsage(status) {
|
|
122
|
+
switch (status) {
|
|
123
|
+
case 'critical':
|
|
124
|
+
return randomFloat(90, 99);
|
|
125
|
+
case 'warning':
|
|
126
|
+
return randomFloat(70, 89);
|
|
127
|
+
case 'maintenance':
|
|
128
|
+
return randomFloat(0, 10);
|
|
129
|
+
default:
|
|
130
|
+
return randomFloat(15, 69);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Generate memory usage based on status
|
|
136
|
+
*/
|
|
137
|
+
function generateMemoryUsage(status) {
|
|
138
|
+
switch (status) {
|
|
139
|
+
case 'critical':
|
|
140
|
+
return randomFloat(92, 99);
|
|
141
|
+
case 'warning':
|
|
142
|
+
return randomFloat(75, 91);
|
|
143
|
+
case 'maintenance':
|
|
144
|
+
return randomFloat(5, 20);
|
|
145
|
+
default:
|
|
146
|
+
return randomFloat(30, 74);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate disk usage (generally more stable than CPU/memory)
|
|
152
|
+
*/
|
|
153
|
+
function generateDiskUsage(status) {
|
|
154
|
+
switch (status) {
|
|
155
|
+
case 'critical':
|
|
156
|
+
return randomFloat(95, 99);
|
|
157
|
+
case 'warning':
|
|
158
|
+
return randomFloat(80, 94);
|
|
159
|
+
default:
|
|
160
|
+
return randomFloat(25, 79);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Generate network I/O in MB/s
|
|
166
|
+
*/
|
|
167
|
+
function generateNetworkIO() {
|
|
168
|
+
return randomFloat(0.5, 150, 2);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Generate request count (for web/api servers)
|
|
173
|
+
*/
|
|
174
|
+
function generateRequestCount(serverId) {
|
|
175
|
+
// Higher for app/api/nginx servers
|
|
176
|
+
if (serverId.match(/^(app|api|nginx)/)) {
|
|
177
|
+
return randomInt(500, 15000);
|
|
178
|
+
}
|
|
179
|
+
// Low for CI/CD servers
|
|
180
|
+
if (serverId.match(/^(jenkins|gitlab)/)) {
|
|
181
|
+
return randomInt(10, 200);
|
|
182
|
+
}
|
|
183
|
+
return randomInt(50, 1000);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Generate response time in ms
|
|
188
|
+
*/
|
|
189
|
+
function generateResponseTime(status) {
|
|
190
|
+
switch (status) {
|
|
191
|
+
case 'critical':
|
|
192
|
+
return randomInt(2000, 10000);
|
|
193
|
+
case 'warning':
|
|
194
|
+
return randomInt(500, 1999);
|
|
195
|
+
default:
|
|
196
|
+
return randomInt(5, 499);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Generate uptime in hours
|
|
202
|
+
*/
|
|
203
|
+
function generateUptime(status) {
|
|
204
|
+
if (status === 'maintenance') {
|
|
205
|
+
return randomFloat(0, 2, 1);
|
|
206
|
+
}
|
|
207
|
+
// Servers typically have long uptimes
|
|
208
|
+
return randomFloat(24, 2160, 1); // Up to 90 days
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Generate column headers
|
|
213
|
+
*/
|
|
214
|
+
function generateDecoyHeaders() {
|
|
215
|
+
return [
|
|
216
|
+
'Timestamp',
|
|
217
|
+
'Server ID',
|
|
218
|
+
'Status',
|
|
219
|
+
'CPU %',
|
|
220
|
+
'Memory %',
|
|
221
|
+
'Disk %',
|
|
222
|
+
'Network (MB/s)',
|
|
223
|
+
'Requests',
|
|
224
|
+
'Resp Time (ms)',
|
|
225
|
+
'Uptime (hrs)',
|
|
226
|
+
];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Generate a single row of server metrics
|
|
231
|
+
*/
|
|
232
|
+
function generateMetricsRow() {
|
|
233
|
+
const serverId = generateServerId();
|
|
234
|
+
const status = generateStatus();
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
timestamp: generateTimestamp(),
|
|
238
|
+
serverId,
|
|
239
|
+
status,
|
|
240
|
+
cpu: generateCpuUsage(status),
|
|
241
|
+
memory: generateMemoryUsage(status),
|
|
242
|
+
disk: generateDiskUsage(status),
|
|
243
|
+
network: generateNetworkIO(),
|
|
244
|
+
requests: generateRequestCount(serverId),
|
|
245
|
+
responseTime: generateResponseTime(status),
|
|
246
|
+
uptime: generateUptime(status),
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Generate decoy data with specified number of rows
|
|
252
|
+
* @param {number} rowCount - Number of rows to generate (default 100)
|
|
253
|
+
* @returns {Array<object>} Array of metrics row objects
|
|
254
|
+
*/
|
|
255
|
+
function generateDecoyData(rowCount = 100) {
|
|
256
|
+
const rows = [];
|
|
257
|
+
for (let i = 0; i < rowCount; i++) {
|
|
258
|
+
rows.push(generateMetricsRow());
|
|
259
|
+
}
|
|
260
|
+
// Sort by timestamp descending (most recent first)
|
|
261
|
+
rows.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
262
|
+
return rows;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Calculate appropriate row count based on payload size
|
|
267
|
+
* @param {number} payloadSizeBytes - Size of encrypted payload
|
|
268
|
+
* @returns {number} Recommended number of decoy rows
|
|
269
|
+
*/
|
|
270
|
+
function calculateDecoyRowCount(payloadSizeBytes) {
|
|
271
|
+
const estimatedBytesPerRow = 150;
|
|
272
|
+
const targetDecoyRatio = 0.4;
|
|
273
|
+
|
|
274
|
+
const minRows = 50;
|
|
275
|
+
const maxRows = 10000;
|
|
276
|
+
|
|
277
|
+
const calculatedRows = Math.floor((payloadSizeBytes * targetDecoyRatio) / estimatedBytesPerRow);
|
|
278
|
+
|
|
279
|
+
return Math.max(minRows, Math.min(maxRows, calculatedRows));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Convert row object to array of values (for Excel)
|
|
284
|
+
*/
|
|
285
|
+
function rowToArray(row) {
|
|
286
|
+
return [
|
|
287
|
+
row.timestamp,
|
|
288
|
+
row.serverId,
|
|
289
|
+
row.status,
|
|
290
|
+
row.cpu,
|
|
291
|
+
row.memory,
|
|
292
|
+
row.disk,
|
|
293
|
+
row.network,
|
|
294
|
+
row.requests,
|
|
295
|
+
row.responseTime,
|
|
296
|
+
row.uptime,
|
|
297
|
+
];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
module.exports = {
|
|
301
|
+
generateDecoyHeaders,
|
|
302
|
+
generateDecoyData,
|
|
303
|
+
calculateDecoyRowCount,
|
|
304
|
+
rowToArray,
|
|
305
|
+
resetTimeWindow,
|
|
306
|
+
};
|