@ajna-inc/vaults 0.1.0 → 0.1.2

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 (208) hide show
  1. package/build/VaultsApi.d.ts +363 -0
  2. package/build/VaultsApi.js +450 -248
  3. package/build/VaultsApi.js.map +1 -0
  4. package/build/VaultsEvents.d.ts +227 -0
  5. package/build/VaultsEvents.js +8 -0
  6. package/build/VaultsEvents.js.map +1 -0
  7. package/build/VaultsModule.d.ts +64 -0
  8. package/build/VaultsModule.js +43 -18
  9. package/build/VaultsModule.js.map +1 -0
  10. package/build/crypto/wasm/VaultCrypto.d.ts +19 -0
  11. package/build/crypto/wasm/VaultCrypto.js +29 -42
  12. package/build/crypto/wasm/VaultCrypto.js.map +1 -0
  13. package/build/errors/BadSuiteError.d.ts +8 -0
  14. package/build/errors/BadSuiteError.js +8 -25
  15. package/build/errors/BadSuiteError.js.map +1 -0
  16. package/build/errors/DecryptAeadError.d.ts +8 -0
  17. package/build/errors/DecryptAeadError.js +8 -25
  18. package/build/errors/DecryptAeadError.js.map +1 -0
  19. package/build/errors/DecryptKemError.d.ts +8 -0
  20. package/build/errors/DecryptKemError.js +8 -25
  21. package/build/errors/DecryptKemError.js.map +1 -0
  22. package/build/errors/PolicyError.d.ts +8 -0
  23. package/build/errors/PolicyError.js +8 -25
  24. package/build/errors/PolicyError.js.map +1 -0
  25. package/build/errors/VaultError.d.ts +52 -0
  26. package/build/errors/VaultError.js +19 -30
  27. package/build/errors/VaultError.js.map +1 -0
  28. package/build/errors/index.d.ts +5 -0
  29. package/build/errors/index.js +1 -0
  30. package/build/errors/index.js.map +1 -0
  31. package/build/handlers/CreateVaultHandler.d.ts +18 -0
  32. package/build/handlers/CreateVaultHandler.js +75 -0
  33. package/build/handlers/CreateVaultHandler.js.map +1 -0
  34. package/build/handlers/DeleteVaultHandler.d.ts +17 -0
  35. package/build/handlers/DeleteVaultHandler.js +48 -0
  36. package/build/handlers/DeleteVaultHandler.js.map +1 -0
  37. package/build/handlers/DenyAccessHandler.d.ts +15 -0
  38. package/build/handlers/DenyAccessHandler.js +39 -0
  39. package/build/handlers/DenyAccessHandler.js.map +1 -0
  40. package/build/handlers/DenyShareHandler.d.ts +17 -0
  41. package/build/handlers/DenyShareHandler.js +49 -0
  42. package/build/handlers/DenyShareHandler.js.map +1 -0
  43. package/build/handlers/GrantAccessHandler.d.ts +17 -0
  44. package/build/handlers/GrantAccessHandler.js +59 -0
  45. package/build/handlers/GrantAccessHandler.js.map +1 -0
  46. package/build/handlers/ProvideShareHandler.d.ts +17 -0
  47. package/build/handlers/ProvideShareHandler.js +77 -0
  48. package/build/handlers/ProvideShareHandler.js.map +1 -0
  49. package/build/handlers/RequestAccessHandler.d.ts +18 -0
  50. package/build/handlers/RequestAccessHandler.js +60 -0
  51. package/build/handlers/RequestAccessHandler.js.map +1 -0
  52. package/build/handlers/RequestShareHandler.d.ts +19 -0
  53. package/build/handlers/RequestShareHandler.js +70 -0
  54. package/build/handlers/RequestShareHandler.js.map +1 -0
  55. package/build/handlers/RequestStorageHandler.d.ts +53 -0
  56. package/build/handlers/RequestStorageHandler.js +158 -0
  57. package/build/handlers/RequestStorageHandler.js.map +1 -0
  58. package/build/handlers/RetrieveVaultHandler.d.ts +18 -0
  59. package/build/handlers/RetrieveVaultHandler.js +65 -0
  60. package/build/handlers/RetrieveVaultHandler.js.map +1 -0
  61. package/build/handlers/StoreVaultHandler.d.ts +17 -0
  62. package/build/handlers/StoreVaultHandler.js +77 -0
  63. package/build/handlers/StoreVaultHandler.js.map +1 -0
  64. package/build/handlers/UpdateVaultHandler.d.ts +18 -0
  65. package/build/handlers/UpdateVaultHandler.js +77 -0
  66. package/build/handlers/UpdateVaultHandler.js.map +1 -0
  67. package/build/handlers/VaultCreatedAckHandler.d.ts +15 -0
  68. package/build/handlers/VaultCreatedAckHandler.js +39 -0
  69. package/build/handlers/VaultCreatedAckHandler.js.map +1 -0
  70. package/build/handlers/VaultDataHandler.d.ts +19 -0
  71. package/build/handlers/VaultDataHandler.js +68 -0
  72. package/build/handlers/VaultDataHandler.js.map +1 -0
  73. package/build/handlers/VaultProblemReportHandler.d.ts +17 -0
  74. package/build/handlers/VaultProblemReportHandler.js +40 -0
  75. package/build/handlers/VaultProblemReportHandler.js.map +1 -0
  76. package/build/handlers/VaultReferenceHandler.d.ts +33 -0
  77. package/build/handlers/VaultReferenceHandler.js +169 -0
  78. package/build/handlers/VaultReferenceHandler.js.map +1 -0
  79. package/build/handlers/VaultStoredAckHandler.d.ts +15 -0
  80. package/build/handlers/VaultStoredAckHandler.js +38 -0
  81. package/build/handlers/VaultStoredAckHandler.js.map +1 -0
  82. package/build/handlers/index.d.ts +17 -0
  83. package/build/handlers/index.js +44 -0
  84. package/build/handlers/index.js.map +1 -0
  85. package/build/index.d.ts +42 -0
  86. package/build/index.js +13 -1
  87. package/build/index.js.map +1 -0
  88. package/build/messages/CreateVaultMessage.d.ts +39 -0
  89. package/build/messages/CreateVaultMessage.js +65 -115
  90. package/build/messages/CreateVaultMessage.js.map +1 -0
  91. package/build/messages/DeleteVaultMessage.d.ts +22 -0
  92. package/build/messages/DeleteVaultMessage.js +51 -103
  93. package/build/messages/DeleteVaultMessage.js.map +1 -0
  94. package/build/messages/DenyAccessMessage.d.ts +22 -0
  95. package/build/messages/DenyAccessMessage.js +50 -103
  96. package/build/messages/DenyAccessMessage.js.map +1 -0
  97. package/build/messages/DenyShareMessage.d.ts +24 -0
  98. package/build/messages/DenyShareMessage.js +56 -109
  99. package/build/messages/DenyShareMessage.js.map +1 -0
  100. package/build/messages/GrantAccessMessage.d.ts +32 -0
  101. package/build/messages/GrantAccessMessage.js +63 -115
  102. package/build/messages/GrantAccessMessage.js.map +1 -0
  103. package/build/messages/ProvideShareMessage.d.ts +26 -0
  104. package/build/messages/ProvideShareMessage.js +62 -115
  105. package/build/messages/ProvideShareMessage.js.map +1 -0
  106. package/build/messages/ProvideStorageMessage.d.ts +90 -0
  107. package/build/messages/ProvideStorageMessage.js +193 -0
  108. package/build/messages/ProvideStorageMessage.js.map +1 -0
  109. package/build/messages/RequestAccessMessage.d.ts +30 -0
  110. package/build/messages/RequestAccessMessage.js +57 -109
  111. package/build/messages/RequestAccessMessage.js.map +1 -0
  112. package/build/messages/RequestShareMessage.d.ts +24 -0
  113. package/build/messages/RequestShareMessage.js +56 -109
  114. package/build/messages/RequestShareMessage.js.map +1 -0
  115. package/build/messages/RequestStorageMessage.d.ts +50 -0
  116. package/build/messages/RequestStorageMessage.js +98 -0
  117. package/build/messages/RequestStorageMessage.js.map +1 -0
  118. package/build/messages/RetrieveVaultMessage.d.ts +20 -0
  119. package/build/messages/RetrieveVaultMessage.js +44 -97
  120. package/build/messages/RetrieveVaultMessage.js.map +1 -0
  121. package/build/messages/StoreVaultMessage.d.ts +23 -0
  122. package/build/messages/StoreVaultMessage.js +51 -103
  123. package/build/messages/StoreVaultMessage.js.map +1 -0
  124. package/build/messages/UpdateVaultMessage.d.ts +25 -0
  125. package/build/messages/UpdateVaultMessage.js +58 -109
  126. package/build/messages/UpdateVaultMessage.js.map +1 -0
  127. package/build/messages/VaultCreatedAckMessage.d.ts +20 -0
  128. package/build/messages/VaultCreatedAckMessage.js +44 -97
  129. package/build/messages/VaultCreatedAckMessage.js.map +1 -0
  130. package/build/messages/VaultDataMessage.d.ts +34 -0
  131. package/build/messages/VaultDataMessage.js +59 -110
  132. package/build/messages/VaultDataMessage.js.map +1 -0
  133. package/build/messages/VaultProblemReportMessage.d.ts +35 -0
  134. package/build/messages/VaultProblemReportMessage.js +56 -102
  135. package/build/messages/VaultProblemReportMessage.js.map +1 -0
  136. package/build/messages/VaultReferenceMessage.d.ts +66 -0
  137. package/build/messages/VaultReferenceMessage.js +138 -0
  138. package/build/messages/VaultReferenceMessage.js.map +1 -0
  139. package/build/messages/VaultStoredAckMessage.d.ts +33 -0
  140. package/build/messages/VaultStoredAckMessage.js +51 -104
  141. package/build/messages/VaultStoredAckMessage.js.map +1 -0
  142. package/build/messages/index.d.ts +18 -0
  143. package/build/messages/index.js +6 -1
  144. package/build/messages/index.js.map +1 -0
  145. package/build/models/ThresholdSession.d.ts +37 -0
  146. package/build/models/ThresholdSession.js +1 -0
  147. package/build/models/ThresholdSession.js.map +1 -0
  148. package/build/models/VaultDocument.d.ts +22 -0
  149. package/build/models/VaultDocument.js +1 -0
  150. package/build/models/VaultDocument.js.map +1 -0
  151. package/build/models/VaultHeader.d.ts +92 -0
  152. package/build/models/VaultHeader.js +4 -6
  153. package/build/models/VaultHeader.js.map +1 -0
  154. package/build/models/VaultPolicy.d.ts +24 -0
  155. package/build/models/VaultPolicy.js +1 -0
  156. package/build/models/VaultPolicy.js.map +1 -0
  157. package/build/models/index.d.ts +4 -0
  158. package/build/models/index.js +1 -0
  159. package/build/models/index.js.map +1 -0
  160. package/build/repository/KemKeypairRecord.d.ts +37 -0
  161. package/build/repository/KemKeypairRecord.js +35 -0
  162. package/build/repository/KemKeypairRecord.js.map +1 -0
  163. package/build/repository/KemKeypairRepository.d.ts +18 -0
  164. package/build/repository/KemKeypairRepository.js +50 -0
  165. package/build/repository/KemKeypairRepository.js.map +1 -0
  166. package/build/repository/ThresholdSessionRecord.d.ts +93 -0
  167. package/build/repository/ThresholdSessionRecord.js +58 -92
  168. package/build/repository/ThresholdSessionRecord.js.map +1 -0
  169. package/build/repository/ThresholdSessionRepository.d.ts +35 -0
  170. package/build/repository/ThresholdSessionRepository.js +72 -208
  171. package/build/repository/ThresholdSessionRepository.js.map +1 -0
  172. package/build/repository/VaultRecord.d.ts +105 -0
  173. package/build/repository/VaultRecord.js +94 -115
  174. package/build/repository/VaultRecord.js.map +1 -0
  175. package/build/repository/VaultRepository.d.ts +35 -0
  176. package/build/repository/VaultRepository.js +66 -192
  177. package/build/repository/VaultRepository.js.map +1 -0
  178. package/build/repository/index.d.ts +9 -0
  179. package/build/repository/index.js +7 -1
  180. package/build/repository/index.js.map +1 -0
  181. package/build/services/HPKEService.d.ts +67 -0
  182. package/build/services/HPKEService.js +106 -0
  183. package/build/services/HPKEService.js.map +1 -0
  184. package/build/services/KemKeyExchangeService.d.ts +207 -0
  185. package/build/services/KemKeyExchangeService.js +323 -0
  186. package/build/services/KemKeyExchangeService.js.map +1 -0
  187. package/build/services/VaultEncryptionService.d.ts +120 -0
  188. package/build/services/VaultEncryptionService.js +469 -588
  189. package/build/services/VaultEncryptionService.js.map +1 -0
  190. package/build/services/VaultService.d.ts +127 -0
  191. package/build/services/VaultService.js +224 -376
  192. package/build/services/VaultService.js.map +1 -0
  193. package/build/services/VaultSigningService.d.ts +216 -0
  194. package/build/services/VaultSigningService.js +498 -0
  195. package/build/services/VaultSigningService.js.map +1 -0
  196. package/build/services/index.d.ts +9 -0
  197. package/build/services/index.js +10 -1
  198. package/build/services/index.js.map +1 -0
  199. package/build/storage/VaultStorageConfig.d.ts +97 -0
  200. package/build/storage/VaultStorageConfig.js +22 -0
  201. package/build/storage/VaultStorageConfig.js.map +1 -0
  202. package/build/storage/VaultStorageService.d.ts +118 -0
  203. package/build/storage/VaultStorageService.js +381 -0
  204. package/build/storage/VaultStorageService.js.map +1 -0
  205. package/build/storage/index.d.ts +2 -0
  206. package/build/storage/index.js +21 -0
  207. package/build/storage/index.js.map +1 -0
  208. package/package.json +5 -2
