@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.
- package/LICENSE +202 -0
- package/build/VaultsApi.js +263 -0
- package/build/VaultsEvents.js +19 -0
- package/build/VaultsModule.js +71 -0
- package/build/crypto/wasm/VaultCrypto.js +70 -0
- package/build/errors/BadSuiteError.js +34 -0
- package/build/errors/DecryptAeadError.js +34 -0
- package/build/errors/DecryptKemError.js +34 -0
- package/build/errors/PolicyError.js +34 -0
- package/build/errors/VaultError.js +77 -0
- package/build/errors/index.js +16 -0
- package/build/index.js +119 -0
- package/build/messages/CreateVaultMessage.js +126 -0
- package/build/messages/DeleteVaultMessage.js +114 -0
- package/build/messages/DenyAccessMessage.js +114 -0
- package/build/messages/DenyShareMessage.js +120 -0
- package/build/messages/GrantAccessMessage.js +126 -0
- package/build/messages/ProvideShareMessage.js +126 -0
- package/build/messages/RequestAccessMessage.js +120 -0
- package/build/messages/RequestShareMessage.js +120 -0
- package/build/messages/RetrieveVaultMessage.js +108 -0
- package/build/messages/StoreVaultMessage.js +114 -0
- package/build/messages/UpdateVaultMessage.js +120 -0
- package/build/messages/VaultCreatedAckMessage.js +108 -0
- package/build/messages/VaultDataMessage.js +121 -0
- package/build/messages/VaultProblemReportMessage.js +124 -0
- package/build/messages/VaultStoredAckMessage.js +115 -0
- package/build/messages/index.js +36 -0
- package/build/models/ThresholdSession.js +24 -0
- package/build/models/VaultDocument.js +28 -0
- package/build/models/VaultHeader.js +31 -0
- package/build/models/VaultPolicy.js +29 -0
- package/build/models/index.js +20 -0
- package/build/repository/ThresholdSessionRecord.js +117 -0
- package/build/repository/ThresholdSessionRepository.js +216 -0
- package/build/repository/VaultRecord.js +128 -0
- package/build/repository/VaultRepository.js +200 -0
- package/build/repository/index.js +13 -0
- package/build/services/VaultEncryptionService.js +613 -0
- package/build/services/VaultService.js +398 -0
- package/build/services/index.js +8 -0
- package/package.json +45 -0
- package/wasm/README.md +166 -0
- package/wasm/package.json +16 -0
- package/wasm/vault_crypto.d.ts +526 -0
- package/wasm/vault_crypto.js +2137 -0
- package/wasm/vault_crypto_bg.wasm +0 -0
- 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
|
+
}
|