stigmergy 1.2.6 → 1.2.8
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/README.md +32 -17
- package/STIGMERGY.md +16 -7
- package/docs/MULTI_USER_WIKI_COLLABORATION_SYSTEM.md +523 -0
- package/docs/PROMPT_BASED_SKILLS_SYSTEM_DESIGN.md +458 -0
- package/docs/SKILL_IMPLEMENTATION_CONSTRAINTS_AND_ALIGNMENT.md +423 -0
- package/docs/TECHNICAL_FEASIBILITY_ANALYSIS.md +308 -0
- package/examples/multilingual-hook-demo.js +125 -0
- package/package.json +14 -17
- package/scripts/dependency-analyzer.js +101 -0
- package/scripts/generate-cli-docs.js +64 -0
- package/scripts/postuninstall.js +46 -0
- package/scripts/preuninstall.js +75 -0
- package/scripts/run-layered-tests.js +3 -3
- package/src/adapters/claude/install_claude_integration.js +17 -17
- package/src/adapters/codebuddy/install_codebuddy_integration.js +13 -13
- package/src/adapters/codex/install_codex_integration.js +27 -27
- package/src/adapters/copilot/install_copilot_integration.js +46 -46
- package/src/adapters/gemini/install_gemini_integration.js +10 -10
- package/src/adapters/iflow/install_iflow_integration.js +7 -7
- package/src/adapters/qoder/install_qoder_integration.js +12 -12
- package/src/adapters/qwen/install_qwen_integration.js +17 -17
- package/src/auth.js +173 -173
- package/src/auth_command.js +208 -208
- package/src/calculator.js +313 -313
- package/src/cli/router.js +151 -7
- package/src/core/cache_cleaner.js +767 -767
- package/src/core/cli_help_analyzer.js +680 -680
- package/src/core/cli_parameter_handler.js +132 -132
- package/src/core/cli_tools.js +89 -89
- package/src/core/coordination/index.js +16 -16
- package/src/core/coordination/nodejs/AdapterManager.js +102 -102
- package/src/core/coordination/nodejs/CLCommunication.js +132 -132
- package/src/core/coordination/nodejs/CLIIntegrationManager.js +272 -272
- package/src/core/coordination/nodejs/HealthChecker.js +76 -76
- package/src/core/coordination/nodejs/HookDeploymentManager.js +463 -274
- package/src/core/coordination/nodejs/StatisticsCollector.js +71 -71
- package/src/core/coordination/nodejs/index.js +90 -90
- package/src/core/coordination/nodejs/utils/Logger.js +29 -29
- package/src/core/enhanced_installer.js +479 -479
- package/src/core/enhanced_uninstaller.js +638 -638
- package/src/core/error_handler.js +406 -406
- package/src/core/installer.js +32 -32
- package/src/core/memory_manager.js +83 -83
- package/src/core/multilingual/language-pattern-manager.js +172 -0
- package/src/core/rest_client.js +160 -160
- package/src/core/smart_router.js +261 -249
- package/src/core/upgrade_manager.js +48 -20
- package/src/data_encryption.js +143 -143
- package/src/data_structures.js +440 -440
- package/src/deploy.js +55 -55
- package/src/index.js +30 -30
- package/src/test/cli-availability-checker.js +194 -194
- package/src/test/test-environment.js +289 -289
- package/src/utils/helpers.js +35 -35
- package/src/utils.js +921 -921
- package/src/weatherProcessor.js +228 -228
- package/test/multilingual/hook-deployment.test.js +91 -0
- package/test/multilingual/language-pattern-manager.test.js +140 -0
- package/test/multilingual/system-test.js +85 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Stigmergy CLI Upgrade Manager
|
|
3
|
-
*
|
|
3
|
+
* 管理所有AI CLI 工具的升级和依赖更新
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const { spawn, spawnSync } = require('child_process');
|
|
@@ -24,7 +24,8 @@ class UpgradeManager {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* 检查CLI 工具的当前版本和最新版本
|
|
28
|
+
*/
|
|
28
29
|
async checkVersions() {
|
|
29
30
|
const versions = {};
|
|
30
31
|
const errors = [];
|
|
@@ -39,12 +40,26 @@ class UpgradeManager {
|
|
|
39
40
|
toolConfig,
|
|
40
41
|
);
|
|
41
42
|
|
|
42
|
-
//
|
|
43
|
+
// 获取最新版本
|
|
44
|
+
let latestVersion;
|
|
45
|
+
try {
|
|
46
|
+
latestVersion = await this.getLatestVersion(toolName, toolConfig);
|
|
47
|
+
} catch (versionError) {
|
|
48
|
+
console.error(`Error retrieving latest version for ${toolName}:`, versionError.message);
|
|
49
|
+
latestVersion = 'Unknown';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Only perform semver comparison if both versions are valid semantic versions
|
|
53
|
+
let needsUpgrade = false;
|
|
54
|
+
if (currentVersion !== 'Not installed' && latestVersion !== 'Unknown' &&
|
|
55
|
+
semver.valid(currentVersion) && semver.valid(latestVersion)) {
|
|
56
|
+
needsUpgrade = semver.gt(latestVersion, currentVersion);
|
|
57
|
+
}
|
|
43
58
|
|
|
44
59
|
versions[toolName] = {
|
|
45
60
|
current: currentVersion,
|
|
46
61
|
latest: latestVersion,
|
|
47
|
-
needsUpgrade:
|
|
62
|
+
needsUpgrade: needsUpgrade,
|
|
48
63
|
config: toolConfig,
|
|
49
64
|
};
|
|
50
65
|
|
|
@@ -54,7 +69,7 @@ class UpgradeManager {
|
|
|
54
69
|
);
|
|
55
70
|
} catch (error) {
|
|
56
71
|
errors.push({ tool: toolName, error: error.message });
|
|
57
|
-
console.log(
|
|
72
|
+
console.log(`❌ ${toolName}: ${error.message}`);
|
|
58
73
|
}
|
|
59
74
|
}
|
|
60
75
|
|
|
@@ -62,7 +77,8 @@ class UpgradeManager {
|
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
/**
|
|
65
|
-
*
|
|
80
|
+
* 获取当前安装的版本
|
|
81
|
+
*/
|
|
66
82
|
async getCurrentVersion(toolName, toolConfig) {
|
|
67
83
|
try {
|
|
68
84
|
const result = spawnSync(toolConfig.version, {
|
|
@@ -79,7 +95,8 @@ class UpgradeManager {
|
|
|
79
95
|
throw new Error(`Version command failed: ${result.stderr}`);
|
|
80
96
|
}
|
|
81
97
|
|
|
82
|
-
//
|
|
98
|
+
// 从输出中提取版本
|
|
99
|
+
const versionMatch = result.stdout.match(/(\d+\.\d+\.\d+)/);
|
|
83
100
|
if (versionMatch) {
|
|
84
101
|
return versionMatch[1];
|
|
85
102
|
}
|
|
@@ -91,10 +108,12 @@ class UpgradeManager {
|
|
|
91
108
|
}
|
|
92
109
|
|
|
93
110
|
/**
|
|
94
|
-
*
|
|
111
|
+
* 获取最新可用版本
|
|
112
|
+
*/
|
|
95
113
|
async getLatestVersion(toolName, toolConfig) {
|
|
96
114
|
try {
|
|
97
|
-
//
|
|
115
|
+
// 从 npm 注册表获取最新版本
|
|
116
|
+
const packageName = this.extractPackageName(toolConfig.install);
|
|
98
117
|
if (!packageName) {
|
|
99
118
|
throw new Error('Could not extract package name');
|
|
100
119
|
}
|
|
@@ -105,8 +124,13 @@ class UpgradeManager {
|
|
|
105
124
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
106
125
|
});
|
|
107
126
|
|
|
127
|
+
// Check for execution errors
|
|
128
|
+
if (result.error) {
|
|
129
|
+
throw new Error(`npm command execution failed: ${result.error.message}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
108
132
|
if (result.status !== 0) {
|
|
109
|
-
throw new Error(`npm view failed: ${result.stderr}`);
|
|
133
|
+
throw new Error(`npm view failed: ${result.stderr || 'Unknown error'}`);
|
|
110
134
|
}
|
|
111
135
|
|
|
112
136
|
const latestVersion = result.stdout.trim();
|
|
@@ -116,6 +140,8 @@ class UpgradeManager {
|
|
|
116
140
|
|
|
117
141
|
throw new Error('No version information available');
|
|
118
142
|
} catch (error) {
|
|
143
|
+
// Log the actual error for debugging, but return 'Unknown' to prevent crashes
|
|
144
|
+
console.error(`Error getting latest version for ${toolName}:`, error.message);
|
|
119
145
|
return 'Unknown';
|
|
120
146
|
}
|
|
121
147
|
}
|
|
@@ -132,12 +158,13 @@ class UpgradeManager {
|
|
|
132
158
|
}
|
|
133
159
|
|
|
134
160
|
/**
|
|
135
|
-
*
|
|
161
|
+
* 检查过时的依赖和警告
|
|
162
|
+
*/
|
|
136
163
|
async checkDeprecations() {
|
|
137
164
|
const deprecations = [];
|
|
138
165
|
|
|
139
166
|
try {
|
|
140
|
-
//
|
|
167
|
+
// 检查npm 警告
|
|
141
168
|
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
142
169
|
if (await this.fileExists(packageJsonPath)) {
|
|
143
170
|
const packageJson = JSON.parse(
|
|
@@ -155,7 +182,7 @@ class UpgradeManager {
|
|
|
155
182
|
}
|
|
156
183
|
}
|
|
157
184
|
|
|
158
|
-
//
|
|
185
|
+
// 检查ImportProcessor 错误
|
|
159
186
|
const importProcessorErrors = await this.checkImportProcessorErrors();
|
|
160
187
|
if (importProcessorErrors.length > 0) {
|
|
161
188
|
deprecations.push({
|
|
@@ -200,7 +227,7 @@ class UpgradeManager {
|
|
|
200
227
|
}
|
|
201
228
|
|
|
202
229
|
/**
|
|
203
|
-
*
|
|
230
|
+
* 检查ImportProcessor 相关错误
|
|
204
231
|
*/
|
|
205
232
|
async checkImportProcessorErrors() {
|
|
206
233
|
const errors = [];
|
|
@@ -335,18 +362,18 @@ class UpgradeManager {
|
|
|
335
362
|
|
|
336
363
|
if (result.status === 0) {
|
|
337
364
|
results.successful.push(upgrade);
|
|
338
|
-
console.log(
|
|
365
|
+
console.log(`✅${upgrade.tool} upgraded successfully`);
|
|
339
366
|
} else {
|
|
340
367
|
results.failed.push({ ...upgrade, error: 'Installation failed' });
|
|
341
|
-
console.log(
|
|
368
|
+
console.log(`❌${upgrade.tool} upgrade failed`);
|
|
342
369
|
}
|
|
343
370
|
} catch (error) {
|
|
344
371
|
results.failed.push({ ...upgrade, error: error.message });
|
|
345
|
-
console.log(
|
|
372
|
+
console.log(`❌${upgrade.tool} upgrade failed: ${error.message}`);
|
|
346
373
|
}
|
|
347
374
|
} else {
|
|
348
375
|
console.log(
|
|
349
|
-
`🔍 Would upgrade ${upgrade.tool}: ${upgrade.from}
|
|
376
|
+
`🔍 Would upgrade ${upgrade.tool}: ${upgrade.from} -> ${upgrade.to}`,
|
|
350
377
|
);
|
|
351
378
|
results.successful.push(upgrade);
|
|
352
379
|
}
|
|
@@ -406,7 +433,8 @@ class UpgradeManager {
|
|
|
406
433
|
}
|
|
407
434
|
|
|
408
435
|
/**
|
|
409
|
-
*
|
|
436
|
+
* 辅助方法:检查文件是否存在
|
|
437
|
+
*/
|
|
410
438
|
async fileExists(filePath) {
|
|
411
439
|
try {
|
|
412
440
|
await fs.access(filePath);
|
|
@@ -417,4 +445,4 @@ class UpgradeManager {
|
|
|
417
445
|
}
|
|
418
446
|
}
|
|
419
447
|
|
|
420
|
-
module.exports = UpgradeManager;
|
|
448
|
+
module.exports = UpgradeManager;
|
package/src/data_encryption.js
CHANGED
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Data encryption utilities for the Stigmergy CLI
|
|
3
|
-
* Provides secure data encryption and decryption functions using AES-256-GCM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const crypto = require('crypto');
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Encrypts data using AES-256-GCM authenticated encryption
|
|
10
|
-
*
|
|
11
|
-
* This function provides secure symmetric encryption with authentication.
|
|
12
|
-
* It generates a random initialization vector for each encryption operation
|
|
13
|
-
* and returns the encrypted data along with the IV and authentication tag.
|
|
14
|
-
*
|
|
15
|
-
* @param {string|Buffer} data - The plaintext data to encrypt
|
|
16
|
-
* @param {string|Buffer} secretKey - The secret key for encryption (must be 32 bytes for AES-256)
|
|
17
|
-
* @returns {Object} Object containing encrypted data, IV, and authentication tag
|
|
18
|
-
* @throws {Error} If encryption fails due to invalid inputs or cryptographic errors
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* const crypto = require('crypto');
|
|
22
|
-
* const secretKey = crypto.randomBytes(32); // 256-bit key
|
|
23
|
-
* const plaintext = "Secret message";
|
|
24
|
-
* const encryptedObj = encryptData(plaintext, secretKey);
|
|
25
|
-
* console.log(encryptedObj);
|
|
26
|
-
* // Output: {
|
|
27
|
-
* // encryptedData: 'a3f5b7c8...',
|
|
28
|
-
* // iv: 'MjRkOGZj...',
|
|
29
|
-
* // authTag: 'YzQyNTgx...'
|
|
30
|
-
* // }
|
|
31
|
-
*/
|
|
32
|
-
function encryptData(data, secretKey) {
|
|
33
|
-
// Validate inputs
|
|
34
|
-
if (!data) {
|
|
35
|
-
throw new Error('Data to encrypt cannot be empty');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (!secretKey) {
|
|
39
|
-
throw new Error('Secret key is required');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Generate a random initialization vector
|
|
43
|
-
const iv = crypto.randomBytes(16);
|
|
44
|
-
|
|
45
|
-
// Create cipher using AES-256-GCM
|
|
46
|
-
const cipher = crypto.createCipherGCM('aes-256-gcm', secretKey, iv);
|
|
47
|
-
|
|
48
|
-
// Encrypt the data
|
|
49
|
-
let encrypted;
|
|
50
|
-
if (typeof data === 'string') {
|
|
51
|
-
encrypted = cipher.update(data, 'utf8', 'hex');
|
|
52
|
-
} else {
|
|
53
|
-
encrypted = cipher.update(data);
|
|
54
|
-
encrypted = encrypted.toString('hex');
|
|
55
|
-
}
|
|
56
|
-
cipher.final();
|
|
57
|
-
|
|
58
|
-
// Get the authentication tag
|
|
59
|
-
const authTag = cipher.getAuthTag();
|
|
60
|
-
|
|
61
|
-
// Return encrypted data with IV and auth tag
|
|
62
|
-
return {
|
|
63
|
-
encryptedData: encrypted,
|
|
64
|
-
iv: iv.toString('base64'),
|
|
65
|
-
authTag: authTag.toString('base64'),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Decrypts data using AES-256-GCM authenticated decryption
|
|
71
|
-
*
|
|
72
|
-
* This function decrypts data that was encrypted with encryptData().
|
|
73
|
-
* It requires the encrypted data object containing the encrypted data,
|
|
74
|
-
* initialization vector, and authentication tag.
|
|
75
|
-
*
|
|
76
|
-
* @param {Object} encryptedObj - Object containing encrypted data, IV, and auth tag
|
|
77
|
-
* @param {string|Buffer} secretKey - The secret key used for encryption
|
|
78
|
-
* @returns {string} The decrypted plaintext data
|
|
79
|
-
* @throws {Error} If decryption fails due to invalid inputs, tampered data, or cryptographic errors
|
|
80
|
-
*
|
|
81
|
-
* @example
|
|
82
|
-
* const decrypted = decryptData(encryptedObj, secretKey);
|
|
83
|
-
* console.log(decrypted); // "Secret message"
|
|
84
|
-
*/
|
|
85
|
-
function decryptData(encryptedObj, secretKey) {
|
|
86
|
-
// Validate inputs
|
|
87
|
-
if (
|
|
88
|
-
!encryptedObj ||
|
|
89
|
-
!encryptedObj.encryptedData ||
|
|
90
|
-
!encryptedObj.iv ||
|
|
91
|
-
!encryptedObj.authTag
|
|
92
|
-
) {
|
|
93
|
-
throw new Error('Invalid encrypted object');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (!secretKey) {
|
|
97
|
-
throw new Error('Secret key is required');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Decode base64 encoded values
|
|
101
|
-
const iv = Buffer.from(encryptedObj.iv, 'base64');
|
|
102
|
-
const authTag = Buffer.from(encryptedObj.authTag, 'base64');
|
|
103
|
-
|
|
104
|
-
// Create decipher using AES-256-GCM
|
|
105
|
-
const decipher = crypto.createDecipherGCM('aes-256-gcm', secretKey, iv);
|
|
106
|
-
|
|
107
|
-
// Set the authentication tag
|
|
108
|
-
decipher.setAuthTag(authTag);
|
|
109
|
-
|
|
110
|
-
// Decrypt the data
|
|
111
|
-
let decrypted;
|
|
112
|
-
if (typeof encryptedObj.encryptedData === 'string') {
|
|
113
|
-
decrypted = decipher.update(encryptedObj.encryptedData, 'hex', 'utf8');
|
|
114
|
-
} else {
|
|
115
|
-
decrypted = decipher.update(encryptedObj.encryptedData);
|
|
116
|
-
decrypted = decrypted.toString('utf8');
|
|
117
|
-
}
|
|
118
|
-
decipher.final();
|
|
119
|
-
|
|
120
|
-
return decrypted;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Generates a cryptographically secure random key
|
|
125
|
-
*
|
|
126
|
-
* This function generates a random key suitable for AES-256 encryption.
|
|
127
|
-
*
|
|
128
|
-
* @param {number} [length=32] - Length of the key in bytes (32 bytes = 256 bits)
|
|
129
|
-
* @returns {Buffer} A cryptographically secure random key
|
|
130
|
-
*
|
|
131
|
-
* @example
|
|
132
|
-
* const key = generateKey(); // 32-byte key for AES-256
|
|
133
|
-
* const shortKey = generateKey(16); // 16-byte key for AES-128
|
|
134
|
-
*/
|
|
135
|
-
function generateKey(length = 32) {
|
|
136
|
-
return crypto.randomBytes(length);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
module.exports = {
|
|
140
|
-
encryptData,
|
|
141
|
-
decryptData,
|
|
142
|
-
generateKey,
|
|
143
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Data encryption utilities for the Stigmergy CLI
|
|
3
|
+
* Provides secure data encryption and decryption functions using AES-256-GCM
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Encrypts data using AES-256-GCM authenticated encryption
|
|
10
|
+
*
|
|
11
|
+
* This function provides secure symmetric encryption with authentication.
|
|
12
|
+
* It generates a random initialization vector for each encryption operation
|
|
13
|
+
* and returns the encrypted data along with the IV and authentication tag.
|
|
14
|
+
*
|
|
15
|
+
* @param {string|Buffer} data - The plaintext data to encrypt
|
|
16
|
+
* @param {string|Buffer} secretKey - The secret key for encryption (must be 32 bytes for AES-256)
|
|
17
|
+
* @returns {Object} Object containing encrypted data, IV, and authentication tag
|
|
18
|
+
* @throws {Error} If encryption fails due to invalid inputs or cryptographic errors
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const crypto = require('crypto');
|
|
22
|
+
* const secretKey = crypto.randomBytes(32); // 256-bit key
|
|
23
|
+
* const plaintext = "Secret message";
|
|
24
|
+
* const encryptedObj = encryptData(plaintext, secretKey);
|
|
25
|
+
* console.log(encryptedObj);
|
|
26
|
+
* // Output: {
|
|
27
|
+
* // encryptedData: 'a3f5b7c8...',
|
|
28
|
+
* // iv: 'MjRkOGZj...',
|
|
29
|
+
* // authTag: 'YzQyNTgx...'
|
|
30
|
+
* // }
|
|
31
|
+
*/
|
|
32
|
+
function encryptData(data, secretKey) {
|
|
33
|
+
// Validate inputs
|
|
34
|
+
if (!data) {
|
|
35
|
+
throw new Error('Data to encrypt cannot be empty');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!secretKey) {
|
|
39
|
+
throw new Error('Secret key is required');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Generate a random initialization vector
|
|
43
|
+
const iv = crypto.randomBytes(16);
|
|
44
|
+
|
|
45
|
+
// Create cipher using AES-256-GCM
|
|
46
|
+
const cipher = crypto.createCipherGCM('aes-256-gcm', secretKey, iv);
|
|
47
|
+
|
|
48
|
+
// Encrypt the data
|
|
49
|
+
let encrypted;
|
|
50
|
+
if (typeof data === 'string') {
|
|
51
|
+
encrypted = cipher.update(data, 'utf8', 'hex');
|
|
52
|
+
} else {
|
|
53
|
+
encrypted = cipher.update(data);
|
|
54
|
+
encrypted = encrypted.toString('hex');
|
|
55
|
+
}
|
|
56
|
+
cipher.final();
|
|
57
|
+
|
|
58
|
+
// Get the authentication tag
|
|
59
|
+
const authTag = cipher.getAuthTag();
|
|
60
|
+
|
|
61
|
+
// Return encrypted data with IV and auth tag
|
|
62
|
+
return {
|
|
63
|
+
encryptedData: encrypted,
|
|
64
|
+
iv: iv.toString('base64'),
|
|
65
|
+
authTag: authTag.toString('base64'),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Decrypts data using AES-256-GCM authenticated decryption
|
|
71
|
+
*
|
|
72
|
+
* This function decrypts data that was encrypted with encryptData().
|
|
73
|
+
* It requires the encrypted data object containing the encrypted data,
|
|
74
|
+
* initialization vector, and authentication tag.
|
|
75
|
+
*
|
|
76
|
+
* @param {Object} encryptedObj - Object containing encrypted data, IV, and auth tag
|
|
77
|
+
* @param {string|Buffer} secretKey - The secret key used for encryption
|
|
78
|
+
* @returns {string} The decrypted plaintext data
|
|
79
|
+
* @throws {Error} If decryption fails due to invalid inputs, tampered data, or cryptographic errors
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* const decrypted = decryptData(encryptedObj, secretKey);
|
|
83
|
+
* console.log(decrypted); // "Secret message"
|
|
84
|
+
*/
|
|
85
|
+
function decryptData(encryptedObj, secretKey) {
|
|
86
|
+
// Validate inputs
|
|
87
|
+
if (
|
|
88
|
+
!encryptedObj ||
|
|
89
|
+
!encryptedObj.encryptedData ||
|
|
90
|
+
!encryptedObj.iv ||
|
|
91
|
+
!encryptedObj.authTag
|
|
92
|
+
) {
|
|
93
|
+
throw new Error('Invalid encrypted object');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!secretKey) {
|
|
97
|
+
throw new Error('Secret key is required');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Decode base64 encoded values
|
|
101
|
+
const iv = Buffer.from(encryptedObj.iv, 'base64');
|
|
102
|
+
const authTag = Buffer.from(encryptedObj.authTag, 'base64');
|
|
103
|
+
|
|
104
|
+
// Create decipher using AES-256-GCM
|
|
105
|
+
const decipher = crypto.createDecipherGCM('aes-256-gcm', secretKey, iv);
|
|
106
|
+
|
|
107
|
+
// Set the authentication tag
|
|
108
|
+
decipher.setAuthTag(authTag);
|
|
109
|
+
|
|
110
|
+
// Decrypt the data
|
|
111
|
+
let decrypted;
|
|
112
|
+
if (typeof encryptedObj.encryptedData === 'string') {
|
|
113
|
+
decrypted = decipher.update(encryptedObj.encryptedData, 'hex', 'utf8');
|
|
114
|
+
} else {
|
|
115
|
+
decrypted = decipher.update(encryptedObj.encryptedData);
|
|
116
|
+
decrypted = decrypted.toString('utf8');
|
|
117
|
+
}
|
|
118
|
+
decipher.final();
|
|
119
|
+
|
|
120
|
+
return decrypted;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Generates a cryptographically secure random key
|
|
125
|
+
*
|
|
126
|
+
* This function generates a random key suitable for AES-256 encryption.
|
|
127
|
+
*
|
|
128
|
+
* @param {number} [length=32] - Length of the key in bytes (32 bytes = 256 bits)
|
|
129
|
+
* @returns {Buffer} A cryptographically secure random key
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* const key = generateKey(); // 32-byte key for AES-256
|
|
133
|
+
* const shortKey = generateKey(16); // 16-byte key for AES-128
|
|
134
|
+
*/
|
|
135
|
+
function generateKey(length = 32) {
|
|
136
|
+
return crypto.randomBytes(length);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = {
|
|
140
|
+
encryptData,
|
|
141
|
+
decryptData,
|
|
142
|
+
generateKey,
|
|
143
|
+
};
|