@@ -1,84 +1,16 @@
1
1
  "use strict";
2
- var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
3
- function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
4
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
5
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
6
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
7
- var _, done = false;
8
- for (var i = decorators.length - 1; i >= 0; i--) {
9
- var context = {};
10
- for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
11
- for (var p in contextIn.access) context.access[p] = contextIn.access[p];
12
- context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
13
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
14
- if (kind === "accessor") {
15
- if (result === void 0) continue;
16
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
17
- if (_ = accept(result.get)) descriptor.get = _;
18
- if (_ = accept(result.set)) descriptor.set = _;
19
- if (_ = accept(result.init)) initializers.unshift(_);
20
- }
21
- else if (_ = accept(result)) {
22
- if (kind === "field") initializers.unshift(_);
23
- else descriptor[key] = _;
24
- }
25
- }
26
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
27
- done = true;
28
- };
29
- var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
30
- var useValue = arguments.length > 2;
31
- for (var i = 0; i < initializers.length; i++) {
32
- value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
33
- }
34
- return useValue ? value : void 0;
35
- };
36
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
37
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
38
- return new (P || (P = Promise))(function (resolve, reject) {
39
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
40
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
41
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
42
- step((generator = generator.apply(thisArg, _arguments || [])).next());
43
- });
44
- };
45
- var __generator = (this && this.__generator) || function (thisArg, body) {
46
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
47
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
48
- function verb(n) { return function (v) { return step([n, v]); }; }
49
- function step(op) {
50
- if (f) throw new TypeError("Generator is already executing.");
51
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
52
- 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;
53
- if (y = 0, t) op = [op[0] & 2, t.value];
54
- switch (op[0]) {
55
- case 0: case 1: t = op; break;
56
- case 4: _.label++; return { value: op[1], done: false };
57
- case 5: _.label++; y = op[1]; op = [0]; continue;
58
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
59
- default:
60
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
61
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
62
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
63
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
64
- if (t[2]) _.ops.pop();
65
- _.trys.pop(); continue;
66
- }
67
- op = body.call(thisArg, _);
68
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
69
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
70
- }
71
- };
72
- var __setFunctionName = (this && this.__setFunctionName) || function (f, name, prefix) {
73
- if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : "";
74
- return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name });
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
75
7
  };
