@ajna-inc/vaults 0.1.0

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.
Files changed (48) hide show
  1. package/LICENSE +202 -0
  2. package/build/VaultsApi.js +263 -0
  3. package/build/VaultsEvents.js +19 -0
  4. package/build/VaultsModule.js +71 -0
  5. package/build/crypto/wasm/VaultCrypto.js +70 -0
  6. package/build/errors/BadSuiteError.js +34 -0
  7. package/build/errors/DecryptAeadError.js +34 -0
  8. package/build/errors/DecryptKemError.js +34 -0
  9. package/build/errors/PolicyError.js +34 -0
  10. package/build/errors/VaultError.js +77 -0
  11. package/build/errors/index.js +16 -0
  12. package/build/index.js +119 -0
  13. package/build/messages/CreateVaultMessage.js +126 -0
  14. package/build/messages/DeleteVaultMessage.js +114 -0
  15. package/build/messages/DenyAccessMessage.js +114 -0
  16. package/build/messages/DenyShareMessage.js +120 -0
  17. package/build/messages/GrantAccessMessage.js +126 -0
  18. package/build/messages/ProvideShareMessage.js +126 -0
  19. package/build/messages/RequestAccessMessage.js +120 -0
  20. package/build/messages/RequestShareMessage.js +120 -0
  21. package/build/messages/RetrieveVaultMessage.js +108 -0
  22. package/build/messages/StoreVaultMessage.js +114 -0
  23. package/build/messages/UpdateVaultMessage.js +120 -0
  24. package/build/messages/VaultCreatedAckMessage.js +108 -0
  25. package/build/messages/VaultDataMessage.js +121 -0
  26. package/build/messages/VaultProblemReportMessage.js +124 -0
  27. package/build/messages/VaultStoredAckMessage.js +115 -0
  28. package/build/messages/index.js +36 -0
  29. package/build/models/ThresholdSession.js +24 -0
  30. package/build/models/VaultDocument.js +28 -0
  31. package/build/models/VaultHeader.js +31 -0
  32. package/build/models/VaultPolicy.js +29 -0
  33. package/build/models/index.js +20 -0
  34. package/build/repository/ThresholdSessionRecord.js +117 -0
  35. package/build/repository/ThresholdSessionRepository.js +216 -0
  36. package/build/repository/VaultRecord.js +128 -0
  37. package/build/repository/VaultRepository.js +200 -0
  38. package/build/repository/index.js +13 -0
  39. package/build/services/VaultEncryptionService.js +613 -0
  40. package/build/services/VaultService.js +398 -0
  41. package/build/services/index.js +8 -0
  42. package/package.json +45 -0
  43. package/wasm/README.md +166 -0
  44. package/wasm/package.json +16 -0
  45. package/wasm/vault_crypto.d.ts +526 -0
  46. package/wasm/vault_crypto.js +2137 -0
  47. package/wasm/vault_crypto_bg.wasm +0 -0
  48. package/wasm/vault_crypto_bg.wasm.d.ts +66 -0
