@sd-jwt/core 0.19.1-next.1 → 0.19.1-next.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -5
- package/dist/index.d.mts +364 -16
- package/dist/index.d.ts +364 -16
- package/dist/index.js +803 -148
- package/dist/index.mjs +744 -133
- package/package.json +4 -7
- package/src/decode/decode.ts +366 -0
- package/src/decode/index.ts +1 -0
- package/src/decoy.ts +2 -2
- package/src/flattenJSON.ts +3 -3
- package/src/generalJSON.ts +3 -3
- package/src/index.ts +230 -14
- package/src/jwt.ts +10 -15
- package/src/kbjwt.ts +19 -15
- package/src/present/index.ts +1 -0
- package/src/present/present.ts +210 -0
- package/src/sdjwt.ts +11 -10
- package/src/test/decode/decode.spec.ts +202 -0
- package/src/test/decoy.spec.ts +2 -2
- package/src/test/generalJSON.spec.ts +1 -1
- package/src/test/index.spec.ts +288 -2
- package/src/test/jwt.spec.ts +7 -13
- package/src/test/kbjwt.spec.ts +216 -5
- package/src/test/present/present.spec.ts +305 -0
- package/src/test/sdjwt.spec.ts +4 -4
- package/src/test/types/type.spec.ts +88 -0
- package/src/test/utils/base64url.spec.ts +33 -0
- package/src/test/utils/disclosure.spec.ts +170 -0
- package/src/test/utils/error.spec.ts +15 -0
- package/src/types/index.ts +2 -0
- package/src/types/type.ts +249 -0
- package/src/types/verification-error.ts +55 -0
- package/src/utils/base64url.ts +6 -0
- package/src/utils/disclosure.ts +98 -0
- package/src/utils/error.ts +25 -0
- package/src/utils/index.ts +3 -0
- package/test/app-e2e.spec.ts +8 -8
- package/test/rfc9901-validation.spec.ts +150 -0
- package/CHANGELOG.md +0 -240
package/dist/index.mjs
CHANGED
|
@@ -17,6 +17,18 @@ var __spreadValues = (a, b) => {
|
|
|
17
17
|
return a;
|
|
18
18
|
};
|
|
19
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
|
+
};
|
|
20
32
|
var __async = (__this, __arguments, generator) => {
|
|
21
33
|
return new Promise((resolve, reject) => {
|
|
22
34
|
var fulfilled = (value) => {
|
|
@@ -38,23 +50,344 @@ var __async = (__this, __arguments, generator) => {
|
|
|
38
50
|
});
|
|
39
51
|
};
|
|
40
52
|
|
|
41
|
-
// src/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
|
47
80
|
import {
|
|
81
|
+
base64UrlToUint8Array,
|
|
48
82
|
base64urlDecode,
|
|
49
|
-
base64urlEncode
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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/disclosure.ts
|
|
106
|
+
var Disclosure = class _Disclosure {
|
|
107
|
+
constructor(data, _meta) {
|
|
108
|
+
this._digest = _meta == null ? void 0 : _meta.digest;
|
|
109
|
+
this._encoded = _meta == null ? void 0 : _meta.encoded;
|
|
110
|
+
if (data.length === 2) {
|
|
111
|
+
this.salt = data[0];
|
|
112
|
+
this.value = data[1];
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (data.length === 3) {
|
|
116
|
+
this.salt = data[0];
|
|
117
|
+
this.key = data[1];
|
|
118
|
+
this.value = data[2];
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
throw new SDJWTException("Invalid disclosure data");
|
|
122
|
+
}
|
|
123
|
+
// We need to digest of the original encoded data.
|
|
124
|
+
// After decode process, we use JSON.stringify to encode the data.
|
|
125
|
+
// This can be different from the original encoded data.
|
|
126
|
+
static fromEncode(s, hash) {
|
|
127
|
+
return __async(this, null, function* () {
|
|
128
|
+
const { hasher, alg } = hash;
|
|
129
|
+
const digest = yield hasher(s, alg);
|
|
130
|
+
const digestStr = uint8ArrayToBase64Url(digest);
|
|
131
|
+
const item = JSON.parse(base64urlDecode(s));
|
|
132
|
+
return _Disclosure.fromArray(item, { digest: digestStr, encoded: s });
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
static fromEncodeSync(s, hash) {
|
|
136
|
+
const { hasher, alg } = hash;
|
|
137
|
+
const digest = hasher(s, alg);
|
|
138
|
+
const digestStr = uint8ArrayToBase64Url(digest);
|
|
139
|
+
const item = JSON.parse(base64urlDecode(s));
|
|
140
|
+
return _Disclosure.fromArray(item, { digest: digestStr, encoded: s });
|
|
141
|
+
}
|
|
142
|
+
static fromArray(item, _meta) {
|
|
143
|
+
return new _Disclosure(item, _meta);
|
|
144
|
+
}
|
|
145
|
+
encode() {
|
|
146
|
+
if (!this._encoded) {
|
|
147
|
+
this._encoded = base64urlEncode(JSON.stringify(this.decode()));
|
|
148
|
+
}
|
|
149
|
+
return this._encoded;
|
|
150
|
+
}
|
|
151
|
+
decode() {
|
|
152
|
+
return this.key ? [this.salt, this.key, this.value] : [this.salt, this.value];
|
|
153
|
+
}
|
|
154
|
+
digest(hash) {
|
|
155
|
+
return __async(this, null, function* () {
|
|
156
|
+
const { hasher, alg } = hash;
|
|
157
|
+
if (!this._digest) {
|
|
158
|
+
const hash2 = yield hasher(this.encode(), alg);
|
|
159
|
+
this._digest = uint8ArrayToBase64Url(hash2);
|
|
160
|
+
}
|
|
161
|
+
return this._digest;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
digestSync(hash) {
|
|
165
|
+
const { hasher, alg } = hash;
|
|
166
|
+
if (!this._digest) {
|
|
167
|
+
const hash2 = hasher(this.encode(), alg);
|
|
168
|
+
this._digest = uint8ArrayToBase64Url(hash2);
|
|
169
|
+
}
|
|
170
|
+
return this._digest;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// src/decode/decode.ts
|
|
175
|
+
var decodeJwt = (jwt) => {
|
|
176
|
+
const { 0: header, 1: payload, 2: signature, length } = jwt.split(".");
|
|
177
|
+
if (length !== 3) {
|
|
178
|
+
throw new SDJWTException("Invalid JWT as input");
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
header: JSON.parse(base64urlDecode(header)),
|
|
182
|
+
payload: JSON.parse(base64urlDecode(payload)),
|
|
183
|
+
signature
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
var splitSdJwt = (sdjwt) => {
|
|
187
|
+
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
|
|
188
|
+
if (encodedDisclosures.length === 0) {
|
|
189
|
+
return {
|
|
190
|
+
jwt: encodedJwt,
|
|
191
|
+
disclosures: []
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
const encodedKeyBindingJwt = encodedDisclosures.pop();
|
|
195
|
+
return {
|
|
196
|
+
jwt: encodedJwt,
|
|
197
|
+
disclosures: encodedDisclosures,
|
|
198
|
+
kbJwt: encodedKeyBindingJwt || void 0
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
var decodeSdJwt = (sdjwt, hasher) => __async(null, null, function* () {
|
|
202
|
+
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
|
|
203
|
+
const jwt = decodeJwt(encodedJwt);
|
|
204
|
+
if (encodedDisclosures.length === 0) {
|
|
205
|
+
return {
|
|
206
|
+
jwt,
|
|
207
|
+
disclosures: []
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const encodedKeyBindingJwt = encodedDisclosures.pop();
|
|
211
|
+
const kbJwt = encodedKeyBindingJwt ? decodeJwt(encodedKeyBindingJwt) : void 0;
|
|
212
|
+
const { _sd_alg } = getSDAlgAndPayload(jwt.payload);
|
|
213
|
+
const disclosures = yield Promise.all(
|
|
214
|
+
encodedDisclosures.map(
|
|
215
|
+
(ed) => Disclosure.fromEncode(ed, { alg: _sd_alg, hasher })
|
|
216
|
+
)
|
|
217
|
+
);
|
|
218
|
+
return {
|
|
219
|
+
jwt,
|
|
220
|
+
disclosures,
|
|
221
|
+
kbJwt
|
|
222
|
+
};
|
|
223
|
+
});
|
|
224
|
+
var decodeSdJwtSync = (sdjwt, hasher) => {
|
|
225
|
+
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
|
|
226
|
+
const jwt = decodeJwt(encodedJwt);
|
|
227
|
+
if (encodedDisclosures.length === 0) {
|
|
228
|
+
return {
|
|
229
|
+
jwt,
|
|
230
|
+
disclosures: []
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
const encodedKeyBindingJwt = encodedDisclosures.pop();
|
|
234
|
+
const kbJwt = encodedKeyBindingJwt ? decodeJwt(encodedKeyBindingJwt) : void 0;
|
|
235
|
+
const { _sd_alg } = getSDAlgAndPayload(jwt.payload);
|
|
236
|
+
const disclosures = encodedDisclosures.map(
|
|
237
|
+
(ed) => Disclosure.fromEncodeSync(ed, { alg: _sd_alg, hasher })
|
|
238
|
+
);
|
|
239
|
+
return {
|
|
240
|
+
jwt,
|
|
241
|
+
disclosures,
|
|
242
|
+
kbJwt
|
|
243
|
+
};
|
|
244
|
+
};
|
|
245
|
+
var getClaims = (rawPayload, disclosures, hasher) => __async(null, null, function* () {
|
|
246
|
+
const { unpackedObj } = yield unpack(rawPayload, disclosures, hasher);
|
|
247
|
+
return unpackedObj;
|
|
248
|
+
});
|
|
249
|
+
var getClaimsSync = (rawPayload, disclosures, hasher) => {
|
|
250
|
+
const { unpackedObj } = unpackSync(rawPayload, disclosures, hasher);
|
|
251
|
+
return unpackedObj;
|
|
252
|
+
};
|
|
253
|
+
var isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
254
|
+
var unpackArray = (arr, map, prefix = "", seenDigests) => {
|
|
255
|
+
const keys = {};
|
|
256
|
+
const unpackedArray = [];
|
|
257
|
+
arr.forEach((item, idx) => {
|
|
258
|
+
if (isRecord(item)) {
|
|
259
|
+
const hash = item[SD_LIST_KEY];
|
|
260
|
+
if (typeof hash === "string") {
|
|
261
|
+
if (seenDigests) {
|
|
262
|
+
if (seenDigests.has(hash)) {
|
|
263
|
+
throw new SDJWTException(
|
|
264
|
+
"Duplicate digest found in SD-JWT payload"
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
seenDigests.add(hash);
|
|
268
|
+
}
|
|
269
|
+
const disclosed = map[hash];
|
|
270
|
+
if (disclosed) {
|
|
271
|
+
const presentKey = prefix ? `${prefix}.${idx}` : `${idx}`;
|
|
272
|
+
keys[presentKey] = hash;
|
|
273
|
+
const { unpackedObj, disclosureKeymap: disclosureKeys } = unpackObjInternal(disclosed.value, map, presentKey, seenDigests);
|
|
274
|
+
unpackedArray.push(unpackedObj);
|
|
275
|
+
Object.assign(keys, disclosureKeys);
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
const newKey = prefix ? `${prefix}.${idx}` : `${idx}`;
|
|
279
|
+
const { unpackedObj, disclosureKeymap: disclosureKeys } = unpackObjInternal(item, map, newKey, seenDigests);
|
|
280
|
+
unpackedArray.push(unpackedObj);
|
|
281
|
+
Object.assign(keys, disclosureKeys);
|
|
282
|
+
}
|
|
283
|
+
} else if (Array.isArray(item)) {
|
|
284
|
+
const newKey = prefix ? `${prefix}.${idx}` : `${idx}`;
|
|
285
|
+
const { unpackedObj, disclosureKeymap: disclosureKeys } = unpackObjInternal(item, map, newKey, seenDigests);
|
|
286
|
+
unpackedArray.push(unpackedObj);
|
|
287
|
+
Object.assign(keys, disclosureKeys);
|
|
288
|
+
} else {
|
|
289
|
+
unpackedArray.push(item);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
return { unpackedObj: unpackedArray, disclosureKeymap: keys };
|
|
293
|
+
};
|
|
294
|
+
var unpackObj = (obj, map) => {
|
|
295
|
+
const copiedObj = JSON.parse(JSON.stringify(obj));
|
|
296
|
+
const seenDigests = /* @__PURE__ */ new Set();
|
|
297
|
+
const result = unpackObjInternal(copiedObj, map, "", seenDigests);
|
|
298
|
+
const mapDigests = Object.keys(map);
|
|
299
|
+
const unusedDigests = mapDigests.filter((d) => !seenDigests.has(d));
|
|
300
|
+
if (unusedDigests.length > 0) {
|
|
301
|
+
throw new SDJWTException("Unreferenced disclosure(s) detected in SD-JWT");
|
|
302
|
+
}
|
|
303
|
+
return result;
|
|
304
|
+
};
|
|
305
|
+
var unpackObjInternal = (obj, map, prefix = "", seenDigests) => {
|
|
306
|
+
const keys = {};
|
|
307
|
+
if (typeof obj === "object" && obj !== null) {
|
|
308
|
+
if (Array.isArray(obj)) {
|
|
309
|
+
return unpackArray(obj, map, prefix, seenDigests);
|
|
310
|
+
}
|
|
311
|
+
const record = obj;
|
|
312
|
+
for (const key in record) {
|
|
313
|
+
if (key !== SD_DIGEST && key !== SD_LIST_KEY && typeof record[key] === "object") {
|
|
314
|
+
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
315
|
+
const { unpackedObj: unpackedObj2, disclosureKeymap: disclosureKeys } = unpackObjInternal(record[key], map, newKey, seenDigests);
|
|
316
|
+
record[key] = unpackedObj2;
|
|
317
|
+
Object.assign(keys, disclosureKeys);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const _a = record, { _sd } = _a, payload = __objRest(_a, ["_sd"]);
|
|
321
|
+
const claims = {};
|
|
322
|
+
if (_sd) {
|
|
323
|
+
for (const hash of _sd) {
|
|
324
|
+
if (seenDigests) {
|
|
325
|
+
if (seenDigests.has(hash)) {
|
|
326
|
+
throw new SDJWTException(
|
|
327
|
+
"Duplicate digest found in SD-JWT payload"
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
seenDigests.add(hash);
|
|
331
|
+
}
|
|
332
|
+
const disclosed = map[hash];
|
|
333
|
+
if (disclosed == null ? void 0 : disclosed.key) {
|
|
334
|
+
if (disclosed.key in payload) {
|
|
335
|
+
throw new SDJWTException(
|
|
336
|
+
`Disclosed claim name "${disclosed.key}" conflicts with existing payload key`
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
const presentKey = prefix ? `${prefix}.${disclosed.key}` : disclosed.key;
|
|
340
|
+
keys[presentKey] = hash;
|
|
341
|
+
const { unpackedObj: unpackedObj2, disclosureKeymap: disclosureKeys } = unpackObjInternal(disclosed.value, map, presentKey, seenDigests);
|
|
342
|
+
claims[disclosed.key] = unpackedObj2;
|
|
343
|
+
Object.assign(keys, disclosureKeys);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
const unpackedObj = Object.assign(payload, claims);
|
|
348
|
+
return { unpackedObj, disclosureKeymap: keys };
|
|
349
|
+
}
|
|
350
|
+
return { unpackedObj: obj, disclosureKeymap: keys };
|
|
351
|
+
};
|
|
352
|
+
var createHashMapping = (disclosures, hash) => __async(null, null, function* () {
|
|
353
|
+
const map = {};
|
|
354
|
+
for (let i = 0; i < disclosures.length; i++) {
|
|
355
|
+
const disclosure = disclosures[i];
|
|
356
|
+
const digest = yield disclosure.digest(hash);
|
|
357
|
+
map[digest] = disclosure;
|
|
358
|
+
}
|
|
359
|
+
return map;
|
|
360
|
+
});
|
|
361
|
+
var createHashMappingSync = (disclosures, hash) => {
|
|
362
|
+
const map = {};
|
|
363
|
+
for (let i = 0; i < disclosures.length; i++) {
|
|
364
|
+
const disclosure = disclosures[i];
|
|
365
|
+
const digest = disclosure.digestSync(hash);
|
|
366
|
+
map[digest] = disclosure;
|
|
367
|
+
}
|
|
368
|
+
return map;
|
|
369
|
+
};
|
|
370
|
+
var getSDAlgAndPayload = (SdJwtPayload) => {
|
|
371
|
+
const _a = SdJwtPayload, { _sd_alg } = _a, payload = __objRest(_a, ["_sd_alg"]);
|
|
372
|
+
if (typeof _sd_alg !== "string") {
|
|
373
|
+
return { _sd_alg: "sha-256", payload };
|
|
374
|
+
}
|
|
375
|
+
return { _sd_alg, payload };
|
|
376
|
+
};
|
|
377
|
+
var unpack = (SdJwtPayload, disclosures, hasher) => __async(null, null, function* () {
|
|
378
|
+
const { _sd_alg, payload } = getSDAlgAndPayload(SdJwtPayload);
|
|
379
|
+
const hash = { hasher, alg: _sd_alg };
|
|
380
|
+
const map = yield createHashMapping(disclosures, hash);
|
|
381
|
+
return unpackObj(payload, map);
|
|
382
|
+
});
|
|
383
|
+
var unpackSync = (SdJwtPayload, disclosures, hasher) => {
|
|
384
|
+
const { _sd_alg, payload } = getSDAlgAndPayload(SdJwtPayload);
|
|
385
|
+
const hash = { hasher, alg: _sd_alg };
|
|
386
|
+
const map = createHashMappingSync(disclosures, hash);
|
|
387
|
+
return unpackObj(payload, map);
|
|
388
|
+
};
|
|
53
389
|
|
|
54
390
|
// src/flattenJSON.ts
|
|
55
|
-
import { splitSdJwt } from "@sd-jwt/decode";
|
|
56
|
-
import { SD_SEPARATOR } from "@sd-jwt/types";
|
|
57
|
-
import { SDJWTException } from "@sd-jwt/utils";
|
|
58
391
|
var FlattenJSON = class _FlattenJSON {
|
|
59
392
|
constructor(data) {
|
|
60
393
|
this.disclosures = data.disclosures;
|
|
@@ -117,9 +450,6 @@ var FlattenJSON = class _FlattenJSON {
|
|
|
117
450
|
};
|
|
118
451
|
|
|
119
452
|
// src/generalJSON.ts
|
|
120
|
-
import { splitSdJwt as splitSdJwt2 } from "@sd-jwt/decode";
|
|
121
|
-
import { SD_SEPARATOR as SD_SEPARATOR2 } from "@sd-jwt/types";
|
|
122
|
-
import { base64urlEncode, SDJWTException as SDJWTException2 } from "@sd-jwt/utils";
|
|
123
453
|
var GeneralJSON = class _GeneralJSON {
|
|
124
454
|
constructor(data) {
|
|
125
455
|
this.payload = data.payload;
|
|
@@ -128,10 +458,10 @@ var GeneralJSON = class _GeneralJSON {
|
|
|
128
458
|
this.signatures = data.signatures;
|
|
129
459
|
}
|
|
130
460
|
static fromEncode(encodedSdJwt) {
|
|
131
|
-
const { jwt, disclosures, kbJwt } =
|
|
461
|
+
const { jwt, disclosures, kbJwt } = splitSdJwt(encodedSdJwt);
|
|
132
462
|
const { 0: protectedHeader, 1: payload, 2: signature } = jwt.split(".");
|
|
133
463
|
if (!protectedHeader || !payload || !signature) {
|
|
134
|
-
throw new
|
|
464
|
+
throw new SDJWTException("Invalid JWT");
|
|
135
465
|
}
|
|
136
466
|
return new _GeneralJSON({
|
|
137
467
|
payload,
|
|
@@ -148,7 +478,7 @@ var GeneralJSON = class _GeneralJSON {
|
|
|
148
478
|
static fromSerialized(json) {
|
|
149
479
|
var _a, _b, _c;
|
|
150
480
|
if (!json.signatures[0]) {
|
|
151
|
-
throw new
|
|
481
|
+
throw new SDJWTException("Invalid JSON");
|
|
152
482
|
}
|
|
153
483
|
const disclosures = (_b = (_a = json.signatures[0].header) == null ? void 0 : _a.disclosures) != null ? _b : [];
|
|
154
484
|
const kb_jwt = (_c = json.signatures[0].header) == null ? void 0 : _c.kb_jwt;
|
|
@@ -194,19 +524,19 @@ var GeneralJSON = class _GeneralJSON {
|
|
|
194
524
|
toEncoded(index) {
|
|
195
525
|
var _a;
|
|
196
526
|
if (index < 0 || index >= this.signatures.length) {
|
|
197
|
-
throw new
|
|
527
|
+
throw new SDJWTException("Index out of bounds");
|
|
198
528
|
}
|
|
199
529
|
const data = [];
|
|
200
530
|
const { protected: protectedHeader, signature } = this.signatures[index];
|
|
201
531
|
const jwt = `${protectedHeader}.${this.payload}.${signature}`;
|
|
202
532
|
data.push(jwt);
|
|
203
533
|
if (this.disclosures && this.disclosures.length > 0) {
|
|
204
|
-
const disclosures = this.disclosures.join(
|
|
534
|
+
const disclosures = this.disclosures.join(SD_SEPARATOR);
|
|
205
535
|
data.push(disclosures);
|
|
206
536
|
}
|
|
207
537
|
const kb = (_a = this.kb_jwt) != null ? _a : "";
|
|
208
538
|
data.push(kb);
|
|
209
|
-
return data.join(
|
|
539
|
+
return data.join(SD_SEPARATOR);
|
|
210
540
|
}
|
|
211
541
|
addSignature(protectedHeader, signer, kid) {
|
|
212
542
|
return __async(this, null, function* () {
|
|
@@ -222,8 +552,6 @@ var GeneralJSON = class _GeneralJSON {
|
|
|
222
552
|
};
|
|
223
553
|
|
|
224
554
|
// src/jwt.ts
|
|
225
|
-
import { decodeJwt } from "@sd-jwt/decode";
|
|
226
|
-
import { base64urlEncode as base64urlEncode2, SDJWTException as SDJWTException3 } from "@sd-jwt/utils";
|
|
227
555
|
var Jwt = class _Jwt {
|
|
228
556
|
constructor(data) {
|
|
229
557
|
this.header = data == null ? void 0 : data.header;
|
|
@@ -258,18 +586,18 @@ var Jwt = class _Jwt {
|
|
|
258
586
|
}
|
|
259
587
|
getUnsignedToken() {
|
|
260
588
|
if (!this.header || !this.payload) {
|
|
261
|
-
throw new
|
|
589
|
+
throw new SDJWTException("Serialize Error: Invalid JWT");
|
|
262
590
|
}
|
|
263
591
|
if (this.encoded) {
|
|
264
592
|
const parts = this.encoded.split(".");
|
|
265
593
|
if (parts.length !== 3) {
|
|
266
|
-
throw new
|
|
594
|
+
throw new SDJWTException(`Invalid JWT format: ${this.encoded}`);
|
|
267
595
|
}
|
|
268
596
|
const unsignedToken = parts.slice(0, 2).join(".");
|
|
269
597
|
return unsignedToken;
|
|
270
598
|
}
|
|
271
|
-
const header =
|
|
272
|
-
const payload =
|
|
599
|
+
const header = base64urlEncode(JSON.stringify(this.header));
|
|
600
|
+
const payload = base64urlEncode(JSON.stringify(this.payload));
|
|
273
601
|
return `${header}.${payload}`;
|
|
274
602
|
}
|
|
275
603
|
sign(signer) {
|
|
@@ -284,10 +612,10 @@ var Jwt = class _Jwt {
|
|
|
284
612
|
return this.encoded;
|
|
285
613
|
}
|
|
286
614
|
if (!this.header || !this.payload || !this.signature) {
|
|
287
|
-
throw new
|
|
615
|
+
throw new SDJWTException("Serialize Error: Invalid JWT");
|
|
288
616
|
}
|
|
289
|
-
const header =
|
|
290
|
-
const payload =
|
|
617
|
+
const header = base64urlEncode(JSON.stringify(this.header));
|
|
618
|
+
const payload = base64urlEncode(JSON.stringify(this.payload));
|
|
291
619
|
const signature = this.signature;
|
|
292
620
|
const compact = `${header}.${payload}.${signature}`;
|
|
293
621
|
this.encoded = compact;
|
|
@@ -305,22 +633,25 @@ var Jwt = class _Jwt {
|
|
|
305
633
|
var _a, _b, _c, _d;
|
|
306
634
|
const skew = (options == null ? void 0 : options.skewSeconds) ? options.skewSeconds : 0;
|
|
307
635
|
const currentDate = (_a = options == null ? void 0 : options.currentDate) != null ? _a : Math.floor(Date.now() / 1e3);
|
|
308
|
-
|
|
309
|
-
|
|
636
|
+
const iat = (_b = this.payload) == null ? void 0 : _b.iat;
|
|
637
|
+
const nbf = (_c = this.payload) == null ? void 0 : _c.nbf;
|
|
638
|
+
const exp = (_d = this.payload) == null ? void 0 : _d.exp;
|
|
639
|
+
if (typeof iat === "number" && iat - skew > currentDate) {
|
|
640
|
+
throw new SDJWTException("Verify Error: JWT is not yet valid");
|
|
310
641
|
}
|
|
311
|
-
if (
|
|
312
|
-
throw new
|
|
642
|
+
if (typeof nbf === "number" && nbf - skew > currentDate) {
|
|
643
|
+
throw new SDJWTException("Verify Error: JWT is not yet valid");
|
|
313
644
|
}
|
|
314
|
-
if (
|
|
315
|
-
throw new
|
|
645
|
+
if (typeof exp === "number" && exp + skew < currentDate) {
|
|
646
|
+
throw new SDJWTException("Verify Error: JWT is expired");
|
|
316
647
|
}
|
|
317
648
|
if (!this.signature) {
|
|
318
|
-
throw new
|
|
649
|
+
throw new SDJWTException("Verify Error: no signature in JWT");
|
|
319
650
|
}
|
|
320
651
|
const data = this.getUnsignedToken();
|
|
321
652
|
const verified = yield verifier(data, this.signature, options);
|
|
322
653
|
if (!verified) {
|
|
323
|
-
throw new
|
|
654
|
+
throw new SDJWTException("Verify Error: Invalid JWT Signature");
|
|
324
655
|
}
|
|
325
656
|
return { payload: this.payload, header: this.header };
|
|
326
657
|
});
|
|
@@ -328,35 +659,25 @@ var Jwt = class _Jwt {
|
|
|
328
659
|
};
|
|
329
660
|
|
|
330
661
|
// src/kbjwt.ts
|
|
331
|
-
import {
|
|
332
|
-
KB_JWT_TYP
|
|
333
|
-
} from "@sd-jwt/types";
|
|
334
|
-
import { SDJWTException as SDJWTException4 } from "@sd-jwt/utils";
|
|
335
662
|
var KBJwt = class _KBJwt extends Jwt {
|
|
336
663
|
// Checking the validity of the key binding jwt
|
|
337
664
|
// 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
|
|
338
665
|
verifyKB(values) {
|
|
339
666
|
return __async(this, null, function* () {
|
|
340
|
-
var _a;
|
|
341
667
|
if (!this.header || !this.payload || !this.signature) {
|
|
342
|
-
throw new
|
|
668
|
+
throw new SDJWTException("Verify Error: Invalid JWT");
|
|
343
669
|
}
|
|
344
670
|
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
|
|
345
|
-
!(this.payload.sd_hash ||
|
|
346
|
-
throw new
|
|
347
|
-
}
|
|
348
|
-
const data = this.getUnsignedToken();
|
|
349
|
-
const verified = yield values.verifier(
|
|
350
|
-
data,
|
|
351
|
-
this.signature,
|
|
352
|
-
values.payload
|
|
353
|
-
);
|
|
354
|
-
if (!verified) {
|
|
355
|
-
throw new SDJWTException4("Verify Error: Invalid JWT Signature");
|
|
671
|
+
!(this.payload.sd_hash || "_sd_hash" in this.payload && this.payload._sd_hash)) {
|
|
672
|
+
throw new SDJWTException("Invalid Key Binding Jwt");
|
|
356
673
|
}
|
|
357
674
|
if (this.payload.nonce !== values.nonce) {
|
|
358
|
-
throw new
|
|
675
|
+
throw new SDJWTException("Verify Error: Invalid Nonce");
|
|
359
676
|
}
|
|
677
|
+
yield this.verify(
|
|
678
|
+
(data, sig) => values.verifier(data, sig, values.payload),
|
|
679
|
+
values.options
|
|
680
|
+
);
|
|
360
681
|
return { payload: this.payload, header: this.header };
|
|
361
682
|
});
|
|
362
683
|
}
|
|
@@ -375,19 +696,7 @@ var KBJwt = class _KBJwt extends Jwt {
|
|
|
375
696
|
}
|
|
376
697
|
};
|
|
377
698
|
|
|
378
|
-
// src/sdjwt.ts
|
|
379
|
-
import { createHashMapping, getSDAlgAndPayload, unpack } from "@sd-jwt/decode";
|
|
380
|
-
import { transformPresentationFrame } from "@sd-jwt/present";
|
|
381
|
-
import {
|
|
382
|
-
SD_DECOY,
|
|
383
|
-
SD_DIGEST,
|
|
384
|
-
SD_LIST_KEY,
|
|
385
|
-
SD_SEPARATOR as SD_SEPARATOR3
|
|
386
|
-
} from "@sd-jwt/types";
|
|
387
|
-
import { Disclosure, SDJWTException as SDJWTException5 } from "@sd-jwt/utils";
|
|
388
|
-
|
|
389
699
|
// src/decoy.ts
|
|
390
|
-
import { uint8ArrayToBase64Url } from "@sd-jwt/utils";
|
|
391
700
|
var createDecoy = (hash, saltGenerator) => __async(null, null, function* () {
|
|
392
701
|
const { hasher, alg } = hash;
|
|
393
702
|
const salt = yield saltGenerator(16);
|
|
@@ -395,6 +704,110 @@ var createDecoy = (hash, saltGenerator) => __async(null, null, function* () {
|
|
|
395
704
|
return uint8ArrayToBase64Url(decoy);
|
|
396
705
|
});
|
|
397
706
|
|
|
707
|
+
// src/present/present.ts
|
|
708
|
+
var presentableKeys = (rawPayload, disclosures, hasher) => __async(null, null, function* () {
|
|
709
|
+
const { disclosureKeymap } = yield unpack(rawPayload, disclosures, hasher);
|
|
710
|
+
return Object.keys(disclosureKeymap).sort();
|
|
711
|
+
});
|
|
712
|
+
var presentableKeysSync = (rawPayload, disclosures, hasher) => {
|
|
713
|
+
const { disclosureKeymap } = unpackSync(rawPayload, disclosures, hasher);
|
|
714
|
+
return Object.keys(disclosureKeymap).sort();
|
|
715
|
+
};
|
|
716
|
+
var present = (sdJwt, presentFrame, hasher) => __async(null, null, function* () {
|
|
717
|
+
const { jwt, kbJwt } = splitSdJwt(sdJwt);
|
|
718
|
+
const {
|
|
719
|
+
jwt: { payload },
|
|
720
|
+
disclosures
|
|
721
|
+
} = yield decodeSdJwt(sdJwt, hasher);
|
|
722
|
+
const { _sd_alg: alg } = getSDAlgAndPayload(payload);
|
|
723
|
+
const hash = { alg, hasher };
|
|
724
|
+
const keys = transformPresentationFrame(presentFrame);
|
|
725
|
+
const hashmap = yield createHashMapping(disclosures, hash);
|
|
726
|
+
const { disclosureKeymap } = yield unpack(payload, disclosures, hasher);
|
|
727
|
+
const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
728
|
+
return [
|
|
729
|
+
jwt,
|
|
730
|
+
...presentedDisclosures.map((d) => d.encode()),
|
|
731
|
+
kbJwt != null ? kbJwt : ""
|
|
732
|
+
].join(SD_SEPARATOR);
|
|
733
|
+
});
|
|
734
|
+
var presentSync = (sdJwt, presentFrame, hasher) => {
|
|
735
|
+
const { jwt, kbJwt } = splitSdJwt(sdJwt);
|
|
736
|
+
const {
|
|
737
|
+
jwt: { payload },
|
|
738
|
+
disclosures
|
|
739
|
+
} = decodeSdJwtSync(sdJwt, hasher);
|
|
740
|
+
const { _sd_alg: alg } = getSDAlgAndPayload(payload);
|
|
741
|
+
const hash = { alg, hasher };
|
|
742
|
+
const keys = transformPresentationFrame(presentFrame);
|
|
743
|
+
const hashmap = createHashMappingSync(disclosures, hash);
|
|
744
|
+
const { disclosureKeymap } = unpackSync(payload, disclosures, hasher);
|
|
745
|
+
const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
746
|
+
return [
|
|
747
|
+
jwt,
|
|
748
|
+
...presentedDisclosures.map((d) => d.encode()),
|
|
749
|
+
kbJwt != null ? kbJwt : ""
|
|
750
|
+
].join(SD_SEPARATOR);
|
|
751
|
+
};
|
|
752
|
+
var transformPresentationFrame = (obj, prefix = "") => {
|
|
753
|
+
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
754
|
+
const newPrefix = prefix ? `${prefix}.${key}` : key;
|
|
755
|
+
if (typeof value === "boolean") {
|
|
756
|
+
if (value) {
|
|
757
|
+
acc.push(newPrefix);
|
|
758
|
+
}
|
|
759
|
+
} else if (typeof value === "object" && value !== null) {
|
|
760
|
+
acc.push(
|
|
761
|
+
newPrefix,
|
|
762
|
+
...transformPresentationFrame(
|
|
763
|
+
value,
|
|
764
|
+
newPrefix
|
|
765
|
+
)
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
return acc;
|
|
769
|
+
}, []);
|
|
770
|
+
};
|
|
771
|
+
var createHashMappingForSerializedDisclosure = (disclosures) => {
|
|
772
|
+
const map = {};
|
|
773
|
+
for (let i = 0; i < disclosures.length; i++) {
|
|
774
|
+
const disclosure = disclosures[i];
|
|
775
|
+
const { digest, encoded, key, salt, value } = disclosure;
|
|
776
|
+
map[digest] = Disclosure.fromArray(
|
|
777
|
+
key ? [salt, key, value] : [salt, value],
|
|
778
|
+
{ digest, encoded }
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
return map;
|
|
782
|
+
};
|
|
783
|
+
var selectDisclosures = (payload, disclosures, presentationFrame) => {
|
|
784
|
+
if (disclosures.length === 0) {
|
|
785
|
+
return [];
|
|
786
|
+
}
|
|
787
|
+
const hashmap = createHashMappingForSerializedDisclosure(disclosures);
|
|
788
|
+
const { disclosureKeymap } = unpackObj(payload, hashmap);
|
|
789
|
+
const keys = transformPresentationFrame(presentationFrame);
|
|
790
|
+
const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
791
|
+
const selectedDisclosures = presentedDisclosures.map(
|
|
792
|
+
(d) => {
|
|
793
|
+
const { salt, key, value, _digest } = d;
|
|
794
|
+
if (!_digest) {
|
|
795
|
+
throw new SDJWTException(
|
|
796
|
+
"Implementation error: _digest is not defined"
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
return {
|
|
800
|
+
digest: _digest,
|
|
801
|
+
encoded: d.encode(),
|
|
802
|
+
salt,
|
|
803
|
+
key,
|
|
804
|
+
value
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
);
|
|
808
|
+
return selectedDisclosures;
|
|
809
|
+
};
|
|
810
|
+
|
|
398
811
|
// src/sdjwt.ts
|
|
399
812
|
var SDJwt = class _SDJwt {
|
|
400
813
|
constructor(data) {
|
|
@@ -404,7 +817,7 @@ var SDJwt = class _SDJwt {
|
|
|
404
817
|
}
|
|
405
818
|
static decodeSDJwt(sdjwt, hasher) {
|
|
406
819
|
return __async(this, null, function* () {
|
|
407
|
-
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(
|
|
820
|
+
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
|
|
408
821
|
const jwt = Jwt.fromEncode(encodedJwt);
|
|
409
822
|
if (!jwt.payload) {
|
|
410
823
|
throw new Error("Payload is undefined on the JWT. Invalid state reached");
|
|
@@ -432,7 +845,7 @@ var SDJwt = class _SDJwt {
|
|
|
432
845
|
}
|
|
433
846
|
static extractJwt(encodedSdJwt) {
|
|
434
847
|
return __async(this, null, function* () {
|
|
435
|
-
const [encodedJwt, ..._encodedDisclosures] = encodedSdJwt.split(
|
|
848
|
+
const [encodedJwt, ..._encodedDisclosures] = encodedSdJwt.split(SD_SEPARATOR);
|
|
436
849
|
return Jwt.fromEncode(encodedJwt);
|
|
437
850
|
});
|
|
438
851
|
}
|
|
@@ -461,7 +874,7 @@ var SDJwt = class _SDJwt {
|
|
|
461
874
|
return __async(this, null, function* () {
|
|
462
875
|
var _a;
|
|
463
876
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
464
|
-
throw new
|
|
877
|
+
throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
|
|
465
878
|
}
|
|
466
879
|
const { _sd_alg: alg } = getSDAlgAndPayload(this.jwt.payload);
|
|
467
880
|
const hash = { alg, hasher };
|
|
@@ -479,16 +892,16 @@ var SDJwt = class _SDJwt {
|
|
|
479
892
|
encodeSDJwt() {
|
|
480
893
|
const data = [];
|
|
481
894
|
if (!this.jwt) {
|
|
482
|
-
throw new
|
|
895
|
+
throw new SDJWTException("Invalid sd-jwt: jwt is missing");
|
|
483
896
|
}
|
|
484
897
|
const encodedJwt = this.jwt.encodeJwt();
|
|
485
898
|
data.push(encodedJwt);
|
|
486
899
|
if (this.disclosures && this.disclosures.length > 0) {
|
|
487
|
-
const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(
|
|
900
|
+
const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(SD_SEPARATOR);
|
|
488
901
|
data.push(encodeddisclosures);
|
|
489
902
|
}
|
|
490
903
|
data.push(this.kbJwt ? this.kbJwt.encodeJwt() : "");
|
|
491
|
-
return data.join(
|
|
904
|
+
return data.join(SD_SEPARATOR);
|
|
492
905
|
}
|
|
493
906
|
keys(hasher) {
|
|
494
907
|
return __async(this, null, function* () {
|
|
@@ -499,7 +912,7 @@ var SDJwt = class _SDJwt {
|
|
|
499
912
|
return __async(this, null, function* () {
|
|
500
913
|
var _a, _b;
|
|
501
914
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
502
|
-
throw new
|
|
915
|
+
throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
|
|
503
916
|
}
|
|
504
917
|
const { disclosureKeymap } = yield unpack(
|
|
505
918
|
(_b = this.jwt) == null ? void 0 : _b.payload,
|
|
@@ -513,7 +926,7 @@ var SDJwt = class _SDJwt {
|
|
|
513
926
|
return __async(this, null, function* () {
|
|
514
927
|
var _a;
|
|
515
928
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
516
|
-
throw new
|
|
929
|
+
throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
|
|
517
930
|
}
|
|
518
931
|
const { unpackedObj } = yield unpack(
|
|
519
932
|
this.jwt.payload,
|
|
@@ -530,8 +943,9 @@ var listKeys = (obj, prefix = "") => {
|
|
|
530
943
|
if (obj[key] === void 0) continue;
|
|
531
944
|
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
532
945
|
keys.push(newKey);
|
|
533
|
-
|
|
534
|
-
|
|
946
|
+
const value = obj[key];
|
|
947
|
+
if (value && typeof value === "object") {
|
|
948
|
+
keys.push(...listKeys(value, newKey));
|
|
535
949
|
}
|
|
536
950
|
}
|
|
537
951
|
return keys;
|
|
@@ -626,7 +1040,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
626
1040
|
this.userConfig = {};
|
|
627
1041
|
if (userConfig) {
|
|
628
1042
|
if (userConfig.hashAlg && !IANA_HASH_ALGORITHMS.includes(userConfig.hashAlg)) {
|
|
629
|
-
throw new
|
|
1043
|
+
throw new SDJWTException(
|
|
630
1044
|
`Invalid hash algorithm: ${userConfig.hashAlg}`
|
|
631
1045
|
);
|
|
632
1046
|
}
|
|
@@ -636,15 +1050,15 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
636
1050
|
createKBJwt(options, sdHash) {
|
|
637
1051
|
return __async(this, null, function* () {
|
|
638
1052
|
if (!this.userConfig.kbSigner) {
|
|
639
|
-
throw new
|
|
1053
|
+
throw new SDJWTException("Key Binding Signer not found");
|
|
640
1054
|
}
|
|
641
1055
|
if (!this.userConfig.kbSignAlg) {
|
|
642
|
-
throw new
|
|
1056
|
+
throw new SDJWTException("Key Binding sign algorithm not specified");
|
|
643
1057
|
}
|
|
644
1058
|
const { payload } = options;
|
|
645
1059
|
const kbJwt = new KBJwt({
|
|
646
1060
|
header: {
|
|
647
|
-
typ:
|
|
1061
|
+
typ: KB_JWT_TYP,
|
|
648
1062
|
alg: this.userConfig.kbSignAlg
|
|
649
1063
|
},
|
|
650
1064
|
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
@@ -656,7 +1070,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
656
1070
|
SignJwt(jwt) {
|
|
657
1071
|
return __async(this, null, function* () {
|
|
658
1072
|
if (!this.userConfig.signer) {
|
|
659
|
-
throw new
|
|
1073
|
+
throw new SDJWTException("Signer not found");
|
|
660
1074
|
}
|
|
661
1075
|
yield jwt.sign(this.userConfig.signer);
|
|
662
1076
|
return jwt;
|
|
@@ -665,7 +1079,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
665
1079
|
VerifyJwt(jwt, options) {
|
|
666
1080
|
return __async(this, null, function* () {
|
|
667
1081
|
if (!this.userConfig.verifier) {
|
|
668
|
-
throw new
|
|
1082
|
+
throw new SDJWTException("Verifier not found");
|
|
669
1083
|
}
|
|
670
1084
|
return jwt.verify(this.userConfig.verifier, options);
|
|
671
1085
|
});
|
|
@@ -674,13 +1088,13 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
674
1088
|
return __async(this, null, function* () {
|
|
675
1089
|
var _a, _b;
|
|
676
1090
|
if (!this.userConfig.hasher) {
|
|
677
|
-
throw new
|
|
1091
|
+
throw new SDJWTException("Hasher not found");
|
|
678
1092
|
}
|
|
679
1093
|
if (!this.userConfig.saltGenerator) {
|
|
680
|
-
throw new
|
|
1094
|
+
throw new SDJWTException("SaltGenerator not found");
|
|
681
1095
|
}
|
|
682
1096
|
if (!this.userConfig.signAlg) {
|
|
683
|
-
throw new
|
|
1097
|
+
throw new SDJWTException("sign alogrithm not specified");
|
|
684
1098
|
}
|
|
685
1099
|
if (disclosureFrame) {
|
|
686
1100
|
this.validateReservedFields(disclosureFrame);
|
|
@@ -723,11 +1137,11 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
723
1137
|
return __async(this, null, function* () {
|
|
724
1138
|
var _a;
|
|
725
1139
|
if (!this.userConfig.hasher) {
|
|
726
|
-
throw new
|
|
1140
|
+
throw new SDJWTException("Hasher not found");
|
|
727
1141
|
}
|
|
728
1142
|
const hasher = this.userConfig.hasher;
|
|
729
1143
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
730
|
-
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new
|
|
1144
|
+
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new SDJWTException("Payload not found");
|
|
731
1145
|
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
732
1146
|
presentationFrame,
|
|
733
1147
|
hasher
|
|
@@ -750,12 +1164,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
750
1164
|
verify(encodedSDJwt, options) {
|
|
751
1165
|
return __async(this, null, function* () {
|
|
752
1166
|
if (!this.userConfig.hasher) {
|
|
753
|
-
throw new
|
|
1167
|
+
throw new SDJWTException("Hasher not found");
|
|
754
1168
|
}
|
|
755
1169
|
const hasher = this.userConfig.hasher;
|
|
756
1170
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
757
1171
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
758
|
-
throw new
|
|
1172
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
759
1173
|
}
|
|
760
1174
|
const { payload, header } = yield this.validate(encodedSDJwt, options);
|
|
761
1175
|
if (options == null ? void 0 : options.requiredClaimKeys) {
|
|
@@ -764,7 +1178,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
764
1178
|
(k) => !keys.includes(k)
|
|
765
1179
|
);
|
|
766
1180
|
if (missingKeys.length > 0) {
|
|
767
|
-
throw new
|
|
1181
|
+
throw new SDJWTException(
|
|
768
1182
|
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
769
1183
|
);
|
|
770
1184
|
}
|
|
@@ -773,15 +1187,16 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
773
1187
|
return { payload, header };
|
|
774
1188
|
}
|
|
775
1189
|
if (!sdjwt.kbJwt) {
|
|
776
|
-
throw new
|
|
1190
|
+
throw new SDJWTException("Key Binding JWT not exist");
|
|
777
1191
|
}
|
|
778
1192
|
if (!this.userConfig.kbVerifier) {
|
|
779
|
-
throw new
|
|
1193
|
+
throw new SDJWTException("Key Binding Verifier not found");
|
|
780
1194
|
}
|
|
781
1195
|
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
782
1196
|
verifier: this.userConfig.kbVerifier,
|
|
783
1197
|
payload,
|
|
784
|
-
nonce: options.keyBindingNonce
|
|
1198
|
+
nonce: options.keyBindingNonce,
|
|
1199
|
+
options
|
|
785
1200
|
});
|
|
786
1201
|
if (!kb) {
|
|
787
1202
|
throw new Error("signature is not valid");
|
|
@@ -798,19 +1213,182 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
798
1213
|
hasher
|
|
799
1214
|
);
|
|
800
1215
|
if (sdHashStr !== sdHashfromKb) {
|
|
801
|
-
throw new
|
|
1216
|
+
throw new SDJWTException("Invalid sd_hash in Key Binding JWT");
|
|
802
1217
|
}
|
|
803
1218
|
return { payload, header, kb };
|
|
804
1219
|
});
|
|
805
1220
|
}
|
|
1221
|
+
/**
|
|
1222
|
+
* Safe verification that collects all errors instead of failing fast.
|
|
1223
|
+
* Returns a result object with either the verified data or an array of all errors.
|
|
1224
|
+
*
|
|
1225
|
+
* @param encodedSDJwt - The encoded SD-JWT to verify
|
|
1226
|
+
* @param options - Verification options
|
|
1227
|
+
* @returns A SafeVerifyResult containing either success data or collected errors
|
|
1228
|
+
*/
|
|
1229
|
+
safeVerify(encodedSDJwt, options) {
|
|
1230
|
+
return __async(this, null, function* () {
|
|
1231
|
+
const errors = [];
|
|
1232
|
+
const addError = (code, message, details) => {
|
|
1233
|
+
errors.push({ code, message, details });
|
|
1234
|
+
};
|
|
1235
|
+
const exceptionToCode = (error) => {
|
|
1236
|
+
const message = error.message.toLowerCase();
|
|
1237
|
+
if (message.includes("hasher not found")) return "HASHER_NOT_FOUND";
|
|
1238
|
+
if (message.includes("verifier not found")) return "VERIFIER_NOT_FOUND";
|
|
1239
|
+
if (message.includes("invalid sd jwt") || message.includes("invalid jwt"))
|
|
1240
|
+
return "INVALID_SD_JWT";
|
|
1241
|
+
if (message.includes("not yet valid")) return "JWT_NOT_YET_VALID";
|
|
1242
|
+
if (message.includes("expired")) return "JWT_EXPIRED";
|
|
1243
|
+
if (message.includes("signature")) return "INVALID_JWT_SIGNATURE";
|
|
1244
|
+
if (message.includes("missing required claim"))
|
|
1245
|
+
return "MISSING_REQUIRED_CLAIMS";
|
|
1246
|
+
if (message.includes("key binding jwt not exist"))
|
|
1247
|
+
return "KEY_BINDING_JWT_MISSING";
|
|
1248
|
+
if (message.includes("key binding verifier not found"))
|
|
1249
|
+
return "KEY_BINDING_VERIFIER_NOT_FOUND";
|
|
1250
|
+
if (message.includes("sd_hash")) return "KEY_BINDING_SD_HASH_INVALID";
|
|
1251
|
+
return "UNKNOWN_ERROR";
|
|
1252
|
+
};
|
|
1253
|
+
if (!this.userConfig.hasher) {
|
|
1254
|
+
addError("HASHER_NOT_FOUND", "Hasher not found");
|
|
1255
|
+
}
|
|
1256
|
+
if (!this.userConfig.verifier) {
|
|
1257
|
+
addError("VERIFIER_NOT_FOUND", "Verifier not found");
|
|
1258
|
+
}
|
|
1259
|
+
if (errors.length > 0) {
|
|
1260
|
+
return { success: false, errors };
|
|
1261
|
+
}
|
|
1262
|
+
if (!this.userConfig.hasher) {
|
|
1263
|
+
throw new SDJWTException("Hasher not found");
|
|
1264
|
+
}
|
|
1265
|
+
const hasher = this.userConfig.hasher;
|
|
1266
|
+
let sdjwt;
|
|
1267
|
+
let payload;
|
|
1268
|
+
let header;
|
|
1269
|
+
try {
|
|
1270
|
+
sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1271
|
+
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1272
|
+
addError("INVALID_SD_JWT", "Invalid SD JWT: missing JWT or payload");
|
|
1273
|
+
}
|
|
1274
|
+
} catch (e) {
|
|
1275
|
+
const error = ensureError(e);
|
|
1276
|
+
addError(
|
|
1277
|
+
"INVALID_SD_JWT",
|
|
1278
|
+
`Failed to decode SD-JWT: ${error.message}`,
|
|
1279
|
+
error
|
|
1280
|
+
);
|
|
1281
|
+
}
|
|
1282
|
+
if (sdjwt == null ? void 0 : sdjwt.jwt) {
|
|
1283
|
+
try {
|
|
1284
|
+
const result = yield this.VerifyJwt(sdjwt.jwt, options);
|
|
1285
|
+
header = result.header;
|
|
1286
|
+
const claims = yield sdjwt.getClaims(hasher);
|
|
1287
|
+
payload = claims;
|
|
1288
|
+
} catch (e) {
|
|
1289
|
+
const error = ensureError(e);
|
|
1290
|
+
const code = exceptionToCode(error);
|
|
1291
|
+
addError(code, error.message, error);
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
if (sdjwt && (options == null ? void 0 : options.requiredClaimKeys)) {
|
|
1295
|
+
try {
|
|
1296
|
+
const keys = yield sdjwt.keys(hasher);
|
|
1297
|
+
const missingKeys = options.requiredClaimKeys.filter(
|
|
1298
|
+
(k) => !keys.includes(k)
|
|
1299
|
+
);
|
|
1300
|
+
if (missingKeys.length > 0) {
|
|
1301
|
+
addError(
|
|
1302
|
+
"MISSING_REQUIRED_CLAIMS",
|
|
1303
|
+
`Missing required claim keys: ${missingKeys.join(", ")}`,
|
|
1304
|
+
{ missingKeys }
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
} catch (e) {
|
|
1308
|
+
const error = ensureError(e);
|
|
1309
|
+
addError(
|
|
1310
|
+
"UNKNOWN_ERROR",
|
|
1311
|
+
`Failed to check required claims: ${error.message}`,
|
|
1312
|
+
error
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
let kb;
|
|
1317
|
+
if ((options == null ? void 0 : options.keyBindingNonce) && sdjwt) {
|
|
1318
|
+
if (!sdjwt.kbJwt) {
|
|
1319
|
+
addError("KEY_BINDING_JWT_MISSING", "Key Binding JWT not exist");
|
|
1320
|
+
} else if (!this.userConfig.kbVerifier) {
|
|
1321
|
+
addError(
|
|
1322
|
+
"KEY_BINDING_VERIFIER_NOT_FOUND",
|
|
1323
|
+
"Key Binding Verifier not found"
|
|
1324
|
+
);
|
|
1325
|
+
} else if (payload) {
|
|
1326
|
+
try {
|
|
1327
|
+
const kbResult = yield sdjwt.kbJwt.verifyKB({
|
|
1328
|
+
verifier: this.userConfig.kbVerifier,
|
|
1329
|
+
payload,
|
|
1330
|
+
nonce: options.keyBindingNonce,
|
|
1331
|
+
options
|
|
1332
|
+
});
|
|
1333
|
+
if (!kbResult) {
|
|
1334
|
+
addError(
|
|
1335
|
+
"KEY_BINDING_SIGNATURE_INVALID",
|
|
1336
|
+
"Key binding signature is not valid"
|
|
1337
|
+
);
|
|
1338
|
+
} else {
|
|
1339
|
+
kb = kbResult;
|
|
1340
|
+
const sdjwtWithoutKb = new SDJwt({
|
|
1341
|
+
jwt: sdjwt.jwt,
|
|
1342
|
+
disclosures: sdjwt.disclosures
|
|
1343
|
+
});
|
|
1344
|
+
const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
|
|
1345
|
+
const sdHashStr = yield this.calculateSDHash(
|
|
1346
|
+
presentSdJwtWithoutKb,
|
|
1347
|
+
sdjwt,
|
|
1348
|
+
hasher
|
|
1349
|
+
);
|
|
1350
|
+
if (sdHashStr !== kbResult.payload.sd_hash) {
|
|
1351
|
+
addError(
|
|
1352
|
+
"KEY_BINDING_SD_HASH_INVALID",
|
|
1353
|
+
"Invalid sd_hash in Key Binding JWT",
|
|
1354
|
+
{
|
|
1355
|
+
expected: sdHashStr,
|
|
1356
|
+
received: kbResult.payload.sd_hash
|
|
1357
|
+
}
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
} catch (e) {
|
|
1362
|
+
const error = ensureError(e);
|
|
1363
|
+
addError(
|
|
1364
|
+
"KEY_BINDING_SIGNATURE_INVALID",
|
|
1365
|
+
`Key binding verification failed: ${error.message}`,
|
|
1366
|
+
error
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
if (errors.length > 0) {
|
|
1372
|
+
return { success: false, errors };
|
|
1373
|
+
}
|
|
1374
|
+
return {
|
|
1375
|
+
success: true,
|
|
1376
|
+
data: {
|
|
1377
|
+
payload,
|
|
1378
|
+
header,
|
|
1379
|
+
kb
|
|
1380
|
+
}
|
|
1381
|
+
};
|
|
1382
|
+
});
|
|
1383
|
+
}
|
|
806
1384
|
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
807
1385
|
return __async(this, null, function* () {
|
|
808
1386
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
809
|
-
throw new
|
|
1387
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
810
1388
|
}
|
|
811
|
-
const { _sd_alg } =
|
|
1389
|
+
const { _sd_alg } = getSDAlgAndPayload(sdjwt.jwt.payload);
|
|
812
1390
|
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
813
|
-
const sdHashStr =
|
|
1391
|
+
const sdHashStr = uint8ArrayToBase64Url(sdHash);
|
|
814
1392
|
return sdHashStr;
|
|
815
1393
|
});
|
|
816
1394
|
}
|
|
@@ -824,12 +1402,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
824
1402
|
validate(encodedSDJwt, options) {
|
|
825
1403
|
return __async(this, null, function* () {
|
|
826
1404
|
if (!this.userConfig.hasher) {
|
|
827
|
-
throw new
|
|
1405
|
+
throw new SDJWTException("Hasher not found");
|
|
828
1406
|
}
|
|
829
1407
|
const hasher = this.userConfig.hasher;
|
|
830
1408
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
831
1409
|
if (!sdjwt.jwt) {
|
|
832
|
-
throw new
|
|
1410
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
833
1411
|
}
|
|
834
1412
|
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt, options);
|
|
835
1413
|
const claims = yield sdjwt.getClaims(hasher);
|
|
@@ -844,14 +1422,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
844
1422
|
}
|
|
845
1423
|
decode(endcodedSDJwt) {
|
|
846
1424
|
if (!this.userConfig.hasher) {
|
|
847
|
-
throw new
|
|
1425
|
+
throw new SDJWTException("Hasher not found");
|
|
848
1426
|
}
|
|
849
1427
|
return SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
850
1428
|
}
|
|
851
1429
|
keys(endcodedSDJwt) {
|
|
852
1430
|
return __async(this, null, function* () {
|
|
853
1431
|
if (!this.userConfig.hasher) {
|
|
854
|
-
throw new
|
|
1432
|
+
throw new SDJWTException("Hasher not found");
|
|
855
1433
|
}
|
|
856
1434
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
857
1435
|
return sdjwt.keys(this.userConfig.hasher);
|
|
@@ -860,7 +1438,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
860
1438
|
presentableKeys(endcodedSDJwt) {
|
|
861
1439
|
return __async(this, null, function* () {
|
|
862
1440
|
if (!this.userConfig.hasher) {
|
|
863
|
-
throw new
|
|
1441
|
+
throw new SDJWTException("Hasher not found");
|
|
864
1442
|
}
|
|
865
1443
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
866
1444
|
return sdjwt.presentableKeys(this.userConfig.hasher);
|
|
@@ -869,7 +1447,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
869
1447
|
getClaims(endcodedSDJwt) {
|
|
870
1448
|
return __async(this, null, function* () {
|
|
871
1449
|
if (!this.userConfig.hasher) {
|
|
872
|
-
throw new
|
|
1450
|
+
throw new SDJWTException("Hasher not found");
|
|
873
1451
|
}
|
|
874
1452
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
875
1453
|
return sdjwt.getClaims(this.userConfig.hasher);
|
|
@@ -889,7 +1467,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
889
1467
|
this.userConfig = {};
|
|
890
1468
|
if (userConfig) {
|
|
891
1469
|
if (userConfig.hashAlg && !IANA_HASH_ALGORITHMS.includes(userConfig.hashAlg)) {
|
|
892
|
-
throw new
|
|
1470
|
+
throw new SDJWTException(
|
|
893
1471
|
`Invalid hash algorithm: ${userConfig.hashAlg}`
|
|
894
1472
|
);
|
|
895
1473
|
}
|
|
@@ -899,15 +1477,15 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
899
1477
|
createKBJwt(options, sdHash) {
|
|
900
1478
|
return __async(this, null, function* () {
|
|
901
1479
|
if (!this.userConfig.kbSigner) {
|
|
902
|
-
throw new
|
|
1480
|
+
throw new SDJWTException("Key Binding Signer not found");
|
|
903
1481
|
}
|
|
904
1482
|
if (!this.userConfig.kbSignAlg) {
|
|
905
|
-
throw new
|
|
1483
|
+
throw new SDJWTException("Key Binding sign algorithm not specified");
|
|
906
1484
|
}
|
|
907
1485
|
const { payload } = options;
|
|
908
1486
|
const kbJwt = new KBJwt({
|
|
909
1487
|
header: {
|
|
910
|
-
typ:
|
|
1488
|
+
typ: KB_JWT_TYP,
|
|
911
1489
|
alg: this.userConfig.kbSignAlg
|
|
912
1490
|
},
|
|
913
1491
|
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
@@ -917,16 +1495,16 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
917
1495
|
});
|
|
918
1496
|
}
|
|
919
1497
|
encodeObj(obj) {
|
|
920
|
-
return
|
|
1498
|
+
return base64urlEncode(JSON.stringify(obj));
|
|
921
1499
|
}
|
|
922
1500
|
issue(payload, disclosureFrame, options) {
|
|
923
1501
|
return __async(this, null, function* () {
|
|
924
1502
|
var _a;
|
|
925
1503
|
if (!this.userConfig.hasher) {
|
|
926
|
-
throw new
|
|
1504
|
+
throw new SDJWTException("Hasher not found");
|
|
927
1505
|
}
|
|
928
1506
|
if (!this.userConfig.saltGenerator) {
|
|
929
|
-
throw new
|
|
1507
|
+
throw new SDJWTException("SaltGenerator not found");
|
|
930
1508
|
}
|
|
931
1509
|
if (disclosureFrame) {
|
|
932
1510
|
this.validateReservedFields(disclosureFrame);
|
|
@@ -978,12 +1556,12 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
978
1556
|
return __async(this, null, function* () {
|
|
979
1557
|
var _a;
|
|
980
1558
|
if (!this.userConfig.hasher) {
|
|
981
|
-
throw new
|
|
1559
|
+
throw new SDJWTException("Hasher not found");
|
|
982
1560
|
}
|
|
983
1561
|
const hasher = this.userConfig.hasher;
|
|
984
1562
|
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
985
1563
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
986
|
-
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new
|
|
1564
|
+
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new SDJWTException("Payload not found");
|
|
987
1565
|
const disclosures = yield sdjwt.getPresentDisclosures(
|
|
988
1566
|
presentationFrame,
|
|
989
1567
|
hasher
|
|
@@ -1018,14 +1596,14 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1018
1596
|
verify(generalJSON, options) {
|
|
1019
1597
|
return __async(this, null, function* () {
|
|
1020
1598
|
if (!this.userConfig.hasher) {
|
|
1021
|
-
throw new
|
|
1599
|
+
throw new SDJWTException("Hasher not found");
|
|
1022
1600
|
}
|
|
1023
1601
|
const hasher = this.userConfig.hasher;
|
|
1024
1602
|
const { payload, headers } = yield this.validate(generalJSON);
|
|
1025
1603
|
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
1026
1604
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1027
1605
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1028
|
-
throw new
|
|
1606
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
1029
1607
|
}
|
|
1030
1608
|
if (options == null ? void 0 : options.requiredClaimKeys) {
|
|
1031
1609
|
const keys = yield sdjwt.keys(hasher);
|
|
@@ -1033,7 +1611,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1033
1611
|
(k) => !keys.includes(k)
|
|
1034
1612
|
);
|
|
1035
1613
|
if (missingKeys.length > 0) {
|
|
1036
|
-
throw new
|
|
1614
|
+
throw new SDJWTException(
|
|
1037
1615
|
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
1038
1616
|
);
|
|
1039
1617
|
}
|
|
@@ -1042,15 +1620,16 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1042
1620
|
return { payload, headers };
|
|
1043
1621
|
}
|
|
1044
1622
|
if (!sdjwt.kbJwt) {
|
|
1045
|
-
throw new
|
|
1623
|
+
throw new SDJWTException("Key Binding JWT not exist");
|
|
1046
1624
|
}
|
|
1047
1625
|
if (!this.userConfig.kbVerifier) {
|
|
1048
|
-
throw new
|
|
1626
|
+
throw new SDJWTException("Key Binding Verifier not found");
|
|
1049
1627
|
}
|
|
1050
1628
|
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
1051
1629
|
verifier: this.userConfig.kbVerifier,
|
|
1052
1630
|
payload,
|
|
1053
|
-
nonce: options.keyBindingNonce
|
|
1631
|
+
nonce: options.keyBindingNonce,
|
|
1632
|
+
options
|
|
1054
1633
|
});
|
|
1055
1634
|
if (!kb) {
|
|
1056
1635
|
throw new Error("signature is not valid");
|
|
@@ -1067,7 +1646,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1067
1646
|
hasher
|
|
1068
1647
|
);
|
|
1069
1648
|
if (sdHashStr !== sdHashfromKb) {
|
|
1070
|
-
throw new
|
|
1649
|
+
throw new SDJWTException("Invalid sd_hash in Key Binding JWT");
|
|
1071
1650
|
}
|
|
1072
1651
|
return { payload, headers, kb };
|
|
1073
1652
|
});
|
|
@@ -1075,11 +1654,11 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1075
1654
|
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
1076
1655
|
return __async(this, null, function* () {
|
|
1077
1656
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1078
|
-
throw new
|
|
1657
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
1079
1658
|
}
|
|
1080
|
-
const { _sd_alg } =
|
|
1659
|
+
const { _sd_alg } = getSDAlgAndPayload(sdjwt.jwt.payload);
|
|
1081
1660
|
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
1082
|
-
const sdHashStr =
|
|
1661
|
+
const sdHashStr = uint8ArrayToBase64Url(sdHash);
|
|
1083
1662
|
return sdHashStr;
|
|
1084
1663
|
});
|
|
1085
1664
|
}
|
|
@@ -1088,10 +1667,10 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1088
1667
|
validate(generalJSON) {
|
|
1089
1668
|
return __async(this, null, function* () {
|
|
1090
1669
|
if (!this.userConfig.hasher) {
|
|
1091
|
-
throw new
|
|
1670
|
+
throw new SDJWTException("Hasher not found");
|
|
1092
1671
|
}
|
|
1093
1672
|
if (!this.userConfig.verifier) {
|
|
1094
|
-
throw new
|
|
1673
|
+
throw new SDJWTException("Verifier not found");
|
|
1095
1674
|
}
|
|
1096
1675
|
const hasher = this.userConfig.hasher;
|
|
1097
1676
|
const verifier = this.userConfig.verifier;
|
|
@@ -1109,12 +1688,12 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1109
1688
|
);
|
|
1110
1689
|
const verified = results.every((r) => r.verified);
|
|
1111
1690
|
if (!verified) {
|
|
1112
|
-
throw new
|
|
1691
|
+
throw new SDJWTException("Signature is not valid");
|
|
1113
1692
|
}
|
|
1114
1693
|
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
1115
1694
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1116
1695
|
if (!sdjwt.jwt) {
|
|
1117
|
-
throw new
|
|
1696
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
1118
1697
|
}
|
|
1119
1698
|
const claims = yield sdjwt.getClaims(hasher);
|
|
1120
1699
|
return { payload: claims, headers: results.map((r) => r.header) };
|
|
@@ -1132,7 +1711,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1132
1711
|
keys(generalSdjwt) {
|
|
1133
1712
|
return __async(this, null, function* () {
|
|
1134
1713
|
if (!this.userConfig.hasher) {
|
|
1135
|
-
throw new
|
|
1714
|
+
throw new SDJWTException("Hasher not found");
|
|
1136
1715
|
}
|
|
1137
1716
|
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1138
1717
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
@@ -1142,7 +1721,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1142
1721
|
presentableKeys(generalSdjwt) {
|
|
1143
1722
|
return __async(this, null, function* () {
|
|
1144
1723
|
if (!this.userConfig.hasher) {
|
|
1145
|
-
throw new
|
|
1724
|
+
throw new SDJWTException("Hasher not found");
|
|
1146
1725
|
}
|
|
1147
1726
|
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1148
1727
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
@@ -1152,7 +1731,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1152
1731
|
getClaims(generalSdjwt) {
|
|
1153
1732
|
return __async(this, null, function* () {
|
|
1154
1733
|
if (!this.userConfig.hasher) {
|
|
1155
|
-
throw new
|
|
1734
|
+
throw new SDJWTException("Hasher not found");
|
|
1156
1735
|
}
|
|
1157
1736
|
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1158
1737
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
@@ -1162,14 +1741,46 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1162
1741
|
};
|
|
1163
1742
|
SDJwtGeneralJSONInstance.DEFAULT_hashAlg = "sha-256";
|
|
1164
1743
|
export {
|
|
1744
|
+
Disclosure,
|
|
1165
1745
|
FlattenJSON,
|
|
1166
1746
|
GeneralJSON,
|
|
1747
|
+
IANA_HASH_ALGORITHMS,
|
|
1167
1748
|
Jwt,
|
|
1168
1749
|
KBJwt,
|
|
1750
|
+
KB_JWT_TYP,
|
|
1751
|
+
SDJWTException,
|
|
1169
1752
|
SDJwt,
|
|
1170
1753
|
SDJwtGeneralJSONInstance,
|
|
1171
1754
|
SDJwtInstance,
|
|
1755
|
+
SD_DECOY,
|
|
1756
|
+
SD_DIGEST,
|
|
1757
|
+
SD_LIST_KEY,
|
|
1758
|
+
SD_SEPARATOR,
|
|
1759
|
+
base64UrlToUint8Array,
|
|
1760
|
+
base64urlDecode,
|
|
1761
|
+
base64urlEncode,
|
|
1172
1762
|
createDecoy,
|
|
1763
|
+
createHashMapping,
|
|
1764
|
+
createHashMappingForSerializedDisclosure,
|
|
1765
|
+
createHashMappingSync,
|
|
1766
|
+
decodeJwt,
|
|
1767
|
+
decodeSdJwt,
|
|
1768
|
+
decodeSdJwtSync,
|
|
1769
|
+
ensureError,
|
|
1770
|
+
getClaims,
|
|
1771
|
+
getClaimsSync,
|
|
1772
|
+
getSDAlgAndPayload,
|
|
1173
1773
|
listKeys,
|
|
1174
|
-
pack
|
|
1774
|
+
pack,
|
|
1775
|
+
present,
|
|
1776
|
+
presentSync,
|
|
1777
|
+
presentableKeys,
|
|
1778
|
+
presentableKeysSync,
|
|
1779
|
+
selectDisclosures,
|
|
1780
|
+
splitSdJwt,
|
|
1781
|
+
transformPresentationFrame,
|
|
1782
|
+
uint8ArrayToBase64Url,
|
|
1783
|
+
unpack,
|
|
1784
|
+
unpackObj,
|
|
1785
|
+
unpackSync
|
|
1175
1786
|
};
|