76
8
  Object.defineProperty(exports, "__esModule", { value: true });
77
9
  exports.VaultEncryptionService = void 0;
78
- var core_1 = require("@credo-ts/core");
79
- var hash_wasm_1 = require("hash-wasm");
80
- var VaultCrypto_1 = require("../crypto/wasm/VaultCrypto");
81
- var errors_1 = require("../errors");
10
+ const core_1 = require("@credo-ts/core");
11
+ const hash_wasm_1 = require("hash-wasm");
12
+ const VaultCrypto_1 = require("../crypto/wasm/VaultCrypto");
13
+ const errors_1 = require("../errors");
82
14
  // ═══════════════════════════════════════════════════════════════════════════
83
15
  // Service
84
16
  // ═══════════════════════════════════════════════════════════════════════════
@@ -91,523 +23,472 @@ var errors_1 = require("../errors");
91
23
  *
92
24
  * All encryption and decryption happens client-side per ZK-Vault spec.
93
25
  */
94
- var VaultEncryptionService = function () {
95
- var _classDecorators = [(0, core_1.injectable)()];
96
- var _classDescriptor;
97
- var _classExtraInitializers = [];
98
- var _classThis;
99
- var VaultEncryptionService = _classThis = /** @class */ (function () {
100
- function VaultEncryptionService_1() {
101
- }
102
- // ═══════════════════════════════════════════════════════════════════════
103
- // S3 SUITE (PASSPHRASE) - For Local Storage
104
- // Spec §4.1: CEK = Argon2id(passphrase, salt, m=64-128MiB, t=2-3)
105
- // ═══════════════════════════════════════════════════════════════════════
106
- /**
107
- * Encrypt data with passphrase (S3 suite)
108
- * All encryption happens CLIENT-SIDE
109
- *
110
- * @param plaintext - Data to encrypt
111
- * @param passphrase - User passphrase
112
- * @param options - Encryption options
113
- * @returns Encrypted vault document
114
- */
115
- VaultEncryptionService_1.prototype.encryptWithPassphrase = function (plaintext, passphrase, options) {
116
- var _a, _b, _c, _d;
117
- if (options === void 0) { options = {}; }
118
- return __awaiter(this, void 0, void 0, function () {
119
- var salt, argon2Params, cek, nonce, docId, vaultId, epoch, aadFields, aad, encResult, ciphertext, kcmp, header;
120
- return __generator(this, function (_e) {
121
- switch (_e.label) {
122
- case 0:
123
- salt = (0, VaultCrypto_1.randomBytes)(32);
124
- argon2Params = {
125
- memory: (_a = options.memory) !== null && _a !== void 0 ? _a : 65536, // 64 MiB
126
- iterations: (_b = options.iterations) !== null && _b !== void 0 ? _b : 3,
127
- parallelism: 1,
128
- };
129
- return [4 /*yield*/, this.deriveKeyArgon2(passphrase, salt, argon2Params)
130
- // 3. Generate nonce (12 bytes for AES-GCM)
131
- ];
132
- case 1:
133
- cek = _e.sent();
134
- nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
135
- docId = (_c = options.docId) !== null && _c !== void 0 ? _c : (0, VaultCrypto_1.generateUuid)();
136
- vaultId = (_d = options.vaultId) !== null && _d !== void 0 ? _d : docId;
137
- epoch = 1;
138
- aadFields = {
139
- v: 1,
140
- suite: 'S3',
141
- aead: 'AES-256-GCM',
142
- docId: docId,
143
- vaultId: vaultId,
144
- epoch: epoch,
145
- policy: { mode: 'passphrase' },
146
- };
147
- aad = (0, VaultCrypto_1.canonicalAad)(aadFields);
148
- encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
149
- ciphertext = encResult.ciphertext();
150
- kcmp = (0, VaultCrypto_1.keyCommitment)(cek);
151
- header = {
152
- v: 1,
153
- suite: 'S3',
154
- aead: 'AES-256-GCM',
155
- docId: docId,
156
- vaultId: vaultId,
157
- epoch: epoch,
158
- nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
159
- kcmp: (0, VaultCrypto_1.toBase64Url)(kcmp),
160
- salt: (0, VaultCrypto_1.toBase64Url)(salt),
161
- argon2: argon2Params,
162
- policy: { mode: 'passphrase' },
163
- };
164
- // 9. Zero out CEK from memory (security best practice)
165
- this.zeroize(cek);
166
- return [2 /*return*/, { header: header, ciphertext: ciphertext }];
167
- }
168
- });
169
- });
170
- };
171
- /**
172
- * Decrypt passphrase-protected vault (S3 suite)
173
- * All decryption happens CLIENT-SIDE
174
- *
175
- * @param vault - Encrypted vault document
176
- * @param passphrase - User passphrase
177
- * @returns Decrypted plaintext
178
- */
179
- VaultEncryptionService_1.prototype.decryptWithPassphrase = function (vault, passphrase) {
180
- return __awaiter(this, void 0, void 0, function () {
181
- var header, ciphertext, salt, cek, expectedKcmp, aad, nonce, plaintext;
182
- return __generator(this, function (_a) {
183
- switch (_a.label) {
184
- case 0:
185
- header = vault.header, ciphertext = vault.ciphertext;
186
- // 1. Validate suite
187
- if (header.suite !== 'S3' && header.suite !== 'S1') {
188
- throw new errors_1.BadSuiteError("Expected S1/S3 suite for passphrase vault, got ".concat(header.suite));
189
- }
190
- if (!header.salt || !header.argon2) {
191
- throw new errors_1.PolicyError('Missing salt or argon2 params for passphrase vault');
192
- }
193
- salt = (0, VaultCrypto_1.fromBase64Url)(header.salt);
194
- return [4 /*yield*/, this.deriveKeyArgon2(passphrase, salt, header.argon2)
195
- // 3. Verify key commitment (spec §9.2 step 3)
196
- ];
197
- case 1:
198
- cek = _a.sent();
199
- expectedKcmp = (0, VaultCrypto_1.fromBase64Url)(header.kcmp);
200
- if (!(0, VaultCrypto_1.verifyKeyCommitment)(cek, expectedKcmp)) {
201
- this.zeroize(cek);
202
- throw new errors_1.DecryptAeadError('Key commitment verification failed - wrong passphrase');
203
- }
204
- aad = (0, VaultCrypto_1.canonicalAad)({
205
- v: header.v,
206
- suite: header.suite,
207
- aead: header.aead,
208
- docId: header.docId,
209
- vaultId: header.vaultId,
210
- epoch: header.epoch,
211
- policy: header.policy,
212
- });
213
- nonce = (0, VaultCrypto_1.fromBase64Url)(header.nonce);
214
- try {
215
- plaintext = (0, VaultCrypto_1.aesGcmDecrypt)(cek, nonce, ciphertext, aad);
216
- this.zeroize(cek);
217
- return [2 /*return*/, plaintext];
218
- }
219
- catch (e) {
220
- this.zeroize(cek);
221
- throw new errors_1.DecryptAeadError('AEAD decryption failed - data may be corrupted or tampered');
222
- }
223
- return [2 /*return*/];
224
- }
225
- });
226
- });
227
- };
228
- // ═══════════════════════════════════════════════════════════════════════
229
- // P1 SUITE (POST-QUANTUM) - For Multi-Party Sharing
230
- // Spec §4.1: KEM = ML-KEM-768, AEAD = AES-256-GCM
231
- // ═══════════════════════════════════════════════════════════════════════
232
- /**
233
- * Encrypt with any-of policy (spec §6.1)
234
- * Each recipient gets their own KEM-wrapped CEK
235
- *
236
- * @param plaintext - Data to encrypt
237
- * @param recipients - Array of recipient public keys
238
- * @param options - Encryption options
239
- * @returns Encrypted vault document
240
- */
241
- VaultEncryptionService_1.prototype.encryptAnyOf = function (plaintext, recipients, options) {
242
- var _a, _b;
243
- if (options === void 0) { options = {}; }
244
- return __awaiter(this, void 0, void 0, function () {
245
- var cek, nonce, docId, vaultId, epoch, aad, encResult, ciphertext, recipientWraps, kcmp, header;
246
- return __generator(this, function (_c) {
247
- if (recipients.length === 0) {
248
- throw new errors_1.PolicyError('At least one recipient required for any-of policy');
249
- }
250
- cek = (0, VaultCrypto_1.generateCek)();
251
- nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
252
- docId = (_a = options.docId) !== null && _a !== void 0 ? _a : (0, VaultCrypto_1.generateUuid)();
253
- vaultId = (_b = options.vaultId) !== null && _b !== void 0 ? _b : docId;
254
- epoch = 1;
255
- aad = (0, VaultCrypto_1.canonicalAad)({
256
- v: 1,
257
- suite: 'P1',
258
- aead: 'AES-256-GCM',
259
- docId: docId,
260
- vaultId: vaultId,
261
- epoch: epoch,
262
- policy: { mode: 'any-of' },
263
- });
264
- encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
265
- ciphertext = encResult.ciphertext();
266
- recipientWraps = recipients.map(function (r) { return ({
267
- kid: r.kid,
268
- kem: 'ML-KEM-768',
269
- ct: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.kemWrapCek)(cek, r.publicKey)),
270
- }); });
271
- kcmp = (0, VaultCrypto_1.keyCommitment)(cek);
272
- header = {
273
- v: 1,
274
- suite: 'P1',
275
- aead: 'AES-256-GCM',
276
- docId: docId,
277
- vaultId: vaultId,
278
- epoch: epoch,
279
- nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
280
- kcmp: (0, VaultCrypto_1.toBase64Url)(kcmp),
281
- policy: { mode: 'any-of' },
282
- recipients: recipientWraps,
283
- };
284
- this.zeroize(cek);
285
- return [2 /*return*/, { header: header, ciphertext: ciphertext }];
286
- });
287
- });
26
+ let VaultEncryptionService = class VaultEncryptionService {
27
+ // ═══════════════════════════════════════════════════════════════════════
28
+ // S3 SUITE (PASSPHRASE) - For Local Storage
29
+ // Spec §4.1: CEK = Argon2id(passphrase, salt, m=64-128MiB, t=2-3)
30
+ // ═══════════════════════════════════════════════════════════════════════
31
+ /**
32
+ * Encrypt data with passphrase (S3 suite)
33
+ * All encryption happens CLIENT-SIDE
34
+ *
35
+ * @param plaintext - Data to encrypt
36
+ * @param passphrase - User passphrase
37
+ * @param options - Encryption options
38
+ * @returns Encrypted vault document
39
+ */
40
+ async encryptWithPassphrase(plaintext, passphrase, options = {}) {
41
+ // 1. Generate salt (32 bytes)
42
+ const salt = (0, VaultCrypto_1.randomBytes)(32);
43
+ // 2. Derive CEK via Argon2id (spec §4.1 S1/S3 suite)
44
+ const argon2Params = {
45
+ memory: options.memory ?? 65536, // 64 MiB
46
+ iterations: options.iterations ?? 3,
47
+ parallelism: 1,
288
48
  };
289
- /**
290
- * Decrypt any-of vault (spec §9.2)
291
- * Try the specified recipient's wrap
292
- *
293
- * @param vault - Encrypted vault document
294
- * @param recipientSecretKey - Recipient's ML-KEM secret key
295
- * @param recipientKid - Recipient's key identifier
296
- * @returns Decrypted plaintext
297
- */
298
- VaultEncryptionService_1.prototype.decryptAnyOf = function (vault, recipientSecretKey, recipientKid) {
299
- var _a;
300
- return __awaiter(this, void 0, void 0, function () {
301
- var header, ciphertext, recipient, wrappedCek, cek, aad, nonce, plaintext;
302
- return __generator(this, function (_b) {
303
- header = vault.header, ciphertext = vault.ciphertext;
304
- if (((_a = header.policy) === null || _a === void 0 ? void 0 : _a.mode) !== 'any-of' || !header.recipients) {
305
- throw new errors_1.PolicyError('Not an any-of policy vault');
306
- }
307
- recipient = header.recipients.find(function (r) { return r.kid === recipientKid; });
308
- if (!recipient) {
309
- throw new errors_1.DecryptKemError("No recipient wrap found for kid: ".concat(recipientKid));
310
- }
311
- wrappedCek = (0, VaultCrypto_1.fromBase64Url)(recipient.ct);
312
- try {
313
- cek = (0, VaultCrypto_1.kemUnwrapCek)(wrappedCek, recipientSecretKey);
314
- }
315
- catch (e) {
316
- throw new errors_1.DecryptKemError('Failed to unwrap CEK - invalid key or corrupted wrap');
317
- }
318
- // Verify key commitment
319
- if (!(0, VaultCrypto_1.verifyKeyCommitment)(cek, (0, VaultCrypto_1.fromBase64Url)(header.kcmp))) {
320
- this.zeroize(cek);
321
- throw new errors_1.DecryptAeadError('Key commitment verification failed');
322
- }
323
- aad = (0, VaultCrypto_1.canonicalAad)({
324
- v: header.v,
325
- suite: header.suite,
326
- aead: header.aead,
327
- docId: header.docId,
328
- vaultId: header.vaultId,
329
- epoch: header.epoch,
330
- policy: header.policy,
331
- });
332
- nonce = (0, VaultCrypto_1.fromBase64Url)(header.nonce);
333
- try {
334
- plaintext = (0, VaultCrypto_1.aesGcmDecrypt)(cek, nonce, ciphertext, aad);
335
- this.zeroize(cek);
336
- return [2 /*return*/, plaintext];
337
- }
338
- catch (e) {
339
- this.zeroize(cek);
340
- throw new errors_1.DecryptAeadError('AEAD decryption failed');
341
- }
342
- return [2 /*return*/];
343
- });
344
- });
49
+ const cek = await this.deriveKeyArgon2(passphrase, salt, argon2Params);
50
+ // 3. Generate nonce (12 bytes for AES-GCM)
51
+ const nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
52
+ // 4. Build document metadata
53
+ const docId = options.docId ?? (0, VaultCrypto_1.generateUuid)();
54
+ const vaultId = options.vaultId ?? docId;
55
+ const epoch = options.epoch ?? 1;
56
+ // 5. Build AAD (spec §5.3)
57
+ const aadFields = {
58
+ v: 1,
59
+ suite: 'S3',
60
+ aead: 'AES-256-GCM',
61
+ docId,
62
+ vaultId,
63
+ epoch,
64
+ policy: { mode: 'passphrase' },
345
65
  };
346
- /**
347
- * Encrypt with all-of policy (spec §6.2)
348
- * Requires ALL listed keys to decrypt via HKDF-join
349
- *
350
- * @param plaintext - Data to encrypt
351
- * @param participants - Array of participant public keys
352
- * @param options - Encryption options
353
- * @returns Encrypted vault document
354
- */
355
- VaultEncryptionService_1.prototype.encryptAllOf = function (plaintext, participants, options) {
356
- var _a, _b;
357
- if (options === void 0) { options = {}; }
358
- return __awaiter(this, void 0, void 0, function () {
359
- var cek, nonce, wrapNonce, docId, vaultId, epoch, keyMaterials, context, wrapKey, wrappedCekResult, aad, encResult, ciphertext, header;
360
- return __generator(this, function (_c) {
361
- if (participants.length < 2) {
362
- throw new errors_1.PolicyError('At least 2 participants required for all-of policy');
363
- }
364
- cek = (0, VaultCrypto_1.generateCek)();
365
- nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
366
- wrapNonce = (0, VaultCrypto_1.generateNonceAesGcm)();
367
- docId = (_a = options.docId) !== null && _a !== void 0 ? _a : (0, VaultCrypto_1.generateUuid)();
368
- vaultId = (_b = options.vaultId) !== null && _b !== void 0 ? _b : docId;
369
- epoch = 1;
370
- keyMaterials = participants.map(function (p) { return ({
371
- kid: p.kid,
372
- key: p.publicKey,
373
- }); });
374
- context = "wrap:doc:".concat(docId, ":epoch:").concat(epoch);
375
- wrapKey = (0, VaultCrypto_1.hkdfJoin)(keyMaterials, context);
376
- wrappedCekResult = (0, VaultCrypto_1.aesGcmEncrypt)(wrapKey, wrapNonce, cek, new Uint8Array(0));
377
- aad = (0, VaultCrypto_1.canonicalAad)({
378
- v: 1,
379
- suite: 'P1',
380
- aead: 'AES-256-GCM',
381
- docId: docId,
382
- vaultId: vaultId,
383
- epoch: epoch,
384
- policy: { mode: 'all-of' },
385
- });
386
- encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
387
- ciphertext = encResult.ciphertext();
388
- header = {
389
- v: 1,
390
- suite: 'P1',
391
- aead: 'AES-256-GCM',
392
- docId: docId,
393
- vaultId: vaultId,
394
- epoch: epoch,
395
- nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
396
- kcmp: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.keyCommitment)(cek)),
397
- policy: { mode: 'all-of' },
398
- wrap_all: {
399
- alg: 'HKDF-join',
400
- kids: participants.map(function (p) { return p.kid; }),
401
- ct: (0, VaultCrypto_1.toBase64Url)(wrappedCekResult.ciphertext()),
402
- },
403
- };
404
- this.zeroize(cek);
405
- this.zeroize(wrapKey);
406
- return [2 /*return*/, { header: header, ciphertext: ciphertext }];
407
- });
408
- });
66
+ const aad = (0, VaultCrypto_1.canonicalAad)(aadFields);
67
+ // 6. Encrypt (spec §9.1 step 3)
68
+ const encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
69
+ const ciphertext = encResult.ciphertext;
70
+ // 7. Compute key commitment (spec §5.1)
71
+ const kcmp = (0, VaultCrypto_1.keyCommitment)(cek);
72
+ // 8. Build header
73
+ const header = {
74
+ v: 1,
75
+ suite: 'S3',
76
+ aead: 'AES-256-GCM',
77
+ docId,
78
+ vaultId,
79
+ epoch,
80
+ nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
81
+ kcmp: (0, VaultCrypto_1.toBase64Url)(kcmp),
82
+ salt: (0, VaultCrypto_1.toBase64Url)(salt),
83
+ argon2: argon2Params,
84
+ policy: { mode: 'passphrase' },
409
85
  };
410
- /**
411
- * Encrypt with threshold policy (spec §6.3)
412
- * Any t-of-n participants can decrypt
413
- *
414
- * @param plaintext - Data to encrypt
415
- * @param threshold - Minimum shares required (t)
416
- * @param participants - Array of participant public keys (n)
417
- * @param options - Encryption options
418
- * @returns Encrypted vault document
419
- */
420
- VaultEncryptionService_1.prototype.encryptThreshold = function (plaintext, threshold, participants, options) {
421
- var _a, _b;
422
- if (options === void 0) { options = {}; }
423
- return __awaiter(this, void 0, void 0, function () {
424
- var n, cek, nonce, docId, vaultId, epoch, shares, thresholdShares, aad, encResult, ciphertext, header, _i, shares_1, share;
425
- return __generator(this, function (_c) {
426
- n = participants.length;
427
- if (threshold < 1 || threshold > n) {
428
- throw new errors_1.PolicyError("Invalid threshold: ".concat(threshold, " of ").concat(n));
429
- }
430
- cek = (0, VaultCrypto_1.generateCek)();
431
- nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
432
- docId = (_a = options.docId) !== null && _a !== void 0 ? _a : (0, VaultCrypto_1.generateUuid)();
433
- vaultId = (_b = options.vaultId) !== null && _b !== void 0 ? _b : docId;
434
- epoch = 1;
435
- shares = (0, VaultCrypto_1.shamirSplit)(cek, threshold, n);
436
- thresholdShares = participants.map(function (p, i) { return ({
437
- kid: p.kid,
438
- enc_share: {
439
- kem: 'ML-KEM-768',
440
- ct: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.kemWrapCek)(shares[i], p.publicKey)),
441
- },
442
- }); });
443
- aad = (0, VaultCrypto_1.canonicalAad)({
444
- v: 1,
445
- suite: 'P1',
446
- aead: 'AES-256-GCM',
447
- docId: docId,
448
- vaultId: vaultId,
449
- epoch: epoch,
450
- policy: { mode: 'threshold', t: threshold, n: n },
451
- });
452
- encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
453
- ciphertext = encResult.ciphertext();
454
- header = {
455
- v: 1,
456
- suite: 'P1',
457
- aead: 'AES-256-GCM',
458
- docId: docId,
459
- vaultId: vaultId,
460
- epoch: epoch,
461
- nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
462
- kcmp: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.keyCommitment)(cek)),
463
- policy: { mode: 'threshold', t: threshold, n: n },
464
- shares: thresholdShares,
465
- };
466
- this.zeroize(cek);
467
- // Zero out shares
468
- for (_i = 0, shares_1 = shares; _i < shares_1.length; _i++) {
469
- share = shares_1[_i];
470
- this.zeroize(share);
471
- }
472
- return [2 /*return*/, { header: header, ciphertext: ciphertext }];
473
- });
474
- });
86
+ // 9. Zero out CEK from memory (security best practice)
87
+ this.zeroize(cek);
88
+ return { header, ciphertext };
89
+ }
90
+ /**
91
+ * Decrypt passphrase-protected vault (S3 suite)
92
+ * All decryption happens CLIENT-SIDE
93
+ *
94
+ * @param vault - Encrypted vault document
95
+ * @param passphrase - User passphrase
96
+ * @returns Decrypted plaintext
97
+ */
98
+ async decryptWithPassphrase(vault, passphrase) {
99
+ const { header, ciphertext } = vault;
100
+ // 1. Validate suite
101
+ if (header.suite !== 'S3' && header.suite !== 'S1') {
102
+ throw new errors_1.BadSuiteError(`Expected S1/S3 suite for passphrase vault, got ${header.suite}`);
103
+ }
104
+ if (!header.salt || !header.argon2) {
105
+ throw new errors_1.PolicyError('Missing salt or argon2 params for passphrase vault');
106
+ }
107
+ // 2. Derive CEK from passphrase
108
+ const salt = (0, VaultCrypto_1.fromBase64Url)(header.salt);
109
+ const cek = await this.deriveKeyArgon2(passphrase, salt, header.argon2);
110
+ // 3. Verify key commitment (spec §9.2 step 3)
111
+ const expectedKcmp = (0, VaultCrypto_1.fromBase64Url)(header.kcmp);
112
+ if (!(0, VaultCrypto_1.verifyKeyCommitment)(cek, expectedKcmp)) {
113
+ this.zeroize(cek);
114
+ throw new errors_1.DecryptAeadError('Key commitment verification failed - wrong passphrase');
115
+ }
116
+ // 4. Rebuild AAD
117
+ const aad = (0, VaultCrypto_1.canonicalAad)({
118
+ v: header.v,
119
+ suite: header.suite,
120
+ aead: header.aead,
121
+ docId: header.docId,
122
+ vaultId: header.vaultId,
123
+ epoch: header.epoch,
124
+ policy: header.policy,
125
+ });
126
+ // 5. Decrypt
127
+ const nonce = (0, VaultCrypto_1.fromBase64Url)(header.nonce);
128
+ try {
129
+ const plaintext = (0, VaultCrypto_1.aesGcmDecrypt)(cek, nonce, ciphertext, aad);
130
+ this.zeroize(cek);
131
+ return plaintext;
132
+ }
133
+ catch (e) {
134
+ this.zeroize(cek);
135
+ throw new errors_1.DecryptAeadError('AEAD decryption failed - data may be corrupted or tampered');
136
+ }
137
+ }
138
+ // ═══════════════════════════════════════════════════════════════════════
139
+ // P1 SUITE (POST-QUANTUM) - For Multi-Party Sharing
140
+ // Spec §4.1: KEM = ML-KEM-768, AEAD = AES-256-GCM
141
+ // ═══════════════════════════════════════════════════════════════════════
142
+ /**
143
+ * Encrypt with any-of policy (spec §6.1)
144
+ * Each recipient gets their own KEM-wrapped CEK
145
+ *
146
+ * @param plaintext - Data to encrypt
147
+ * @param recipients - Array of recipient public keys
148
+ * @param options - Encryption options
149
+ * @returns Encrypted vault document
150
+ */
151
+ async encryptAnyOf(plaintext, recipients, options = {}) {
152
+ if (recipients.length === 0) {
153
+ throw new errors_1.PolicyError('At least one recipient required for any-of policy');
154
+ }
155
+ // 1. Generate random CEK
156
+ const cek = (0, VaultCrypto_1.generateCek)();
157
+ const nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
158
+ const docId = options.docId ?? (0, VaultCrypto_1.generateUuid)();
159
+ const vaultId = options.vaultId ?? docId;
160
+ const epoch = 1;
161
+ // 2. Build AAD
162
+ const aad = (0, VaultCrypto_1.canonicalAad)({
163
+ v: 1,
164
+ suite: 'P1',
165
+ aead: 'AES-256-GCM',
166
+ docId,
167
+ vaultId,
168
+ epoch,
169
+ policy: { mode: 'any-of' },
170
+ });
171
+ // 3. Encrypt plaintext
172
+ const encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
173
+ const ciphertext = encResult.ciphertext;
174
+ // 4. KEM-wrap CEK for each recipient (spec §6.1)
175
+ const recipientWraps = recipients.map((r) => ({
176
+ kid: r.kid,
177
+ kem: 'ML-KEM-768',
178
+ ct: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.kemWrapCek)(cek, r.publicKey)),
179
+ }));
180
+ // 5. Key commitment
181
+ const kcmp = (0, VaultCrypto_1.keyCommitment)(cek);
182
+ // 6. Build header
183
+ const header = {
184
+ v: 1,
185
+ suite: 'P1',
186
+ aead: 'AES-256-GCM',
187
+ docId,
188
+ vaultId,
189
+ epoch,
190
+ nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
191
+ kcmp: (0, VaultCrypto_1.toBase64Url)(kcmp),
192
+ policy: { mode: 'any-of' },
193
+ recipients: recipientWraps,
475
194
  };
