@sd-jwt/core 0.1.0 → 0.1.1-next.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 (170) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/LICENSE +201 -0
  3. package/README.md +106 -0
  4. package/dist/index.d.mts +659 -0
  5. package/dist/index.d.ts +659 -0
  6. package/dist/index.js +1906 -0
  7. package/dist/index.mjs +1846 -0
  8. package/package.json +59 -47
  9. package/src/decode/decode.ts +376 -0
  10. package/src/decode/index.ts +1 -0
  11. package/src/decoy.ts +15 -0
  12. package/src/flattenJSON.ts +99 -0
  13. package/src/generalJSON.ts +148 -0
  14. package/src/index.ts +945 -0
  15. package/src/jwt.ts +190 -0
  16. package/src/kbjwt.ts +81 -0
  17. package/src/present/index.ts +1 -0
  18. package/src/present/present.ts +210 -0
  19. package/src/sdjwt.ts +354 -0
  20. package/src/test/decode/decode.spec.ts +202 -0
  21. package/src/test/decoy.spec.ts +30 -0
  22. package/src/test/flattenJSON.spec.ts +122 -0
  23. package/src/test/generalJSON.spec.ts +198 -0
  24. package/src/test/index.spec.ts +974 -0
  25. package/src/test/jwt.spec.ts +301 -0
  26. package/src/test/kbjwt.spec.ts +565 -0
  27. package/src/test/pass.spec.ts +7 -0
  28. package/src/test/present/present.spec.ts +305 -0
  29. package/src/test/sdjwt.spec.ts +384 -0
  30. package/src/test/types/type.spec.ts +88 -0
  31. package/src/test/utils/base64url.spec.ts +33 -0
  32. package/src/test/utils/disclosure.spec.ts +170 -0
  33. package/src/test/utils/error.spec.ts +15 -0
  34. package/src/types/index.ts +2 -0
  35. package/src/types/type.ts +249 -0
  36. package/src/types/verification-error.ts +55 -0
  37. package/src/utils/base64url.ts +6 -0
  38. package/src/utils/disclosure.ts +101 -0
  39. package/src/utils/error.ts +25 -0
  40. package/src/utils/index.ts +3 -0
  41. package/src/utils/strict-json.ts +17 -0
  42. package/test/app-e2e.spec.ts +292 -0
  43. package/test/array_data_types.json +31 -0
  44. package/test/array_full_sd.json +21 -0
  45. package/test/array_in_sd.json +13 -0
  46. package/test/array_nested_in_plain.json +29 -0
  47. package/test/array_none_disclosed.json +17 -0
  48. package/test/array_of_nulls.json +15 -0
  49. package/test/array_of_objects.json +65 -0
  50. package/test/array_of_scalars.json +19 -0
  51. package/test/array_recursive_sd.json +35 -0
  52. package/test/array_recursive_sd_some_disclosed.json +63 -0
  53. package/test/complex.json +43 -0
  54. package/test/header_mod.json +48 -0
  55. package/test/json_serialization.json +48 -0
  56. package/test/key_binding.json +48 -0
  57. package/test/no_sd.json +36 -0
  58. package/test/object_data_types.json +62 -0
  59. package/test/recursions.json +117 -0
  60. package/test/rfc9901-validation.spec.ts +150 -0
  61. package/tsconfig.json +7 -0
  62. package/vitest.config.mts +4 -0
  63. package/build/base64url.d.ts +0 -28
  64. package/build/base64url.js +0 -40
  65. package/build/base64url.js.map +0 -1
  66. package/build/hasherAlgorithm.d.ts +0 -70
  67. package/build/hasherAlgorithm.js +0 -75
  68. package/build/hasherAlgorithm.js.map +0 -1
  69. package/build/index.d.ts +0 -11
  70. package/build/index.js +0 -20
  71. package/build/index.js.map +0 -1
  72. package/build/jwt/compact.d.ts +0 -6
  73. package/build/jwt/compact.js +0 -27
  74. package/build/jwt/compact.js.map +0 -1
  75. package/build/jwt/error.d.ts +0 -2
  76. package/build/jwt/error.js +0 -7
  77. package/build/jwt/error.js.map +0 -1
  78. package/build/jwt/index.d.ts +0 -3
  79. package/build/jwt/index.js +0 -20
  80. package/build/jwt/index.js.map +0 -1
  81. package/build/jwt/jwt.d.ts +0 -204
  82. package/build/jwt/jwt.js +0 -324
  83. package/build/jwt/jwt.js.map +0 -1
  84. package/build/keyBinding/index.d.ts +0 -1
  85. package/build/keyBinding/index.js +0 -18
  86. package/build/keyBinding/index.js.map +0 -1
  87. package/build/keyBinding/keyBinding.d.ts +0 -56
  88. package/build/keyBinding/keyBinding.js +0 -99
  89. package/build/keyBinding/keyBinding.js.map +0 -1
  90. package/build/sdJwt/compact.d.ts +0 -8
  91. package/build/sdJwt/compact.js +0 -39
  92. package/build/sdJwt/compact.js.map +0 -1
  93. package/build/sdJwt/decoys.d.ts +0 -2
  94. package/build/sdJwt/decoys.js +0 -35
  95. package/build/sdJwt/decoys.js.map +0 -1
  96. package/build/sdJwt/disclosureFrame.d.ts +0 -7
  97. package/build/sdJwt/disclosureFrame.js +0 -89
  98. package/build/sdJwt/disclosureFrame.js.map +0 -1
  99. package/build/sdJwt/disclosureMapping.d.ts +0 -44
  100. package/build/sdJwt/disclosureMapping.js +0 -289
  101. package/build/sdJwt/disclosureMapping.js.map +0 -1
  102. package/build/sdJwt/disclosures.d.ts +0 -14
  103. package/build/sdJwt/disclosures.js +0 -59
  104. package/build/sdJwt/disclosures.js.map +0 -1
  105. package/build/sdJwt/error.d.ts +0 -2
  106. package/build/sdJwt/error.js +0 -7
  107. package/build/sdJwt/error.js.map +0 -1
  108. package/build/sdJwt/index.d.ts +0 -7
  109. package/build/sdJwt/index.js +0 -24
  110. package/build/sdJwt/index.js.map +0 -1
  111. package/build/sdJwt/presentationFrame.d.ts +0 -4
  112. package/build/sdJwt/presentationFrame.js +0 -73
  113. package/build/sdJwt/presentationFrame.js.map +0 -1
  114. package/build/sdJwt/sdJwt.d.ts +0 -204
  115. package/build/sdJwt/sdJwt.js +0 -383
  116. package/build/sdJwt/sdJwt.js.map +0 -1
  117. package/build/sdJwt/swapClaim.d.ts +0 -3
  118. package/build/sdJwt/swapClaim.js +0 -90
  119. package/build/sdJwt/swapClaim.js.map +0 -1
  120. package/build/sdJwt/types.d.ts +0 -5
  121. package/build/sdJwt/types.js +0 -3
  122. package/build/sdJwt/types.js.map +0 -1
  123. package/build/sdJwtVc/error.d.ts +0 -2
  124. package/build/sdJwtVc/error.js +0 -7
  125. package/build/sdJwtVc/error.js.map +0 -1
  126. package/build/sdJwtVc/index.d.ts +0 -2
  127. package/build/sdJwtVc/index.js +0 -19
  128. package/build/sdJwtVc/index.js.map +0 -1
  129. package/build/sdJwtVc/sdJwtVc.d.ts +0 -47
  130. package/build/sdJwtVc/sdJwtVc.js +0 -125
  131. package/build/sdJwtVc/sdJwtVc.js.map +0 -1
  132. package/build/signatureAndEncryptionAlgorithm.d.ts +0 -105
  133. package/build/signatureAndEncryptionAlgorithm.js +0 -110
  134. package/build/signatureAndEncryptionAlgorithm.js.map +0 -1
  135. package/build/types/disclosure.d.ts +0 -5
  136. package/build/types/disclosure.js +0 -3
  137. package/build/types/disclosure.js.map +0 -1
  138. package/build/types/frame.d.ts +0 -5
  139. package/build/types/frame.js +0 -3
  140. package/build/types/frame.js.map +0 -1
  141. package/build/types/hasher.d.ts +0 -14
  142. package/build/types/hasher.js +0 -3
  143. package/build/types/hasher.js.map +0 -1
  144. package/build/types/index.d.ts +0 -6
  145. package/build/types/index.js +0 -23
  146. package/build/types/index.js.map +0 -1
  147. package/build/types/present.d.ts +0 -2
  148. package/build/types/present.js +0 -3
  149. package/build/types/present.js.map +0 -1
  150. package/build/types/saltGenerator.d.ts +0 -17
  151. package/build/types/saltGenerator.js +0 -3
  152. package/build/types/saltGenerator.js.map +0 -1
  153. package/build/types/signer.d.ts +0 -2
  154. package/build/types/signer.js +0 -3
  155. package/build/types/signer.js.map +0 -1
  156. package/build/types/utils.d.ts +0 -5
  157. package/build/types/utils.js +0 -3
  158. package/build/types/utils.js.map +0 -1
  159. package/build/types/verifier.d.ts +0 -14
  160. package/build/types/verifier.js +0 -3
  161. package/build/types/verifier.js.map +0 -1
  162. package/build/utils/index.d.ts +0 -2
  163. package/build/utils/index.js +0 -19
  164. package/build/utils/index.js.map +0 -1
  165. package/build/utils/traverse.d.ts +0 -8
  166. package/build/utils/traverse.js +0 -29
  167. package/build/utils/traverse.js.map +0 -1
  168. package/build/utils/utils.d.ts +0 -7
  169. package/build/utils/utils.js +0 -109
  170. package/build/utils/utils.js.map +0 -1
