@hotfusion/cipher 0.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.
@@ -0,0 +1,6 @@
1
+ export { Cipher } from "./lib/cipher";
2
+ export { CipherError } from "./lib/cipher";
3
+ export { Luks } from "./lib/luks";
4
+ export type { ICipherConfig, ICipherLevel, ISecret, ISecretKey, ISecretResult, ICollection } from "./lib/cipher";
5
+ export type { ILuks } from "./lib/luks";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAA;AACnC,OAAO,EAAC,WAAW,EAAC,MAAM,cAAc,CAAA;AACxC,OAAO,EAAC,IAAI,EAAC,MAAM,YAAY,CAAA;AAI/B,YAAY,EACR,aAAa,EACb,YAAY,EACZ,OAAO,EACP,UAAU,EACV,aAAa,EACb,WAAW,EACd,MAAM,cAAc,CAAA;AAErB,YAAY,EACR,KAAK,EACR,MAAM,YAAY,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Luks = exports.CipherError = exports.Cipher = void 0;
4
+ var cipher_1 = require("./lib/cipher");
5
+ Object.defineProperty(exports, "Cipher", { enumerable: true, get: function () { return cipher_1.Cipher; } });
6
+ var cipher_2 = require("./lib/cipher");
7
+ Object.defineProperty(exports, "CipherError", { enumerable: true, get: function () { return cipher_2.CipherError; } });
8
+ var luks_1 = require("./lib/luks");
9
+ Object.defineProperty(exports, "Luks", { enumerable: true, get: function () { return luks_1.Luks; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,uCAAmC;AAA3B,gGAAA,MAAM,OAAA;AACd,uCAAwC;AAAhC,qGAAA,WAAW,OAAA;AACnB,mCAA+B;AAAvB,4FAAA,IAAI,OAAA"}
@@ -0,0 +1,122 @@
1
+ import { Luks, LuksError } from './luks';
2
+ export type ICipherLevel = 0 | 1 | 2;
3
+ export interface ICipherConfig {
4
+ readonly?: boolean;
5
+ path: string;
6
+ password: string;
7
+ level?: ICipherLevel;
8
+ size?: number;
9
+ }
10
+ export interface ISecret {
11
+ id: string;
12
+ secret: any;
13
+ version: number;
14
+ keyName?: string;
15
+ meta?: {
16
+ readonly?: boolean;
17
+ version?: number;
18
+ __created?: number;
19
+ __updated?: number;
20
+ };
21
+ }
22
+ export interface ISecretKey {
23
+ id: string;
24
+ keyName?: string;
25
+ }
26
+ export interface ISecretResult {
27
+ key: {
28
+ [key: string]: string;
29
+ };
30
+ meta: {
31
+ version: number;
32
+ readonly?: boolean;
33
+ };
34
+ _id: number;
35
+ }
36
+ export interface ICollection {
37
+ name: string;
38
+ schema?: any;
39
+ }
40
+ export declare class CipherError extends Error {
41
+ code: string;
42
+ details?: string;
43
+ constructor(code: string, message: string, details?: string);
44
+ }
45
+ interface LokiCollection {
46
+ name: string;
47
+ insert(doc: any): any;
48
+ find(query?: any): any[];
49
+ findAndRemove(query?: any): void;
50
+ get(id: number): any;
51
+ chain(): {
52
+ find(query?: any): {
53
+ simplesort(prop: string, isDesc?: boolean): {
54
+ data(): any[];
55
+ };
56
+ };
57
+ };
58
+ findOne(query: any): any | null;
59
+ update(doc: any): void;
60
+ data: any[];
61
+ idIndex: number[] | null;
62
+ binaryIndices: {
63
+ [key: string]: {
64
+ name: string;
65
+ dirty: boolean;
66
+ values: number[];
67
+ };
68
+ };
69
+ uniqueNames: string[];
70
+ }
71
+ declare class SecretCollection {
72
+ private ajv;
73
+ private cipher;
74
+ private collection;
75
+ private schema;
76
+ constructor(cipher: Cipher, collection: LokiCollection, schema: {
77
+ keySchema?: any;
78
+ });
79
+ private validateKey;
80
+ insert(key: ISecretKey, secret: any, meta?: {
81
+ readonly?: boolean;
82
+ version?: number;
83
+ }): Promise<void>;
84
+ update(key: ISecretKey, secret: any, meta?: {
85
+ readonly?: boolean;
86
+ version?: number;
87
+ }): Promise<void>;
88
+ delete(key: ISecretKey, meta?: {
89
+ readonly?: boolean;
90
+ }): Promise<void>;
91
+ find(key: ISecretKey): ISecretResult | null;
92
+ unseal(id: string): any;
93
+ list(): Array<{
94
+ key: {
95
+ [key: string]: string;
96
+ };
97
+ meta: {
98
+ version: number;
99
+ readonly?: boolean;
100
+ };
101
+ }>;
102
+ }
103
+ export declare class Cipher {
104
+ private settings;
105
+ private collections;
106
+ private loki;
107
+ private readyPromise;
108
+ private luks?;
109
+ private mounted;
110
+ constructor(settings: ICipherConfig, collections?: ICollection[]);
111
+ private databaseInitialize;
112
+ canWrite(meta: any): boolean;
113
+ save(): Promise<void>;
114
+ collection(name: string): SecretCollection;
115
+ ready(): Promise<void>;
116
+ changePassword(oldPassword: string, newPassword: string): Promise<void>;
117
+ unmount(): Promise<void>;
118
+ getInfo(): any;
119
+ isMounted(): boolean;
120
+ }
121
+ export { Luks, LuksError };
122
+ //# sourceMappingURL=cipher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cipher.d.ts","sourceRoot":"","sources":["../../src/lib/cipher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,362 @@
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.LuksError = exports.Luks = exports.Cipher = exports.CipherError = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const crypto = __importStar(require("crypto"));
39
+ //@ts-ignore
40
+ const Loki = __importStar(require("lokijs"));
41
+ const Ajv = __importStar(require("ajv"));
42
+ const luks_1 = require("./luks");
43
+ Object.defineProperty(exports, "Luks", { enumerable: true, get: function () { return luks_1.Luks; } });
44
+ Object.defineProperty(exports, "LuksError", { enumerable: true, get: function () { return luks_1.LuksError; } });
45
+ // ?? Encryption constants ??????????????????????????????????????????????????????
46
+ const algorithm = 'aes-256-gcm';
47
+ const keyLen = 32;
48
+ const ivLen = 12;
49
+ const saltLen = 16;
50
+ const tagLen = 16;
51
+ // ?? Errors ??????????????????????????????????????????????????????????????????
52
+ class CipherError extends Error {
53
+ constructor(code, message, details) {
54
+ super(message);
55
+ this.code = code;
56
+ this.details = details;
57
+ this.name = 'CipherError';
58
+ }
59
+ }
60
+ exports.CipherError = CipherError;
61
+ // ?? Encrypted LokiJS adapter ??????????????????????????????????????????????????
62
+ class EncryptedFsAdapter {
63
+ constructor(password) {
64
+ this.password = password;
65
+ }
66
+ deriveKey(salt) {
67
+ return crypto.pbkdf2Sync(this.password, salt, 100000, keyLen, 'sha256');
68
+ }
69
+ loadDatabase(dbname, callback) {
70
+ if (!fs.existsSync(dbname)) {
71
+ return callback(null, '{}');
72
+ }
73
+ fs.readFile(dbname, (err, data) => {
74
+ if (err)
75
+ return callback(err);
76
+ try {
77
+ const salt = data.slice(0, saltLen);
78
+ const iv = data.slice(saltLen, saltLen + ivLen);
79
+ const tag = data.slice(saltLen + ivLen, saltLen + ivLen + tagLen);
80
+ const encrypted = data.slice(saltLen + ivLen + tagLen);
81
+ const key = this.deriveKey(salt);
82
+ const decipher = crypto.createDecipheriv(algorithm, key, iv);
83
+ decipher.setAuthTag(tag);
84
+ let decrypted = decipher.update(encrypted, undefined, 'utf8');
85
+ decrypted += decipher.final('utf8');
86
+ callback(null, decrypted);
87
+ }
88
+ catch (e) {
89
+ callback(e);
90
+ }
91
+ });
92
+ }
93
+ saveDatabase(dbname, dbstring, callback) {
94
+ try {
95
+ const salt = crypto.randomBytes(saltLen);
96
+ const iv = crypto.randomBytes(ivLen);
97
+ const key = this.deriveKey(salt);
98
+ const cipher = crypto.createCipheriv(algorithm, key, iv);
99
+ let encrypted = cipher.update(dbstring, 'utf8');
100
+ encrypted = Buffer.concat([encrypted, cipher.final()]);
101
+ const tag = cipher.getAuthTag();
102
+ const data = Buffer.concat([salt, iv, tag, encrypted]);
103
+ fs.writeFile(dbname, data, (err) => {
104
+ if (err)
105
+ return callback(err);
106
+ callback(null);
107
+ });
108
+ }
109
+ catch (e) {
110
+ callback(e);
111
+ }
112
+ }
113
+ }
114
+ // ?? SecretCollection ????????????????????????????????????????????????????????
115
+ class SecretCollection {
116
+ constructor(cipher, collection, schema) {
117
+ this.cipher = cipher;
118
+ this.collection = collection;
119
+ this.schema = schema;
120
+ this.ajv = new Ajv.default({ allErrors: true });
121
+ }
122
+ validateKey(key) {
123
+ if (this.schema?.keySchema) {
124
+ const validate = this.ajv.compile(this.schema.keySchema);
125
+ if (!validate(key))
126
+ throw new CipherError('KEY_VALIDATION_FAILED', 'Key validation failed', JSON.stringify(validate.errors, null, 2));
127
+ }
128
+ }
129
+ async insert(key, secret, meta = {}) {
130
+ if (!this.cipher.canWrite(meta))
131
+ throw new CipherError('READONLY_MODE', 'Cannot insert: cipher is in readonly mode');
132
+ this.validateKey(key);
133
+ const id = key.id;
134
+ const keyName = key.keyName || 'id';
135
+ const existing = this.collection.findOne({ id });
136
+ if (existing)
137
+ throw new CipherError('KEY_EXISTS', `Secret with id "${id}" already exists; use update instead`);
138
+ const version = meta.version ?? 1;
139
+ if (version < 1)
140
+ throw new CipherError('INVALID_VERSION', 'Version must be at least 1');
141
+ this.collection.insert({
142
+ id,
143
+ secret,
144
+ version,
145
+ keyName,
146
+ meta: { ...meta, version, __created: Date.now(), __updated: Date.now() },
147
+ });
148
+ await this.cipher.save();
149
+ }
150
+ async update(key, secret, meta = {}) {
151
+ if (!this.cipher.canWrite(meta))
152
+ throw new CipherError('READONLY_MODE', 'Cannot update: cipher is in readonly mode');
153
+ this.validateKey(key);
154
+ const id = key.id;
155
+ const existing = this.collection.findOne({ id });
156
+ if (!existing)
157
+ throw new CipherError('KEY_NOT_FOUND', `Secret with id "${id}" not found; use insert instead`);
158
+ const newVersion = meta.version ?? existing.version + 1;
159
+ if (newVersion <= existing.version)
160
+ throw new CipherError('INVALID_VERSION', `Version must be higher than current (${existing.version})`);
161
+ existing.secret = secret;
162
+ existing.version = newVersion;
163
+ existing.meta = { ...existing.meta, ...meta, version: newVersion, __updated: Date.now() };
164
+ this.collection.update(existing);
165
+ await this.cipher.save();
166
+ }
167
+ async delete(key, meta = {}) {
168
+ if (!this.cipher.canWrite(meta))
169
+ throw new CipherError('READONLY_MODE', 'Cannot delete: cipher is in readonly mode');
170
+ this.validateKey(key);
171
+ this.collection.findAndRemove({ id: key.id });
172
+ await this.cipher.save();
173
+ }
174
+ find(key) {
175
+ this.validateKey(key);
176
+ const existing = this.collection.findOne({ id: key.id });
177
+ if (!existing)
178
+ return null;
179
+ const keyName = existing.keyName || 'id';
180
+ return {
181
+ key: { [keyName]: existing.id },
182
+ meta: { version: existing.version, readonly: existing.meta.readonly },
183
+ _id: existing.$loki,
184
+ };
185
+ }
186
+ unseal(id) {
187
+ const doc = this.collection.findOne({ id });
188
+ if (!doc)
189
+ throw new CipherError('KEY_NOT_FOUND', `Secret with id "${id}" not found`);
190
+ return doc.secret;
191
+ }
192
+ list() {
193
+ return this.collection.find().map(doc => ({
194
+ key: { [doc.keyName || 'id']: doc.id },
195
+ meta: { version: doc.version, readonly: doc.meta.readonly },
196
+ }));
197
+ }
198
+ }
199
+ // ?? Cipher ??????????????????????????????????????????????????????????????????
200
+ class Cipher {
201
+ constructor(settings, collections = [{ name: 'secrets', schema: {} }]) {
202
+ this.mounted = false;
203
+ this.collections = new Map();
204
+ // Password can come from:
205
+ // 1. settings.password
206
+ // 2. --password=xxx CLI argument
207
+ // 3. CIPHER_PASSWORD env variable
208
+ const cliPassword = process.argv.find(arg => arg.startsWith('--password='))?.split('=')[1];
209
+ settings.password = settings.password || cliPassword || process.env.CIPHER_PASSWORD || '';
210
+ if (!settings.password) {
211
+ throw new CipherError('NO_PASSWORD', 'Cipher requires a password. Pass it via settings.password, --password=xxx CLI arg, or CIPHER_PASSWORD env variable.');
212
+ }
213
+ // Validate password strength
214
+ if (settings.password.length < 12) {
215
+ throw new CipherError('WEAK_PASSWORD', 'Password must be at least 12 characters');
216
+ }
217
+ this.settings = settings;
218
+ const level = settings.level ?? 0;
219
+ try {
220
+ // ?? Level 0: plain encrypted file ?????????????????????????????????????
221
+ if (level === 0) {
222
+ if (!fs.existsSync(settings.path))
223
+ fs.mkdirSync(settings.path, { recursive: true, mode: 0o700 });
224
+ }
225
+ // ?? Level 1: LUKS container + encrypted file ??????????????????????????
226
+ else if (level === 1) {
227
+ if (!settings.size) {
228
+ throw new CipherError('MISSING_SIZE', 'Cipher level 1 requires a size (MB) for the LUKS container');
229
+ }
230
+ this.luks = new luks_1.Luks(settings.path, {
231
+ size: settings.size,
232
+ password: settings.password,
233
+ locked: settings.readonly ?? false,
234
+ });
235
+ this.luks.mount();
236
+ this.mounted = true;
237
+ }
238
+ // ?? Level 2: VM-level isolation (future) ??????????????????????????????
239
+ else if (level === 2) {
240
+ throw new CipherError('NOT_IMPLEMENTED', 'Cipher level 2 (VM-level isolation) is not yet implemented');
241
+ }
242
+ else {
243
+ throw new CipherError('INVALID_LEVEL', `Unknown cipher level: ${level}`);
244
+ }
245
+ }
246
+ catch (err) {
247
+ if (err instanceof CipherError)
248
+ throw err;
249
+ if (err instanceof luks_1.LuksError) {
250
+ throw new CipherError('LUKS_ERROR', `LUKS initialization failed: ${err.message}`, err.details);
251
+ }
252
+ throw err;
253
+ }
254
+ const adapter = new EncryptedFsAdapter(settings.password);
255
+ let resolveReady;
256
+ let rejectReady;
257
+ this.readyPromise = new Promise((res, rej) => {
258
+ resolveReady = res;
259
+ rejectReady = rej;
260
+ });
261
+ const dbPath = `${settings.path}/database.db`;
262
+ this.loki = new (Loki.default || Loki)(dbPath, {
263
+ adapter,
264
+ autoload: true,
265
+ autosave: false,
266
+ autoloadCallback: (err) => {
267
+ if (err) {
268
+ rejectReady(err);
269
+ return;
270
+ }
271
+ this.databaseInitialize(collections);
272
+ resolveReady();
273
+ },
274
+ });
275
+ }
276
+ databaseInitialize(collections) {
277
+ for (const col of collections) {
278
+ let collection = this.loki.getCollection(col.name);
279
+ if (!collection) {
280
+ collection = this.loki.addCollection(col.name, {
281
+ indices: ['id', 'version'],
282
+ unique: ['id'],
283
+ });
284
+ }
285
+ this.collections.set(col.name, { collection, schema: col.schema });
286
+ }
287
+ }
288
+ canWrite(meta) {
289
+ const readonlyOverride = meta.hasOwnProperty('readonly') ? meta.readonly : this.settings.readonly;
290
+ return !readonlyOverride;
291
+ }
292
+ async save() {
293
+ return new Promise((resolve, reject) => {
294
+ this.loki.saveDatabase((err) => {
295
+ if (err)
296
+ reject(err);
297
+ else
298
+ resolve();
299
+ });
300
+ });
301
+ }
302
+ collection(name) {
303
+ const col = this.collections.get(name);
304
+ if (!col)
305
+ throw new CipherError('COLLECTION_NOT_FOUND', `Collection "${name}" not found`);
306
+ return new SecretCollection(this, col.collection, col.schema);
307
+ }
308
+ async ready() {
309
+ return this.readyPromise;
310
+ }
311
+ async changePassword(oldPassword, newPassword) {
312
+ if (newPassword.length < 12) {
313
+ throw new CipherError('WEAK_PASSWORD', 'New password must be at least 12 characters');
314
+ }
315
+ if (this.settings.level === 1 && this.luks) {
316
+ try {
317
+ await this.luks.changePassword(oldPassword, newPassword);
318
+ this.settings.password = newPassword;
319
+ }
320
+ catch (err) {
321
+ if (err instanceof luks_1.LuksError) {
322
+ throw new CipherError('PASSWORD_CHANGE_FAILED', `Failed to change password: ${err.message}`, err.details);
323
+ }
324
+ throw err;
325
+ }
326
+ }
327
+ else {
328
+ // For level 0, we would need to re-encrypt the database file
329
+ // This is a placeholder - implement if needed
330
+ throw new CipherError('NOT_IMPLEMENTED', 'Password change for level 0 encryption not yet implemented');
331
+ }
332
+ }
333
+ async unmount() {
334
+ if (this.luks && this.mounted) {
335
+ try {
336
+ this.luks.unmount();
337
+ this.mounted = false;
338
+ }
339
+ catch (err) {
340
+ if (err instanceof luks_1.LuksError) {
341
+ throw new CipherError('UNMOUNT_FAILED', `Failed to unmount: ${err.message}`, err.details);
342
+ }
343
+ throw err;
344
+ }
345
+ }
346
+ }
347
+ getInfo() {
348
+ return {
349
+ level: this.settings.level ?? 0,
350
+ path: this.settings.path,
351
+ readonly: this.settings.readonly ?? false,
352
+ mounted: this.mounted,
353
+ collections: Array.from(this.collections.keys()),
354
+ luks: this.luks?.getInfo() ?? null,
355
+ };
356
+ }
357
+ isMounted() {
358
+ return this.mounted;
359
+ }
360
+ }
361
+ exports.Cipher = Cipher;
362
+ //# sourceMappingURL=cipher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cipher.js","sourceRoot":"","sources":["../../src/lib/cipher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ interface IContainer {
2
+ size: number;
3
+ directory: string;
4
+ password: string;
5
+ locked: boolean;
6
+ }
7
+ export type ILuks = Omit<IContainer, 'directory'>;
8
+ export type IContainerSettings = Pick<IContainer, 'locked'>;
9
+ export interface ILuksError {
10
+ code: string;
11
+ message: string;
12
+ details?: string;
13
+ }
14
+ declare class LuksError extends Error implements ILuksError {
15
+ code: string;
16
+ details?: string;
17
+ constructor(code: string, message: string, details?: string);
18
+ }
19
+ declare class Container {
20
+ private config;
21
+ imagepath: string;
22
+ id: string;
23
+ constructor(config: IContainer);
24
+ getSettings(): IContainerSettings;
25
+ isMounted(): boolean;
26
+ private executeCommand;
27
+ mount(): void;
28
+ unmount(): Container;
29
+ delete(force?: boolean): Container;
30
+ resize(targetMB: number): Container;
31
+ changePassword(oldPassword: string, newPassword: string): Promise<Container>;
32
+ getInfo(): any;
33
+ }
34
+ export declare class Luks {
35
+ private directory;
36
+ private config;
37
+ container: Container;
38
+ constructor(directory: string, config: ILuks);
39
+ static list(): any[];
40
+ mount(): Luks;
41
+ unmount(): Luks;
42
+ delete(force?: boolean): Luks;
43
+ resize(size: number): Luks;
44
+ changePassword(oldPassword: string, newPassword: string): Promise<Luks>;
45
+ getInfo(): any;
46
+ isMounted(): boolean;
47
+ }
48
+ export { LuksError };
49
+ //# sourceMappingURL=luks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"luks.d.ts","sourceRoot":"","sources":["../../src/lib/luks.ts"],"names":[],"mappings":"AAMA,UAAU,UAAU;IAChB,IAAI,EAAQ,MAAM,CAAA;IAClB,SAAS,EAAG,MAAM,CAAA;IAClB,QAAQ,EAAI,MAAM,CAAA;IAClB,MAAM,EAAM,OAAO,CAAA;CACtB;AAED,MAAM,MAAM,KAAK,GAAgB,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AAC/D,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAE5D,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,cAAM,SAAU,SAAQ,KAAM,YAAW,UAAU;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;gBAEL,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAM9D;AAID,cAAM,SAAS;IACX,OAAO,CAAC,MAAM,CAAe;IAC7B,SAAS,EAAS,MAAM,CAAC;IACzB,EAAE,EAAgB,MAAM,CAAkB;gBAE9B,MAAM,EAAE,UAAU;IAW9B,WAAW,IAAI,kBAAkB;IAQjC,SAAS,IAAI,OAAO;IASpB,OAAO,CAAC,cAAc;IAiBtB,KAAK;IA+EL,OAAO,IAAI,SAAS;IAmBpB,MAAM,CAAC,KAAK,GAAE,OAAe,GAAG,SAAS;IA6BzC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS;IA0D7B,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAqBlF,OAAO,IAAI,GAAG;CAejB;AAID,qBAAa,IAAI;IACb,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,MAAM,CAAY;IAC1B,SAAS,EAAW,SAAS,CAAC;gBAElB,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;IAM5C,MAAM,CAAC,IAAI,IAAI,GAAG,EAAE;IAYpB,KAAK,IAAI,IAAI;IAKb,OAAO,IAAI,IAAI;IAKf,MAAM,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAKpC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKpB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7E,OAAO,IAAI,GAAG;IAId,SAAS,IAAI,OAAO;CAGvB;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -0,0 +1,302 @@
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.LuksError = exports.Luks = void 0;
37
+ const child_process_1 = require("child_process");
38
+ const fs = __importStar(require("fs"));
39
+ const path_1 = require("path");
40
+ // ?? Errors ??????????????????????????????????????????????????????????????????
41
+ class LuksError extends Error {
42
+ constructor(code, message, details) {
43
+ super(message);
44
+ this.code = code;
45
+ this.details = details;
46
+ this.name = 'LuksError';
47
+ }
48
+ }
49
+ exports.LuksError = LuksError;
50
+ // ?? Container ??????????????????????????????????????????????????????????????
51
+ class Container {
52
+ constructor(config) {
53
+ this.id = '_.cipher.img';
54
+ this.config = config;
55
+ this.id = `_.${(0, path_1.basename)(this.config.directory).replace(/[^a-z0-9-]/gi, '_')}`;
56
+ this.imagepath = `${(0, path_1.dirname)(this.config.directory)}/${this.id}.img`;
57
+ // Validate password strength
58
+ if (this.config.password.length < 12) {
59
+ throw new LuksError('WEAK_PASSWORD', 'Password must be at least 12 characters');
60
+ }
61
+ }
62
+ getSettings() {
63
+ try {
64
+ return JSON.parse(fs.readFileSync((0, path_1.join)(this.config.directory, "_.settings.json")).toString());
65
+ }
66
+ catch (e) {
67
+ return { locked: false };
68
+ }
69
+ }
70
+ isMounted() {
71
+ try {
72
+ (0, child_process_1.execSync)(`mountpoint -q ${this.config.directory}`);
73
+ return true;
74
+ }
75
+ catch {
76
+ return false;
77
+ }
78
+ }
79
+ executeCommand(cmd, description) {
80
+ try {
81
+ const output = (0, child_process_1.execSync)(cmd, {
82
+ stdio: ['pipe', 'pipe', 'pipe'],
83
+ timeout: 30000 // 30 second timeout
84
+ });
85
+ return output.toString();
86
+ }
87
+ catch (err) {
88
+ const errorMsg = err.stderr?.toString() || err.message || String(err);
89
+ throw new LuksError('EXEC_FAILED', `${description} failed`, errorMsg);
90
+ }
91
+ }
92
+ mount() {
93
+ try {
94
+ // Check if already mounted
95
+ if (this.isMounted()) {
96
+ return;
97
+ }
98
+ // Create directories
99
+ if (!fs.existsSync(this.config.directory))
100
+ fs.mkdirSync(this.config.directory, { recursive: true, mode: 0o700 });
101
+ if (!fs.existsSync((0, path_1.dirname)(this.imagepath)))
102
+ fs.mkdirSync((0, path_1.dirname)(this.imagepath), { recursive: true, mode: 0o700 });
103
+ // New container - create and format
104
+ if (!fs.existsSync(this.imagepath)) {
105
+ console.log(`Creating LUKS container at ${this.imagepath} (${this.config.size}MB)...`);
106
+ // Create disk image
107
+ this.executeCommand(`dd if=/dev/zero of=${this.imagepath} bs=1M count=${this.config.size} 2>/dev/null`, 'Create disk image');
108
+ // Format as LUKS
109
+ this.executeCommand(`echo -n "${this.config.password.replace(/"/g, '\\"')}" | cryptsetup luksFormat --batch-mode ${this.imagepath}`, 'Format LUKS container');
110
+ // Open LUKS
111
+ this.executeCommand(`echo -n "${this.config.password.replace(/"/g, '\\"')}" | cryptsetup luksOpen ${this.imagepath} ${this.id}`, 'Open LUKS container');
112
+ // Create filesystem
113
+ this.executeCommand(`mkfs.ext4 -F /dev/mapper/${this.id} -q`, 'Create ext4 filesystem');
114
+ // Mount
115
+ this.executeCommand(`mount -o defaults /dev/mapper/${this.id} ${this.config.directory}`, 'Mount filesystem');
116
+ // Write settings
117
+ fs.writeFileSync((0, path_1.join)(this.config.directory, "_.settings.json"), JSON.stringify({ locked: this.config.locked }, null, 2), { mode: 0o600 });
118
+ console.log(`✓ LUKS container mounted at ${this.config.directory}`);
119
+ }
120
+ // Existing container - open and mount
121
+ else {
122
+ console.log(`Opening existing LUKS container at ${this.imagepath}...`);
123
+ this.executeCommand(`echo -n "${this.config.password.replace(/"/g, '\\"')}" | cryptsetup luksOpen ${this.imagepath} ${this.id}`, 'Open LUKS container');
124
+ this.executeCommand(`mount -o defaults /dev/mapper/${this.id} ${this.config.directory}`, 'Mount filesystem');
125
+ console.log(`✓ LUKS container mounted at ${this.config.directory}`);
126
+ }
127
+ }
128
+ catch (err) {
129
+ if (err instanceof LuksError)
130
+ throw err;
131
+ throw new LuksError('MOUNT_FAILED', 'Failed to mount container', String(err));
132
+ }
133
+ }
134
+ unmount() {
135
+ try {
136
+ if (!this.isMounted()) {
137
+ return this;
138
+ }
139
+ this.executeCommand(`umount ${this.config.directory}`, 'Unmount filesystem');
140
+ this.executeCommand(`cryptsetup luksClose ${this.id}`, 'Close LUKS container');
141
+ console.log(`✓ LUKS container unmounted`);
142
+ }
143
+ catch (err) {
144
+ // Don't throw on unmount - try to force unmount
145
+ try {
146
+ (0, child_process_1.execSync)(`umount -f ${this.config.directory} 2>/dev/null`);
147
+ (0, child_process_1.execSync)(`cryptsetup luksClose ${this.id} 2>/dev/null`);
148
+ }
149
+ catch { }
150
+ }
151
+ return this;
152
+ }
153
+ delete(force = false) {
154
+ try {
155
+ this.mount();
156
+ if (this.getSettings()?.locked && !force) {
157
+ throw new LuksError('CONTAINER_LOCKED', 'Container is protected from deletion. Use force: true to override');
158
+ }
159
+ this.unmount();
160
+ if (fs.existsSync(this.config.directory)) {
161
+ fs.rmSync(this.config.directory, { recursive: true, force: true });
162
+ }
163
+ if (fs.existsSync(this.imagepath)) {
164
+ fs.unlinkSync(this.imagepath);
165
+ }
166
+ console.log(`✓ LUKS container deleted`);
167
+ }
168
+ catch (err) {
169
+ if (err instanceof LuksError)
170
+ throw err;
171
+ throw new LuksError('DELETE_FAILED', 'Failed to delete container', String(err));
172
+ }
173
+ return this;
174
+ }
175
+ resize(targetMB) {
176
+ try {
177
+ if (!this.isMounted()) {
178
+ this.mount();
179
+ }
180
+ // Calculate space requirements
181
+ const usedOutput = (0, child_process_1.execSync)(`du -sb ${this.config.directory}`, { encoding: 'utf-8' });
182
+ const usedBytes = parseInt(usedOutput.split(/\s+/)[0], 10);
183
+ const usedMB = Math.ceil(usedBytes / (1024 * 1024));
184
+ const bufferMB = Math.max(5, Math.ceil(usedMB * 0.1)); // 10% buffer
185
+ const minMB = usedMB + bufferMB;
186
+ if (targetMB < minMB) {
187
+ console.warn(`Target ${targetMB}MB too small, resizing to ${minMB}MB (used: ${usedMB}MB + buffer: ${bufferMB}MB)`);
188
+ targetMB = minMB;
189
+ }
190
+ // Check available disk space
191
+ const dfOutput = (0, child_process_1.execSync)(`df -B1 ${(0, path_1.dirname)(this.imagepath)}`, { encoding: 'utf-8' }).split('\n')[1];
192
+ const freeBytes = parseInt(dfOutput.split(/\s+/)[3], 10);
193
+ const freeMB = Math.floor(freeBytes / (1024 * 1024));
194
+ if (targetMB > freeMB) {
195
+ throw new LuksError('INSUFFICIENT_SPACE', `Target ${targetMB}MB exceeds available space ${freeMB}MB`);
196
+ }
197
+ const currentSizeBytes = fs.statSync(this.imagepath).size;
198
+ const currentSizeMB = Math.ceil(currentSizeBytes / (1024 * 1024));
199
+ const isShrinking = targetMB < currentSizeMB;
200
+ console.log(`Resizing container from ${currentSizeMB}MB to ${targetMB}MB...`);
201
+ if (isShrinking) {
202
+ // Shrink: check → resize fs → resize crypto → truncate
203
+ this.executeCommand(`e2fsck -f -y /dev/mapper/${this.id}`, 'Check filesystem');
204
+ this.executeCommand(`resize2fs /dev/mapper/${this.id} ${targetMB}M`, 'Resize filesystem');
205
+ this.executeCommand(`cryptsetup resize ${this.id}`, 'Resize crypto layer');
206
+ this.executeCommand(`truncate -s ${targetMB}M ${this.imagepath}`, 'Truncate image');
207
+ }
208
+ else {
209
+ // Grow: truncate → resize crypto → resize fs → check
210
+ this.executeCommand(`truncate -s ${targetMB}M ${this.imagepath}`, 'Truncate image');
211
+ this.executeCommand(`cryptsetup resize ${this.id}`, 'Resize crypto layer');
212
+ this.executeCommand(`resize2fs /dev/mapper/${this.id} ${targetMB}M`, 'Resize filesystem');
213
+ this.executeCommand(`e2fsck -f -y /dev/mapper/${this.id}`, 'Check filesystem');
214
+ }
215
+ console.log(`✓ Container resized to ${targetMB}MB`);
216
+ }
217
+ catch (err) {
218
+ if (err instanceof LuksError)
219
+ throw err;
220
+ throw new LuksError('RESIZE_FAILED', 'Failed to resize container', String(err));
221
+ }
222
+ return this;
223
+ }
224
+ async changePassword(oldPassword, newPassword) {
225
+ try {
226
+ if (newPassword.length < 12) {
227
+ throw new LuksError('WEAK_PASSWORD', 'New password must be at least 12 characters');
228
+ }
229
+ console.log('Changing LUKS password...');
230
+ this.executeCommand(`echo -e "${oldPassword.replace(/"/g, '\\"')}\n${newPassword.replace(/"/g, '\\"')}" | cryptsetup luksChangeKey ${this.imagepath}`, 'Change LUKS password');
231
+ this.config.password = newPassword;
232
+ console.log(`✓ Password changed successfully`);
233
+ }
234
+ catch (err) {
235
+ if (err instanceof LuksError)
236
+ throw err;
237
+ throw new LuksError('PASSWORD_CHANGE_FAILED', 'Failed to change password', String(err));
238
+ }
239
+ return this;
240
+ }
241
+ getInfo() {
242
+ try {
243
+ const output = (0, child_process_1.execSync)(`cryptsetup luksDump ${this.imagepath}`, { encoding: 'utf-8' });
244
+ return {
245
+ locked: this.getSettings().locked,
246
+ mounted: this.isMounted(),
247
+ imagePath: this.imagepath,
248
+ containerPath: this.config.directory,
249
+ size: this.config.size,
250
+ raw: output
251
+ };
252
+ }
253
+ catch (err) {
254
+ throw new LuksError('INFO_FAILED', 'Failed to get container info', String(err));
255
+ }
256
+ }
257
+ }
258
+ // ?? Luks (Public API) ?????????????????????????????????????????????????????
259
+ class Luks {
260
+ constructor(directory, config) {
261
+ this.directory = directory;
262
+ this.config = config;
263
+ this.container = new Container({ ...this.config, directory: this.directory });
264
+ }
265
+ static list() {
266
+ try {
267
+ const output = (0, child_process_1.execSync)("lsblk -J | jq '[.blockdevices[] | select(.fstype == null and .children != null) | {name: .name, uuid: .uuid, children: .children}]'", { encoding: 'utf-8' });
268
+ return JSON.parse(output);
269
+ }
270
+ catch (err) {
271
+ throw new LuksError('LIST_FAILED', 'Failed to list LUKS containers', String(err));
272
+ }
273
+ }
274
+ mount() {
275
+ this.container.mount();
276
+ return this;
277
+ }
278
+ unmount() {
279
+ this.container.unmount();
280
+ return this;
281
+ }
282
+ delete(force = false) {
283
+ this.container.delete(force);
284
+ return this;
285
+ }
286
+ resize(size) {
287
+ this.container.resize(size);
288
+ return this;
289
+ }
290
+ async changePassword(oldPassword, newPassword) {
291
+ await this.container.changePassword(oldPassword, newPassword);
292
+ return this;
293
+ }
294
+ getInfo() {
295
+ return this.container.getInfo();
296
+ }
297
+ isMounted() {
298
+ return this.container.isMounted();
299
+ }
300
+ }
301
+ exports.Luks = Luks;
302
+ //# sourceMappingURL=luks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"luks.js","sourceRoot":"","sources":["../../src/lib/luks.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@hotfusion/cipher",
3
+ "version": "0.0.1",
4
+ "description": "Vault-like secrets management with AES-256-GCM encryption and optional LUKS container support",
5
+ "keywords": [
6
+ "secrets",
7
+ "vault",
8
+ "encryption",
9
+ "aes-256-gcm",
10
+ "luks",
11
+ "security",
12
+ "key-management"
13
+ ],
14
+ "author": "Alex Loginov <you@example.com>",
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/yourusername/cipher.git"
19
+ },
20
+ "main": "dist/index.js",
21
+ "types": "dist/index.d.ts",
22
+ "exports": {
23
+ ".": {
24
+ "import": "./dist/index.js",
25
+ "require": "./dist/index.cjs",
26
+ "types": "./dist/index.d.ts"
27
+ },
28
+ "./luks": {
29
+ "import": "./dist/luks.js",
30
+ "require": "./dist/luks.cjs",
31
+ "types": "./dist/luks.d.ts"
32
+ }
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsc && npm run build:cjs",
41
+ "build:cjs": "tsc --module commonjs --outDir dist",
42
+ "test": "vitest",
43
+ "test:coverage": "vitest --coverage",
44
+ "lint": "eslint src --ext .ts",
45
+ "prepack": "npm run build"
46
+ },
47
+ "dependencies": {
48
+ "ajv": "^8.12.0",
49
+ "lokijs": "^1.5.12"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.0.0",
53
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
54
+ "@typescript-eslint/parser": "^6.0.0",
55
+ "eslint": "^8.0.0",
56
+ "typescript": "^5.0.0",
57
+ "vitest": "^0.34.0"
58
+ },
59
+ "engines": {
60
+ "node": ">=16.0.0"
61
+ },
62
+ "publishConfig": {
63
+ "registry": "https://registry.npmjs.org/",
64
+ "access": "public"
65
+ }
66
+ }
package/readme.md ADDED
@@ -0,0 +1,369 @@
1
+ # @hotfusion/cipher
2
+
3
+ A production-ready, Vault-like secrets management library for Node.js with **AES-256-GCM encryption** and optional **LUKS container support**.
4
+
5
+ ## Features
6
+
7
+ ✅ **AES-256-GCM encryption** - Industry-standard authenticated encryption
8
+ ✅ **PBKDF2 key derivation** - 100,000 iterations for security
9
+ ✅ **Three security levels:**
10
+ - **Level 0**: Plain encrypted file (fast, no root required)
11
+ - **Level 1**: LUKS container + AES-256-GCM (maximum security, requires root)
12
+ - **Level 2**: VM-level isolation (coming soon)
13
+
14
+ ✅ **Version control** - Track secret versions, prevent downgrade attacks
15
+ ✅ **Readonly mode** - Immutable deployments
16
+ ✅ **Password lifecycle** - Change passwords, rotate credentials
17
+ ✅ **LokiJS database** - In-memory with persistent encryption
18
+ ✅ **AJV schema validation** - Optional key schemas
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ npm install @hotfusion/cipher
24
+ ```
25
+
26
+ Or with yarn:
27
+ ```bash
28
+ yarn add @hotfusion/cipher
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ### Level 0: Simple Encrypted Storage
34
+
35
+ ```typescript
36
+ import { Cipher } from '@hotfusion/cipher';
37
+
38
+ // Create cipher
39
+ const cipher = new Cipher({
40
+ path: './secrets',
41
+ password: 'super-secure-password-min-12-chars',
42
+ level: 0 // plain encrypted file
43
+ });
44
+
45
+ await cipher.ready();
46
+
47
+ // Store a secret
48
+ const secrets = cipher.collection('secrets');
49
+ await secrets.insert(
50
+ { id: 'api_key' },
51
+ { token: 'super-secret-token' }
52
+ );
53
+
54
+ // Retrieve a secret
55
+ const found = secrets.find({ id: 'api_key' });
56
+ const unsealed = secrets.unseal('api_key');
57
+ console.log(unsealed); // { token: 'super-secret-token' }
58
+ ```
59
+
60
+ ### Level 1: LUKS Container (Requires root/sudo)
61
+
62
+ ```typescript
63
+ const cipher = new Cipher({
64
+ path: '/mnt/secrets',
65
+ password: 'super-secure-password-min-12-chars',
66
+ level: 1, // LUKS encrypted container
67
+ size: 1024 // 1GB container
68
+ });
69
+
70
+ await cipher.ready();
71
+
72
+ // Same API as level 0
73
+ const secrets = cipher.collection('secrets');
74
+ await secrets.insert({ id: 'db_password' }, { pwd: '...' });
75
+ ```
76
+
77
+ **Note**: Level 1 requires:
78
+ - Linux with cryptsetup/LUKS support
79
+ - Root/sudo access (for mount/unmount)
80
+ - The LUKS container is automatically mounted on initialization
81
+
82
+ ## API Reference
83
+
84
+ ### Cipher
85
+
86
+ #### Constructor
87
+
88
+ ```typescript
89
+ new Cipher(config: ICipherConfig, collections?: ICollection[])
90
+ ```
91
+
92
+ **Config options:**
93
+ ```typescript
94
+ {
95
+ path: string; // Directory to store secrets
96
+ password: string; // Min 12 characters
97
+ level?: 0 | 1 | 2; // Default: 0
98
+ size?: number; // MB (required for level 1)
99
+ readonly?: boolean; // Default: false
100
+ }
101
+ ```
102
+
103
+ **Password sources** (in order of precedence):
104
+ 1. `config.password`
105
+ 2. `--password=xxx` CLI argument
106
+ 3. `CIPHER_PASSWORD` environment variable
107
+
108
+ #### Methods
109
+
110
+ ```typescript
111
+ // Wait for database to load
112
+ await cipher.ready(): Promise<void>
113
+
114
+ // Get collection by name
115
+ cipher.collection(name: string): SecretCollection
116
+
117
+ // Save all changes to disk
118
+ await cipher.save(): Promise<void>
119
+
120
+ // Change password (level 1 only)
121
+ await cipher.changePassword(oldPassword: string, newPassword: string): Promise<void>
122
+
123
+ // Unmount LUKS container (level 1 only)
124
+ await cipher.unmount(): Promise<void>
125
+
126
+ // Get cipher info
127
+ cipher.getInfo(): {
128
+ level: number;
129
+ path: string;
130
+ readonly: boolean;
131
+ mounted: boolean;
132
+ collections: string[];
133
+ }
134
+
135
+ // Check if container is mounted
136
+ cipher.isMounted(): boolean
137
+ ```
138
+
139
+ ### SecretCollection
140
+
141
+ #### Methods
142
+
143
+ ```typescript
144
+ // Insert a new secret (fails if exists)
145
+ await collection.insert(
146
+ key: { id: string },
147
+ secret: any,
148
+ options?: { readonly?: boolean; version?: number }
149
+ ): Promise<void>
150
+
151
+ // Update existing secret (fails if not exists)
152
+ await collection.update(
153
+ key: { id: string },
154
+ secret: any,
155
+ options?: { readonly?: boolean; version?: number }
156
+ ): Promise<void>
157
+
158
+ // Delete a secret
159
+ await collection.delete(
160
+ key: { id: string },
161
+ options?: { readonly?: boolean }
162
+ ): Promise<void>
163
+
164
+ // Find secret metadata
165
+ collection.find(key: { id: string }): {
166
+ key: { [key: string]: string };
167
+ meta: { version: number; readonly?: boolean };
168
+ _id: number;
169
+ } | null
170
+
171
+ // Retrieve secret value
172
+ collection.unseal(id: string): any
173
+
174
+ // List all secrets (metadata only)
175
+ collection.list(): Array<{ key: any; meta: any }>
176
+ ```
177
+
178
+ ## Examples
179
+
180
+ ### Full Example: API Credentials
181
+
182
+ ```typescript
183
+ import { Cipher } from '@hotfusion/cipher';
184
+
185
+ const cipher = new Cipher({
186
+ path: './vault',
187
+ password: process.env.VAULT_PASSWORD!,
188
+ level: 0
189
+ });
190
+
191
+ await cipher.ready();
192
+
193
+ const creds = cipher.collection('credentials');
194
+
195
+ // Store API key
196
+ await creds.insert(
197
+ { id: 'github_token' },
198
+ {
199
+ token: 'ghp_xxxxxxxxxxxxxxxxxxxx',
200
+ scope: 'repo,gist,user'
201
+ }
202
+ );
203
+
204
+ // Store database password
205
+ await creds.insert(
206
+ { id: 'db_password' },
207
+ {
208
+ password: 'postgres-password',
209
+ database: 'myapp_prod',
210
+ host: 'db.example.com'
211
+ }
212
+ );
213
+
214
+ // Update with new version
215
+ await creds.update(
216
+ { id: 'github_token' },
217
+ {
218
+ token: 'ghp_new_token',
219
+ scope: 'repo,gist,user'
220
+ },
221
+ { version: 2 }
222
+ );
223
+
224
+ // List all secrets
225
+ const all = creds.list();
226
+ console.log(all);
227
+ // [
228
+ // { key: { id: 'github_token' }, meta: { version: 2, readonly: false } },
229
+ // { key: { id: 'db_password' }, meta: { version: 1, readonly: false } }
230
+ // ]
231
+
232
+ // Retrieve secret
233
+ const dbCreds = creds.unseal('db_password');
234
+ console.log(dbCreds);
235
+ // { password: 'postgres-password', database: 'myapp_prod', host: '...' }
236
+ ```
237
+
238
+ ### With Schema Validation
239
+
240
+ ```typescript
241
+ const cipher = new Cipher({
242
+ path: './vault',
243
+ password: 'xxx',
244
+ }, [
245
+ {
246
+ name: 'api_keys',
247
+ schema: {
248
+ keySchema: {
249
+ type: 'object',
250
+ properties: {
251
+ id: { type: 'string', minLength: 3 }
252
+ },
253
+ required: ['id']
254
+ }
255
+ }
256
+ }
257
+ ]);
258
+
259
+ await cipher.ready();
260
+
261
+ const keys = cipher.collection('api_keys');
262
+
263
+ // This will fail validation
264
+ try {
265
+ await keys.insert({ id: 'ab' }, { token: '...' });
266
+ } catch (err) {
267
+ console.error(err.message); // Key validation failed
268
+ }
269
+ ```
270
+
271
+ ### Environment-based Configuration
272
+
273
+ ```typescript
274
+ const cipher = new Cipher({
275
+ path: process.env.CIPHER_PATH || './vault',
276
+ password: process.env.CIPHER_PASSWORD!,
277
+ level: (process.env.CIPHER_LEVEL ?? 0) as any,
278
+ size: process.env.CIPHER_LEVEL === '1' ? 1024 : undefined,
279
+ readonly: process.env.NODE_ENV === 'production'
280
+ });
281
+
282
+ await cipher.ready();
283
+ ```
284
+
285
+ ## Security Considerations
286
+
287
+ ### Password Strength
288
+
289
+ - Minimum **12 characters** (enforced)
290
+ - Use strong, random passwords
291
+ - Store in environment variables or secure vaults (not in code)
292
+
293
+ ### LUKS Containers (Level 1)
294
+
295
+ - Requires **root/sudo** access
296
+ - Automatically mounted during `Cipher` initialization
297
+ - Automatically unmounted on error
298
+ - Use for maximum security (encryption at filesystem level)
299
+
300
+ ### File Permissions
301
+
302
+ - Database files created with mode `0o600` (read/write owner only)
303
+ - Container directories created with mode `0o700` (rwx owner only)
304
+
305
+ ### Key Rotation
306
+
307
+ - Secrets support versioning to prevent downgrade
308
+ - Use `update()` with new version to rotate credentials
309
+ - Change password with `changePassword()` (re-encrypts entire vault)
310
+
311
+ ### Readonly Mode
312
+
313
+ - Set `readonly: true` for immutable deployments
314
+ - Prevents any insert/update/delete operations
315
+ - Useful for CI/CD pipelines
316
+
317
+ ## Error Handling
318
+
319
+ ```typescript
320
+ import { Cipher, CipherError } from '@hotfusion/cipher';
321
+
322
+ try {
323
+ const cipher = new Cipher({ path: './vault', password: 'xxx' });
324
+ await cipher.ready();
325
+ } catch (err) {
326
+ if (err instanceof CipherError) {
327
+ console.error(`[${err.code}] ${err.message}`);
328
+ console.error(err.details);
329
+ }
330
+ }
331
+ ```
332
+
333
+ **Common error codes:**
334
+
335
+ | Code | Meaning |
336
+ |------|---------|
337
+ | `NO_PASSWORD` | Password not provided |
338
+ | `WEAK_PASSWORD` | Password < 12 characters |
339
+ | `KEY_EXISTS` | Secret already exists |
340
+ | `KEY_NOT_FOUND` | Secret doesn't exist |
341
+ | `READONLY_MODE` | Cannot modify in readonly mode |
342
+ | `COLLECTION_NOT_FOUND` | Collection doesn't exist |
343
+ | `INVALID_VERSION` | Version constraint violated |
344
+ | `LUKS_ERROR` | LUKS container error |
345
+
346
+ ## Performance
347
+
348
+ - **Level 0**: ~1-5ms per operation (local SSD)
349
+ - **Level 1**: ~5-50ms per operation (LUKS mount overhead)
350
+ - Encryption: AES-256-GCM with 100k PBKDF2 iterations
351
+
352
+ ## Limitations
353
+
354
+ - **Level 2** (VM-level isolation) not yet implemented
355
+ - LUKS requires Linux + cryptsetup
356
+ - Single-process (no distributed locking)
357
+ - LokiJS is in-memory (loaded at startup)
358
+
359
+ ## License
360
+
361
+ MIT
362
+
363
+ ## Contributing
364
+
365
+ Contributions welcome! Please submit PRs to the [GitHub repository](https://github.com/yourusername/cipher).
366
+
367
+ ---
368
+
369
+ **Made with ❤️ for secure secrets management**