476
- /**
477
- * Decrypt threshold vault with collected shares
478
- *
479
- * @param vault - Encrypted vault document
480
- * @param decryptedShares - Array of decrypted shares (at least t shares)
481
- * @returns Decrypted plaintext
482
- */
483
- VaultEncryptionService_1.prototype.decryptThreshold = function (vault, decryptedShares) {
484
- var _a, _b;
485
- return __awaiter(this, void 0, void 0, function () {
486
- var header, ciphertext, threshold, shareData, cek, aad, nonce, plaintext;
487
- return __generator(this, function (_c) {
488
- header = vault.header, ciphertext = vault.ciphertext;
489
- if (((_a = header.policy) === null || _a === void 0 ? void 0 : _a.mode) !== 'threshold') {
490
- throw new errors_1.PolicyError('Not a threshold policy vault');
491
- }
492
- threshold = (_b = header.policy.t) !== null && _b !== void 0 ? _b : 1;
493
- if (decryptedShares.length < threshold) {
494
- throw new errors_1.PolicyError("Need ".concat(threshold, " shares, got ").concat(decryptedShares.length));
495
- }
496
- shareData = decryptedShares.map(function (s) { return ({
497
- index: s.index,
498
- data: s.share,
499
- }); });
500
- cek = (0, VaultCrypto_1.shamirReconstruct)(shareData);
501
- // Verify key commitment
502
- if (!(0, VaultCrypto_1.verifyKeyCommitment)(cek, (0, VaultCrypto_1.fromBase64Url)(header.kcmp))) {
503
- this.zeroize(cek);
504
- throw new errors_1.DecryptAeadError('Key commitment verification failed');
505
- }
506
- aad = (0, VaultCrypto_1.canonicalAad)({
507
- v: header.v,
508
- suite: header.suite,
509
- aead: header.aead,
510
- docId: header.docId,
511
- vaultId: header.vaultId,
512
- epoch: header.epoch,
513
- policy: header.policy,
514
- });
515
- nonce = (0, VaultCrypto_1.fromBase64Url)(header.nonce);
516
- try {
517
- plaintext = (0, VaultCrypto_1.aesGcmDecrypt)(cek, nonce, ciphertext, aad);
518
- this.zeroize(cek);
519
- return [2 /*return*/, plaintext];
520
- }
521
- catch (e) {
522
- this.zeroize(cek);
523
- throw new errors_1.DecryptAeadError('AEAD decryption failed');
524
- }
525
- return [2 /*return*/];
526
- });
527
- });
195
+ this.zeroize(cek);
196
+ return { header, ciphertext };
197
+ }
198
+ /**
199
+ * Decrypt any-of vault (spec §9.2)
200
+ * Try the specified recipient's wrap
201
+ *
202
+ * @param vault - Encrypted vault document
203
+ * @param recipientSecretKey - Recipient's ML-KEM secret key
204
+ * @param recipientKid - Recipient's key identifier
205
+ * @returns Decrypted plaintext
206
+ */
207
+ async decryptAnyOf(vault, recipientSecretKey, recipientKid) {
208
+ const { header, ciphertext } = vault;
209
+ if (header.policy?.mode !== 'any-of' || !header.recipients) {
210
+ throw new errors_1.PolicyError('Not an any-of policy vault');
211
+ }
212
+ // Find matching recipient
213
+ const recipient = header.recipients.find((r) => r.kid === recipientKid);
214
+ if (!recipient) {
215
+ throw new errors_1.DecryptKemError(`No recipient wrap found for kid: ${recipientKid}`);
216
+ }
217
+ // Unwrap CEK
218
+ const wrappedCek = (0, VaultCrypto_1.fromBase64Url)(recipient.ct);
219
+ let cek;
220
+ try {
221
+ cek = (0, VaultCrypto_1.kemUnwrapCek)(wrappedCek, recipientSecretKey);
222
+ }
223
+ catch (e) {
224
+ throw new errors_1.DecryptKemError('Failed to unwrap CEK - invalid key or corrupted wrap');
225
+ }
226
+ // Verify key commitment
227
+ if (!(0, VaultCrypto_1.verifyKeyCommitment)(cek, (0, VaultCrypto_1.fromBase64Url)(header.kcmp))) {
228
+ this.zeroize(cek);
229
+ throw new errors_1.DecryptAeadError('Key commitment verification failed');
230
+ }
231
+ // Decrypt
232
+ const aad = (0, VaultCrypto_1.canonicalAad)({
233
+ v: header.v,
234
+ suite: header.suite,
235
+ aead: header.aead,
236
+ docId: header.docId,
237
+ vaultId: header.vaultId,
238
+ epoch: header.epoch,
239
+ policy: header.policy,
240
+ });
241
+ const nonce = (0, VaultCrypto_1.fromBase64Url)(header.nonce);
242
+ try {
243
+ const plaintext = (0, VaultCrypto_1.aesGcmDecrypt)(cek, nonce, ciphertext, aad);
244
+ this.zeroize(cek);
245
+ return plaintext;
246
+ }
247
+ catch (e) {
248
+ this.zeroize(cek);
249
+ throw new errors_1.DecryptAeadError('AEAD decryption failed');
250
+ }
251
+ }
252
+ /**
253
+ * Encrypt with all-of policy (spec §6.2)
254
+ * Requires ALL listed keys to decrypt via HKDF-join
255
+ *
256
+ * @param plaintext - Data to encrypt
257
+ * @param participants - Array of participant public keys
258
+ * @param options - Encryption options
259
+ * @returns Encrypted vault document
260
+ */
261
+ async encryptAllOf(plaintext, participants, options = {}) {
262
+ if (participants.length < 2) {
263
+ throw new errors_1.PolicyError('At least 2 participants required for all-of policy');
264
+ }
265
+ // 1. Generate random CEK
266
+ const cek = (0, VaultCrypto_1.generateCek)();
267
+ const nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
268
+ const wrapNonce = (0, VaultCrypto_1.generateNonceAesGcm)();
269
+ const docId = options.docId ?? (0, VaultCrypto_1.generateUuid)();
270
+ const vaultId = options.vaultId ?? docId;
271
+ const epoch = 1;
272
+ // 2. Derive joint wrap key via HKDF-join (spec §6.2)
273
+ const keyMaterials = participants.map((p) => ({
274
+ kid: p.kid,
275
+ key: p.publicKey,
276
+ }));
277
+ const context = `wrap:doc:${docId}:epoch:${epoch}`;
278
+ const wrapKey = (0, VaultCrypto_1.hkdfJoin)(keyMaterials, context);
279
+ // 3. Wrap CEK under joint key
280
+ const wrappedCekResult = (0, VaultCrypto_1.aesGcmEncrypt)(wrapKey, wrapNonce, cek, new Uint8Array(0));
281
+ // 4. Build AAD and encrypt plaintext
282
+ const aad = (0, VaultCrypto_1.canonicalAad)({
283
+ v: 1,
284
+ suite: 'P1',
285
+ aead: 'AES-256-GCM',
286
+ docId,
287
+ vaultId,
288
+ epoch,
289
+ policy: { mode: 'all-of' },
290
+ });
291
+ const encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
292
+ const ciphertext = encResult.ciphertext;
293
+ // 5. Build header
294
+ const header = {
295
+ v: 1,
296
+ suite: 'P1',
297
+ aead: 'AES-256-GCM',
298
+ docId,
299
+ vaultId,
300
+ epoch,
301
+ nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
302
+ kcmp: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.keyCommitment)(cek)),
303
+ policy: { mode: 'all-of' },
304
+ wrap_all: {
305
+ alg: 'HKDF-join',
306
+ kids: participants.map((p) => p.kid),
307
+ ct: (0, VaultCrypto_1.toBase64Url)(wrappedCekResult.ciphertext),
308
+ },
528
309
  };