package/dist/index.mjs ADDED
@@ -0,0 +1,1846 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+ var __async = (__this, __arguments, generator) => {
33
+ return new Promise((resolve, reject) => {
34
+ var fulfilled = (value) => {
35
+ try {
36
+ step(generator.next(value));
37
+ } catch (e) {
38
+ reject(e);
39
+ }
40
+ };
41
+ var rejected = (value) => {
42
+ try {
43
+ step(generator.throw(value));
44
+ } catch (e) {
45
+ reject(e);
46
+ }
47
+ };
48
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
49
+ step((generator = generator.apply(__this, __arguments)).next());
50
+ });
51
+ };
52
+
53
+ // src/types/type.ts
54
+ var SD_SEPARATOR = "~";
55
+ var SD_LIST_KEY = "...";
56
+ var SD_DIGEST = "_sd";
57
+ var SD_DECOY = "_sd_decoy";
58
+ var KB_JWT_TYP = "kb+jwt";
59
+ var IANA_HASH_ALGORITHMS = [
60
+ "sha-256",
61
+ "sha-256-128",
62
+ "sha-256-120",
63
+ "sha-256-96",
64
+ "sha-256-64",
65
+ "sha-256-32",
66
+ "sha-384",
67
+ "sha-512",
68
+ "sha3-224",
69
+ "sha3-256",
70
+ "sha3-384",
71
+ "sha3-512",
72
+ "blake2s-256",
73
+ "blake2b-256",
74
+ "blake2b-512",
75
+ "k12-256",
76
+ "k12-512"
77
+ ];
78
+
79
+ // src/utils/base64url.ts
80
+ import {
81
+ base64UrlToUint8Array,
82
+ base64urlDecode,
83
+ base64urlEncode,
84
+ uint8ArrayToBase64Url
85
+ } from "@owf/identity-common";
86
+
87
+ // src/utils/error.ts
88
+ var SDJWTException = class _SDJWTException extends Error {
89
+ constructor(message, details) {
90
+ super(message);
91
+ Object.setPrototypeOf(this, _SDJWTException.prototype);
92
+ this.name = "SDJWTException";
93
+ this.details = details;
94
+ }
95
+ getFullMessage() {
96
+ return `${this.name}: ${this.message} ${this.details ? `- ${JSON.stringify(this.details)}` : ""}`;
97
+ }
98
+ };
99
+ function ensureError(value) {
100
+ if (value instanceof Error) return value;
101
+ if (typeof value === "string") return new Error(value);
102
+ return new Error(String(value));
103
+ }
104
+
105
+ // src/utils/strict-json.ts
106
+ var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
107
+ var decodeBase64urlJsonStrict = (encoded, errorMessage) => {
108
+ try {
109
+ const bytes = base64UrlToUint8Array(encoded);
110
+ const decoded = utf8Decoder.decode(bytes);
111
+ return JSON.parse(decoded);
112
+ } catch (e) {
113
+ throw new SDJWTException(errorMessage);
114
+ }
115
+ };
116
+
117
+ // src/utils/disclosure.ts
118
+ var Disclosure = class _Disclosure {
119
+ constructor(data, _meta) {
120
+ this._digest = _meta == null ? void 0 : _meta.digest;
121
+ this._encoded = _meta == null ? void 0 : _meta.encoded;
122
+ if (data.length === 2) {
123
+ this.salt = data[0];
124
+ this.value = data[1];
125
+ return;
126
+ }
127
+ if (data.length === 3) {
128
+ this.salt = data[0];
129
+ this.key = data[1];
130
+ this.value = data[2];
131
+ return;
132
+ }
133
+ throw new SDJWTException("Invalid disclosure data");
134
+ }
135
+ // We need to digest of the original encoded data.
136
+ // After decode process, we use JSON.stringify to encode the data.
137
+ // This can be different from the original encoded data.
138
+ static fromEncode(s, hash) {
139
+ return __async(this, null, function* () {
140
+ const { hasher, alg } = hash;
141
+ const digest = yield hasher(s, alg);
142
+ const digestStr = uint8ArrayToBase64Url(digest);
143
+ const item = decodeBase64urlJsonStrict(
144
+ s,
145
+ "Invalid disclosure data"
146
+ );
147
+ return _Disclosure.fromArray(item, { digest: digestStr, encoded: s });
148
+ });
149
+ }
150
+ static fromEncodeSync(s, hash) {
151
+ const { hasher, alg } = hash;
152
+ const digest = hasher(s, alg);
153
+ const digestStr = uint8ArrayToBase64Url(digest);
154
+ const item = decodeBase64urlJsonStrict(
155
+ s,
156
+ "Invalid disclosure data"
157
+ );
158
+ return _Disclosure.fromArray(item, { digest: digestStr, encoded: s });
159
+ }
160
+ static fromArray(item, _meta) {
161
+ return new _Disclosure(item, _meta);
162
+ }
163
+ encode() {
164
+ if (!this._encoded) {
165
+ this._encoded = base64urlEncode(JSON.stringify(this.decode()));
166
+ }
167
+ return this._encoded;
168
+ }
169
+ decode() {
170
+ return this.key ? [this.salt, this.key, this.value] : [this.salt, this.value];
171
+ }
172
+ digest(hash) {
173
+ return __async(this, null, function* () {
174
+ const { hasher, alg } = hash;
175
+ if (!this._digest) {
176
+ const hash2 = yield hasher(this.encode(), alg);
177
+ this._digest = uint8ArrayToBase64Url(hash2);
178
+ }
179
+ return this._digest;
180
+ });
181
+ }
182
+ digestSync(hash) {
183
+ const { hasher, alg } = hash;
184
+ if (!this._digest) {
185
+ const hash2 = hasher(this.encode(), alg);
186
+ this._digest = uint8ArrayToBase64Url(hash2);
187
+ }
188
+ return this._digest;
189
+ }
190
+ };
191
+
192
+ // src/decode/decode.ts
193
+ var decodeJwt = (jwt) => {
194
+ const { 0: header, 1: payload, 2: signature, length } = jwt.split(".");
195
+ if (length !== 3) {
196
+ throw new SDJWTException("Invalid JWT as input");
197
+ }
198
+ return {
199
+ header: decodeBase64urlJsonStrict(header, "Invalid JWT as input"),
200
+ payload: decodeBase64urlJsonStrict(payload, "Invalid JWT as input"),
201
+ signature
202
+ };
203
+ };
204
+ var splitSdJwt = (sdjwt) => {
205
+ const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
206
+ if (encodedDisclosures.length === 0) {
207
+ return {
208
+ jwt: encodedJwt,
209
+ disclosures: []
210
+ };
211
+ }
212
+ const encodedKeyBindingJwt = encodedDisclosures.pop();
213
+ return {
214
+ jwt: encodedJwt,
215
+ disclosures: encodedDisclosures,
216
+ kbJwt: encodedKeyBindingJwt || void 0
217
+ };
218
+ };
219
+ var decodeSdJwt = (sdjwt, hasher) => __async(null, null, function* () {
220
+ const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
221
+ const jwt = decodeJwt(encodedJwt);
222
+ if (encodedDisclosures.length === 0) {
223
+ return {
224
+ jwt,
225
+ disclosures: []
226
+ };
227
+ }
228
+ const encodedKeyBindingJwt = encodedDisclosures.pop();
229
+ const kbJwt = encodedKeyBindingJwt ? decodeJwt(encodedKeyBindingJwt) : void 0;
230
+ const { _sd_alg } = getSDAlgAndPayload(jwt.payload);
231
+ const disclosures = yield Promise.all(
232
+ encodedDisclosures.map(
233
+ (ed) => Disclosure.fromEncode(ed, { alg: _sd_alg, hasher })
234
+ )
235
+ );
236
+ return {
237
+ jwt,
238
+ disclosures,
239
+ kbJwt
240
+ };
241
+ });
242
+ var decodeSdJwtSync = (sdjwt, hasher) => {
243
+ const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
244
+ const jwt = decodeJwt(encodedJwt);
245
+ if (encodedDisclosures.length === 0) {
246
+ return {
247
+ jwt,
248
+ disclosures: []
249
+ };
250
+ }
251
+ const encodedKeyBindingJwt = encodedDisclosures.pop();
252
+ const kbJwt = encodedKeyBindingJwt ? decodeJwt(encodedKeyBindingJwt) : void 0;
253
+ const { _sd_alg } = getSDAlgAndPayload(jwt.payload);
254
+ const disclosures = encodedDisclosures.map(
255
+ (ed) => Disclosure.fromEncodeSync(ed, { alg: _sd_alg, hasher })
256
+ );
257
+ return {
258
+ jwt,
259
+ disclosures,
260
+ kbJwt
261
+ };
262
+ };
263
+ var getClaims = (rawPayload, disclosures, hasher) => __async(null, null, function* () {
264
+ const { unpackedObj } = yield unpack(rawPayload, disclosures, hasher);
265
+ return unpackedObj;
266
+ });
267
+ var getClaimsSync = (rawPayload, disclosures, hasher) => {
268
+ const { unpackedObj } = unpackSync(rawPayload, disclosures, hasher);
269
+ return unpackedObj;
270
+ };
271
+ var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
272
+ var unpackArray = (arr, map, prefix = "", seenDigests) => {
273
+ const keys = {};
274
+ const unpackedArray = [];
275
+ arr.forEach((item, idx) => {
276
+ if (isRecord(item)) {
277
+ const hash = item[SD_LIST_KEY];
278
+ if (typeof hash === "string") {
279
+ if (seenDigests) {
280
+ if (seenDigests.has(hash)) {
281
+ throw new SDJWTException(
282
+ "Duplicate digest found in SD-JWT payload"
283
+ );
284
+ }
285
+ seenDigests.add(hash);
286
+ }
287
+ const disclosed = map[hash];
288
+ if (disclosed) {
289
+ const presentKey = prefix ? `${prefix}.${idx}` : `${idx}`;
290
+ keys[presentKey] = hash;
291
+ const { unpackedObj, disclosureKeymap: disclosureKeys } = unpackObjInternal(disclosed.value, map, presentKey, seenDigests);
292
+ unpackedArray.push(unpackedObj);
293
+ Object.assign(keys, disclosureKeys);
294
+ }
295
+ } else {
296
+ const newKey = prefix ? `${prefix}.${idx}` : `${idx}`;
297
+ const { unpackedObj, disclosureKeymap: disclosureKeys } = unpackObjInternal(item, map, newKey, seenDigests);
298
+ unpackedArray.push(unpackedObj);
299
+ Object.assign(keys, disclosureKeys);
300
+ }
301
+ } else if (Array.isArray(item)) {
302
+ const newKey = prefix ? `${prefix}.${idx}` : `${idx}`;
303
+ const { unpackedObj, disclosureKeymap: disclosureKeys } = unpackObjInternal(item, map, newKey, seenDigests);
304
+ unpackedArray.push(unpackedObj);
305
+ Object.assign(keys, disclosureKeys);
306
+ } else {
307
+ unpackedArray.push(item);
308
+ }
309
+ });
310
+ return { unpackedObj: unpackedArray, disclosureKeymap: keys };
311
+ };
312
+ var unpackObj = (obj, map) => {
313
+ const copiedObj = JSON.parse(JSON.stringify(obj));
314
+ const seenDigests = /* @__PURE__ */ new Set();
315
+ const result = unpackObjInternal(copiedObj, map, "", seenDigests);
316
+ const mapDigests = Object.keys(map);
317
+ const unusedDigests = mapDigests.filter((d) => !seenDigests.has(d));
318
+ if (unusedDigests.length > 0) {
319
+ throw new SDJWTException("Unreferenced disclosure(s) detected in SD-JWT");
320
+ }
321
+ return result;
322
+ };
323
+ var unpackObjInternal = (obj, map, prefix = "", seenDigests) => {
324
+ const keys = {};
325
+ if (typeof obj === "object" && obj !== null) {
326
+ if (Array.isArray(obj)) {
327
+ return unpackArray(obj, map, prefix, seenDigests);
328
+ }
329
+ const record = obj;
330
+ for (const key in record) {
331
+ if (key !== SD_DIGEST && key !== SD_LIST_KEY && typeof record[key] === "object") {
332
+ const newKey = prefix ? `${prefix}.${key}` : key;
333
+ const { unpackedObj: unpackedObj2, disclosureKeymap: disclosureKeys } = unpackObjInternal(record[key], map, newKey, seenDigests);
334
+ record[key] = unpackedObj2;
335
+ Object.assign(keys, disclosureKeys);
336
+ }
337
+ }
338
+ const _a = record, { _sd } = _a, payload = __objRest(_a, ["_sd"]);
339
+ const claims = {};
340
+ if (_sd) {
341
+ for (const hash of _sd) {
342
+ if (seenDigests) {
343
+ if (seenDigests.has(hash)) {
344
+ throw new SDJWTException(
345
+ "Duplicate digest found in SD-JWT payload"
346
+ );
347
+ }
348
+ seenDigests.add(hash);
349
+ }
350
+ const disclosed = map[hash];
351
+ if (disclosed == null ? void 0 : disclosed.key) {
352
+ if (disclosed.key in payload) {
353
+ throw new SDJWTException(
354
+ `Disclosed claim name "${disclosed.key}" conflicts with existing payload key`
355
+ );
356
+ }
357
+ const presentKey = prefix ? `${prefix}.${disclosed.key}` : disclosed.key;
358
+ keys[presentKey] = hash;
359
+ const { unpackedObj: unpackedObj2, disclosureKeymap: disclosureKeys } = unpackObjInternal(disclosed.value, map, presentKey, seenDigests);
360
+ claims[disclosed.key] = unpackedObj2;
361
+ Object.assign(keys, disclosureKeys);
362
+ }
363
+ }
364
+ }
365
+ const unpackedObj = Object.assign(payload, claims);
366
+ return { unpackedObj, disclosureKeymap: keys };
367
+ }
368
+ return { unpackedObj: obj, disclosureKeymap: keys };
369
+ };
370
+ var createHashMapping = (disclosures, hash) => __async(null, null, function* () {
371
+ const map = {};
372
+ for (let i = 0; i < disclosures.length; i++) {
373
+ const disclosure = disclosures[i];
374
+ const digest = yield disclosure.digest(hash);
375
+ map[digest] = disclosure;
376
+ }
377
+ return map;
378
+ });
379
+ var createHashMappingSync = (disclosures, hash) => {
380
+ const map = {};
381
+ for (let i = 0; i < disclosures.length; i++) {
382
+ const disclosure = disclosures[i];
383
+ const digest = disclosure.digestSync(hash);
384
+ map[digest] = disclosure;
385
+ }
386
+ return map;
387
+ };
388
+ var getSDAlgAndPayload = (SdJwtPayload) => {
389
+ const _a = SdJwtPayload, { _sd_alg } = _a, payload = __objRest(_a, ["_sd_alg"]);
390
+ if (typeof _sd_alg !== "string") {
391
+ return { _sd_alg: "sha-256", payload };
392
+ }
393
+ if (!IANA_HASH_ALGORITHMS.includes(
394
+ _sd_alg
395
+ )) {
396
+ throw new SDJWTException(`Invalid _sd_alg: ${_sd_alg}`);
397
+ }
398
+ return { _sd_alg, payload };
399
+ };
400
+ var unpack = (SdJwtPayload, disclosures, hasher) => __async(null, null, function* () {
401
+ const { _sd_alg, payload } = getSDAlgAndPayload(SdJwtPayload);
402
+ const hash = { hasher, alg: _sd_alg };
403
+ const map = yield createHashMapping(disclosures, hash);
404
+ return unpackObj(payload, map);
405
+ });
406
+ var unpackSync = (SdJwtPayload, disclosures, hasher) => {
407
+ const { _sd_alg, payload } = getSDAlgAndPayload(SdJwtPayload);
408
+ const hash = { hasher, alg: _sd_alg };
409
+ const map = createHashMappingSync(disclosures, hash);
410
+ return unpackObj(payload, map);
411
+ };
412
+
413
+ // src/flattenJSON.ts
414
+ var FlattenJSON = class _FlattenJSON {
415
+ constructor(data) {
416
+ this.disclosures = data.disclosures;
417
+ this.kb_jwt = data.kb_jwt;
418
+ this.payload = data.jwtData.payload;
419
+ this.signature = data.jwtData.signature;
420
+ this.protected = data.jwtData.protected;
421
+ }
422
+ static fromEncode(encodedSdJwt) {
423
+ const { jwt, disclosures, kbJwt } = splitSdJwt(encodedSdJwt);
424
+ const { 0: protectedHeader, 1: payload, 2: signature } = jwt.split(".");
425
+ if (!protectedHeader || !payload || !signature) {
426
+ throw new SDJWTException("Invalid JWT");
427
+ }
428
+ return new _FlattenJSON({
429
+ jwtData: {
430
+ protected: protectedHeader,
431
+ payload,
432
+ signature
433
+ },
434
+ disclosures,
435
+ kb_jwt: kbJwt
436
+ });
437
+ }
438
+ static fromSerialized(json) {
439
+ return new _FlattenJSON({
440
+ jwtData: {
441
+ protected: json.protected,
442
+ payload: json.payload,
443
+ signature: json.signature
444
+ },
445
+ disclosures: json.header.disclosures,
446
+ kb_jwt: json.header.kb_jwt
447
+ });
448
+ }
449
+ toJson() {
450
+ return {
451
+ payload: this.payload,
452
+ signature: this.signature,
453
+ protected: this.protected,
454
+ header: {
455
+ disclosures: this.disclosures,
456
+ kb_jwt: this.kb_jwt
457
+ }
458
+ };
459
+ }
460
+ toEncoded() {
461
+ var _a;
462
+ const data = [];
463
+ const jwt = `${this.protected}.${this.payload}.${this.signature}`;
464
+ data.push(jwt);
465
+ if (this.disclosures && this.disclosures.length > 0) {
466
+ const disclosures = this.disclosures.join(SD_SEPARATOR);
467
+ data.push(disclosures);
468
+ }
469
+ const kb_jwt = (_a = this.kb_jwt) != null ? _a : "";
470
+ data.push(kb_jwt);
471
+ return data.join(SD_SEPARATOR);
472
+ }
473
+ };
474
+
475
+ // src/generalJSON.ts
476
+ var GeneralJSON = class _GeneralJSON {
477
+ constructor(data) {
478
+ this.payload = data.payload;
479
+ this.disclosures = data.disclosures;
480
+ this.kb_jwt = data.kb_jwt;
481
+ this.signatures = data.signatures;
482
+ }
483
+ static fromEncode(encodedSdJwt) {
484
+ const { jwt, disclosures, kbJwt } = splitSdJwt(encodedSdJwt);
485
+ const { 0: protectedHeader, 1: payload, 2: signature } = jwt.split(".");
486
+ if (!protectedHeader || !payload || !signature) {
487
+ throw new SDJWTException("Invalid JWT");
488
+ }
489
+ return new _GeneralJSON({
490
+ payload,
491
+ disclosures,
492
+ kb_jwt: kbJwt,
493
+ signatures: [
494
+ {
495
+ protected: protectedHeader,
496
+ signature
497
+ }
498
+ ]
499
+ });
500
+ }
501
+ static fromSerialized(json) {
502
+ var _a, _b, _c;
503
+ if (!json.signatures[0]) {
504
+ throw new SDJWTException("Invalid JSON");
505
+ }
506
+ const disclosures = (_b = (_a = json.signatures[0].header) == null ? void 0 : _a.disclosures) != null ? _b : [];
507
+ const kb_jwt = (_c = json.signatures[0].header) == null ? void 0 : _c.kb_jwt;
508
+ return new _GeneralJSON({
509
+ payload: json.payload,
510
+ disclosures,
511
+ kb_jwt,
512
+ signatures: json.signatures.map((s) => {
513
+ var _a2;
514
+ return {
515
+ protected: s.protected,
516
+ signature: s.signature,
517
+ kid: (_a2 = s.header) == null ? void 0 : _a2.kid
518
+ };
519
+ })
520
+ });
521
+ }
522
+ toJson() {
523
+ return {
524
+ payload: this.payload,
525
+ signatures: this.signatures.map((s, i) => {
526
+ if (i !== 0) {
527
+ return {
528
+ header: {
529
+ kid: s.kid
530
+ },
531
+ protected: s.protected,
532
+ signature: s.signature
533
+ };
534
+ }
535
+ return {
536
+ header: {
537
+ disclosures: this.disclosures,
538
+ kid: s.kid,
539
+ kb_jwt: this.kb_jwt
540
+ },
541
+ protected: s.protected,
542
+ signature: s.signature
543
+ };
544
+ })
545
+ };
546
+ }
547
+ toEncoded(index) {
548
+ var _a;
549
+ if (index < 0 || index >= this.signatures.length) {
550
+ throw new SDJWTException("Index out of bounds");
551
+ }
552
+ const data = [];
553
+ const { protected: protectedHeader, signature } = this.signatures[index];
554
+ const jwt = `${protectedHeader}.${this.payload}.${signature}`;
555
+ data.push(jwt);
556
+ if (this.disclosures && this.disclosures.length > 0) {
557
+ const disclosures = this.disclosures.join(SD_SEPARATOR);
558
+ data.push(disclosures);
559
+ }
560
+ const kb = (_a = this.kb_jwt) != null ? _a : "";
561
+ data.push(kb);
562
+ return data.join(SD_SEPARATOR);
563
+ }
564
+ addSignature(protectedHeader, signer, kid) {
565
+ return __async(this, null, function* () {
566
+ const header = base64urlEncode(JSON.stringify(protectedHeader));
567
+ const signature = yield signer(`${header}.${this.payload}`);
568
+ this.signatures.push({
569
+ protected: header,
570
+ signature,
571
+ kid
572
+ });
573
+ });
574
+ }
575
+ };
576
+
577
+ // src/jwt.ts
578
+ var Jwt = class _Jwt {
579
+ constructor(data) {
580
+ this.header = data == null ? void 0 : data.header;
581
+ this.payload = data == null ? void 0 : data.payload;
582
+ this.signature = data == null ? void 0 : data.signature;
583
+ this.encoded = data == null ? void 0 : data.encoded;
584
+ }
585
+ static decodeJWT(jwt) {
586
+ return decodeJwt(jwt);
587
+ }
588
+ static fromEncode(encodedJwt) {
589
+ const { header, payload, signature } = _Jwt.decodeJWT(
590
+ encodedJwt
591
+ );
592
+ const jwt = new _Jwt({
593
+ header,
594
+ payload,
595
+ signature,
596
+ encoded: encodedJwt
597
+ });
598
+ return jwt;
599
+ }
600
+ setHeader(header) {
601
+ this.header = header;
602
+ this.encoded = void 0;
603
+ return this;
604
+ }
605
+ setPayload(payload) {
606
+ this.payload = payload;
607
+ this.encoded = void 0;
608
+ return this;
609
+ }
610
+ getUnsignedToken() {
611
+ if (!this.header || !this.payload) {
612
+ throw new SDJWTException("Serialize Error: Invalid JWT");
613
+ }
614
+ if (this.encoded) {
615
+ const parts = this.encoded.split(".");
616
+ if (parts.length !== 3) {
617
+ throw new SDJWTException(`Invalid JWT format: ${this.encoded}`);
618
+ }
619
+ const unsignedToken = parts.slice(0, 2).join(".");
620
+ return unsignedToken;
621
+ }
622
+ const header = base64urlEncode(JSON.stringify(this.header));
623
+ const payload = base64urlEncode(JSON.stringify(this.payload));
624
+ return `${header}.${payload}`;
625
+ }
626
+ sign(signer) {
627
+ return __async(this, null, function* () {
628
+ const data = this.getUnsignedToken();
629
+ this.signature = yield signer(data);
630
+ return this.encodeJwt();
631
+ });
632
+ }
633
+ encodeJwt() {
634
+ if (this.encoded) {
635
+ return this.encoded;
636
+ }
637
+ if (!this.header || !this.payload || !this.signature) {
638
+ throw new SDJWTException("Serialize Error: Invalid JWT");
639
+ }
640
+ const header = base64urlEncode(JSON.stringify(this.header));
641
+ const payload = base64urlEncode(JSON.stringify(this.payload));
642
+ const signature = this.signature;
643
+ const compact = `${header}.${payload}.${signature}`;
644
+ this.encoded = compact;
645
+ return compact;
646
+ }
647
+ /**
648
+ * Verify the JWT using the provided verifier function.
649
+ * It checks the signature and validates the iat, nbf, and exp claims if they are present.
650
+ * @param verifier
651
+ * @param options - Options for verification, such as current date and skew seconds
652
+ * @returns
653
+ */
654
+ verify(verifier, options) {
655
+ return __async(this, null, function* () {
656
+ var _a, _b, _c, _d;
657
+ const skew = (options == null ? void 0 : options.skewSeconds) ? options.skewSeconds : 0;
658
+ const currentDate = (_a = options == null ? void 0 : options.currentDate) != null ? _a : Math.floor(Date.now() / 1e3);
659
+ const iat = (_b = this.payload) == null ? void 0 : _b.iat;
660
+ const nbf = (_c = this.payload) == null ? void 0 : _c.nbf;
661
+ const exp = (_d = this.payload) == null ? void 0 : _d.exp;
662
+ if (typeof iat === "number" && iat - skew > currentDate) {
663
+ throw new SDJWTException("Verify Error: JWT is not yet valid");
664
+ }
665
+ if (typeof nbf === "number" && nbf - skew > currentDate) {
666
+ throw new SDJWTException("Verify Error: JWT is not yet valid");
667
+ }
668
+ if (typeof exp === "number" && exp + skew < currentDate) {
669
+ throw new SDJWTException("Verify Error: JWT is expired");
670
+ }
671
+ if (!this.signature) {
672
+ throw new SDJWTException("Verify Error: no signature in JWT");
673
+ }
674
+ const data = this.getUnsignedToken();
675
+ const verified = yield verifier(data, this.signature, options);
676
+ if (!verified) {
677
+ throw new SDJWTException("Verify Error: Invalid JWT Signature");
678
+ }
679
+ return { payload: this.payload, header: this.header };
680
+ });
681
+ }
682
+ };
683
+
684
+ // src/kbjwt.ts
685
+ var KBJwt = class _KBJwt extends Jwt {
686
+ // Checking the validity of the key binding jwt
687
+ // the type unknown is not good, but we don't know at this point how to get the public key of the signer, this is defined in the kbVerifier
688
+ verifyKB(values) {
689
+ return __async(this, null, function* () {
690
+ if (!this.header || !this.payload || !this.signature) {
691
+ throw new SDJWTException("Verify Error: Invalid JWT");
692
+ }
693
+ if (!this.header.alg || this.header.alg === "none" || !this.header.typ || this.header.typ !== KB_JWT_TYP || !this.payload.iat || !this.payload.aud || !this.payload.nonce || // this is for backward compatibility with version 06
694
+ !(this.payload.sd_hash || "_sd_hash" in this.payload && this.payload._sd_hash)) {
695
+ throw new SDJWTException("Invalid Key Binding Jwt");
696
+ }
697
+ if (this.payload.nonce !== values.nonce) {
698
+ throw new SDJWTException("Verify Error: Invalid Nonce");
699
+ }
700
+ yield this.verify(
701
+ (data, sig) => values.verifier(data, sig, values.payload),
702
+ values.options
703
+ );
704
+ return { payload: this.payload, header: this.header };
705
+ });
706
+ }
707
+ // This function is for creating KBJwt object for verify properly
708
+ static fromKBEncode(encodedJwt) {
709
+ const { header, payload, signature } = Jwt.decodeJWT(
710
+ encodedJwt
711
+ );
712
+ const jwt = new _KBJwt({
713
+ header,
714
+ payload,
715
+ signature,
716
+ encoded: encodedJwt
717
+ });
718
+ return jwt;
719
+ }
720
+ };
721
+
722
+ // src/decoy.ts
723
+ var createDecoy = (hash, saltGenerator) => __async(null, null, function* () {
724
+ const { hasher, alg } = hash;
725
+ const salt = yield saltGenerator(16);
726
+ const decoy = yield hasher(salt, alg);
727
+ return uint8ArrayToBase64Url(decoy);
728
+ });
729
+
730
+ // src/present/present.ts
731
+ var presentableKeys = (rawPayload, disclosures, hasher) => __async(null, null, function* () {
732
+ const { disclosureKeymap } = yield unpack(rawPayload, disclosures, hasher);
733
+ return Object.keys(disclosureKeymap).sort();
734
+ });
735
+ var presentableKeysSync = (rawPayload, disclosures, hasher) => {
736
+ const { disclosureKeymap } = unpackSync(rawPayload, disclosures, hasher);
737
+ return Object.keys(disclosureKeymap).sort();
738
+ };
739
+ var present = (sdJwt, presentFrame, hasher) => __async(null, null, function* () {
740
+ const { jwt, kbJwt } = splitSdJwt(sdJwt);
741
+ const {
742
+ jwt: { payload },
743
+ disclosures
744
+ } = yield decodeSdJwt(sdJwt, hasher);
745
+ const { _sd_alg: alg } = getSDAlgAndPayload(payload);
746
+ const hash = { alg, hasher };
747
+ const keys = transformPresentationFrame(presentFrame);
748
+ const hashmap = yield createHashMapping(disclosures, hash);
749
+ const { disclosureKeymap } = yield unpack(payload, disclosures, hasher);
750
+ const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
751
+ return [
752
+ jwt,
753
+ ...presentedDisclosures.map((d) => d.encode()),
754
+ kbJwt != null ? kbJwt : ""
755
+ ].join(SD_SEPARATOR);
756
+ });
757
+ var presentSync = (sdJwt, presentFrame, hasher) => {
758
+ const { jwt, kbJwt } = splitSdJwt(sdJwt);
759
+ const {
760
+ jwt: { payload },
761
+ disclosures
762
+ } = decodeSdJwtSync(sdJwt, hasher);
763
+ const { _sd_alg: alg } = getSDAlgAndPayload(payload);
764
+ const hash = { alg, hasher };
765
+ const keys = transformPresentationFrame(presentFrame);
766
+ const hashmap = createHashMappingSync(disclosures, hash);
767
+ const { disclosureKeymap } = unpackSync(payload, disclosures, hasher);
768
+ const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
769
+ return [
770
+ jwt,
771
+ ...presentedDisclosures.map((d) => d.encode()),
772
+ kbJwt != null ? kbJwt : ""
773
+ ].join(SD_SEPARATOR);
774
+ };
775
+ var transformPresentationFrame = (obj, prefix = "") => {
776
+ return Object.entries(obj).reduce((acc, [key, value]) => {
777
+ const newPrefix = prefix ? `${prefix}.${key}` : key;
778
+ if (typeof value === "boolean") {
779
+ if (value) {
780
+ acc.push(newPrefix);
781
+ }
782
+ } else if (typeof value === "object" && value !== null) {
783
+ acc.push(
784
+ newPrefix,
785
+ ...transformPresentationFrame(
786
+ value,
787
+ newPrefix
788
+ )
789
+ );
790
+ }
791
+ return acc;
792
+ }, []);
793
+ };
794
+ var createHashMappingForSerializedDisclosure = (disclosures) => {
795
+ const map = {};
796
+ for (let i = 0; i < disclosures.length; i++) {
797
+ const disclosure = disclosures[i];
798
+ const { digest, encoded, key, salt, value } = disclosure;
799
+ map[digest] = Disclosure.fromArray(
800
+ key ? [salt, key, value] : [salt, value],
801
+ { digest, encoded }
802
+ );
803
+ }
804
+ return map;
805
+ };
806
+ var selectDisclosures = (payload, disclosures, presentationFrame) => {
807
+ if (disclosures.length === 0) {
808
+ return [];
809
+ }
810
+ const hashmap = createHashMappingForSerializedDisclosure(disclosures);
811
+ const { disclosureKeymap } = unpackObj(payload, hashmap);
812
+ const keys = transformPresentationFrame(presentationFrame);
813
+ const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
814
+ const selectedDisclosures = presentedDisclosures.map(
815
+ (d) => {
816
+ const { salt, key, value, _digest } = d;
817
+ if (!_digest) {
818
+ throw new SDJWTException(
819
+ "Implementation error: _digest is not defined"
820
+ );
821
+ }
822
+ return {
823
+ digest: _digest,
824
+ encoded: d.encode(),
825
+ salt,
826
+ key,
827
+ value
828
+ };
829
+ }
830
+ );
831
+ return selectedDisclosures;
832
+ };
833
+
834
+ // src/sdjwt.ts
835
+ var SDJwt = class _SDJwt {
836
+ constructor(data) {
837
+ this.jwt = data == null ? void 0 : data.jwt;
838
+ this.disclosures = data == null ? void 0 : data.disclosures;
839
+ this.kbJwt = data == null ? void 0 : data.kbJwt;
840
+ }
841
+ static decodeSDJwt(sdjwt, hasher) {
842
+ return __async(this, null, function* () {
843
+ const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
844
+ const jwt = Jwt.fromEncode(encodedJwt);
845
+ if (!jwt.payload) {
846
+ throw new Error("Payload is undefined on the JWT. Invalid state reached");
847
+ }
848
+ if (encodedDisclosures.length === 0) {
849
+ return {
850
+ jwt,
851
+ disclosures: []
852
+ };
853
+ }
854
+ const encodedKeyBindingJwt = encodedDisclosures.pop();
855
+ const kbJwt = encodedKeyBindingJwt ? KBJwt.fromKBEncode(encodedKeyBindingJwt) : void 0;
856
+ const { _sd_alg } = getSDAlgAndPayload(jwt.payload);
857
+ const disclosures = yield Promise.all(
858
+ encodedDisclosures.map(
859
+ (ed) => Disclosure.fromEncode(ed, { alg: _sd_alg, hasher })
860
+ )
861
+ );
862
+ return {
863
+ jwt,
864
+ disclosures,
865
+ kbJwt
866
+ };
867
+ });
868
+ }
869
+ static extractJwt(encodedSdJwt) {
870
+ return __async(this, null, function* () {
871
+ const [encodedJwt, ..._encodedDisclosures] = encodedSdJwt.split(SD_SEPARATOR);
872
+ return Jwt.fromEncode(encodedJwt);
873
+ });
874
+ }
875
+ static fromEncode(encodedSdJwt, hasher) {
876
+ return __async(this, null, function* () {
877
+ const { jwt, disclosures, kbJwt } = yield _SDJwt.decodeSDJwt(encodedSdJwt, hasher);
878
+ return new _SDJwt({
879
+ jwt,
880
+ disclosures,
881
+ kbJwt
882
+ });
883
+ });
884
+ }
885
+ present(presentFrame, hasher) {
886
+ return __async(this, null, function* () {
887
+ const disclosures = yield this.getPresentDisclosures(presentFrame, hasher);
888
+ const presentSDJwt = new _SDJwt({
889
+ jwt: this.jwt,
890
+ disclosures,
891
+ kbJwt: this.kbJwt
892
+ });
893
+ return presentSDJwt.encodeSDJwt();
894
+ });
895
+ }
896
+ getPresentDisclosures(presentFrame, hasher) {
897
+ return __async(this, null, function* () {
898
+ var _a;
899
+ if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
900
+ throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
901
+ }
902
+ const { _sd_alg: alg } = getSDAlgAndPayload(this.jwt.payload);
903
+ const hash = { alg, hasher };
904
+ const hashmap = yield createHashMapping(this.disclosures, hash);
905
+ const { disclosureKeymap } = yield unpack(
906
+ this.jwt.payload,
907
+ this.disclosures,
908
+ hasher
909
+ );
910
+ const keys = presentFrame ? transformPresentationFrame(presentFrame) : yield this.presentableKeys(hasher);
911
+ const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
912
+ return disclosures;
913
+ });
914
+ }
915
+ encodeSDJwt() {
916
+ const data = [];
917
+ if (!this.jwt) {
918
+ throw new SDJWTException("Invalid sd-jwt: jwt is missing");
919
+ }
920
+ const encodedJwt = this.jwt.encodeJwt();
921
+ data.push(encodedJwt);
922
+ if (this.disclosures && this.disclosures.length > 0) {
923
+ const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(SD_SEPARATOR);
924
+ data.push(encodeddisclosures);
925
+ }
926
+ data.push(this.kbJwt ? this.kbJwt.encodeJwt() : "");
927
+ return data.join(SD_SEPARATOR);
928
+ }
929
+ keys(hasher) {
930
+ return __async(this, null, function* () {
931
+ return listKeys(yield this.getClaims(hasher)).sort();
932
+ });
933
+ }
934
+ presentableKeys(hasher) {
935
+ return __async(this, null, function* () {
936
+ var _a, _b;
937
+ if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
938
+ throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
939
+ }
940
+ const { disclosureKeymap } = yield unpack(
941
+ (_b = this.jwt) == null ? void 0 : _b.payload,
942
+ this.disclosures,
943
+ hasher
944
+ );
945
+ return Object.keys(disclosureKeymap).sort();
946
+ });
947
+ }
948
+ getClaims(hasher) {
949
+ return __async(this, null, function* () {
950
+ var _a;
951
+ if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
952
+ throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
953
+ }
954
+ const { unpackedObj } = yield unpack(
955
+ this.jwt.payload,
956
+ this.disclosures,
957
+ hasher
958
+ );
959
+ return unpackedObj;
960
+ });
961
+ }
962
+ };
963
+ var listKeys = (obj, prefix = "") => {
964
+ const keys = [];
965
+ for (const key in obj) {
966
+ if (obj[key] === void 0) continue;
967
+ const newKey = prefix ? `${prefix}.${key}` : key;
968
+ keys.push(newKey);
969
+ const value = obj[key];
970
+ if (value && typeof value === "object") {
971
+ keys.push(...listKeys(value, newKey));
972
+ }
973
+ }
974
+ return keys;
975
+ };
976
+ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(null, null, function* () {
977
+ var _a, _b;
978
+ if (!disclosureFrame) {
979
+ return {
980
+ packedClaims: claims,
981
+ disclosures: []
982
+ };
983
+ }
984
+ const sd = (_a = disclosureFrame[SD_DIGEST]) != null ? _a : [];
985
+ const decoyCount = (_b = disclosureFrame[SD_DECOY]) != null ? _b : 0;
986
+ if (Array.isArray(claims)) {
987
+ const packedClaims2 = [];
988
+ const disclosures2 = [];
989
+ const recursivePackedClaims2 = {};
990
+ for (const key in disclosureFrame) {
991
+ if (key !== SD_DIGEST) {
992
+ const idx = Number.parseInt(key, 10);
993
+ const packed = yield pack(
994
+ claims[idx],
995
+ disclosureFrame[idx],
996
+ hash,
997
+ saltGenerator
998
+ );
999
+ recursivePackedClaims2[idx] = packed.packedClaims;
1000
+ disclosures2.push(...packed.disclosures);
1001
+ }
1002
+ }
1003
+ for (let i = 0; i < claims.length; i++) {
1004
+ const claim = recursivePackedClaims2[i] ? recursivePackedClaims2[i] : claims[i];
1005
+ if (sd.includes(i)) {
1006
+ const salt = yield saltGenerator(16);
1007
+ const disclosure = new Disclosure([salt, claim]);
1008
+ const digest = yield disclosure.digest(hash);
1009
+ packedClaims2.push({ [SD_LIST_KEY]: digest });
1010
+ disclosures2.push(disclosure);
1011
+ } else {
1012
+ packedClaims2.push(claim);
1013
+ }
1014
+ }
1015
+ for (let j = 0; j < decoyCount; j++) {
1016
+ const decoyDigest = yield createDecoy(hash, saltGenerator);
1017
+ packedClaims2.push({ [SD_LIST_KEY]: decoyDigest });
1018
+ }
1019
+ return { packedClaims: packedClaims2, disclosures: disclosures2 };
1020
+ }
1021
+ const packedClaims = {};
1022
+ const disclosures = [];
1023
+ const recursivePackedClaims = {};
1024
+ for (const key in disclosureFrame) {
1025
+ if (key !== SD_DIGEST) {
1026
+ const packed = yield pack(
1027
+ // @ts-expect-error
1028
+ claims[key],
1029
+ disclosureFrame[key],
1030
+ hash,
1031
+ saltGenerator
1032
+ );
1033
+ recursivePackedClaims[key] = packed.packedClaims;
1034
+ disclosures.push(...packed.disclosures);
1035
+ }
1036
+ }
1037
+ const _sd = [];
1038
+ for (const key in claims) {
1039
+ const claim = recursivePackedClaims[key] ? recursivePackedClaims[key] : claims[key];
1040
+ if (sd.includes(key)) {
1041
+ const salt = yield saltGenerator(16);
1042
+ const disclosure = new Disclosure([salt, key, claim]);
1043
+ const digest = yield disclosure.digest(hash);
1044
+ _sd.push(digest);
1045
+ disclosures.push(disclosure);
1046
+ } else {
1047
+ packedClaims[key] = claim;
1048
+ }
1049
+ }
1050
+ for (let j = 0; j < decoyCount; j++) {
1051
+ const decoyDigest = yield createDecoy(hash, saltGenerator);
1052
+ _sd.push(decoyDigest);
1053
+ }
1054
+ if (_sd.length > 0) {
1055
+ packedClaims[SD_DIGEST] = _sd.sort();
1056
+ }
1057
+ return { packedClaims, disclosures };
1058
+ });
1059
+
1060
+ // src/index.ts
1061
+ var _SDJwtInstance = class _SDJwtInstance {
1062
+ constructor(userConfig) {
1063
+ this.userConfig = {};
1064
+ if (userConfig) {
1065
+ if (userConfig.hashAlg && !IANA_HASH_ALGORITHMS.includes(userConfig.hashAlg)) {
1066
+ throw new SDJWTException(
1067
+ `Invalid hash algorithm: ${userConfig.hashAlg}`
1068
+ );
1069
+ }
1070
+ this.userConfig = userConfig;
1071
+ }
1072
+ }
1073
+ createKBJwt(options, sdHash) {
1074
+ return __async(this, null, function* () {
1075
+ if (!this.userConfig.kbSigner) {
1076
+ throw new SDJWTException("Key Binding Signer not found");
1077
+ }
1078
+ if (!this.userConfig.kbSignAlg) {
1079
+ throw new SDJWTException("Key Binding sign algorithm not specified");
1080
+ }
1081
+ const { payload } = options;
1082
+ const kbJwt = new KBJwt({
1083
+ header: {
1084
+ typ: KB_JWT_TYP,
1085
+ alg: this.userConfig.kbSignAlg
1086
+ },
1087
+ payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
1088
+ });
1089
+ yield kbJwt.sign(this.userConfig.kbSigner);
1090
+ return kbJwt;
1091
+ });
1092
+ }
1093
+ SignJwt(jwt) {
1094
+ return __async(this, null, function* () {
1095
+ if (!this.userConfig.signer) {
1096
+ throw new SDJWTException("Signer not found");
1097
+ }
1098
+ yield jwt.sign(this.userConfig.signer);
1099
+ return jwt;
1100
+ });
1101
+ }
1102
+ VerifyJwt(jwt, options) {
1103
+ return __async(this, null, function* () {
1104
+ if (!this.userConfig.verifier) {
1105
+ throw new SDJWTException("Verifier not found");
1106
+ }
1107
+ return jwt.verify(this.userConfig.verifier, options);
1108
+ });
1109
+ }
1110
+ issue(payload, disclosureFrame, options) {
1111
+ return __async(this, null, function* () {
1112
+ var _a, _b;
1113
+ if (!this.userConfig.hasher) {
1114
+ throw new SDJWTException("Hasher not found");
1115
+ }
1116
+ if (!this.userConfig.saltGenerator) {
1117
+ throw new SDJWTException("SaltGenerator not found");
1118
+ }
1119
+ if (!this.userConfig.signAlg) {
1120
+ throw new SDJWTException("sign alogrithm not specified");
1121
+ }
1122
+ this.validateReservedFields(payload);
1123
+ this.validateDisclosureFrame(disclosureFrame);
1124
+ const hasher = this.userConfig.hasher;
1125
+ const hashAlg = (_a = this.userConfig.hashAlg) != null ? _a : _SDJwtInstance.DEFAULT_hashAlg;
1126
+ const { packedClaims, disclosures } = yield pack(
1127
+ payload,
1128
+ disclosureFrame,
1129
+ { hasher, alg: hashAlg },
1130
+ this.userConfig.saltGenerator
1131
+ );
1132
+ const alg = this.userConfig.signAlg;
1133
+ const OptionHeader = (_b = options == null ? void 0 : options.header) != null ? _b : {};
1134
+ const CustomHeader = this.userConfig.omitTyp ? OptionHeader : __spreadValues({ typ: this.type }, OptionHeader);
1135
+ const header = __spreadProps(__spreadValues({}, CustomHeader), { alg });
1136
+ const jwt = new Jwt({
1137
+ header,
1138
+ payload: __spreadProps(__spreadValues({}, packedClaims), {
1139
+ _sd_alg: disclosureFrame ? hashAlg : void 0
1140
+ })
1141
+ });
1142
+ yield this.SignJwt(jwt);
1143
+ const sdJwt = new SDJwt({
1144
+ jwt,
1145
+ disclosures
1146
+ });
1147
+ return sdJwt.encodeSDJwt();
1148
+ });
1149
+ }
1150
+ /**
1151
+ * Validates if the payload contains any reserved claim names. If so it will throw an error.
1152
+ * @param payload
1153
+ * @returns
1154
+ */
1155
+ validateReservedFields(payload) {
1156
+ const reservedFields = /* @__PURE__ */ new Set([SD_DIGEST, "_sd_alg", SD_DECOY]);
1157
+ const visit = (node) => {
1158
+ if (!node || typeof node !== "object") {
1159
+ return;
1160
+ }
1161
+ for (const [key, value] of Object.entries(
1162
+ node
1163
+ )) {
1164
+ if (reservedFields.has(key)) {
1165
+ throw new SDJWTException(
1166
+ `Reserved field name "${key}" is not allowed`
1167
+ );
1168
+ }
1169
+ visit(value);
1170
+ }
1171
+ };
1172
+ visit(payload);
1173
+ }
1174
+ validateDisclosureFrame(_disclosureFrame) {
1175
+ return;
1176
+ }
1177
+ present(encodedSDJwt, presentationFrame, options) {
1178
+ return __async(this, null, function* () {
1179
+ var _a;
1180
+ if (!this.userConfig.hasher) {
1181
+ throw new SDJWTException("Hasher not found");
1182
+ }
1183
+ const hasher = this.userConfig.hasher;
1184
+ const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
1185
+ if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new SDJWTException("Payload not found");
1186
+ const presentSdJwtWithoutKb = yield sdjwt.present(
1187
+ presentationFrame,
1188
+ hasher
1189
+ );
1190
+ if (!(options == null ? void 0 : options.kb)) {
1191
+ return presentSdJwtWithoutKb;
1192
+ }
1193
+ const sdHashStr = yield this.calculateSDHash(
1194
+ presentSdJwtWithoutKb,
1195
+ sdjwt,
1196
+ hasher
1197
+ );
1198
+ sdjwt.kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
1199
+ return sdjwt.present(presentationFrame, hasher);
1200
+ });
1201
+ }
1202
+ // This function is for verifying the SD JWT
1203
+ // If requiredClaimKeys is provided, it will check if the required claim keys are presentation in the SD JWT
1204
+ // If requireKeyBindings is true, it will check if the key binding JWT is presentation and verify it
1205
+ verify(encodedSDJwt, options) {
1206
+ return __async(this, null, function* () {
1207
+ if (!this.userConfig.hasher) {
1208
+ throw new SDJWTException("Hasher not found");
1209
+ }
1210
+ const hasher = this.userConfig.hasher;
1211
+ const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
1212
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
1213
+ throw new SDJWTException("Invalid SD JWT");
1214
+ }
1215
+ const { payload, header } = yield this.validate(encodedSDJwt, options);
1216
+ if (options == null ? void 0 : options.requiredClaimKeys) {
1217
+ const keys = yield sdjwt.keys(hasher);
1218
+ const missingKeys = options.requiredClaimKeys.filter(
1219
+ (k) => !keys.includes(k)
1220
+ );
1221
+ if (missingKeys.length > 0) {
1222
+ throw new SDJWTException(
1223
+ `Missing required claim keys: ${missingKeys.join(", ")}`
1224
+ );
1225
+ }
1226
+ }
1227
+ if (!(options == null ? void 0 : options.keyBindingNonce)) {
1228
+ return { payload, header };
1229
+ }
1230
+ if (!sdjwt.kbJwt) {
1231
+ throw new SDJWTException("Key Binding JWT not exist");
1232
+ }
1233
+ if (!this.userConfig.kbVerifier) {
1234
+ throw new SDJWTException("Key Binding Verifier not found");
1235
+ }
1236
+ const kb = yield sdjwt.kbJwt.verifyKB({
1237
+ verifier: this.userConfig.kbVerifier,
1238
+ payload,
1239
+ nonce: options.keyBindingNonce,
1240
+ options
1241
+ });
1242
+ if (!kb) {
1243
+ throw new Error("signature is not valid");
1244
+ }
1245
+ const sdHashfromKb = kb.payload.sd_hash;
1246
+ const sdjwtWithoutKb = new SDJwt({
1247
+ jwt: sdjwt.jwt,
1248
+ disclosures: sdjwt.disclosures
1249
+ });
1250
+ const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
1251
+ const sdHashStr = yield this.calculateSDHash(
1252
+ presentSdJwtWithoutKb,
1253
+ sdjwt,
1254
+ hasher
1255
+ );
1256
+ if (sdHashStr !== sdHashfromKb) {
1257
+ throw new SDJWTException("Invalid sd_hash in Key Binding JWT");
1258
+ }
1259
+ return { payload, header, kb };
1260
+ });
1261
+ }
1262
+ /**
1263
+ * Safe verification that collects all errors instead of failing fast.
1264
+ * Returns a result object with either the verified data or an array of all errors.
1265
+ *
1266
+ * @param encodedSDJwt - The encoded SD-JWT to verify
1267
+ * @param options - Verification options
1268
+ * @returns A SafeVerifyResult containing either success data or collected errors
1269
+ */
1270
+ safeVerify(encodedSDJwt, options) {
1271
+ return __async(this, null, function* () {
1272
+ const errors = [];
1273
+ const addError = (code, message, details) => {
1274
+ errors.push({ code, message, details });
1275
+ };
1276
+ const exceptionToCode = (error) => {
1277
+ const message = error.message.toLowerCase();
1278
+ if (message.includes("hasher not found")) return "HASHER_NOT_FOUND";
1279
+ if (message.includes("verifier not found")) return "VERIFIER_NOT_FOUND";
1280
+ if (message.includes("invalid sd jwt") || message.includes("invalid jwt"))
1281
+ return "INVALID_SD_JWT";
1282
+ if (message.includes("not yet valid")) return "JWT_NOT_YET_VALID";
1283
+ if (message.includes("expired")) return "JWT_EXPIRED";
1284
+ if (message.includes("signature")) return "INVALID_JWT_SIGNATURE";
1285
+ if (message.includes("missing required claim"))
1286
+ return "MISSING_REQUIRED_CLAIMS";
1287
+ if (message.includes("key binding jwt not exist"))
1288
+ return "KEY_BINDING_JWT_MISSING";
1289
+ if (message.includes("key binding verifier not found"))
1290
+ return "KEY_BINDING_VERIFIER_NOT_FOUND";
1291
+ if (message.includes("sd_hash")) return "KEY_BINDING_SD_HASH_INVALID";
1292
+ return "UNKNOWN_ERROR";
1293
+ };
1294
+ if (!this.userConfig.hasher) {
1295
+ addError("HASHER_NOT_FOUND", "Hasher not found");
1296
+ }
1297
+ if (!this.userConfig.verifier) {
1298
+ addError("VERIFIER_NOT_FOUND", "Verifier not found");
1299
+ }
1300
+ if (errors.length > 0) {
1301
+ return { success: false, errors };
1302
+ }
1303
+ if (!this.userConfig.hasher) {
1304
+ throw new SDJWTException("Hasher not found");
1305
+ }
1306
+ const hasher = this.userConfig.hasher;
1307
+ let sdjwt;
1308
+ let payload;
1309
+ let header;
1310
+ try {
1311
+ sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
1312
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
1313
+ addError("INVALID_SD_JWT", "Invalid SD JWT: missing JWT or payload");
1314
+ }
1315
+ } catch (e) {
1316
+ const error = ensureError(e);
1317
+ addError(
1318
+ "INVALID_SD_JWT",
1319
+ `Failed to decode SD-JWT: ${error.message}`,
1320
+ error
1321
+ );
1322
+ }
1323
+ if (sdjwt == null ? void 0 : sdjwt.jwt) {
1324
+ try {
1325
+ const result = yield this.VerifyJwt(sdjwt.jwt, options);
1326
+ header = result.header;
1327
+ const claims = yield sdjwt.getClaims(hasher);
1328
+ payload = claims;
1329
+ } catch (e) {
1330
+ const error = ensureError(e);
1331
+ const code = exceptionToCode(error);
1332
+ addError(code, error.message, error);
1333
+ }
1334
+ }
1335
+ if (sdjwt && (options == null ? void 0 : options.requiredClaimKeys)) {
1336
+ try {
1337
+ const keys = yield sdjwt.keys(hasher);
1338
+ const missingKeys = options.requiredClaimKeys.filter(
1339
+ (k) => !keys.includes(k)
1340
+ );
1341
+ if (missingKeys.length > 0) {
1342
+ addError(
1343
+ "MISSING_REQUIRED_CLAIMS",
1344
+ `Missing required claim keys: ${missingKeys.join(", ")}`,
1345
+ { missingKeys }
1346
+ );
1347
+ }
1348
+ } catch (e) {
1349
+ const error = ensureError(e);
1350
+ addError(
1351
+ "UNKNOWN_ERROR",
1352
+ `Failed to check required claims: ${error.message}`,
1353
+ error
1354
+ );
1355
+ }
1356
+ }
1357
+ let kb;
1358
+ if ((options == null ? void 0 : options.keyBindingNonce) && sdjwt) {
1359
+ if (!sdjwt.kbJwt) {
1360
+ addError("KEY_BINDING_JWT_MISSING", "Key Binding JWT not exist");
1361
+ } else if (!this.userConfig.kbVerifier) {
1362
+ addError(
1363
+ "KEY_BINDING_VERIFIER_NOT_FOUND",
1364
+ "Key Binding Verifier not found"
1365
+ );
1366
+ } else if (payload) {
1367
+ try {
1368
+ const kbResult = yield sdjwt.kbJwt.verifyKB({
1369
+ verifier: this.userConfig.kbVerifier,
1370
+ payload,
1371
+ nonce: options.keyBindingNonce,
1372
+ options
1373
+ });
1374
+ if (!kbResult) {
1375
+ addError(
1376
+ "KEY_BINDING_SIGNATURE_INVALID",
1377
+ "Key binding signature is not valid"
1378
+ );
1379
+ } else {
1380
+ kb = kbResult;
1381
+ const sdjwtWithoutKb = new SDJwt({
1382
+ jwt: sdjwt.jwt,
1383
+ disclosures: sdjwt.disclosures
1384
+ });
1385
+ const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
1386
+ const sdHashStr = yield this.calculateSDHash(
1387
+ presentSdJwtWithoutKb,
1388
+ sdjwt,
1389
+ hasher
1390
+ );
1391
+ if (sdHashStr !== kbResult.payload.sd_hash) {
1392
+ addError(
1393
+ "KEY_BINDING_SD_HASH_INVALID",
1394
+ "Invalid sd_hash in Key Binding JWT",
1395
+ {
1396
+ expected: sdHashStr,
1397
+ received: kbResult.payload.sd_hash
1398
+ }
1399
+ );
1400
+ }
1401
+ }
1402
+ } catch (e) {
1403
+ const error = ensureError(e);
1404
+ addError(
1405
+ "KEY_BINDING_SIGNATURE_INVALID",
1406
+ `Key binding verification failed: ${error.message}`,
1407
+ error
1408
+ );
1409
+ }
1410
+ }
1411
+ }
1412
+ if (errors.length > 0) {
1413
+ return { success: false, errors };
1414
+ }
1415
+ return {
1416
+ success: true,
1417
+ data: {
1418
+ payload,
1419
+ header,
1420
+ kb
1421
+ }
1422
+ };
1423
+ });
1424
+ }
1425
+ calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
1426
+ return __async(this, null, function* () {
1427
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
1428
+ throw new SDJWTException("Invalid SD JWT");
1429
+ }
1430
+ const { _sd_alg } = getSDAlgAndPayload(sdjwt.jwt.payload);
1431
+ const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
1432
+ const sdHashStr = uint8ArrayToBase64Url(sdHash);
1433
+ return sdHashStr;
1434
+ });
1435
+ }
1436
+ /**
1437
+ * This function is for validating the SD JWT
1438
+ * Checking signature, if provided the iat and exp when provided and return its the claims
1439
+ * @param encodedSDJwt
1440
+ * @param options
1441
+ * @returns
1442
+ */
1443
+ validate(encodedSDJwt, options) {
1444
+ return __async(this, null, function* () {
1445
+ if (!this.userConfig.hasher) {
1446
+ throw new SDJWTException("Hasher not found");
1447
+ }
1448
+ const hasher = this.userConfig.hasher;
1449
+ const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
1450
+ if (!sdjwt.jwt) {
1451
+ throw new SDJWTException("Invalid SD JWT");
1452
+ }
1453
+ const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt, options);
1454
+ const claims = yield sdjwt.getClaims(hasher);
1455
+ return { payload: claims, header: verifiedPayloads.header };
1456
+ });
1457
+ }
1458
+ config(newConfig) {
1459
+ this.userConfig = __spreadValues(__spreadValues({}, this.userConfig), newConfig);
1460
+ }
1461
+ encode(sdJwt) {
1462
+ return sdJwt.encodeSDJwt();
1463
+ }
1464
+ decode(endcodedSDJwt) {
1465
+ if (!this.userConfig.hasher) {
1466
+ throw new SDJWTException("Hasher not found");
1467
+ }
1468
+ return SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
1469
+ }
1470
+ keys(endcodedSDJwt) {
1471
+ return __async(this, null, function* () {
1472
+ if (!this.userConfig.hasher) {
1473
+ throw new SDJWTException("Hasher not found");
1474
+ }
1475
+ const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
1476
+ return sdjwt.keys(this.userConfig.hasher);
1477
+ });
1478
+ }
1479
+ presentableKeys(endcodedSDJwt) {
1480
+ return __async(this, null, function* () {
1481
+ if (!this.userConfig.hasher) {
1482
+ throw new SDJWTException("Hasher not found");
1483
+ }
1484
+ const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
1485
+ return sdjwt.presentableKeys(this.userConfig.hasher);
1486
+ });
1487
+ }
1488
+ getClaims(endcodedSDJwt) {
1489
+ return __async(this, null, function* () {
1490
+ if (!this.userConfig.hasher) {
1491
+ throw new SDJWTException("Hasher not found");
1492
+ }
1493
+ const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
1494
+ return sdjwt.getClaims(this.userConfig.hasher);
1495
+ });
1496
+ }
1497
+ toFlattenJSON(endcodedSDJwt) {
1498
+ return FlattenJSON.fromEncode(endcodedSDJwt);
1499
+ }
1500
+ toGeneralJSON(endcodedSDJwt) {
1501
+ return GeneralJSON.fromEncode(endcodedSDJwt);
1502
+ }
1503
+ };
1504
+ _SDJwtInstance.DEFAULT_hashAlg = "sha-256";
1505
+ var SDJwtInstance = _SDJwtInstance;
1506
+ var SDJwtGeneralJSONInstance = class {
1507
+ constructor(userConfig) {
1508
+ this.userConfig = {};
1509
+ if (userConfig) {
1510
+ if (userConfig.hashAlg && !IANA_HASH_ALGORITHMS.includes(userConfig.hashAlg)) {
1511
+ throw new SDJWTException(
1512
+ `Invalid hash algorithm: ${userConfig.hashAlg}`
1513
+ );
1514
+ }
1515
+ this.userConfig = userConfig;
1516
+ }
1517
+ }
1518
+ createKBJwt(options, sdHash) {
1519
+ return __async(this, null, function* () {
1520
+ if (!this.userConfig.kbSigner) {
1521
+ throw new SDJWTException("Key Binding Signer not found");
1522
+ }
1523
+ if (!this.userConfig.kbSignAlg) {
1524
+ throw new SDJWTException("Key Binding sign algorithm not specified");
1525
+ }
1526
+ const { payload } = options;
1527
+ const kbJwt = new KBJwt({
1528
+ header: {
1529
+ typ: KB_JWT_TYP,
1530
+ alg: this.userConfig.kbSignAlg
1531
+ },
1532
+ payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
1533
+ });
1534
+ yield kbJwt.sign(this.userConfig.kbSigner);
1535
+ return kbJwt;
1536
+ });
1537
+ }
1538
+ encodeObj(obj) {
1539
+ return base64urlEncode(JSON.stringify(obj));
1540
+ }
1541
+ issue(payload, disclosureFrame, options) {
1542
+ return __async(this, null, function* () {
1543
+ var _a;
1544
+ if (!this.userConfig.hasher) {
1545
+ throw new SDJWTException("Hasher not found");
1546
+ }
1547
+ if (!this.userConfig.saltGenerator) {
1548
+ throw new SDJWTException("SaltGenerator not found");
1549
+ }
1550
+ this.validateReservedFields(payload);
1551
+ this.validateDisclosureFrame(disclosureFrame);
1552
+ const hasher = this.userConfig.hasher;
1553
+ const hashAlg = (_a = this.userConfig.hashAlg) != null ? _a : SDJwtInstance.DEFAULT_hashAlg;
1554
+ const { packedClaims, disclosures } = yield pack(
1555
+ payload,
1556
+ disclosureFrame,
1557
+ { hasher, alg: hashAlg },
1558
+ this.userConfig.saltGenerator
1559
+ );
1560
+ const encodedSDJwtPayload = this.encodeObj(__spreadProps(__spreadValues({}, packedClaims), {
1561
+ _sd_alg: disclosureFrame ? hashAlg : void 0
1562
+ }));
1563
+ const encodedDisclosures = disclosures.map(
1564
+ (disclosure) => disclosure.encode()
1565
+ );
1566
+ const signatures = yield Promise.all(
1567
+ options.sigs.map((s) => __async(this, null, function* () {
1568
+ const { signer, alg, kid, header } = s;
1569
+ const protectedHeader = __spreadValues({ typ: this.type, alg, kid }, header);
1570
+ const encodedProtectedHeader = this.encodeObj(protectedHeader);
1571
+ const signature = yield signer(
1572
+ `${encodedProtectedHeader}.${encodedSDJwtPayload}`
1573
+ );
1574
+ return {
1575
+ protected: encodedProtectedHeader,
1576
+ signature
1577
+ };
1578
+ }))
1579
+ );
1580
+ const generalJson = new GeneralJSON({
1581
+ payload: encodedSDJwtPayload,
1582
+ disclosures: encodedDisclosures,
1583
+ signatures
1584
+ });
1585
+ return generalJson;
1586
+ });
1587
+ }
1588
+ /**
1589
+ * Validates if the payload contains any reserved claim names. If so it will throw an error.
1590
+ * @param payload
1591
+ * @returns
1592
+ */
1593
+ validateReservedFields(payload) {
1594
+ const reservedFields = /* @__PURE__ */ new Set([SD_DIGEST, "_sd_alg", SD_DECOY]);
1595
+ const visit = (node) => {
1596
+ if (!node || typeof node !== "object") {
1597
+ return;
1598
+ }
1599
+ for (const [key, value] of Object.entries(
1600
+ node
1601
+ )) {
1602
+ if (reservedFields.has(key)) {
1603
+ throw new SDJWTException(
1604
+ `Reserved field name "${key}" is not allowed`
1605
+ );
1606
+ }
1607
+ visit(value);
1608
+ }
1609
+ };
1610
+ visit(payload);
1611
+ }
1612
+ validateDisclosureFrame(_disclosureFrame) {
1613
+ return;
1614
+ }
1615
+ present(generalJSON, presentationFrame, options) {
1616
+ return __async(this, null, function* () {
1617
+ var _a;
1618
+ if (!this.userConfig.hasher) {
1619
+ throw new SDJWTException("Hasher not found");
1620
+ }
1621
+ const hasher = this.userConfig.hasher;
1622
+ const encodedSDJwt = generalJSON.toEncoded(0);
1623
+ const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
1624
+ if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new SDJWTException("Payload not found");
1625
+ const disclosures = yield sdjwt.getPresentDisclosures(
1626
+ presentationFrame,
1627
+ hasher
1628
+ );
1629
+ const encodedDisclosures = disclosures.map((d) => d.encode());
1630
+ const presentedGeneralJSON = new GeneralJSON({
1631
+ payload: generalJSON.payload,
1632
+ disclosures: encodedDisclosures,
1633
+ signatures: generalJSON.signatures
1634
+ });
1635
+ if (!(options == null ? void 0 : options.kb)) {
1636
+ return presentedGeneralJSON;
1637
+ }
1638
+ const presentSdJwtWithoutKb = yield sdjwt.present(
1639
+ presentationFrame,
1640
+ hasher
1641
+ );
1642
+ const sdHashStr = yield this.calculateSDHash(
1643
+ presentSdJwtWithoutKb,
1644
+ sdjwt,
1645
+ hasher
1646
+ );
1647
+ const kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
1648
+ const encodedKbJwt = kbJwt.encodeJwt();
1649
+ presentedGeneralJSON.kb_jwt = encodedKbJwt;
1650
+ return presentedGeneralJSON;
1651
+ });
1652
+ }
1653
+ // This function is for verifying the SD JWT
1654
+ // If requiredClaimKeys is provided, it will check if the required claim keys are presentation in the SD JWT
1655
+ // If requireKeyBindings is true, it will check if the key binding JWT is presentation and verify it
1656
+ verify(generalJSON, options) {
1657
+ return __async(this, null, function* () {
1658
+ if (!this.userConfig.hasher) {
1659
+ throw new SDJWTException("Hasher not found");
1660
+ }
1661
+ const hasher = this.userConfig.hasher;
1662
+ const { payload, headers } = yield this.validate(generalJSON);
1663
+ const encodedSDJwt = generalJSON.toEncoded(0);
1664
+ const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
1665
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
1666
+ throw new SDJWTException("Invalid SD JWT");
1667
+ }
1668
+ if (options == null ? void 0 : options.requiredClaimKeys) {
1669
+ const keys = yield sdjwt.keys(hasher);
1670
+ const missingKeys = options == null ? void 0 : options.requiredClaimKeys.filter(
1671
+ (k) => !keys.includes(k)
1672
+ );
1673
+ if (missingKeys.length > 0) {
1674
+ throw new SDJWTException(
1675
+ `Missing required claim keys: ${missingKeys.join(", ")}`
1676
+ );
1677
+ }
1678
+ }
1679
+ if (!(options == null ? void 0 : options.keyBindingNonce)) {
1680
+ return { payload, headers };
1681
+ }
1682
+ if (!sdjwt.kbJwt) {
1683
+ throw new SDJWTException("Key Binding JWT not exist");
1684
+ }
1685
+ if (!this.userConfig.kbVerifier) {
1686
+ throw new SDJWTException("Key Binding Verifier not found");
1687
+ }
1688
+ const kb = yield sdjwt.kbJwt.verifyKB({
1689
+ verifier: this.userConfig.kbVerifier,
1690
+ payload,
1691
+ nonce: options.keyBindingNonce,
1692
+ options
1693
+ });
1694
+ if (!kb) {
1695
+ throw new Error("signature is not valid");
1696
+ }
1697
+ const sdHashfromKb = kb.payload.sd_hash;
1698
+ const sdjwtWithoutKb = new SDJwt({
1699
+ jwt: sdjwt.jwt,
1700
+ disclosures: sdjwt.disclosures
1701
+ });
1702
+ const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
1703
+ const sdHashStr = yield this.calculateSDHash(
1704
+ presentSdJwtWithoutKb,
1705
+ sdjwt,
1706
+ hasher
1707
+ );
1708
+ if (sdHashStr !== sdHashfromKb) {
1709
+ throw new SDJWTException("Invalid sd_hash in Key Binding JWT");
1710
+ }
1711
+ return { payload, headers, kb };
1712
+ });
1713
+ }
1714
+ calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
1715
+ return __async(this, null, function* () {
1716
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
1717
+ throw new SDJWTException("Invalid SD JWT");
1718
+ }
1719
+ const { _sd_alg } = getSDAlgAndPayload(sdjwt.jwt.payload);
1720
+ const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
1721
+ const sdHashStr = uint8ArrayToBase64Url(sdHash);
1722
+ return sdHashStr;
1723
+ });
1724
+ }
1725
+ // This function is for validating the SD JWT
1726
+ // Just checking signature and return its the claims
1727
+ validate(generalJSON) {
1728
+ return __async(this, null, function* () {
1729
+ if (!this.userConfig.hasher) {
1730
+ throw new SDJWTException("Hasher not found");
1731
+ }
1732
+ if (!this.userConfig.verifier) {
1733
+ throw new SDJWTException("Verifier not found");
1734
+ }
1735
+ const hasher = this.userConfig.hasher;
1736
+ const verifier = this.userConfig.verifier;
1737
+ const { payload, signatures } = generalJSON;
1738
+ const results = yield Promise.all(
1739
+ signatures.map((s) => __async(this, null, function* () {
1740
+ const { protected: encodedHeader, signature } = s;
1741
+ const verified2 = yield verifier(
1742
+ `${encodedHeader}.${payload}`,
1743
+ signature
1744
+ );
1745
+ const header = decodeBase64urlJsonStrict(encodedHeader, "Invalid JWT");
1746
+ return { verified: verified2, header };
1747
+ }))
1748
+ );
1749
+ const verified = results.every((r) => r.verified);
1750
+ if (!verified) {
1751
+ throw new SDJWTException("Signature is not valid");
1752
+ }
1753
+ const encodedSDJwt = generalJSON.toEncoded(0);
1754
+ const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
1755
+ if (!sdjwt.jwt) {
1756
+ throw new SDJWTException("Invalid SD JWT");
1757
+ }
1758
+ const claims = yield sdjwt.getClaims(hasher);
1759
+ return { payload: claims, headers: results.map((r) => r.header) };
1760
+ });
1761
+ }
1762
+ config(newConfig) {
1763
+ this.userConfig = __spreadValues(__spreadValues({}, this.userConfig), newConfig);
1764
+ }
1765
+ encode(sdJwt, index) {
1766
+ return sdJwt.toEncoded(index);
1767
+ }
1768
+ decode(endcodedSDJwt) {
1769
+ return GeneralJSON.fromEncode(endcodedSDJwt);
1770
+ }
1771
+ keys(generalSdjwt) {
1772
+ return __async(this, null, function* () {
1773
+ if (!this.userConfig.hasher) {
1774
+ throw new SDJWTException("Hasher not found");
1775
+ }
1776
+ const endcodedSDJwt = generalSdjwt.toEncoded(0);
1777
+ const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
1778
+ return sdjwt.keys(this.userConfig.hasher);
1779
+ });
1780
+ }
1781
+ presentableKeys(generalSdjwt) {
1782
+ return __async(this, null, function* () {
1783
+ if (!this.userConfig.hasher) {
1784
+ throw new SDJWTException("Hasher not found");
1785
+ }
1786
+ const endcodedSDJwt = generalSdjwt.toEncoded(0);
1787
+ const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
1788
+ return sdjwt.presentableKeys(this.userConfig.hasher);
1789
+ });
1790
+ }
1791
+ getClaims(generalSdjwt) {
1792
+ return __async(this, null, function* () {
1793
+ if (!this.userConfig.hasher) {
1794
+ throw new SDJWTException("Hasher not found");
1795
+ }
1796
+ const endcodedSDJwt = generalSdjwt.toEncoded(0);
1797
+ const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
1798
+ return sdjwt.getClaims(this.userConfig.hasher);
1799
+ });
1800
+ }
1801
+ };
1802
+ SDJwtGeneralJSONInstance.DEFAULT_hashAlg = "sha-256";
1803
+ export {
1804
+ Disclosure,
1805
+ FlattenJSON,
1806
+ GeneralJSON,
1807
+ IANA_HASH_ALGORITHMS,
1808
+ Jwt,
1809
+ KBJwt,
1810
+ KB_JWT_TYP,
1811
+ SDJWTException,
1812
+ SDJwt,
1813
+ SDJwtGeneralJSONInstance,
1814
+ SDJwtInstance,
1815
+ SD_DECOY,
1816
+ SD_DIGEST,
1817
+ SD_LIST_KEY,
1818
+ SD_SEPARATOR,
1819
+ base64UrlToUint8Array,
1820
+ base64urlDecode,
1821
+ base64urlEncode,
1822
+ createDecoy,
1823
+ createHashMapping,
1824
+ createHashMappingForSerializedDisclosure,
1825
+ createHashMappingSync,
1826
+ decodeJwt,
1827
+ decodeSdJwt,
1828
+ decodeSdJwtSync,
1829
+ ensureError,
1830
+ getClaims,
1831
+ getClaimsSync,
1832
+ getSDAlgAndPayload,
1833
+ listKeys,
1834
+ pack,
1835
+ present,
1836
+ presentSync,
1837
+ presentableKeys,
1838
+ presentableKeysSync,
1839
+ selectDisclosures,
1840
+ splitSdJwt,
1841
+ transformPresentationFrame,
1842
+ uint8ArrayToBase64Url,
1843
+ unpack,
1844
+ unpackObj,
1845
+ unpackSync
1846
+ };