abmind 0.1.8-alpha.2 → 0.1.8-alpha.3
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abmind-passwd.d.ts","sourceRoot":"","sources":["../../cli/abmind-passwd.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"abmind-passwd.d.ts","sourceRoot":"","sources":["../../cli/abmind-passwd.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -1,64 +1,147 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* abmind passwd — change encryption passphrase.
|
|
3
|
+
* Re-encrypts: DB memories (classification=3) + file-based secrets.
|
|
3
4
|
*/
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
6
5
|
import { createInterface } from "node:readline";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { createDecipheriv, createCipheriv, randomBytes, hkdfSync } from "node:crypto";
|
|
10
|
+
import { deriveFromPassphrase, validateKey, writeKeyVerify, loadKeyFromFile, _resetKeyCache } from "../src/crypto.js";
|
|
11
|
+
function ask(rl, question) {
|
|
12
|
+
return new Promise(resolve => rl.question(question, resolve));
|
|
12
13
|
}
|
|
13
|
-
const paths = packagePaths("abmind");
|
|
14
|
-
const manifest = await readManifest(paths.manifest);
|
|
15
|
-
const encryptionUser = manifest?.encryptionUser ?? process.env["USER"] ?? "default";
|
|
16
|
-
const keyPath = join(paths.home, "secret", "abmind.key");
|
|
17
|
-
// Get old + new passphrase (positional or interactive)
|
|
18
14
|
const args = process.argv.slice(2);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
oldPass = await prompt("Current passphrase: ");
|
|
23
|
-
if (!oldPass) {
|
|
24
|
-
console.error("Error: passphrase required");
|
|
25
|
-
process.exit(1);
|
|
15
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
16
|
+
console.log("Usage: abmind passwd [--secrets-dir <path>]\n\nChange encryption passphrase. Re-encrypts DB secrets + file secrets.\n\nOptions:\n --secrets-dir <path> Directory with ENC: files (default: ~/.abtars/secret)");
|
|
17
|
+
process.exit(0);
|
|
26
18
|
}
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
19
|
+
const sdIdx = args.indexOf("--secrets-dir");
|
|
20
|
+
const secretDir = sdIdx >= 0 && args[sdIdx + 1]
|
|
21
|
+
? args[sdIdx + 1]
|
|
22
|
+
: join(process.env["ABTARS_HOME"] ?? join(homedir(), ".abtars"), "secret");
|
|
23
|
+
const keyFile = join(process.env["ABMIND_HOME"] ?? join(homedir(), ".abmind"), "secret", "abmind.key");
|
|
24
|
+
const verifyFile = join(process.env["ABMIND_HOME"] ?? join(homedir(), ".abmind"), "secret", "key.verify");
|
|
25
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
26
|
+
try {
|
|
27
|
+
const username = await ask(rl, "Username (same on all machines): ");
|
|
28
|
+
if (!username.trim()) {
|
|
29
|
+
console.error("Username cannot be empty.");
|
|
30
|
+
process.exit(1);
|
|
35
31
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
let oldKey;
|
|
33
|
+
const oldPass = await ask(rl, "Current passphrase (empty = migrate from key file): ");
|
|
34
|
+
if (oldPass) {
|
|
35
|
+
oldKey = deriveFromPassphrase(oldPass, username.trim());
|
|
36
|
+
if (!existsSync(verifyFile)) {
|
|
37
|
+
console.error("No key.verify file — cannot validate. Run migration with empty old passphrase first.");
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
if (!validateKey(oldKey)) {
|
|
41
|
+
console.error("Wrong passphrase.");
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
if (!existsSync(keyFile)) {
|
|
47
|
+
console.error(`No key file at ${keyFile} and no passphrase.`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
oldKey = loadKeyFromFile(keyFile);
|
|
51
|
+
}
|
|
52
|
+
const newPass = await ask(rl, "New passphrase (min 6 chars): ");
|
|
53
|
+
if (newPass.length < 6) {
|
|
54
|
+
console.error("Too short.");
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
const confirm = await ask(rl, "Confirm: ");
|
|
45
58
|
if (newPass !== confirm) {
|
|
46
|
-
console.error("
|
|
59
|
+
console.error("Mismatch.");
|
|
47
60
|
process.exit(1);
|
|
48
61
|
}
|
|
62
|
+
const newKey = deriveFromPassphrase(newPass, username.trim());
|
|
63
|
+
// Re-encrypt DB memories (classification=3)
|
|
64
|
+
let dbCount = 0;
|
|
65
|
+
try {
|
|
66
|
+
const memDir = process.env["ABMIND_HOME"] ?? join(homedir(), ".abmind");
|
|
67
|
+
const dbPath = join(memDir, "memory", "memory.db");
|
|
68
|
+
if (existsSync(dbPath)) {
|
|
69
|
+
const oldDbKey = Buffer.from(hkdfSync("sha256", oldKey, "", "abmind-secrets-v1", 32));
|
|
70
|
+
const newDbKey = Buffer.from(hkdfSync("sha256", newKey, "", "abmind-secrets-v1", 32));
|
|
71
|
+
const { loadNative } = await import("../src/native-loader.js");
|
|
72
|
+
const Database = loadNative("better-sqlite3");
|
|
73
|
+
const db = new Database(dbPath, { readonly: false });
|
|
74
|
+
const rows = db.prepare("SELECT id, content_en FROM extracted_memories WHERE classification = 3").all();
|
|
75
|
+
const update = db.prepare("UPDATE extracted_memories SET content_en = ? WHERE id = ?");
|
|
76
|
+
for (const row of rows) {
|
|
77
|
+
try {
|
|
78
|
+
const buf = Buffer.from(row.content_en, "base64");
|
|
79
|
+
const iv = buf.subarray(0, 12);
|
|
80
|
+
const tag = buf.subarray(buf.length - 16);
|
|
81
|
+
const ct = buf.subarray(12, buf.length - 16);
|
|
82
|
+
const d = createDecipheriv("aes-256-gcm", oldDbKey, iv);
|
|
83
|
+
d.setAuthTag(tag);
|
|
84
|
+
const plain = d.update(ct, undefined, "utf-8") + d.final("utf-8");
|
|
85
|
+
const newIv = randomBytes(12);
|
|
86
|
+
const c = createCipheriv("aes-256-gcm", newDbKey, newIv);
|
|
87
|
+
const enc = Buffer.concat([c.update(plain, "utf-8"), c.final()]);
|
|
88
|
+
update.run(Buffer.concat([newIv, enc, c.getAuthTag()]).toString("base64"), row.id);
|
|
89
|
+
dbCount++;
|
|
90
|
+
}
|
|
91
|
+
catch { /* skip corrupted */ }
|
|
92
|
+
}
|
|
93
|
+
db.close();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch { /* DB not available */ }
|
|
97
|
+
// Re-encrypt file-based secrets
|
|
98
|
+
let fileCount = 0;
|
|
99
|
+
if (existsSync(secretDir)) {
|
|
100
|
+
const oldPurpose = Buffer.from(hkdfSync("sha256", oldKey, "", "abtars-secrets-files-v1", 32));
|
|
101
|
+
const newPurpose = Buffer.from(hkdfSync("sha256", newKey, "", "abtars-secrets-files-v1", 32));
|
|
102
|
+
for (const f of readdirSync(secretDir)) {
|
|
103
|
+
const fp = join(secretDir, f);
|
|
104
|
+
if (statSync(fp).isDirectory())
|
|
105
|
+
continue;
|
|
106
|
+
const raw = readFileSync(fp, "utf-8").trim();
|
|
107
|
+
if (!raw.startsWith("ENC:"))
|
|
108
|
+
continue;
|
|
109
|
+
try {
|
|
110
|
+
const buf = Buffer.from(raw.slice(4), "base64");
|
|
111
|
+
const iv = buf.subarray(1, 13);
|
|
112
|
+
const tag = buf.subarray(buf.length - 16);
|
|
113
|
+
const ct = buf.subarray(13, buf.length - 16);
|
|
114
|
+
const d = createDecipheriv("aes-256-gcm", oldPurpose, iv);
|
|
115
|
+
d.setAuthTag(tag);
|
|
116
|
+
const plain = d.update(ct, undefined, "utf-8") + d.final("utf-8");
|
|
117
|
+
const newIv = randomBytes(12);
|
|
118
|
+
const c = createCipheriv("aes-256-gcm", newPurpose, newIv);
|
|
119
|
+
const enc = Buffer.concat([c.update(plain, "utf-8"), c.final()]);
|
|
120
|
+
const blob = "ENC:" + Buffer.concat([Buffer.from([0x01]), newIv, enc, c.getAuthTag()]).toString("base64");
|
|
121
|
+
writeFileSync(fp, blob, { mode: 0o600 });
|
|
122
|
+
fileCount++;
|
|
123
|
+
}
|
|
124
|
+
catch { /* skip */ }
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Finalize
|
|
128
|
+
_resetKeyCache();
|
|
129
|
+
writeFileSync(keyFile, newKey.toString("hex") + "\n", { mode: 0o600 });
|
|
130
|
+
writeKeyVerify(newKey);
|
|
131
|
+
let stored = false;
|
|
132
|
+
try {
|
|
133
|
+
const kr = await import("../src/keyring.js");
|
|
134
|
+
stored = kr.writeToKeyring(newPass);
|
|
135
|
+
}
|
|
136
|
+
catch { /* optional */ }
|
|
137
|
+
console.log(`✓ Done. ${dbCount} memories + ${fileCount} secrets re-encrypted.`);
|
|
138
|
+
console.log(`\nKey saved to ${keyFile} (daemon uses this automatically).`);
|
|
139
|
+
if (stored)
|
|
140
|
+
console.log("✓ Passphrase also stored in OS keyring.");
|
|
141
|
+
else
|
|
142
|
+
console.log(`If running without disk access (containers, CI), export ABMIND_KEY=${newKey.toString("hex")} instead.`);
|
|
49
143
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
54
|
-
// Derive new key and overwrite
|
|
55
|
-
const newKey = deriveFromPassphrase(newPass, encryptionUser);
|
|
56
|
-
writeFileSync(keyPath, newKey.toString("hex"), { mode: 0o600 });
|
|
57
|
-
writeKeyVerify(newKey);
|
|
58
|
-
try {
|
|
59
|
-
const kr = await import("../src/keyring.js");
|
|
60
|
-
kr.writeToKeyring(newPass);
|
|
144
|
+
finally {
|
|
145
|
+
rl.close();
|
|
61
146
|
}
|
|
62
|
-
catch { /* optional */ }
|
|
63
|
-
console.log("✓ passphrase changed");
|
|
64
147
|
//# sourceMappingURL=abmind-passwd.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"abmind-passwd.js","sourceRoot":"","sources":["../../cli/abmind-passwd.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"abmind-passwd.js","sourceRoot":"","sources":["../../cli/abmind-passwd.ts"],"names":[],"mappings":"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"}
|