529
- /**
530
- * Unwrap a single threshold share for a participant
531
- *
532
- * @param vault - Encrypted vault document
533
- * @param participantSecretKey - Participant's ML-KEM secret key
534
- * @param participantKid - Participant's key identifier
535
- * @returns Decrypted share with its index
536
- */
537
- VaultEncryptionService_1.prototype.unwrapThresholdShare = function (vault, participantSecretKey, participantKid) {
538
- var _a;
539
- return __awaiter(this, void 0, void 0, function () {
540
- var header, shareIndex, shareEntry, wrappedShare, share;
541
- return __generator(this, function (_b) {
542
- header = vault.header;
543
- if (((_a = header.policy) === null || _a === void 0 ? void 0 : _a.mode) !== 'threshold' || !header.shares) {
544
- throw new errors_1.PolicyError('Not a threshold policy vault');
545
- }
546
- shareIndex = header.shares.findIndex(function (s) { return s.kid === participantKid; });
547
- if (shareIndex === -1) {
548
- throw new errors_1.DecryptKemError("No share found for kid: ".concat(participantKid));
549
- }
550
- shareEntry = header.shares[shareIndex];
551
- wrappedShare = (0, VaultCrypto_1.fromBase64Url)(shareEntry.enc_share.ct);
552
- try {
553
- share = (0, VaultCrypto_1.kemUnwrapCek)(wrappedShare, participantSecretKey);
554
- }
555
- catch (e) {
556
- throw new errors_1.DecryptKemError('Failed to unwrap share - invalid key');
557
- }
558
- // Return with 1-based index (Shamir convention)
559
- return [2 /*return*/, {
560
- index: shareIndex + 1,
561
- share: share,
562
- }];
563
- });
564
- });
310
+ this.zeroize(cek);
311
+ this.zeroize(wrapKey);
312
+ return { header, ciphertext };
313
+ }
314
+ /**
315
+ * Encrypt with threshold policy (spec §6.3)
316
+ * Any t-of-n participants can decrypt
317
+ *
318
+ * @param plaintext - Data to encrypt
319
+ * @param threshold - Minimum shares required (t)
320
+ * @param participants - Array of participant public keys (n)
321
+ * @param options - Encryption options
322
+ * @returns Encrypted vault document
323
+ */
324
+ async encryptThreshold(plaintext, threshold, participants, options = {}) {
325
+ const n = participants.length;
326
+ if (threshold < 1 || threshold > n) {
327
+ throw new errors_1.PolicyError(`Invalid threshold: ${threshold} of ${n}`);
328
+ }
329
+ // 1. Generate CEK
330
+ const cek = (0, VaultCrypto_1.generateCek)();
331
+ const nonce = (0, VaultCrypto_1.generateNonceAesGcm)();
332
+ const docId = options.docId ?? (0, VaultCrypto_1.generateUuid)();
333
+ const vaultId = options.vaultId ?? docId;
334
+ const epoch = 1;
335
+ // 2. Split CEK using Shamir (spec §6.3)
336
+ const shares = (0, VaultCrypto_1.shamirSplit)(cek, threshold, n);
337
+ // 3. KEM-wrap each share for its participant
338
+ // shares[i] is a SecretShare object with .identifier and .value properties
339
+ const thresholdShares = participants.map((p, i) => ({
340
+ kid: p.kid,
341
+ enc_share: {
342
+ kem: 'ML-KEM-768',
343
+ ct: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.kemWrapCek)(shares[i].value, p.publicKey)),
344
+ },
345
+ }));
346
+ // 4. Encrypt plaintext
347
+ const aad = (0, VaultCrypto_1.canonicalAad)({
348
+ v: 1,
349
+ suite: 'P1',
350
+ aead: 'AES-256-GCM',
351
+ docId,
352
+ vaultId,
353
+ epoch,
354
+ policy: { mode: 'threshold', t: threshold, n },
355
+ });
356
+ const encResult = (0, VaultCrypto_1.aesGcmEncrypt)(cek, nonce, plaintext, aad);
357
+ const ciphertext = encResult.ciphertext;
358
+ // 5. Build header
359
+ const header = {
360
+ v: 1,
361
+ suite: 'P1',
362
+ aead: 'AES-256-GCM',
363
+ docId,
364
+ vaultId,
365
+ epoch,
366
+ nonce: (0, VaultCrypto_1.toBase64Url)(nonce),
367
+ kcmp: (0, VaultCrypto_1.toBase64Url)((0, VaultCrypto_1.keyCommitment)(cek)),
368
+ policy: { mode: 'threshold', t: threshold, n },
369
+ shares: thresholdShares,
565
370
  };
