apteva 0.3.6 → 0.3.7
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/package.json +1 -1
- package/src/crypto.ts +48 -7
package/package.json
CHANGED
package/src/crypto.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createCipheriv, createDecipheriv, randomBytes, scryptSync, createHash } from "crypto";
|
|
2
2
|
import { hostname, userInfo } from "os";
|
|
3
3
|
import { join } from "path";
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
5
|
+
import { homedir } from "os";
|
|
4
6
|
|
|
5
7
|
const ALGORITHM = "aes-256-gcm";
|
|
6
8
|
const IV_LENGTH = 16;
|
|
@@ -8,15 +10,54 @@ const SALT_LENGTH = 32;
|
|
|
8
10
|
const TAG_LENGTH = 16;
|
|
9
11
|
const KEY_LENGTH = 32;
|
|
10
12
|
|
|
13
|
+
// Cache the encryption secret to avoid repeated file reads
|
|
14
|
+
let cachedSecret: string | null = null;
|
|
15
|
+
|
|
16
|
+
// Get the path for storing the encryption secret
|
|
17
|
+
function getSecretPath(): string {
|
|
18
|
+
const dataDir = process.env.DATA_DIR || join(homedir(), ".apteva");
|
|
19
|
+
return join(dataDir, ".encryption-key");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Get or create a persistent encryption secret
|
|
23
|
+
// This ensures keys can be decrypted after container/app restarts
|
|
24
|
+
function getOrCreateSecret(): string {
|
|
25
|
+
if (cachedSecret) return cachedSecret;
|
|
26
|
+
|
|
27
|
+
const secretPath = getSecretPath();
|
|
28
|
+
|
|
29
|
+
// Try to read existing secret
|
|
30
|
+
if (existsSync(secretPath)) {
|
|
31
|
+
try {
|
|
32
|
+
cachedSecret = readFileSync(secretPath, "utf8").trim();
|
|
33
|
+
if (cachedSecret && cachedSecret.length >= 32) {
|
|
34
|
+
return cachedSecret;
|
|
35
|
+
}
|
|
36
|
+
} catch {
|
|
37
|
+
// Fall through to create new
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Create new secret and persist it
|
|
42
|
+
cachedSecret = randomBytes(32).toString("hex");
|
|
43
|
+
try {
|
|
44
|
+
const dir = process.env.DATA_DIR || join(homedir(), ".apteva");
|
|
45
|
+
if (!existsSync(dir)) {
|
|
46
|
+
mkdirSync(dir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
writeFileSync(secretPath, cachedSecret, { mode: 0o600 });
|
|
49
|
+
} catch (err) {
|
|
50
|
+
console.error("[crypto] Warning: Could not persist encryption key:", err);
|
|
51
|
+
// Continue with in-memory key - will work for this session but not across restarts
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return cachedSecret;
|
|
55
|
+
}
|
|
56
|
+
|
|
11
57
|
// Get a machine-specific identifier for key derivation
|
|
58
|
+
// Now uses a persistent secret instead of volatile machine factors
|
|
12
59
|
function getMachineId(): string {
|
|
13
|
-
|
|
14
|
-
hostname(),
|
|
15
|
-
userInfo().username,
|
|
16
|
-
process.env.HOME || process.env.USERPROFILE || "",
|
|
17
|
-
__dirname, // Installation path adds uniqueness
|
|
18
|
-
];
|
|
19
|
-
return factors.join("|");
|
|
60
|
+
return getOrCreateSecret();
|
|
20
61
|
}
|
|
21
62
|
|
|
22
63
|
// Derive encryption key from machine ID and salt
|