@sd-jwt/core 0.19.1-next.0 → 0.19.1-next.10
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 +359 -16
- package/dist/index.d.ts +359 -16
- package/dist/index.js +795 -138
- package/dist/index.mjs +736 -123
- 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 +227 -14
- package/src/jwt.ts +10 -15
- package/src/kbjwt.ts +5 -6
- 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 +154 -2
- package/src/test/jwt.spec.ts +7 -13
- package/src/test/kbjwt.spec.ts +5 -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,22 +659,17 @@ 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
|
|
671
|
+
!(this.payload.sd_hash || "_sd_hash" in this.payload && this.payload._sd_hash)) {
|
|
672
|
+
throw new SDJWTException("Invalid Key Binding Jwt");
|
|
347
673
|
}
|
|
348
674
|
const data = this.getUnsignedToken();
|
|
349
675
|
const verified = yield values.verifier(
|
|
@@ -352,10 +678,10 @@ var KBJwt = class _KBJwt extends Jwt {
|
|
|
352
678
|
values.payload
|
|
353
679
|
);
|
|
354
680
|
if (!verified) {
|
|
355
|
-
throw new
|
|
681
|
+
throw new SDJWTException("Verify Error: Invalid JWT Signature");
|
|
356
682
|
}
|
|
357
683
|
if (this.payload.nonce !== values.nonce) {
|
|
358
|
-
throw new
|
|
684
|
+
throw new SDJWTException("Verify Error: Invalid Nonce");
|
|
359
685
|
}
|
|
360
686
|
return { payload: this.payload, header: this.header };
|
|
361
687
|
});
|
|
@@ -375,19 +701,7 @@ var KBJwt = class _KBJwt extends Jwt {
|
|
|
375
701
|
}
|
|
376
702
|
};
|
|
377
703
|
|
|
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
704
|
// src/decoy.ts
|
|
390
|
-
import { uint8ArrayToBase64Url } from "@sd-jwt/utils";
|
|
391
705
|
var createDecoy = (hash, saltGenerator) => __async(null, null, function* () {
|
|
392
706
|
const { hasher, alg } = hash;
|
|
393
707
|
const salt = yield saltGenerator(16);
|
|
@@ -395,6 +709,110 @@ var createDecoy = (hash, saltGenerator) => __async(null, null, function* () {
|
|
|
395
709
|
return uint8ArrayToBase64Url(decoy);
|
|
396
710
|
});
|
|
397
711
|
|
|
712
|
+
// src/present/present.ts
|
|
713
|
+
var presentableKeys = (rawPayload, disclosures, hasher) => __async(null, null, function* () {
|
|
714
|
+
const { disclosureKeymap } = yield unpack(rawPayload, disclosures, hasher);
|
|
715
|
+
return Object.keys(disclosureKeymap).sort();
|
|
716
|
+
});
|
|
717
|
+
var presentableKeysSync = (rawPayload, disclosures, hasher) => {
|
|
718
|
+
const { disclosureKeymap } = unpackSync(rawPayload, disclosures, hasher);
|
|
719
|
+
return Object.keys(disclosureKeymap).sort();
|
|
720
|
+
};
|
|
721
|
+
var present = (sdJwt, presentFrame, hasher) => __async(null, null, function* () {
|
|
722
|
+
const { jwt, kbJwt } = splitSdJwt(sdJwt);
|
|
723
|
+
const {
|
|
724
|
+
jwt: { payload },
|
|
725
|
+
disclosures
|
|
726
|
+
} = yield decodeSdJwt(sdJwt, hasher);
|
|
727
|
+
const { _sd_alg: alg } = getSDAlgAndPayload(payload);
|
|
728
|
+
const hash = { alg, hasher };
|
|
729
|
+
const keys = transformPresentationFrame(presentFrame);
|
|
730
|
+
const hashmap = yield createHashMapping(disclosures, hash);
|
|
731
|
+
const { disclosureKeymap } = yield unpack(payload, disclosures, hasher);
|
|
732
|
+
const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
733
|
+
return [
|
|
734
|
+
jwt,
|
|
735
|
+
...presentedDisclosures.map((d) => d.encode()),
|
|
736
|
+
kbJwt != null ? kbJwt : ""
|
|
737
|
+
].join(SD_SEPARATOR);
|
|
738
|
+
});
|
|
739
|
+
var presentSync = (sdJwt, presentFrame, hasher) => {
|
|
740
|
+
const { jwt, kbJwt } = splitSdJwt(sdJwt);
|
|
741
|
+
const {
|
|
742
|
+
jwt: { payload },
|
|
743
|
+
disclosures
|
|
744
|
+
} = decodeSdJwtSync(sdJwt, hasher);
|
|
745
|
+
const { _sd_alg: alg } = getSDAlgAndPayload(payload);
|
|
746
|
+
const hash = { alg, hasher };
|
|
747
|
+
const keys = transformPresentationFrame(presentFrame);
|
|
748
|
+
const hashmap = createHashMappingSync(disclosures, hash);
|
|
749
|
+
const { disclosureKeymap } = unpackSync(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 transformPresentationFrame = (obj, prefix = "") => {
|
|
758
|
+
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
759
|
+
const newPrefix = prefix ? `${prefix}.${key}` : key;
|
|
760
|
+
if (typeof value === "boolean") {
|
|
761
|
+
if (value) {
|
|
762
|
+
acc.push(newPrefix);
|
|
763
|
+
}
|
|
764
|
+
} else if (typeof value === "object" && value !== null) {
|
|
765
|
+
acc.push(
|
|
766
|
+
newPrefix,
|
|
767
|
+
...transformPresentationFrame(
|
|
768
|
+
value,
|
|
769
|
+
newPrefix
|
|
770
|
+
)
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
return acc;
|
|
774
|
+
}, []);
|
|
775
|
+
};
|
|
776
|
+
var createHashMappingForSerializedDisclosure = (disclosures) => {
|
|
777
|
+
const map = {};
|
|
778
|
+
for (let i = 0; i < disclosures.length; i++) {
|
|
779
|
+
const disclosure = disclosures[i];
|
|
780
|
+
const { digest, encoded, key, salt, value } = disclosure;
|
|
781
|
+
map[digest] = Disclosure.fromArray(
|
|
782
|
+
key ? [salt, key, value] : [salt, value],
|
|
783
|
+
{ digest, encoded }
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
return map;
|
|
787
|
+
};
|
|
788
|
+
var selectDisclosures = (payload, disclosures, presentationFrame) => {
|
|
789
|
+
if (disclosures.length === 0) {
|
|
790
|
+
return [];
|
|
791
|
+
}
|
|
792
|
+
const hashmap = createHashMappingForSerializedDisclosure(disclosures);
|
|
793
|
+
const { disclosureKeymap } = unpackObj(payload, hashmap);
|
|
794
|
+
const keys = transformPresentationFrame(presentationFrame);
|
|
795
|
+
const presentedDisclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
796
|
+
const selectedDisclosures = presentedDisclosures.map(
|
|
797
|
+
(d) => {
|
|
798
|
+
const { salt, key, value, _digest } = d;
|
|
799
|
+
if (!_digest) {
|
|
800
|
+
throw new SDJWTException(
|
|
801
|
+
"Implementation error: _digest is not defined"
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
return {
|
|
805
|
+
digest: _digest,
|
|
806
|
+
encoded: d.encode(),
|
|
807
|
+
salt,
|
|
808
|
+
key,
|
|
809
|
+
value
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
);
|
|
813
|
+
return selectedDisclosures;
|
|
814
|
+
};
|
|
815
|
+
|
|
398
816
|
// src/sdjwt.ts
|
|
399
817
|
var SDJwt = class _SDJwt {
|
|
400
818
|
constructor(data) {
|
|
@@ -404,7 +822,7 @@ var SDJwt = class _SDJwt {
|
|
|
404
822
|
}
|
|
405
823
|
static decodeSDJwt(sdjwt, hasher) {
|
|
406
824
|
return __async(this, null, function* () {
|
|
407
|
-
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(
|
|
825
|
+
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(SD_SEPARATOR);
|
|
408
826
|
const jwt = Jwt.fromEncode(encodedJwt);
|
|
409
827
|
if (!jwt.payload) {
|
|
410
828
|
throw new Error("Payload is undefined on the JWT. Invalid state reached");
|
|
@@ -432,7 +850,7 @@ var SDJwt = class _SDJwt {
|
|
|
432
850
|
}
|
|
433
851
|
static extractJwt(encodedSdJwt) {
|
|
434
852
|
return __async(this, null, function* () {
|
|
435
|
-
const [encodedJwt, ..._encodedDisclosures] = encodedSdJwt.split(
|
|
853
|
+
const [encodedJwt, ..._encodedDisclosures] = encodedSdJwt.split(SD_SEPARATOR);
|
|
436
854
|
return Jwt.fromEncode(encodedJwt);
|
|
437
855
|
});
|
|
438
856
|
}
|
|
@@ -461,7 +879,7 @@ var SDJwt = class _SDJwt {
|
|
|
461
879
|
return __async(this, null, function* () {
|
|
462
880
|
var _a;
|
|
463
881
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
464
|
-
throw new
|
|
882
|
+
throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
|
|
465
883
|
}
|
|
466
884
|
const { _sd_alg: alg } = getSDAlgAndPayload(this.jwt.payload);
|
|
467
885
|
const hash = { alg, hasher };
|
|
@@ -479,16 +897,16 @@ var SDJwt = class _SDJwt {
|
|
|
479
897
|
encodeSDJwt() {
|
|
480
898
|
const data = [];
|
|
481
899
|
if (!this.jwt) {
|
|
482
|
-
throw new
|
|
900
|
+
throw new SDJWTException("Invalid sd-jwt: jwt is missing");
|
|
483
901
|
}
|
|
484
902
|
const encodedJwt = this.jwt.encodeJwt();
|
|
485
903
|
data.push(encodedJwt);
|
|
486
904
|
if (this.disclosures && this.disclosures.length > 0) {
|
|
487
|
-
const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(
|
|
905
|
+
const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(SD_SEPARATOR);
|
|
488
906
|
data.push(encodeddisclosures);
|
|
489
907
|
}
|
|
490
908
|
data.push(this.kbJwt ? this.kbJwt.encodeJwt() : "");
|
|
491
|
-
return data.join(
|
|
909
|
+
return data.join(SD_SEPARATOR);
|
|
492
910
|
}
|
|
493
911
|
keys(hasher) {
|
|
494
912
|
return __async(this, null, function* () {
|
|
@@ -499,7 +917,7 @@ var SDJwt = class _SDJwt {
|
|
|
499
917
|
return __async(this, null, function* () {
|
|
500
918
|
var _a, _b;
|
|
501
919
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
502
|
-
throw new
|
|
920
|
+
throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
|
|
503
921
|
}
|
|
504
922
|
const { disclosureKeymap } = yield unpack(
|
|
505
923
|
(_b = this.jwt) == null ? void 0 : _b.payload,
|
|
@@ -513,7 +931,7 @@ var SDJwt = class _SDJwt {
|
|
|
513
931
|
return __async(this, null, function* () {
|
|
514
932
|
var _a;
|
|
515
933
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
516
|
-
throw new
|
|
934
|
+
throw new SDJWTException("Invalid sd-jwt: jwt or disclosures is missing");
|
|
517
935
|
}
|
|
518
936
|
const { unpackedObj } = yield unpack(
|
|
519
937
|
this.jwt.payload,
|
|
@@ -530,8 +948,9 @@ var listKeys = (obj, prefix = "") => {
|
|
|
530
948
|
if (obj[key] === void 0) continue;
|
|
531
949
|
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
532
950
|
keys.push(newKey);
|
|
533
|
-
|
|
534
|
-
|
|
951
|
+
const value = obj[key];
|
|
952
|
+
if (value && typeof value === "object") {
|
|
953
|
+
keys.push(...listKeys(value, newKey));
|
|
535
954
|
}
|
|
536
955
|
}
|
|
537
956
|
return keys;
|
|
@@ -626,7 +1045,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
626
1045
|
this.userConfig = {};
|
|
627
1046
|
if (userConfig) {
|
|
628
1047
|
if (userConfig.hashAlg && !IANA_HASH_ALGORITHMS.includes(userConfig.hashAlg)) {
|
|
629
|
-
throw new
|
|
1048
|
+
throw new SDJWTException(
|
|
630
1049
|
`Invalid hash algorithm: ${userConfig.hashAlg}`
|
|
631
1050
|
);
|
|
632
1051
|
}
|
|
@@ -636,15 +1055,15 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
636
1055
|
createKBJwt(options, sdHash) {
|
|
637
1056
|
return __async(this, null, function* () {
|
|
638
1057
|
if (!this.userConfig.kbSigner) {
|
|
639
|
-
throw new
|
|
1058
|
+
throw new SDJWTException("Key Binding Signer not found");
|
|
640
1059
|
}
|
|
641
1060
|
if (!this.userConfig.kbSignAlg) {
|
|
642
|
-
throw new
|
|
1061
|
+
throw new SDJWTException("Key Binding sign algorithm not specified");
|
|
643
1062
|
}
|
|
644
1063
|
const { payload } = options;
|
|
645
1064
|
const kbJwt = new KBJwt({
|
|
646
1065
|
header: {
|
|
647
|
-
typ:
|
|
1066
|
+
typ: KB_JWT_TYP,
|
|
648
1067
|
alg: this.userConfig.kbSignAlg
|
|
649
1068
|
},
|
|
650
1069
|
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
@@ -656,7 +1075,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
656
1075
|
SignJwt(jwt) {
|
|
657
1076
|
return __async(this, null, function* () {
|
|
658
1077
|
if (!this.userConfig.signer) {
|
|
659
|
-
throw new
|
|
1078
|
+
throw new SDJWTException("Signer not found");
|
|
660
1079
|
}
|
|
661
1080
|
yield jwt.sign(this.userConfig.signer);
|
|
662
1081
|
return jwt;
|
|
@@ -665,7 +1084,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
665
1084
|
VerifyJwt(jwt, options) {
|
|
666
1085
|
return __async(this, null, function* () {
|
|
667
1086
|
if (!this.userConfig.verifier) {
|
|
668
|
-
throw new
|
|
1087
|
+
throw new SDJWTException("Verifier not found");
|
|
669
1088
|
}
|
|
670
1089
|
return jwt.verify(this.userConfig.verifier, options);
|
|
671
1090
|
});
|
|
@@ -674,13 +1093,13 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
674
1093
|
return __async(this, null, function* () {
|
|
675
1094
|
var _a, _b;
|
|
676
1095
|
if (!this.userConfig.hasher) {
|
|
677
|
-
throw new
|
|
1096
|
+
throw new SDJWTException("Hasher not found");
|
|
678
1097
|
}
|
|
679
1098
|
if (!this.userConfig.saltGenerator) {
|
|
680
|
-
throw new
|
|
1099
|
+
throw new SDJWTException("SaltGenerator not found");
|
|
681
1100
|
}
|
|
682
1101
|
if (!this.userConfig.signAlg) {
|
|
683
|
-
throw new
|
|
1102
|
+
throw new SDJWTException("sign alogrithm not specified");
|
|
684
1103
|
}
|
|
685
1104
|
if (disclosureFrame) {
|
|
686
1105
|
this.validateReservedFields(disclosureFrame);
|
|
@@ -723,11 +1142,11 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
723
1142
|
return __async(this, null, function* () {
|
|
724
1143
|
var _a;
|
|
725
1144
|
if (!this.userConfig.hasher) {
|
|
726
|
-
throw new
|
|
1145
|
+
throw new SDJWTException("Hasher not found");
|
|
727
1146
|
}
|
|
728
1147
|
const hasher = this.userConfig.hasher;
|
|
729
1148
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
730
|
-
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new
|
|
1149
|
+
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new SDJWTException("Payload not found");
|
|
731
1150
|
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
732
1151
|
presentationFrame,
|
|
733
1152
|
hasher
|
|
@@ -750,12 +1169,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
750
1169
|
verify(encodedSDJwt, options) {
|
|
751
1170
|
return __async(this, null, function* () {
|
|
752
1171
|
if (!this.userConfig.hasher) {
|
|
753
|
-
throw new
|
|
1172
|
+
throw new SDJWTException("Hasher not found");
|
|
754
1173
|
}
|
|
755
1174
|
const hasher = this.userConfig.hasher;
|
|
756
1175
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
757
1176
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
758
|
-
throw new
|
|
1177
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
759
1178
|
}
|
|
760
1179
|
const { payload, header } = yield this.validate(encodedSDJwt, options);
|
|
761
1180
|
if (options == null ? void 0 : options.requiredClaimKeys) {
|
|
@@ -764,7 +1183,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
764
1183
|
(k) => !keys.includes(k)
|
|
765
1184
|
);
|
|
766
1185
|
if (missingKeys.length > 0) {
|
|
767
|
-
throw new
|
|
1186
|
+
throw new SDJWTException(
|
|
768
1187
|
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
769
1188
|
);
|
|
770
1189
|
}
|
|
@@ -773,10 +1192,10 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
773
1192
|
return { payload, header };
|
|
774
1193
|
}
|
|
775
1194
|
if (!sdjwt.kbJwt) {
|
|
776
|
-
throw new
|
|
1195
|
+
throw new SDJWTException("Key Binding JWT not exist");
|
|
777
1196
|
}
|
|
778
1197
|
if (!this.userConfig.kbVerifier) {
|
|
779
|
-
throw new
|
|
1198
|
+
throw new SDJWTException("Key Binding Verifier not found");
|
|
780
1199
|
}
|
|
781
1200
|
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
782
1201
|
verifier: this.userConfig.kbVerifier,
|
|
@@ -798,19 +1217,181 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
798
1217
|
hasher
|
|
799
1218
|
);
|
|
800
1219
|
if (sdHashStr !== sdHashfromKb) {
|
|
801
|
-
throw new
|
|
1220
|
+
throw new SDJWTException("Invalid sd_hash in Key Binding JWT");
|
|
802
1221
|
}
|
|
803
1222
|
return { payload, header, kb };
|
|
804
1223
|
});
|
|
805
1224
|
}
|
|
1225
|
+
/**
|
|
1226
|
+
* Safe verification that collects all errors instead of failing fast.
|
|
1227
|
+
* Returns a result object with either the verified data or an array of all errors.
|
|
1228
|
+
*
|
|
1229
|
+
* @param encodedSDJwt - The encoded SD-JWT to verify
|
|
1230
|
+
* @param options - Verification options
|
|
1231
|
+
* @returns A SafeVerifyResult containing either success data or collected errors
|
|
1232
|
+
*/
|
|
1233
|
+
safeVerify(encodedSDJwt, options) {
|
|
1234
|
+
return __async(this, null, function* () {
|
|
1235
|
+
const errors = [];
|
|
1236
|
+
const addError = (code, message, details) => {
|
|
1237
|
+
errors.push({ code, message, details });
|
|
1238
|
+
};
|
|
1239
|
+
const exceptionToCode = (error) => {
|
|
1240
|
+
const message = error.message.toLowerCase();
|
|
1241
|
+
if (message.includes("hasher not found")) return "HASHER_NOT_FOUND";
|
|
1242
|
+
if (message.includes("verifier not found")) return "VERIFIER_NOT_FOUND";
|
|
1243
|
+
if (message.includes("invalid sd jwt") || message.includes("invalid jwt"))
|
|
1244
|
+
return "INVALID_SD_JWT";
|
|
1245
|
+
if (message.includes("not yet valid")) return "JWT_NOT_YET_VALID";
|
|
1246
|
+
if (message.includes("expired")) return "JWT_EXPIRED";
|
|
1247
|
+
if (message.includes("signature")) return "INVALID_JWT_SIGNATURE";
|
|
1248
|
+
if (message.includes("missing required claim"))
|
|
1249
|
+
return "MISSING_REQUIRED_CLAIMS";
|
|
1250
|
+
if (message.includes("key binding jwt not exist"))
|
|
1251
|
+
return "KEY_BINDING_JWT_MISSING";
|
|
1252
|
+
if (message.includes("key binding verifier not found"))
|
|
1253
|
+
return "KEY_BINDING_VERIFIER_NOT_FOUND";
|
|
1254
|
+
if (message.includes("sd_hash")) return "KEY_BINDING_SD_HASH_INVALID";
|
|
1255
|
+
return "UNKNOWN_ERROR";
|
|
1256
|
+
};
|
|
1257
|
+
if (!this.userConfig.hasher) {
|
|
1258
|
+
addError("HASHER_NOT_FOUND", "Hasher not found");
|
|
1259
|
+
}
|
|
1260
|
+
if (!this.userConfig.verifier) {
|
|
1261
|
+
addError("VERIFIER_NOT_FOUND", "Verifier not found");
|
|
1262
|
+
}
|
|
1263
|
+
if (errors.length > 0) {
|
|
1264
|
+
return { success: false, errors };
|
|
1265
|
+
}
|
|
1266
|
+
if (!this.userConfig.hasher) {
|
|
1267
|
+
throw new SDJWTException("Hasher not found");
|
|
1268
|
+
}
|
|
1269
|
+
const hasher = this.userConfig.hasher;
|
|
1270
|
+
let sdjwt;
|
|
1271
|
+
let payload;
|
|
1272
|
+
let header;
|
|
1273
|
+
try {
|
|
1274
|
+
sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1275
|
+
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1276
|
+
addError("INVALID_SD_JWT", "Invalid SD JWT: missing JWT or payload");
|
|
1277
|
+
}
|
|
1278
|
+
} catch (e) {
|
|
1279
|
+
const error = ensureError(e);
|
|
1280
|
+
addError(
|
|
1281
|
+
"INVALID_SD_JWT",
|
|
1282
|
+
`Failed to decode SD-JWT: ${error.message}`,
|
|
1283
|
+
error
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
if (sdjwt == null ? void 0 : sdjwt.jwt) {
|
|
1287
|
+
try {
|
|
1288
|
+
const result = yield this.VerifyJwt(sdjwt.jwt, options);
|
|
1289
|
+
header = result.header;
|
|
1290
|
+
const claims = yield sdjwt.getClaims(hasher);
|
|
1291
|
+
payload = claims;
|
|
1292
|
+
} catch (e) {
|
|
1293
|
+
const error = ensureError(e);
|
|
1294
|
+
const code = exceptionToCode(error);
|
|
1295
|
+
addError(code, error.message, error);
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
if (sdjwt && (options == null ? void 0 : options.requiredClaimKeys)) {
|
|
1299
|
+
try {
|
|
1300
|
+
const keys = yield sdjwt.keys(hasher);
|
|
1301
|
+
const missingKeys = options.requiredClaimKeys.filter(
|
|
1302
|
+
(k) => !keys.includes(k)
|
|
1303
|
+
);
|
|
1304
|
+
if (missingKeys.length > 0) {
|
|
1305
|
+
addError(
|
|
1306
|
+
"MISSING_REQUIRED_CLAIMS",
|
|
1307
|
+
`Missing required claim keys: ${missingKeys.join(", ")}`,
|
|
1308
|
+
{ missingKeys }
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
} catch (e) {
|
|
1312
|
+
const error = ensureError(e);
|
|
1313
|
+
addError(
|
|
1314
|
+
"UNKNOWN_ERROR",
|
|
1315
|
+
`Failed to check required claims: ${error.message}`,
|
|
1316
|
+
error
|
|
1317
|
+
);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
let kb;
|
|
1321
|
+
if ((options == null ? void 0 : options.keyBindingNonce) && sdjwt) {
|
|
1322
|
+
if (!sdjwt.kbJwt) {
|
|
1323
|
+
addError("KEY_BINDING_JWT_MISSING", "Key Binding JWT not exist");
|
|
1324
|
+
} else if (!this.userConfig.kbVerifier) {
|
|
1325
|
+
addError(
|
|
1326
|
+
"KEY_BINDING_VERIFIER_NOT_FOUND",
|
|
1327
|
+
"Key Binding Verifier not found"
|
|
1328
|
+
);
|
|
1329
|
+
} else if (payload) {
|
|
1330
|
+
try {
|
|
1331
|
+
const kbResult = yield sdjwt.kbJwt.verifyKB({
|
|
1332
|
+
verifier: this.userConfig.kbVerifier,
|
|
1333
|
+
payload,
|
|
1334
|
+
nonce: options.keyBindingNonce
|
|
1335
|
+
});
|
|
1336
|
+
if (!kbResult) {
|
|
1337
|
+
addError(
|
|
1338
|
+
"KEY_BINDING_SIGNATURE_INVALID",
|
|
1339
|
+
"Key binding signature is not valid"
|
|
1340
|
+
);
|
|
1341
|
+
} else {
|
|
1342
|
+
kb = kbResult;
|
|
1343
|
+
const sdjwtWithoutKb = new SDJwt({
|
|
1344
|
+
jwt: sdjwt.jwt,
|
|
1345
|
+
disclosures: sdjwt.disclosures
|
|
1346
|
+
});
|
|
1347
|
+
const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
|
|
1348
|
+
const sdHashStr = yield this.calculateSDHash(
|
|
1349
|
+
presentSdJwtWithoutKb,
|
|
1350
|
+
sdjwt,
|
|
1351
|
+
hasher
|
|
1352
|
+
);
|
|
1353
|
+
if (sdHashStr !== kbResult.payload.sd_hash) {
|
|
1354
|
+
addError(
|
|
1355
|
+
"KEY_BINDING_SD_HASH_INVALID",
|
|
1356
|
+
"Invalid sd_hash in Key Binding JWT",
|
|
1357
|
+
{
|
|
1358
|
+
expected: sdHashStr,
|
|
1359
|
+
received: kbResult.payload.sd_hash
|
|
1360
|
+
}
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
} catch (e) {
|
|
1365
|
+
const error = ensureError(e);
|
|
1366
|
+
addError(
|
|
1367
|
+
"KEY_BINDING_SIGNATURE_INVALID",
|
|
1368
|
+
`Key binding verification failed: ${error.message}`,
|
|
1369
|
+
error
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (errors.length > 0) {
|
|
1375
|
+
return { success: false, errors };
|
|
1376
|
+
}
|
|
1377
|
+
return {
|
|
1378
|
+
success: true,
|
|
1379
|
+
data: {
|
|
1380
|
+
payload,
|
|
1381
|
+
header,
|
|
1382
|
+
kb
|
|
1383
|
+
}
|
|
1384
|
+
};
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
806
1387
|
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
807
1388
|
return __async(this, null, function* () {
|
|
808
1389
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
809
|
-
throw new
|
|
1390
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
810
1391
|
}
|
|
811
|
-
const { _sd_alg } =
|
|
1392
|
+
const { _sd_alg } = getSDAlgAndPayload(sdjwt.jwt.payload);
|
|
812
1393
|
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
813
|
-
const sdHashStr =
|
|
1394
|
+
const sdHashStr = uint8ArrayToBase64Url(sdHash);
|
|
814
1395
|
return sdHashStr;
|
|
815
1396
|
});
|
|
816
1397
|
}
|
|
@@ -824,12 +1405,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
824
1405
|
validate(encodedSDJwt, options) {
|
|
825
1406
|
return __async(this, null, function* () {
|
|
826
1407
|
if (!this.userConfig.hasher) {
|
|
827
|
-
throw new
|
|
1408
|
+
throw new SDJWTException("Hasher not found");
|
|
828
1409
|
}
|
|
829
1410
|
const hasher = this.userConfig.hasher;
|
|
830
1411
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
831
1412
|
if (!sdjwt.jwt) {
|
|
832
|
-
throw new
|
|
1413
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
833
1414
|
}
|
|
834
1415
|
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt, options);
|
|
835
1416
|
const claims = yield sdjwt.getClaims(hasher);
|
|
@@ -844,14 +1425,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
844
1425
|
}
|
|
845
1426
|
decode(endcodedSDJwt) {
|
|
846
1427
|
if (!this.userConfig.hasher) {
|
|
847
|
-
throw new
|
|
1428
|
+
throw new SDJWTException("Hasher not found");
|
|
848
1429
|
}
|
|
849
1430
|
return SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
850
1431
|
}
|
|
851
1432
|
keys(endcodedSDJwt) {
|
|
852
1433
|
return __async(this, null, function* () {
|
|
853
1434
|
if (!this.userConfig.hasher) {
|
|
854
|
-
throw new
|
|
1435
|
+
throw new SDJWTException("Hasher not found");
|
|
855
1436
|
}
|
|
856
1437
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
857
1438
|
return sdjwt.keys(this.userConfig.hasher);
|
|
@@ -860,7 +1441,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
860
1441
|
presentableKeys(endcodedSDJwt) {
|
|
861
1442
|
return __async(this, null, function* () {
|
|
862
1443
|
if (!this.userConfig.hasher) {
|
|
863
|
-
throw new
|
|
1444
|
+
throw new SDJWTException("Hasher not found");
|
|
864
1445
|
}
|
|
865
1446
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
866
1447
|
return sdjwt.presentableKeys(this.userConfig.hasher);
|
|
@@ -869,7 +1450,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
869
1450
|
getClaims(endcodedSDJwt) {
|
|
870
1451
|
return __async(this, null, function* () {
|
|
871
1452
|
if (!this.userConfig.hasher) {
|
|
872
|
-
throw new
|
|
1453
|
+
throw new SDJWTException("Hasher not found");
|
|
873
1454
|
}
|
|
874
1455
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
875
1456
|
return sdjwt.getClaims(this.userConfig.hasher);
|
|
@@ -889,7 +1470,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
889
1470
|
this.userConfig = {};
|
|
890
1471
|
if (userConfig) {
|
|
891
1472
|
if (userConfig.hashAlg && !IANA_HASH_ALGORITHMS.includes(userConfig.hashAlg)) {
|
|
892
|
-
throw new
|
|
1473
|
+
throw new SDJWTException(
|
|
893
1474
|
`Invalid hash algorithm: ${userConfig.hashAlg}`
|
|
894
1475
|
);
|
|
895
1476
|
}
|
|
@@ -899,15 +1480,15 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
899
1480
|
createKBJwt(options, sdHash) {
|
|
900
1481
|
return __async(this, null, function* () {
|
|
901
1482
|
if (!this.userConfig.kbSigner) {
|
|
902
|
-
throw new
|
|
1483
|
+
throw new SDJWTException("Key Binding Signer not found");
|
|
903
1484
|
}
|
|
904
1485
|
if (!this.userConfig.kbSignAlg) {
|
|
905
|
-
throw new
|
|
1486
|
+
throw new SDJWTException("Key Binding sign algorithm not specified");
|
|
906
1487
|
}
|
|
907
1488
|
const { payload } = options;
|
|
908
1489
|
const kbJwt = new KBJwt({
|
|
909
1490
|
header: {
|
|
910
|
-
typ:
|
|
1491
|
+
typ: KB_JWT_TYP,
|
|
911
1492
|
alg: this.userConfig.kbSignAlg
|
|
912
1493
|
},
|
|
913
1494
|
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
@@ -917,16 +1498,16 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
917
1498
|
});
|
|
918
1499
|
}
|
|
919
1500
|
encodeObj(obj) {
|
|
920
|
-
return
|
|
1501
|
+
return base64urlEncode(JSON.stringify(obj));
|
|
921
1502
|
}
|
|
922
1503
|
issue(payload, disclosureFrame, options) {
|
|
923
1504
|
return __async(this, null, function* () {
|
|
924
1505
|
var _a;
|
|
925
1506
|
if (!this.userConfig.hasher) {
|
|
926
|
-
throw new
|
|
1507
|
+
throw new SDJWTException("Hasher not found");
|
|
927
1508
|
}
|
|
928
1509
|
if (!this.userConfig.saltGenerator) {
|
|
929
|
-
throw new
|
|
1510
|
+
throw new SDJWTException("SaltGenerator not found");
|
|
930
1511
|
}
|
|
931
1512
|
if (disclosureFrame) {
|
|
932
1513
|
this.validateReservedFields(disclosureFrame);
|
|
@@ -978,12 +1559,12 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
978
1559
|
return __async(this, null, function* () {
|
|
979
1560
|
var _a;
|
|
980
1561
|
if (!this.userConfig.hasher) {
|
|
981
|
-
throw new
|
|
1562
|
+
throw new SDJWTException("Hasher not found");
|
|
982
1563
|
}
|
|
983
1564
|
const hasher = this.userConfig.hasher;
|
|
984
1565
|
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
985
1566
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
986
|
-
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new
|
|
1567
|
+
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload)) throw new SDJWTException("Payload not found");
|
|
987
1568
|
const disclosures = yield sdjwt.getPresentDisclosures(
|
|
988
1569
|
presentationFrame,
|
|
989
1570
|
hasher
|
|
@@ -1018,14 +1599,14 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1018
1599
|
verify(generalJSON, options) {
|
|
1019
1600
|
return __async(this, null, function* () {
|
|
1020
1601
|
if (!this.userConfig.hasher) {
|
|
1021
|
-
throw new
|
|
1602
|
+
throw new SDJWTException("Hasher not found");
|
|
1022
1603
|
}
|
|
1023
1604
|
const hasher = this.userConfig.hasher;
|
|
1024
1605
|
const { payload, headers } = yield this.validate(generalJSON);
|
|
1025
1606
|
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
1026
1607
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1027
1608
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1028
|
-
throw new
|
|
1609
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
1029
1610
|
}
|
|
1030
1611
|
if (options == null ? void 0 : options.requiredClaimKeys) {
|
|
1031
1612
|
const keys = yield sdjwt.keys(hasher);
|
|
@@ -1033,7 +1614,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1033
1614
|
(k) => !keys.includes(k)
|
|
1034
1615
|
);
|
|
1035
1616
|
if (missingKeys.length > 0) {
|
|
1036
|
-
throw new
|
|
1617
|
+
throw new SDJWTException(
|
|
1037
1618
|
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
1038
1619
|
);
|
|
1039
1620
|
}
|
|
@@ -1042,10 +1623,10 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1042
1623
|
return { payload, headers };
|
|
1043
1624
|
}
|
|
1044
1625
|
if (!sdjwt.kbJwt) {
|
|
1045
|
-
throw new
|
|
1626
|
+
throw new SDJWTException("Key Binding JWT not exist");
|
|
1046
1627
|
}
|
|
1047
1628
|
if (!this.userConfig.kbVerifier) {
|
|
1048
|
-
throw new
|
|
1629
|
+
throw new SDJWTException("Key Binding Verifier not found");
|
|
1049
1630
|
}
|
|
1050
1631
|
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
1051
1632
|
verifier: this.userConfig.kbVerifier,
|
|
@@ -1067,7 +1648,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1067
1648
|
hasher
|
|
1068
1649
|
);
|
|
1069
1650
|
if (sdHashStr !== sdHashfromKb) {
|
|
1070
|
-
throw new
|
|
1651
|
+
throw new SDJWTException("Invalid sd_hash in Key Binding JWT");
|
|
1071
1652
|
}
|
|
1072
1653
|
return { payload, headers, kb };
|
|
1073
1654
|
});
|
|
@@ -1075,11 +1656,11 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1075
1656
|
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
1076
1657
|
return __async(this, null, function* () {
|
|
1077
1658
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1078
|
-
throw new
|
|
1659
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
1079
1660
|
}
|
|
1080
|
-
const { _sd_alg } =
|
|
1661
|
+
const { _sd_alg } = getSDAlgAndPayload(sdjwt.jwt.payload);
|
|
1081
1662
|
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
1082
|
-
const sdHashStr =
|
|
1663
|
+
const sdHashStr = uint8ArrayToBase64Url(sdHash);
|
|
1083
1664
|
return sdHashStr;
|
|
1084
1665
|
});
|
|
1085
1666
|
}
|
|
@@ -1088,10 +1669,10 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1088
1669
|
validate(generalJSON) {
|
|
1089
1670
|
return __async(this, null, function* () {
|
|
1090
1671
|
if (!this.userConfig.hasher) {
|
|
1091
|
-
throw new
|
|
1672
|
+
throw new SDJWTException("Hasher not found");
|
|
1092
1673
|
}
|
|
1093
1674
|
if (!this.userConfig.verifier) {
|
|
1094
|
-
throw new
|
|
1675
|
+
throw new SDJWTException("Verifier not found");
|
|
1095
1676
|
}
|
|
1096
1677
|
const hasher = this.userConfig.hasher;
|
|
1097
1678
|
const verifier = this.userConfig.verifier;
|
|
@@ -1109,12 +1690,12 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1109
1690
|
);
|
|
1110
1691
|
const verified = results.every((r) => r.verified);
|
|
1111
1692
|
if (!verified) {
|
|
1112
|
-
throw new
|
|
1693
|
+
throw new SDJWTException("Signature is not valid");
|
|
1113
1694
|
}
|
|
1114
1695
|
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
1115
1696
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1116
1697
|
if (!sdjwt.jwt) {
|
|
1117
|
-
throw new
|
|
1698
|
+
throw new SDJWTException("Invalid SD JWT");
|
|
1118
1699
|
}
|
|
1119
1700
|
const claims = yield sdjwt.getClaims(hasher);
|
|
1120
1701
|
return { payload: claims, headers: results.map((r) => r.header) };
|
|
@@ -1132,7 +1713,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1132
1713
|
keys(generalSdjwt) {
|
|
1133
1714
|
return __async(this, null, function* () {
|
|
1134
1715
|
if (!this.userConfig.hasher) {
|
|
1135
|
-
throw new
|
|
1716
|
+
throw new SDJWTException("Hasher not found");
|
|
1136
1717
|
}
|
|
1137
1718
|
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1138
1719
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
@@ -1142,7 +1723,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1142
1723
|
presentableKeys(generalSdjwt) {
|
|
1143
1724
|
return __async(this, null, function* () {
|
|
1144
1725
|
if (!this.userConfig.hasher) {
|
|
1145
|
-
throw new
|
|
1726
|
+
throw new SDJWTException("Hasher not found");
|
|
1146
1727
|
}
|
|
1147
1728
|
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1148
1729
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
@@ -1152,7 +1733,7 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1152
1733
|
getClaims(generalSdjwt) {
|
|
1153
1734
|
return __async(this, null, function* () {
|
|
1154
1735
|
if (!this.userConfig.hasher) {
|
|
1155
|
-
throw new
|
|
1736
|
+
throw new SDJWTException("Hasher not found");
|
|
1156
1737
|
}
|
|
1157
1738
|
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1158
1739
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
@@ -1162,14 +1743,46 @@ var SDJwtGeneralJSONInstance = class {
|
|
|
1162
1743
|
};
|
|
1163
1744
|
SDJwtGeneralJSONInstance.DEFAULT_hashAlg = "sha-256";
|
|
1164
1745
|
export {
|
|
1746
|
+
Disclosure,
|
|
1165
1747
|
FlattenJSON,
|
|
1166
1748
|
GeneralJSON,
|
|
1749
|
+
IANA_HASH_ALGORITHMS,
|
|
1167
1750
|
Jwt,
|
|
1168
1751
|
KBJwt,
|
|
1752
|
+
KB_JWT_TYP,
|
|
1753
|
+
SDJWTException,
|
|
1169
1754
|
SDJwt,
|
|
1170
1755
|
SDJwtGeneralJSONInstance,
|
|
1171
1756
|
SDJwtInstance,
|
|
1757
|
+
SD_DECOY,
|
|
1758
|
+
SD_DIGEST,
|
|
1759
|
+
SD_LIST_KEY,
|
|
1760
|
+
SD_SEPARATOR,
|
|
1761
|
+
base64UrlToUint8Array,
|
|
1762
|
+
base64urlDecode,
|
|
1763
|
+
base64urlEncode,
|
|
1172
1764
|
createDecoy,
|
|
1765
|
+
createHashMapping,
|
|
1766
|
+
createHashMappingForSerializedDisclosure,
|
|
1767
|
+
createHashMappingSync,
|
|
1768
|
+
decodeJwt,
|
|
1769
|
+
decodeSdJwt,
|
|
1770
|
+
decodeSdJwtSync,
|
|
1771
|
+
ensureError,
|
|
1772
|
+
getClaims,
|
|
1773
|
+
getClaimsSync,
|
|
1774
|
+
getSDAlgAndPayload,
|
|
1173
1775
|
listKeys,
|
|
1174
|
-
pack
|
|
1776
|
+
pack,
|
|
1777
|
+
present,
|
|
1778
|
+
presentSync,
|
|
1779
|
+
presentableKeys,
|
|
1780
|
+
presentableKeysSync,
|
|
1781
|
+
selectDisclosures,
|
|
1782
|
+
splitSdJwt,
|
|
1783
|
+
transformPresentationFrame,
|
|
1784
|
+
uint8ArrayToBase64Url,
|
|
1785
|
+
unpack,
|
|
1786
|
+
unpackObj,
|
|
1787
|
+
unpackSync
|
|
1175
1788
|
};
|