566
- // ═══════════════════════════════════════════════════════════════════════
567
- // HELPER METHODS
568
- // ═══════════════════════════════════════════════════════════════════════
569
- /**
570
- * Derive key from passphrase using Argon2id
571
- * Spec §4.1 S1/S3 suite
572
- */
573
- VaultEncryptionService_1.prototype.deriveKeyArgon2 = function (passphrase, salt, params) {
574
- return __awaiter(this, void 0, void 0, function () {
575
- var hash;
576
- return __generator(this, function (_a) {
577
- switch (_a.label) {
578
- case 0: return [4 /*yield*/, (0, hash_wasm_1.argon2id)({
579
- password: passphrase,
580
- salt: salt,
581
- parallelism: params.parallelism,
582
- iterations: params.iterations,
583
- memorySize: params.memory,
584
- hashLength: 32,
585
- outputType: 'binary',
586
- })];
587
- case 1:
588
- hash = _a.sent();
589
- return [2 /*return*/, new Uint8Array(hash)];
590
- }
591
- });
371
+ this.zeroize(cek);
372
+ // Note: shares from shamirSplit are SecretShare objects, not raw Uint8Arrays
373
+ // Their internal data is already handled by the WASM module
374
+ return { header, ciphertext };
375
+ }
376
+ /**
377
+ * Decrypt threshold vault with collected shares
378
+ *
379
+ * @param vault - Encrypted vault document
380
+ * @param decryptedShares - Array of decrypted shares (at least t shares)
381
+ * @returns Decrypted plaintext
382
+ */
383
+ async decryptThreshold(vault, decryptedShares) {
384
+ const { header, ciphertext } = vault;
385
+ if (header.policy?.mode !== 'threshold') {
386
+ throw new errors_1.PolicyError('Not a threshold policy vault');
387
+ }
388
+ const threshold = header.policy.t ?? 1;
389
+ if (decryptedShares.length < threshold) {
390
+ throw new errors_1.PolicyError(`Need ${threshold} shares, got ${decryptedShares.length}`);
391
+ }
392
+ // Reconstruct CEK from shares
393
+ // Convert DecryptedShare to SecretShare objects expected by WASM
394
+ const shareObjects = decryptedShares.map((s) => {
395
+ // SecretShare.fromJson expects {identifier, value} format
396
+ const json = JSON.stringify({
397
+ identifier: s.index,
398
+ value: Array.from(s.share),
592
399
  });
400
+ return VaultCrypto_1.SecretShare.fromJson(json);
401
+ });
402
+ const cek = (0, VaultCrypto_1.shamirReconstruct)(shareObjects);
403
+ // Verify key commitment
404
+ if (!(0, VaultCrypto_1.verifyKeyCommitment)(cek, (0, VaultCrypto_1.fromBase64Url)(header.kcmp))) {
405
+ this.zeroize(cek);
406
+ throw new errors_1.DecryptAeadError('Key commitment verification failed');
407
+ }
408
+ // Decrypt
409
+ const aad = (0, VaultCrypto_1.canonicalAad)({
410
+ v: header.v,
411
+ suite: header.suite,
412
+ aead: header.aead,
413
+ docId: header.docId,
414
+ vaultId: header.vaultId,
415
+ epoch: header.epoch,
416
+ policy: header.policy,
417
+ });
418
+ const nonce = (0, VaultCrypto_1.fromBase64Url)(header.nonce);
419
+ try {
420
+ const plaintext = (0, VaultCrypto_1.aesGcmDecrypt)(cek, nonce, ciphertext, aad);
421
+ this.zeroize(cek);
422
+ return plaintext;
423
+ }
424
+ catch (e) {
425
+ this.zeroize(cek);
426
+ throw new errors_1.DecryptAeadError('AEAD decryption failed');
427
+ }
428
+ }
429
+ /**
430
+ * Unwrap a single threshold share for a participant
431
+ *
432
+ * @param vault - Encrypted vault document
433
+ * @param participantSecretKey - Participant's ML-KEM secret key
434
+ * @param participantKid - Participant's key identifier
435
+ * @returns Decrypted share with its index
436
+ */
437
+ async unwrapThresholdShare(vault, participantSecretKey, participantKid) {
438
+ const { header } = vault;
439
+ if (header.policy?.mode !== 'threshold' || !header.shares) {
440
+ throw new errors_1.PolicyError('Not a threshold policy vault');
441
+ }
442
+ // Find the participant's share
443
+ const shareIndex = header.shares.findIndex((s) => s.kid === participantKid);
444
+ if (shareIndex === -1) {
445
+ throw new errors_1.DecryptKemError(`No share found for kid: ${participantKid}`);
446
+ }
447
+ const shareEntry = header.shares[shareIndex];
448
+ const wrappedShare = (0, VaultCrypto_1.fromBase64Url)(shareEntry.enc_share.ct);
449
+ // Unwrap the share
450
+ let share;
451
+ try {
452
+ share = (0, VaultCrypto_1.kemUnwrapCek)(wrappedShare, participantSecretKey);
453
+ }
454
+ catch (e) {
455
+ throw new errors_1.DecryptKemError('Failed to unwrap share - invalid key');
456
+ }
457
+ // Return with 1-based index (Shamir convention)
458
+ return {
459
+ index: shareIndex + 1,
460
+ share,
593
461
  };
594
- /**
595
- * Zero out sensitive data from memory
596
- * Security best practice to minimize exposure window
597
- */
598
- VaultEncryptionService_1.prototype.zeroize = function (data) {
599
- data.fill(0);
600
- };
601
- return VaultEncryptionService_1;
602
- }());
603
- __setFunctionName(_classThis, "VaultEncryptionService");
604
- (function () {
605
- var _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
606
- __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
607
- VaultEncryptionService = _classThis = _classDescriptor.value;
608
- if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
609
- __runInitializers(_classThis, _classExtraInitializers);
610
- })();
611
- return VaultEncryptionService = _classThis;
612
- }();
462
+ }
463
+ // ═══════════════════════════════════════════════════════════════════════
464
+ // HELPER METHODS
465
+ // ═══════════════════════════════════════════════════════════════════════
466
+ /**
467
+ * Derive key from passphrase using Argon2id
468
+ * Spec §4.1 S1/S3 suite
469
+ */
470
+ async deriveKeyArgon2(passphrase, salt, params) {
471
+ const hash = await (0, hash_wasm_1.argon2id)({
472
+ password: passphrase,
473
+ salt,
474
+ parallelism: params.parallelism,
475
+ iterations: params.iterations,
476
+ memorySize: params.memory,
477
+ hashLength: 32,
478
+ outputType: 'binary',
479
+ });
480
+ return new Uint8Array(hash);
481
+ }
482
+ /**
483
+ * Zero out sensitive data from memory
484
+ * Security best practice to minimize exposure window
485
+ */
486
+ zeroize(data) {
487
+ data.fill(0);
488
+ }
489
+ };
613
490
  exports.VaultEncryptionService = VaultEncryptionService;
491
+ exports.VaultEncryptionService = VaultEncryptionService = __decorate([
492
+ (0, core_1.injectable)()
493
+ ], VaultEncryptionService);
494
+ //# sourceMappingURL=VaultEncryptionService.js.map