@@ -0,0 +1,398 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
14
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
15
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
16
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
17
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
18
+ var _, done = false;
19
+ for (var i = decorators.length - 1; i >= 0; i--) {
20
+ var context = {};
21
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
22
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
23
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
24
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
25
+ if (kind === "accessor") {
26
+ if (result === void 0) continue;
27
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
28
+ if (_ = accept(result.get)) descriptor.get = _;
29
+ if (_ = accept(result.set)) descriptor.set = _;
30
+ if (_ = accept(result.init)) initializers.unshift(_);
31
+ }
32
+ else if (_ = accept(result)) {
33
+ if (kind === "field") initializers.unshift(_);
34
+ else descriptor[key] = _;
35
+ }
36
+ }
37
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
38
+ done = true;
39
+ };
40
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
41
+ var useValue = arguments.length > 2;
42
+ for (var i = 0; i < initializers.length; i++) {
43
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
44
+ }
45
+ return useValue ? value : void 0;
46
+ };
47
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
48
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
49
+ return new (P || (P = Promise))(function (resolve, reject) {
50
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
51
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
52
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
53
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
54
+ });
55
+ };
56
+ var __generator = (this && this.__generator) || function (thisArg, body) {
57
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
58
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
59
+ function verb(n) { return function (v) { return step([n, v]); }; }
60
+ function step(op) {
61
+ if (f) throw new TypeError("Generator is already executing.");
62
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
63
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
64
+ if (y = 0, t) op = [op[0] & 2, t.value];
65
+ switch (op[0]) {
66
+ case 0: case 1: t = op; break;
67
+ case 4: _.label++; return { value: op[1], done: false };
68
+ case 5: _.label++; y = op[1]; op = [0]; continue;
69
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
70
+ default:
71
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
72
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
73
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
74
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
75
+ if (t[2]) _.ops.pop();
76
+ _.trys.pop(); continue;
77
+ }
78
+ op = body.call(thisArg, _);
79
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
80
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
81
+ }
82
+ };
83
+ var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
84
+ if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
85
+ return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
86
+ };
87
+ Object.defineProperty(exports, "__esModule", { value: true });
88
+ exports.VaultService = void 0;
89
+ var core_1 = require("@credo-ts/core");
90
+ var VaultRecord_1 = require("../repository/VaultRecord");
91
+ var errors_1 = require("../errors");
92
+ var VaultCrypto_1 = require("../crypto/wasm/VaultCrypto");
93
+ var VaultsEvents_1 = require("../VaultsEvents");
94
+ // ═══════════════════════════════════════════════════════════════════════════
95
+ // Service
96
+ // ═══════════════════════════════════════════════════════════════════════════
97
+ /**
98
+ * Vault Service
99
+ *
100
+ * Main orchestration layer for vault operations.
101
+ * Coordinates encryption, storage, and events.
102
+ *
103
+ * All encryption/decryption happens client-side.
104
+ */
105
+ var VaultService = function () {
106
+ var _classDecorators = [(0, core_1.injectable)()];
107
+ var _classDescriptor;
108
+ var _classExtraInitializers = [];
109
+ var _classThis;
110
+ var VaultService = _classThis = /** @class */ (function () {
111
+ function VaultService_1(encryptionService, vaultRepository, eventEmitter) {
112
+ this.encryptionService = encryptionService;
113
+ this.vaultRepository = vaultRepository;
114
+ this.eventEmitter = eventEmitter;
115
+ }
116
+ /**
117
+ * Create a new vault with passphrase encryption
118
+ * Stores encrypted data locally in agent storage
119
+ *
120
+ * @param agentContext - Agent context
121
+ * @param data - Raw data to encrypt
122
+ * @param options - Creation options including passphrase
123
+ * @returns Created vault identifiers
124
+ */
125
+ VaultService_1.prototype.createVault = function (agentContext, data, options) {
126
+ var _a;
127
+ return __awaiter(this, void 0, void 0, function () {
128
+ var vault, record;
129
+ return __generator(this, function (_b) {
130
+ switch (_b.label) {
131
+ case 0: return [4 /*yield*/, this.encryptionService.encryptWithPassphrase(data, options.passphrase, {
132
+ vaultId: options.vaultId,
133
+ memory: options.memory,
134
+ iterations: options.iterations,
135
+ })
136
+ // 2. Add metadata to header
137
+ ];
138
+ case 1:
139
+ vault = _b.sent();
140
+ // 2. Add metadata to header
141
+ if (options.metadata) {
142
+ vault.header.metadata = __assign(__assign({}, vault.header.metadata), { description: options.metadata.description, tags: options.metadata.tags, createdAt: new Date().toISOString() });
143
+ }
144
+ else {
145
+ vault.header.metadata = {
146
+ createdAt: new Date().toISOString(),
147
+ };
148
+ }
149
+ record = new VaultRecord_1.VaultRecord({
150
+ vaultId: (_a = vault.header.vaultId) !== null && _a !== void 0 ? _a : vault.header.docId,
151
+ docId: vault.header.docId,
152
+ header: vault.header,
153
+ ciphertext: (0, VaultCrypto_1.toBase64Url)(vault.ciphertext),
154
+ ownerDid: agentContext.contextCorrelationId,
155
+ });
156
+ // 4. Save to local storage
157
+ return [4 /*yield*/, this.vaultRepository.save(agentContext, record)
158
+ // 5. Emit event
159
+ ];
160
+ case 2:
161
+ // 4. Save to local storage
162
+ _b.sent();
163
+ // 5. Emit event
164
+ this.eventEmitter.emit(agentContext, {
165
+ type: VaultsEvents_1.VaultEventTypes.VaultCreated,
166
+ payload: {
167
+ vaultId: record.vaultId,
168
+ docId: record.docId,
169
+ policyMode: record.policyMode,
170
+ },
171
+ });
172
+ return [2 /*return*/, {
173
+ vaultId: record.vaultId,
174
+ docId: record.docId,
175
+ }];
176
+ }
177
+ });
178
+ });
179
+ };
180
+ /**
181
+ * Open (decrypt) a vault
182
+ * All decryption happens client-side
183
+ *
184
+ * @param agentContext - Agent context
185
+ * @param vaultId - Vault identifier
186
+ * @param options - Open options including passphrase
187
+ * @returns Decrypted data
188
+ */
189
+ VaultService_1.prototype.openVault = function (agentContext, vaultId, options) {
190
+ return __awaiter(this, void 0, void 0, function () {
191
+ var record, vault, plaintext;
192
+ return __generator(this, function (_a) {
193
+ switch (_a.label) {
194
+ case 0: return [4 /*yield*/, this.vaultRepository.findByVaultId(agentContext, vaultId)];
195
+ case 1:
196
+ record = _a.sent();
197
+ if (!record) {
198
+ throw new errors_1.VaultError(errors_1.VaultErrorCode.NOT_FOUND, "Vault not found: ".concat(vaultId));
199
+ }
200
+ vault = {
201
+ header: record.header,
202
+ ciphertext: (0, VaultCrypto_1.fromBase64Url)(record.ciphertext),
203
+ };
204
+ return [4 /*yield*/, this.encryptionService.decryptWithPassphrase(vault, options.passphrase)
205
+ // 4. Emit event
206
+ ];
207
+ case 2:
208
+ plaintext = _a.sent();
209
+ // 4. Emit event
210
+ this.eventEmitter.emit(agentContext, {
211
+ type: VaultsEvents_1.VaultEventTypes.VaultOpened,
212
+ payload: {
213
+ vaultId: record.vaultId,
214
+ docId: record.docId,
215
+ },
216
+ });
217
+ return [2 /*return*/, plaintext];
218
+ }
219
+ });
220
+ });
221
+ };
222
+ /**
223
+ * Update vault content (re-encrypt with new data)
224
+ * Increments epoch for revocation tracking
225
+ *
226
+ * @param agentContext - Agent context
227
+ * @param vaultId - Vault identifier
228
+ * @param newData - New data to encrypt
229
+ * @param options - Update options including passphrase
230
+ */
231
+ VaultService_1.prototype.updateVault = function (agentContext, vaultId, newData, options) {
232
+ return __awaiter(this, void 0, void 0, function () {
233
+ var record, vault;
234
+ return __generator(this, function (_a) {
235
+ switch (_a.label) {
236
+ case 0: return [4 /*yield*/, this.vaultRepository.findByVaultId(agentContext, vaultId)];
237
+ case 1:
238
+ record = _a.sent();
239
+ if (!record) {
240
+ throw new errors_1.VaultError(errors_1.VaultErrorCode.NOT_FOUND, "Vault not found: ".concat(vaultId));
241
+ }
242
+ return [4 /*yield*/, this.encryptionService.encryptWithPassphrase(newData, options.passphrase, {
243
+ docId: record.docId,
244
+ vaultId: record.vaultId,
245
+ })
246
+ // 3. Increment epoch (spec §12 - key rotation)
247
+ ];
248
+ case 2:
249
+ vault = _a.sent();
250
+ // 3. Increment epoch (spec §12 - key rotation)
251
+ vault.header.epoch = record.header.epoch + 1;
252
+ // 4. Update metadata
253
+ vault.header.metadata = __assign(__assign(__assign({}, record.header.metadata), options.metadata), { updatedAt: new Date().toISOString() });
254
+ // 5. Update record
255
+ record.header = vault.header;
256
+ record.ciphertext = (0, VaultCrypto_1.toBase64Url)(vault.ciphertext);
257
+ record.updatedAt = new Date();
258
+ return [4 /*yield*/, this.vaultRepository.update(agentContext, record)
259
+ // 6. Emit event
260
+ ];
261
+ case 3:
262
+ _a.sent();
263
+ // 6. Emit event
264
+ this.eventEmitter.emit(agentContext, {
265
+ type: VaultsEvents_1.VaultEventTypes.VaultUpdated,
266
+ payload: {
267
+ vaultId: record.vaultId,
268
+ docId: record.docId,
269
+ epoch: vault.header.epoch,
270
+ },
271
+ });
272
+ return [2 /*return*/];
273
+ }
274
+ });
275
+ });
276
+ };
277
+ /**
278
+ * Delete a vault
279
+ *
280
+ * @param agentContext - Agent context
281
+ * @param vaultId - Vault identifier
282
+ */
283
+ VaultService_1.prototype.deleteVault = function (agentContext, vaultId) {
284
+ return __awaiter(this, void 0, void 0, function () {
285
+ var record;
286
+ return __generator(this, function (_a) {
287
+ switch (_a.label) {
288
+ case 0: return [4 /*yield*/, this.vaultRepository.findByVaultId(agentContext, vaultId)];
289
+ case 1:
290
+ record = _a.sent();
291
+ if (!record) {
292
+ throw new errors_1.VaultError(errors_1.VaultErrorCode.NOT_FOUND, "Vault not found: ".concat(vaultId));
293
+ }
294
+ return [4 /*yield*/, this.vaultRepository.delete(agentContext, record)];
295
+ case 2:
296
+ _a.sent();
297
+ this.eventEmitter.emit(agentContext, {
298
+ type: VaultsEvents_1.VaultEventTypes.VaultDeleted,
299
+ payload: {
300
+ vaultId: record.vaultId,
301
+ docId: record.docId,
302
+ },
303
+ });
304
+ return [2 /*return*/];
305
+ }
306
+ });
307
+ });
308
+ };
309
+ /**
310
+ * List all vaults
311
+ *
312
+ * @param agentContext - Agent context
313
+ * @returns Array of vault records
314
+ */
315
+ VaultService_1.prototype.listVaults = function (agentContext) {
316
+ return __awaiter(this, void 0, void 0, function () {
317
+ return __generator(this, function (_a) {
318
+ return [2 /*return*/, this.vaultRepository.getAll(agentContext)];
319
+ });
320
+ });
321
+ };
322
+ /**
323
+ * Get vault info (metadata without decrypting)
324
+ *
325
+ * @param agentContext - Agent context
326
+ * @param vaultId - Vault identifier
327
+ * @returns Vault information
328
+ */
329
+ VaultService_1.prototype.getVaultInfo = function (agentContext, vaultId) {
330
+ return __awaiter(this, void 0, void 0, function () {
331
+ var record;
332
+ return __generator(this, function (_a) {
333
+ switch (_a.label) {
334
+ case 0: return [4 /*yield*/, this.vaultRepository.findByVaultId(agentContext, vaultId)];
335
+ case 1:
336
+ record = _a.sent();
337
+ if (!record) {
338
+ throw new errors_1.VaultError(errors_1.VaultErrorCode.NOT_FOUND, "Vault not found: ".concat(vaultId));
339
+ }
340
+ return [2 /*return*/, {
341
+ vaultId: record.vaultId,
342
+ docId: record.docId,
343
+ recordId: record.id,
344
+ header: record.header,
345
+ createdAt: record.createdAt,
346
+ updatedAt: record.updatedAt,
347
+ }];
348
+ }
349
+ });
350
+ });
351
+ };
352
+ /**
353
+ * Check if a vault exists
354
+ *
355
+ * @param agentContext - Agent context
356
+ * @param vaultId - Vault identifier
357
+ * @returns True if vault exists
358
+ */
359
+ VaultService_1.prototype.vaultExists = function (agentContext, vaultId) {
360
+ return __awaiter(this, void 0, void 0, function () {
361
+ var record;
362
+ return __generator(this, function (_a) {
363
+ switch (_a.label) {
364
+ case 0: return [4 /*yield*/, this.vaultRepository.findByVaultId(agentContext, vaultId)];
365
+ case 1:
366
+ record = _a.sent();
367
+ return [2 /*return*/, record !== null];
368
+ }
369
+ });
370
+ });
371
+ };
372
+ /**
373
+ * Get vault record by ID (for advanced operations)
374
+ *
375
+ * @param agentContext - Agent context
376
+ * @param vaultId - Vault identifier
377
+ * @returns Vault record or null
378
+ */
379
+ VaultService_1.prototype.getVaultRecord = function (agentContext, vaultId) {
380
+ return __awaiter(this, void 0, void 0, function () {
381
+ return __generator(this, function (_a) {
382
+ return [2 /*return*/, this.vaultRepository.findByVaultId(agentContext, vaultId)];
383
+ });
384
+ });
385
+ };
386
+ return VaultService_1;
387
+ }());
388
+ __setFunctionName(_classThis, "VaultService");
389
+ (function () {
390
+ var _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
391
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
392
+ VaultService = _classThis = _classDescriptor.value;
393
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
394
+ __runInitializers(_classThis, _classExtraInitializers);
395
+ })();
396
+ return VaultService = _classThis;
397
+ }();
398
+ exports.VaultService = VaultService;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VaultService = exports.VaultEncryptionService = void 0;
4
+ // Core services
5
+ var VaultEncryptionService_1 = require("./VaultEncryptionService");
6
+ Object.defineProperty(exports, "VaultEncryptionService", { enumerable: true, get: function () { return VaultEncryptionService_1.VaultEncryptionService; } });
7
+ var VaultService_1 = require("./VaultService");
8
+ Object.defineProperty(exports, "VaultService", { enumerable: true, get: function () { return VaultService_1.VaultService; } });
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@ajna-inc/vaults",
3
+ "version": "0.1.0",
4
+ "description": "Post-quantum encrypted vaults with DIDComm protocol for Credo",
5
+ "license": "Apache-2.0",
6
+ "main": "build/index.js",
7
+ "types": "build/index.d.ts",
8
+ "files": [
9
+ "build",
10
+ "wasm"
11
+ ],
12
+ "dependencies": {
13
+ "@hpke/core": "^1.7.4",
14
+ "@noble/hashes": "^1.3.3",
15
+ "class-transformer": "^0.5.1",
16
+ "class-validator": "^0.14.0",
17
+ "hash-wasm": "^4.11.0",
18
+ "@credo-ts/core": "0.5.17"
19
+ },
20
+ "optionalDependencies": {
21
+ "@aws-sdk/client-s3": "^3.400.0",
22
+ "@aws-sdk/s3-request-presigner": "^3.400.0"
23
+ },
24
+ "devDependencies": {
25
+ "@types/jest": "^29.5.0",
26
+ "@types/node": "^18.0.0",
27
+ "jest": "^29.5.0",
28
+ "ts-jest": "^29.1.0",
29
+ "typescript": "~5.3.0"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/ajna-inc/credo-ts",
34
+ "directory": "packages/vaults"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "scripts": {
40
+ "build": "tsc",
41
+ "test": "jest",
42
+ "test:watch": "jest --watch",
43
+ "build:wasm": "cd ../../../rust/wasm/vault-crypto && wasm-pack build --target nodejs --out-dir ../../../credo-ts/packages/vaults/wasm"
44
+ }
45
+ }
package/wasm/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # vault-crypto
2
+
3
+ Post-quantum cryptographic primitives for the ZK-Vault protocol, compiled to WebAssembly.
4
+
5
+ ## Features
6
+
7
+ - **AEAD Encryption**: AES-256-GCM and XChaCha20-Poly1305
8
+ - **Post-Quantum KEM**: ML-KEM-768 (Kyber-768) key encapsulation
9
+ - **Key Derivation**: HKDF-SHA256 and HKDF-join for all-of policies
10
+ - **Secret Sharing**: Shamir (t, n)-threshold secret splitting
11
+ - **Utilities**: Key commitment, random generation, hashing
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @ajna-inc/vault-crypto
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ### Generate and Encrypt with CEK
22
+
23
+ ```typescript
24
+ import * as vault from '@ajna-inc/vault-crypto';
25
+
26
+ // Initialize WASM
27
+ await vault.init();
28
+
29
+ // Generate a random CEK
30
+ const cek = vault.generateCek();
31
+
32
+ // Generate nonce
33
+ const nonce = vault.generateNonceAesGcm();
34
+
35
+ // Encrypt data
36
+ const plaintext = new TextEncoder().encode('Secret document');
37
+ const aad = new TextEncoder().encode('{"docId":"abc","epoch":0}');
38
+
39
+ const result = vault.aesGcmEncrypt(cek, nonce, plaintext, aad);
40
+ const ciphertext = result.ciphertext();
41
+
42
+ // Decrypt
43
+ const decrypted = vault.aesGcmDecrypt(cek, nonce, ciphertext, aad);
44
+ console.log(new TextDecoder().decode(decrypted)); // "Secret document"
45
+ ```
46
+
47
+ ### KEM: Wrap CEK for Recipient
48
+
49
+ ```typescript
50
+ // Recipient generates keypair
51
+ const keypair = vault.kemGenerateKeypair();
52
+ const publicKey = keypair.publicKey();
53
+ const secretKey = keypair.secretKey();
54
+
55
+ // Sender wraps CEK to recipient's public key
56
+ const wrappedCek = vault.kemWrapCek(cek, publicKey);
57
+
58
+ // Recipient unwraps
59
+ const unwrappedCek = vault.kemUnwrapCek(wrappedCek, secretKey);
60
+ ```
61
+
62
+ ### Shamir Secret Sharing
63
+
64
+ ```typescript
65
+ // Split CEK into 5 shares, need any 3 to reconstruct
66
+ const shares = vault.shamirSplit(cek, 3, 5);
67
+
68
+ // Reconstruct from any 3 shares
69
+ const selected = [shares[0], shares[2], shares[4]];
70
+ const reconstructed = vault.shamirReconstruct(selected);
71
+ ```
72
+
73
+ ### HKDF-join for All-Of Policy
74
+
75
+ ```typescript
76
+ // Combine multiple keys into joint wrap key
77
+ const keys = [
78
+ { kid: 'alice', key: aliceKey },
79
+ { kid: 'bob', key: bobKey },
80
+ ];
81
+
82
+ const wrapKey = vault.hkdfJoin(keys, 'doc:123:epoch:0');
83
+ ```
84
+
85
+ ### Key Commitment
86
+
87
+ ```typescript
88
+ // Compute key commitment
89
+ const kcmp = vault.keyCommitment(cek);
90
+
91
+ // Verify
92
+ const valid = vault.verifyKeyCommitment(cek, kcmp);
93
+ ```
94
+
95
+ ## API Reference
96
+
97
+ ### AEAD Encryption
98
+
99
+ - `aesGcmEncrypt(key, nonce, plaintext, aad)` → `AeadResult`
100
+ - `aesGcmDecrypt(key, nonce, ciphertext, aad)` → `Uint8Array`
101
+ - `xchachaEncrypt(key, nonce, plaintext, aad)` → `AeadResult`
102
+ - `xchachaDecrypt(key, nonce, ciphertext, aad)` → `Uint8Array`
103
+
104
+ ### KEM (ML-KEM-768)
105
+
106
+ - `kemGenerateKeypair()` → `KemKeypair`
107
+ - `kemEncapsulate(recipientPublicKey)` → `KemEncapResult`
108
+ - `kemDecapsulate(ciphertext, secretKey)` → `Uint8Array`
109
+ - `kemWrapCek(cek, recipientPublicKey)` → `Uint8Array`
110
+ - `kemUnwrapCek(wrappedCek, secretKey)` → `Uint8Array`
111
+
112
+ ### Key Derivation
113
+
114
+ - `hkdfExpand(ikm, salt, info, length)` → `Uint8Array`
115
+ - `hkdfJoin(keys, context)` → `Uint8Array`
116
+ - `deriveCek(seed, context)` → `Uint8Array`
117
+ - `deriveKid(publicKey)` → `string`
118
+ - `deriveSymmetricKid(key)` → `string`
119
+
120
+ ### Shamir Secret Sharing
121
+
122
+ - `shamirSplit(secret, threshold, totalShares)` → `SecretShare[]`
123
+ - `shamirReconstruct(shares)` → `Uint8Array`
124
+ - `shamirSplitAndWrap(secret, threshold, publicKeys)` → `WrappedShare[]`
125
+ - `shamirUnwrapAndReconstruct(wrappedShares, secretKeys)` → `Uint8Array`
126
+
127
+ ### Utilities
128
+
129
+ - `generateCek()` → `Uint8Array` (32 bytes)
130
+ - `generateNonceAesGcm()` → `Uint8Array` (12 bytes)
131
+ - `generateNonceXchacha()` → `Uint8Array` (24 bytes)
132
+ - `randomBytes(length)` → `Uint8Array`
133
+ - `keyCommitment(cek)` → `Uint8Array`
134
+ - `verifyKeyCommitment(cek, kcmp)` → `boolean`
135
+ - `sha256(data)` → `Uint8Array`
136
+ - `blake2s256(data)` → `Uint8Array`
137
+ - `computeSummary(digest)` → `Uint8Array` (16 bytes)
138
+ - `constantTimeEq(a, b)` → `boolean`
139
+ - `toBase64Url(data)` → `string`
140
+ - `fromBase64Url(encoded)` → `Uint8Array`
141
+ - `toHex(data)` → `string`
142
+ - `fromHex(encoded)` → `Uint8Array`
143
+ - `generateUuid()` → `string`
144
+ - `canonicalAad(headerFields)` → `Uint8Array`
145
+ - `buildContext(docId, epoch)` → `string`
146
+
147
+ ## Building from Source
148
+
149
+ ```bash
150
+ # Install wasm-pack
151
+ curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
152
+
153
+ # Build for web
154
+ wasm-pack build --target web --release
155
+
156
+ # Build for Node.js
157
+ wasm-pack build --target nodejs --release
158
+
159
+ # Run tests
160
+ cargo test
161
+ wasm-pack test --headless --firefox
162
+ ```
163
+
164
+ ## License
165
+
166
+ Proprietary - Copyright © 2025 Ajna Inc. All rights reserved.
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "vault-crypto",
3
+ "collaborators": [
4
+ "Ajna Inc."
5
+ ],
6
+ "description": "Post-quantum vault cryptography for browser and Node.js",
7
+ "version": "0.1.0",
8
+ "license": "PROPRIETARY",
9
+ "files": [
10
+ "vault_crypto_bg.wasm",
11
+ "vault_crypto.js",
12
+ "vault_crypto.d.ts"
13
+ ],
14
+ "main": "vault_crypto.js",
15
+ "types": "vault_crypto.d.ts"
16
+ }