@sd-jwt/core 0.3.2-next.99 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +27 -33
- package/dist/index.mjs +16 -20
- package/package.json +7 -6
- package/src/index.ts +5 -5
- package/src/jwt.ts +1 -1
- package/src/kbjwt.ts +18 -9
- package/src/sdjwt.ts +12 -13
- package/src/test/index.spec.ts +117 -52
- package/test/app-e2e.spec.ts +12 -4
- package/test/array_data_types.json +10 -8
- package/test/array_full_sd.json +1 -1
- package/test/array_in_sd.json +1 -1
- package/test/array_nested_in_plain.json +10 -1
- package/test/array_none_disclosed.json +1 -1
- package/test/array_of_nulls.json +1 -1
- package/test/array_of_objects.json +8 -1
- package/test/array_of_scalars.json +5 -1
- package/test/array_recursive_sd.json +1 -1
- package/test/array_recursive_sd_some_disclosed.json +14 -6
- package/test/complex.json +1 -1
- package/test/header_mod.json +5 -1
- package/test/json_serialization.json +5 -1
- package/test/key_binding.json +5 -1
- package/test/no_sd.json +1 -1
- package/test/object_data_types.json +11 -9
- package/test/recursions.json +36 -17
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
|
+
|
|
6
|
+
# 0.4.0 (2024-03-08)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* add publish config ([#93](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/93)) ([2e4c5c1](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/2e4c5c176dc88e58e49d06783b7658d8ad872313))
|
|
12
|
+
* add the payload that is required ([6c53580](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/6c53580d12e4361c40435b90628302749fa32b1c))
|
|
13
|
+
* change SDJwtPayload to SdJwtPayload ([9f06ef7](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/9f06ef7bd31a1dff4e9bf988e425200a5e1aa82d))
|
|
14
|
+
* convert any usage into or typed version ([#80](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/80)) ([de4df54](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/de4df54f2a0a77fdbf97e10abac555a98e70c6e0))
|
|
15
|
+
* implement kbverify function ([#127](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/127)) ([e5609f2](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/e5609f26fab8c4991d3bd6c36066a95a30cfb972))
|
|
16
|
+
* make sdjwt instance non abstract ([#122](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/122)) ([e85aae8](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/e85aae89910f5d9468e29ef14ef3b3d3215b86fd))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* add jwk type ([#130](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/130)) ([8ce255a](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/8ce255a64b0940e92e647aa544bf5990b48279b7))
|
|
22
|
+
* add new package for sd-jwt-vc ([ed99188](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/ed99188f13184d58db64b4211e39fb67f3f78cb5))
|
|
23
|
+
* Apply lerna to move src to core ([#67](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/67)) ([49e272b](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/49e272b6b51c5226e22732c469e566fd3c14c57c))
|
|
24
|
+
* calcuate sd_hash in kb JWT ([#117](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/117)) ([3415550](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/3415550fbcd99f97babff442a4928cc827c5c9cc))
|
|
25
|
+
* checking kb header value ([#133](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/133)) ([cd2991b](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/cd2991b88a0522e39251c5ca2b67593130baa585))
|
|
26
|
+
* create kb jwt when present all ([#129](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/129)) ([72ed1ad](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/72ed1ad64b850876ba3b5d5e5df6128471fb44ac))
|
|
27
|
+
* fix async handling in jwt verify ([#131](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/131)) ([76cb930](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/76cb93021dd62c241c87656975f74dd44b3766cf))
|
|
28
|
+
* fixing exclude _sd_alg when no disclosure ([#120](https://github.com/openwallet-foundation-labs/sd-jwt-js/issues/120)) ([dcaf1f6](https://github.com/openwallet-foundation-labs/sd-jwt-js/commit/dcaf1f6fad3289ea7cbe0f3f410fdc15c0f77fda))
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _sd_jwt_types from '@sd-jwt/types';
|
|
2
|
-
import { Base64urlString, Signer, Verifier, kbHeader, kbPayload, KbVerifier, JwtPayload, SDJWTCompact, Hasher, DisclosureFrame, HasherAndAlg, SaltGenerator, SDJWTConfig, KBOptions } from '@sd-jwt/types';
|
|
2
|
+
import { Base64urlString, Signer, Verifier, kbHeader, kbPayload, KbVerifier, JwtPayload, SDJWTCompact, Hasher, PresentationFrame, DisclosureFrame, HasherAndAlg, SaltGenerator, SDJWTConfig, KBOptions } from '@sd-jwt/types';
|
|
3
3
|
import { Disclosure } from '@sd-jwt/utils';
|
|
4
4
|
|
|
5
5
|
type JwtData<Header extends Record<string, unknown>, Payload extends Record<string, unknown>> = {
|
|
@@ -55,7 +55,7 @@ declare class SDJwt<Header extends Record<string, unknown> = Record<string, unkn
|
|
|
55
55
|
kbJwt?: KBJwt<KBHeader, KBPayload>;
|
|
56
56
|
}>;
|
|
57
57
|
static fromEncode<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>, KBHeader extends kbHeader = kbHeader, KBPayload extends kbPayload = kbPayload>(encodedSdJwt: SDJWTCompact, hasher: Hasher): Promise<SDJwt<Header, Payload>>;
|
|
58
|
-
present(
|
|
58
|
+
present<T extends Record<string, unknown>>(presentFrame: PresentationFrame<T> | undefined, hasher: Hasher): Promise<SDJWTCompact>;
|
|
59
59
|
encodeSDJwt(): SDJWTCompact;
|
|
60
60
|
keys(hasher: Hasher): Promise<string[]>;
|
|
61
61
|
presentableKeys(hasher: Hasher): Promise<string[]>;
|
|
@@ -87,7 +87,7 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
87
87
|
* @returns
|
|
88
88
|
*/
|
|
89
89
|
protected validateReservedFields<T extends ExtendedPayload>(disclosureFrame: DisclosureFrame<T>): void;
|
|
90
|
-
present(encodedSDJwt: string,
|
|
90
|
+
present<T extends Record<string, unknown>>(encodedSDJwt: string, presentationFrame?: PresentationFrame<T>, options?: {
|
|
91
91
|
kb?: KBOptions;
|
|
92
92
|
}): Promise<SDJWTCompact>;
|
|
93
93
|
verify(encodedSDJwt: string, requiredClaimKeys?: string[], requireKeyBindings?: boolean): Promise<{
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _sd_jwt_types from '@sd-jwt/types';
|
|
2
|
-
import { Base64urlString, Signer, Verifier, kbHeader, kbPayload, KbVerifier, JwtPayload, SDJWTCompact, Hasher, DisclosureFrame, HasherAndAlg, SaltGenerator, SDJWTConfig, KBOptions } from '@sd-jwt/types';
|
|
2
|
+
import { Base64urlString, Signer, Verifier, kbHeader, kbPayload, KbVerifier, JwtPayload, SDJWTCompact, Hasher, PresentationFrame, DisclosureFrame, HasherAndAlg, SaltGenerator, SDJWTConfig, KBOptions } from '@sd-jwt/types';
|
|
3
3
|
import { Disclosure } from '@sd-jwt/utils';
|
|
4
4
|
|
|
5
5
|
type JwtData<Header extends Record<string, unknown>, Payload extends Record<string, unknown>> = {
|
|
@@ -55,7 +55,7 @@ declare class SDJwt<Header extends Record<string, unknown> = Record<string, unkn
|
|
|
55
55
|
kbJwt?: KBJwt<KBHeader, KBPayload>;
|
|
56
56
|
}>;
|
|
57
57
|
static fromEncode<Header extends Record<string, unknown> = Record<string, unknown>, Payload extends Record<string, unknown> = Record<string, unknown>, KBHeader extends kbHeader = kbHeader, KBPayload extends kbPayload = kbPayload>(encodedSdJwt: SDJWTCompact, hasher: Hasher): Promise<SDJwt<Header, Payload>>;
|
|
58
|
-
present(
|
|
58
|
+
present<T extends Record<string, unknown>>(presentFrame: PresentationFrame<T> | undefined, hasher: Hasher): Promise<SDJWTCompact>;
|
|
59
59
|
encodeSDJwt(): SDJWTCompact;
|
|
60
60
|
keys(hasher: Hasher): Promise<string[]>;
|
|
61
61
|
presentableKeys(hasher: Hasher): Promise<string[]>;
|
|
@@ -87,7 +87,7 @@ declare class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
87
87
|
* @returns
|
|
88
88
|
*/
|
|
89
89
|
protected validateReservedFields<T extends ExtendedPayload>(disclosureFrame: DisclosureFrame<T>): void;
|
|
90
|
-
present(encodedSDJwt: string,
|
|
90
|
+
present<T extends Record<string, unknown>>(encodedSDJwt: string, presentationFrame?: PresentationFrame<T>, options?: {
|
|
91
91
|
kb?: KBOptions;
|
|
92
92
|
}): Promise<SDJWTCompact>;
|
|
93
93
|
verify(encodedSDJwt: string, requiredClaimKeys?: string[], requireKeyBindings?: boolean): Promise<{
|
package/dist/index.js
CHANGED
|
@@ -129,7 +129,7 @@ var Jwt = class _Jwt {
|
|
|
129
129
|
const header = (0, import_utils.Base64urlEncode)(JSON.stringify(this.header));
|
|
130
130
|
const payload = (0, import_utils.Base64urlEncode)(JSON.stringify(this.payload));
|
|
131
131
|
const data = `${header}.${payload}`;
|
|
132
|
-
const verified = verifier(data, this.signature);
|
|
132
|
+
const verified = yield verifier(data, this.signature);
|
|
133
133
|
if (!verified) {
|
|
134
134
|
throw new import_utils.SDJWTException("Verify Error: Invalid JWT Signature");
|
|
135
135
|
}
|
|
@@ -140,19 +140,20 @@ var Jwt = class _Jwt {
|
|
|
140
140
|
|
|
141
141
|
// src/kbjwt.ts
|
|
142
142
|
var import_utils2 = require("@sd-jwt/utils");
|
|
143
|
+
var import_types = require("@sd-jwt/types");
|
|
143
144
|
var KBJwt = class _KBJwt extends Jwt {
|
|
144
145
|
// Checking the validity of the key binding jwt
|
|
145
146
|
// 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
|
|
146
147
|
verifyKB(values) {
|
|
147
148
|
return __async(this, null, function* () {
|
|
148
|
-
var _a
|
|
149
|
-
if (!((_a = this.header) == null ? void 0 : _a.alg) || !this.header.typ || !((_b = this.payload) == null ? void 0 : _b.iat) || !((_c = this.payload) == null ? void 0 : _c.aud) || !((_d = this.payload) == null ? void 0 : _d.nonce) || // this is for backward compatibility with version 06
|
|
150
|
-
!(((_e = this.payload) == null ? void 0 : _e.sd_hash) || ((_f = this.payload) == null ? void 0 : _f._sd_hash))) {
|
|
151
|
-
throw new import_utils2.SDJWTException("Invalid Key Binding Jwt");
|
|
152
|
-
}
|
|
149
|
+
var _a;
|
|
153
150
|
if (!this.header || !this.payload || !this.signature) {
|
|
154
151
|
throw new import_utils2.SDJWTException("Verify Error: Invalid JWT");
|
|
155
152
|
}
|
|
153
|
+
if (!this.header.alg || this.header.alg === "none" || !this.header.typ || this.header.typ !== import_types.KB_JWT_TYP || !this.payload.iat || !this.payload.aud || !this.payload.nonce || // this is for backward compatibility with version 06
|
|
154
|
+
!(this.payload.sd_hash || ((_a = this.payload) == null ? void 0 : _a._sd_hash))) {
|
|
155
|
+
throw new import_utils2.SDJWTException("Invalid Key Binding Jwt");
|
|
156
|
+
}
|
|
156
157
|
const header = (0, import_utils2.Base64urlEncode)(JSON.stringify(this.header));
|
|
157
158
|
const payload = (0, import_utils2.Base64urlEncode)(JSON.stringify(this.payload));
|
|
158
159
|
const data = `${header}.${payload}`;
|
|
@@ -192,8 +193,9 @@ var createDecoy = (hash, saltGenerator) => __async(void 0, null, function* () {
|
|
|
192
193
|
|
|
193
194
|
// src/sdjwt.ts
|
|
194
195
|
var import_utils4 = require("@sd-jwt/utils");
|
|
195
|
-
var
|
|
196
|
+
var import_types2 = require("@sd-jwt/types");
|
|
196
197
|
var import_decode2 = require("@sd-jwt/decode");
|
|
198
|
+
var import_present = require("@sd-jwt/present");
|
|
197
199
|
var SDJwt = class _SDJwt {
|
|
198
200
|
constructor(data) {
|
|
199
201
|
this.jwt = data == null ? void 0 : data.jwt;
|
|
@@ -202,7 +204,7 @@ var SDJwt = class _SDJwt {
|
|
|
202
204
|
}
|
|
203
205
|
static decodeSDJwt(sdjwt, hasher) {
|
|
204
206
|
return __async(this, null, function* () {
|
|
205
|
-
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(
|
|
207
|
+
const [encodedJwt, ...encodedDisclosures] = sdjwt.split(import_types2.SD_SEPARATOR);
|
|
206
208
|
const jwt = Jwt.fromEncode(encodedJwt);
|
|
207
209
|
if (!jwt.payload) {
|
|
208
210
|
throw new Error("Payload is undefined on the JWT. Invalid state reached");
|
|
@@ -238,7 +240,7 @@ var SDJwt = class _SDJwt {
|
|
|
238
240
|
});
|
|
239
241
|
});
|
|
240
242
|
}
|
|
241
|
-
present(
|
|
243
|
+
present(presentFrame, hasher) {
|
|
242
244
|
return __async(this, null, function* () {
|
|
243
245
|
var _a;
|
|
244
246
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
@@ -252,14 +254,8 @@ var SDJwt = class _SDJwt {
|
|
|
252
254
|
this.disclosures,
|
|
253
255
|
hasher
|
|
254
256
|
);
|
|
255
|
-
const
|
|
256
|
-
const
|
|
257
|
-
if (missingKeys.length > 0) {
|
|
258
|
-
throw new import_utils4.SDJWTException(
|
|
259
|
-
`Invalid sd-jwt: invalid present keys: ${missingKeys.join(", ")}`
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]);
|
|
257
|
+
const keys = presentFrame ? (0, import_present.transformPresentationFrame)(presentFrame) : yield this.presentableKeys(hasher);
|
|
258
|
+
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
263
259
|
const presentSDJwt = new _SDJwt({
|
|
264
260
|
jwt: this.jwt,
|
|
265
261
|
disclosures,
|
|
@@ -276,11 +272,11 @@ var SDJwt = class _SDJwt {
|
|
|
276
272
|
const encodedJwt = this.jwt.encodeJwt();
|
|
277
273
|
data.push(encodedJwt);
|
|
278
274
|
if (this.disclosures && this.disclosures.length > 0) {
|
|
279
|
-
const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(
|
|
275
|
+
const encodeddisclosures = this.disclosures.map((dc) => dc.encode()).join(import_types2.SD_SEPARATOR);
|
|
280
276
|
data.push(encodeddisclosures);
|
|
281
277
|
}
|
|
282
278
|
data.push(this.kbJwt ? this.kbJwt.encodeJwt() : "");
|
|
283
|
-
return data.join(
|
|
279
|
+
return data.join(import_types2.SD_SEPARATOR);
|
|
284
280
|
}
|
|
285
281
|
keys(hasher) {
|
|
286
282
|
return __async(this, null, function* () {
|
|
@@ -337,14 +333,14 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
|
|
|
337
333
|
disclosures: []
|
|
338
334
|
};
|
|
339
335
|
}
|
|
340
|
-
const sd = (_a = disclosureFrame[
|
|
341
|
-
const decoyCount = (_b = disclosureFrame[
|
|
336
|
+
const sd = (_a = disclosureFrame[import_types2.SD_DIGEST]) != null ? _a : [];
|
|
337
|
+
const decoyCount = (_b = disclosureFrame[import_types2.SD_DECOY]) != null ? _b : 0;
|
|
342
338
|
if (Array.isArray(claims)) {
|
|
343
339
|
const packedClaims2 = [];
|
|
344
340
|
const disclosures2 = [];
|
|
345
341
|
const recursivePackedClaims2 = {};
|
|
346
342
|
for (const key in disclosureFrame) {
|
|
347
|
-
if (key !==
|
|
343
|
+
if (key !== import_types2.SD_DIGEST) {
|
|
348
344
|
const idx = parseInt(key);
|
|
349
345
|
const packed = yield pack(
|
|
350
346
|
claims[idx],
|
|
@@ -362,7 +358,7 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
|
|
|
362
358
|
const salt = yield saltGenerator(16);
|
|
363
359
|
const disclosure = new import_utils4.Disclosure([salt, claim]);
|
|
364
360
|
const digest = yield disclosure.digest(hash);
|
|
365
|
-
packedClaims2.push({ [
|
|
361
|
+
packedClaims2.push({ [import_types2.SD_LIST_KEY]: digest });
|
|
366
362
|
disclosures2.push(disclosure);
|
|
367
363
|
} else {
|
|
368
364
|
packedClaims2.push(claim);
|
|
@@ -370,7 +366,7 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
|
|
|
370
366
|
}
|
|
371
367
|
for (let j = 0; j < decoyCount; j++) {
|
|
372
368
|
const decoyDigest = yield createDecoy(hash, saltGenerator);
|
|
373
|
-
packedClaims2.push({ [
|
|
369
|
+
packedClaims2.push({ [import_types2.SD_LIST_KEY]: decoyDigest });
|
|
374
370
|
}
|
|
375
371
|
return { packedClaims: packedClaims2, disclosures: disclosures2 };
|
|
376
372
|
}
|
|
@@ -378,7 +374,7 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
|
|
|
378
374
|
const disclosures = [];
|
|
379
375
|
const recursivePackedClaims = {};
|
|
380
376
|
for (const key in disclosureFrame) {
|
|
381
|
-
if (key !==
|
|
377
|
+
if (key !== import_types2.SD_DIGEST) {
|
|
382
378
|
const packed = yield pack(
|
|
383
379
|
// @ts-ignore
|
|
384
380
|
claims[key],
|
|
@@ -408,13 +404,13 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
|
|
|
408
404
|
_sd.push(decoyDigest);
|
|
409
405
|
}
|
|
410
406
|
if (_sd.length > 0) {
|
|
411
|
-
packedClaims[
|
|
407
|
+
packedClaims[import_types2.SD_DIGEST] = _sd.sort();
|
|
412
408
|
}
|
|
413
409
|
return { packedClaims, disclosures };
|
|
414
410
|
});
|
|
415
411
|
|
|
416
412
|
// src/index.ts
|
|
417
|
-
var
|
|
413
|
+
var import_types3 = require("@sd-jwt/types");
|
|
418
414
|
var import_decode3 = require("@sd-jwt/decode");
|
|
419
415
|
var _SDJwtInstance = class _SDJwtInstance {
|
|
420
416
|
constructor(userConfig) {
|
|
@@ -434,7 +430,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
434
430
|
const { payload } = options;
|
|
435
431
|
const kbJwt = new KBJwt({
|
|
436
432
|
header: {
|
|
437
|
-
typ:
|
|
433
|
+
typ: import_types3.KB_JWT_TYP,
|
|
438
434
|
alg: this.userConfig.kbSignAlg
|
|
439
435
|
},
|
|
440
436
|
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
@@ -509,11 +505,9 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
509
505
|
validateReservedFields(disclosureFrame) {
|
|
510
506
|
return;
|
|
511
507
|
}
|
|
512
|
-
present(encodedSDJwt,
|
|
508
|
+
present(encodedSDJwt, presentationFrame, options) {
|
|
513
509
|
return __async(this, null, function* () {
|
|
514
510
|
var _a;
|
|
515
|
-
if (!presentationKeys)
|
|
516
|
-
return encodedSDJwt;
|
|
517
511
|
if (!this.userConfig.hasher) {
|
|
518
512
|
throw new import_utils5.SDJWTException("Hasher not found");
|
|
519
513
|
}
|
|
@@ -522,7 +516,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
522
516
|
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
|
|
523
517
|
throw new import_utils5.SDJWTException("Payload not found");
|
|
524
518
|
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
525
|
-
|
|
519
|
+
presentationFrame,
|
|
526
520
|
hasher
|
|
527
521
|
);
|
|
528
522
|
if (!(options == null ? void 0 : options.kb)) {
|
|
@@ -534,7 +528,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
534
528
|
hasher
|
|
535
529
|
);
|
|
536
530
|
sdjwt.kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
|
|
537
|
-
return sdjwt.present(
|
|
531
|
+
return sdjwt.present(presentationFrame, hasher);
|
|
538
532
|
});
|
|
539
533
|
}
|
|
540
534
|
// This function is for verifying the SD JWT
|
package/dist/index.mjs
CHANGED
|
@@ -102,7 +102,7 @@ var Jwt = class _Jwt {
|
|
|
102
102
|
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
103
103
|
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
104
104
|
const data = `${header}.${payload}`;
|
|
105
|
-
const verified = verifier(data, this.signature);
|
|
105
|
+
const verified = yield verifier(data, this.signature);
|
|
106
106
|
if (!verified) {
|
|
107
107
|
throw new SDJWTException("Verify Error: Invalid JWT Signature");
|
|
108
108
|
}
|
|
@@ -113,19 +113,22 @@ var Jwt = class _Jwt {
|
|
|
113
113
|
|
|
114
114
|
// src/kbjwt.ts
|
|
115
115
|
import { Base64urlEncode as Base64urlEncode2, SDJWTException as SDJWTException2 } from "@sd-jwt/utils";
|
|
116
|
+
import {
|
|
117
|
+
KB_JWT_TYP
|
|
118
|
+
} from "@sd-jwt/types";
|
|
116
119
|
var KBJwt = class _KBJwt extends Jwt {
|
|
117
120
|
// Checking the validity of the key binding jwt
|
|
118
121
|
// 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
|
|
119
122
|
verifyKB(values) {
|
|
120
123
|
return __async(this, null, function* () {
|
|
121
|
-
var _a
|
|
122
|
-
if (!((_a = this.header) == null ? void 0 : _a.alg) || !this.header.typ || !((_b = this.payload) == null ? void 0 : _b.iat) || !((_c = this.payload) == null ? void 0 : _c.aud) || !((_d = this.payload) == null ? void 0 : _d.nonce) || // this is for backward compatibility with version 06
|
|
123
|
-
!(((_e = this.payload) == null ? void 0 : _e.sd_hash) || ((_f = this.payload) == null ? void 0 : _f._sd_hash))) {
|
|
124
|
-
throw new SDJWTException2("Invalid Key Binding Jwt");
|
|
125
|
-
}
|
|
124
|
+
var _a;
|
|
126
125
|
if (!this.header || !this.payload || !this.signature) {
|
|
127
126
|
throw new SDJWTException2("Verify Error: Invalid JWT");
|
|
128
127
|
}
|
|
128
|
+
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
|
|
129
|
+
!(this.payload.sd_hash || ((_a = this.payload) == null ? void 0 : _a._sd_hash))) {
|
|
130
|
+
throw new SDJWTException2("Invalid Key Binding Jwt");
|
|
131
|
+
}
|
|
129
132
|
const header = Base64urlEncode2(JSON.stringify(this.header));
|
|
130
133
|
const payload = Base64urlEncode2(JSON.stringify(this.payload));
|
|
131
134
|
const data = `${header}.${payload}`;
|
|
@@ -172,6 +175,7 @@ import {
|
|
|
172
175
|
SD_SEPARATOR
|
|
173
176
|
} from "@sd-jwt/types";
|
|
174
177
|
import { createHashMapping, getSDAlgAndPayload, unpack } from "@sd-jwt/decode";
|
|
178
|
+
import { transformPresentationFrame } from "@sd-jwt/present";
|
|
175
179
|
var SDJwt = class _SDJwt {
|
|
176
180
|
constructor(data) {
|
|
177
181
|
this.jwt = data == null ? void 0 : data.jwt;
|
|
@@ -216,7 +220,7 @@ var SDJwt = class _SDJwt {
|
|
|
216
220
|
});
|
|
217
221
|
});
|
|
218
222
|
}
|
|
219
|
-
present(
|
|
223
|
+
present(presentFrame, hasher) {
|
|
220
224
|
return __async(this, null, function* () {
|
|
221
225
|
var _a;
|
|
222
226
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
@@ -230,14 +234,8 @@ var SDJwt = class _SDJwt {
|
|
|
230
234
|
this.disclosures,
|
|
231
235
|
hasher
|
|
232
236
|
);
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
if (missingKeys.length > 0) {
|
|
236
|
-
throw new SDJWTException3(
|
|
237
|
-
`Invalid sd-jwt: invalid present keys: ${missingKeys.join(", ")}`
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]);
|
|
237
|
+
const keys = presentFrame ? transformPresentationFrame(presentFrame) : yield this.presentableKeys(hasher);
|
|
238
|
+
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
241
239
|
const presentSDJwt = new _SDJwt({
|
|
242
240
|
jwt: this.jwt,
|
|
243
241
|
disclosures,
|
|
@@ -489,11 +487,9 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
489
487
|
validateReservedFields(disclosureFrame) {
|
|
490
488
|
return;
|
|
491
489
|
}
|
|
492
|
-
present(encodedSDJwt,
|
|
490
|
+
present(encodedSDJwt, presentationFrame, options) {
|
|
493
491
|
return __async(this, null, function* () {
|
|
494
492
|
var _a;
|
|
495
|
-
if (!presentationKeys)
|
|
496
|
-
return encodedSDJwt;
|
|
497
493
|
if (!this.userConfig.hasher) {
|
|
498
494
|
throw new SDJWTException4("Hasher not found");
|
|
499
495
|
}
|
|
@@ -502,7 +498,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
502
498
|
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
|
|
503
499
|
throw new SDJWTException4("Payload not found");
|
|
504
500
|
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
505
|
-
|
|
501
|
+
presentationFrame,
|
|
506
502
|
hasher
|
|
507
503
|
);
|
|
508
504
|
if (!(options == null ? void 0 : options.kb)) {
|
|
@@ -514,7 +510,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
514
510
|
hasher
|
|
515
511
|
);
|
|
516
512
|
sdjwt.kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
|
|
517
|
-
return sdjwt.present(
|
|
513
|
+
return sdjwt.present(presentationFrame, hasher);
|
|
518
514
|
});
|
|
519
515
|
}
|
|
520
516
|
// This function is for verifying the SD JWT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -38,12 +38,13 @@
|
|
|
38
38
|
},
|
|
39
39
|
"license": "Apache-2.0",
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@sd-jwt/crypto-nodejs": "0.
|
|
41
|
+
"@sd-jwt/crypto-nodejs": "0.4.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@sd-jwt/decode": "0.
|
|
45
|
-
"@sd-jwt/
|
|
46
|
-
"@sd-jwt/
|
|
44
|
+
"@sd-jwt/decode": "0.4.0",
|
|
45
|
+
"@sd-jwt/present": "0.4.0",
|
|
46
|
+
"@sd-jwt/types": "0.4.0",
|
|
47
|
+
"@sd-jwt/utils": "0.4.0"
|
|
47
48
|
},
|
|
48
49
|
"publishConfig": {
|
|
49
50
|
"access": "public"
|
|
@@ -61,5 +62,5 @@
|
|
|
61
62
|
"esm"
|
|
62
63
|
]
|
|
63
64
|
},
|
|
64
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "391a36550a66833b3d393ff0deb699b1b72cca59"
|
|
65
66
|
}
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
Hasher,
|
|
8
8
|
KBOptions,
|
|
9
9
|
KB_JWT_TYP,
|
|
10
|
+
PresentationFrame,
|
|
10
11
|
SDJWTCompact,
|
|
11
12
|
SDJWTConfig,
|
|
12
13
|
} from '@sd-jwt/types';
|
|
@@ -139,14 +140,13 @@ export class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
139
140
|
return;
|
|
140
141
|
}
|
|
141
142
|
|
|
142
|
-
public async present(
|
|
143
|
+
public async present<T extends Record<string, unknown>>(
|
|
143
144
|
encodedSDJwt: string,
|
|
144
|
-
|
|
145
|
+
presentationFrame?: PresentationFrame<T>,
|
|
145
146
|
options?: {
|
|
146
147
|
kb?: KBOptions;
|
|
147
148
|
},
|
|
148
149
|
): Promise<SDJWTCompact> {
|
|
149
|
-
if (!presentationKeys) return encodedSDJwt;
|
|
150
150
|
if (!this.userConfig.hasher) {
|
|
151
151
|
throw new SDJWTException('Hasher not found');
|
|
152
152
|
}
|
|
@@ -156,7 +156,7 @@ export class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
156
156
|
|
|
157
157
|
if (!sdjwt.jwt?.payload) throw new SDJWTException('Payload not found');
|
|
158
158
|
const presentSdJwtWithoutKb = await sdjwt.present(
|
|
159
|
-
|
|
159
|
+
presentationFrame,
|
|
160
160
|
hasher,
|
|
161
161
|
);
|
|
162
162
|
|
|
@@ -171,7 +171,7 @@ export class SDJwtInstance<ExtendedPayload extends SdJwtPayload> {
|
|
|
171
171
|
);
|
|
172
172
|
|
|
173
173
|
sdjwt.kbJwt = await this.createKBJwt(options.kb, sdHashStr);
|
|
174
|
-
return sdjwt.present(
|
|
174
|
+
return sdjwt.present(presentationFrame, hasher);
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
// This function is for verifying the SD JWT
|
package/src/jwt.ts
CHANGED
|
@@ -98,7 +98,7 @@ export class Jwt<
|
|
|
98
98
|
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
|
99
99
|
const data = `${header}.${payload}`;
|
|
100
100
|
|
|
101
|
-
const verified = verifier(data, this.signature);
|
|
101
|
+
const verified = await verifier(data, this.signature);
|
|
102
102
|
if (!verified) {
|
|
103
103
|
throw new SDJWTException('Verify Error: Invalid JWT Signature');
|
|
104
104
|
}
|
package/src/kbjwt.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { Base64urlEncode, SDJWTException } from '@sd-jwt/utils';
|
|
2
2
|
import { Jwt } from './jwt';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
JwtPayload,
|
|
5
|
+
KB_JWT_TYP,
|
|
6
|
+
kbHeader,
|
|
7
|
+
kbPayload,
|
|
8
|
+
KbVerifier,
|
|
9
|
+
} from '@sd-jwt/types';
|
|
4
10
|
|
|
5
11
|
export class KBJwt<
|
|
6
12
|
Header extends kbHeader = kbHeader,
|
|
@@ -9,23 +15,26 @@ export class KBJwt<
|
|
|
9
15
|
// Checking the validity of the key binding jwt
|
|
10
16
|
// 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
|
|
11
17
|
public async verifyKB(values: { verifier: KbVerifier; payload: JwtPayload }) {
|
|
18
|
+
if (!this.header || !this.payload || !this.signature) {
|
|
19
|
+
throw new SDJWTException('Verify Error: Invalid JWT');
|
|
20
|
+
}
|
|
21
|
+
|
|
12
22
|
if (
|
|
13
|
-
!this.header
|
|
23
|
+
!this.header.alg ||
|
|
24
|
+
this.header.alg === 'none' ||
|
|
14
25
|
!this.header.typ ||
|
|
15
|
-
|
|
16
|
-
!this.payload
|
|
17
|
-
!this.payload
|
|
26
|
+
this.header.typ !== KB_JWT_TYP ||
|
|
27
|
+
!this.payload.iat ||
|
|
28
|
+
!this.payload.aud ||
|
|
29
|
+
!this.payload.nonce ||
|
|
18
30
|
// this is for backward compatibility with version 06
|
|
19
31
|
!(
|
|
20
|
-
this.payload
|
|
32
|
+
this.payload.sd_hash ||
|
|
21
33
|
(this.payload as Record<string, unknown> | undefined)?._sd_hash
|
|
22
34
|
)
|
|
23
35
|
) {
|
|
24
36
|
throw new SDJWTException('Invalid Key Binding Jwt');
|
|
25
37
|
}
|
|
26
|
-
if (!this.header || !this.payload || !this.signature) {
|
|
27
|
-
throw new SDJWTException('Verify Error: Invalid JWT');
|
|
28
|
-
}
|
|
29
38
|
|
|
30
39
|
const header = Base64urlEncode(JSON.stringify(this.header));
|
|
31
40
|
const payload = Base64urlEncode(JSON.stringify(this.payload));
|
package/src/sdjwt.ts
CHANGED
|
@@ -6,19 +6,18 @@ import {
|
|
|
6
6
|
DisclosureFrame,
|
|
7
7
|
Hasher,
|
|
8
8
|
HasherAndAlg,
|
|
9
|
-
|
|
10
|
-
KB_JWT_TYP,
|
|
9
|
+
PresentationFrame,
|
|
11
10
|
SDJWTCompact,
|
|
12
11
|
SD_DECOY,
|
|
13
12
|
SD_DIGEST,
|
|
14
13
|
SD_LIST_KEY,
|
|
15
14
|
SD_SEPARATOR,
|
|
16
15
|
SaltGenerator,
|
|
17
|
-
Signer,
|
|
18
16
|
kbHeader,
|
|
19
17
|
kbPayload,
|
|
20
18
|
} from '@sd-jwt/types';
|
|
21
19
|
import { createHashMapping, getSDAlgAndPayload, unpack } from '@sd-jwt/decode';
|
|
20
|
+
import { transformPresentationFrame } from '@sd-jwt/present';
|
|
22
21
|
|
|
23
22
|
export type SDJwtData<
|
|
24
23
|
Header extends Record<string, unknown>,
|
|
@@ -117,7 +116,10 @@ export class SDJwt<
|
|
|
117
116
|
});
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
public async present
|
|
119
|
+
public async present<T extends Record<string, unknown>>(
|
|
120
|
+
presentFrame: PresentationFrame<T> | undefined,
|
|
121
|
+
hasher: Hasher,
|
|
122
|
+
): Promise<SDJWTCompact> {
|
|
121
123
|
if (!this.jwt?.payload || !this.disclosures) {
|
|
122
124
|
throw new SDJWTException('Invalid sd-jwt: jwt or disclosures is missing');
|
|
123
125
|
}
|
|
@@ -130,15 +132,12 @@ export class SDJwt<
|
|
|
130
132
|
hasher,
|
|
131
133
|
);
|
|
132
134
|
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]);
|
|
135
|
+
const keys = presentFrame
|
|
136
|
+
? transformPresentationFrame(presentFrame)
|
|
137
|
+
: await this.presentableKeys(hasher);
|
|
138
|
+
const disclosures = keys
|
|
139
|
+
.map((k) => hashmap[disclosureKeymap[k]])
|
|
140
|
+
.filter((d) => d !== undefined);
|
|
142
141
|
const presentSDJwt = new SDJwt({
|
|
143
142
|
jwt: this.jwt,
|
|
144
143
|
disclosures,
|
package/src/test/index.spec.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { SDJwtInstance, SdJwtPayload } from '../index';
|
|
2
|
-
import { Signer, Verifier } from '@sd-jwt/types';
|
|
2
|
+
import { Signer, Verifier, KbVerifier, JwtPayload } from '@sd-jwt/types';
|
|
3
3
|
import Crypto, { KeyLike } from 'node:crypto';
|
|
4
4
|
import { describe, expect, test } from 'vitest';
|
|
5
5
|
import { digest, generateSalt } from '@sd-jwt/crypto-nodejs';
|
|
6
|
-
import { KbVerifier, JwtPayload } from '@sd-jwt/types';
|
|
7
6
|
import { importJWK, exportJWK, JWK } from 'jose';
|
|
8
7
|
|
|
9
8
|
export const createSignerVerifier = () => {
|
|
@@ -54,15 +53,19 @@ describe('index', () => {
|
|
|
54
53
|
|
|
55
54
|
expect(credential).toBeDefined();
|
|
56
55
|
|
|
57
|
-
const presentation = await sdjwt.present(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
56
|
+
const presentation = await sdjwt.present(
|
|
57
|
+
credential,
|
|
58
|
+
{ foo: true },
|
|
59
|
+
{
|
|
60
|
+
kb: {
|
|
61
|
+
payload: {
|
|
62
|
+
aud: '1',
|
|
63
|
+
iat: 1,
|
|
64
|
+
nonce: '342',
|
|
65
|
+
},
|
|
63
66
|
},
|
|
64
67
|
},
|
|
65
|
-
|
|
68
|
+
);
|
|
66
69
|
|
|
67
70
|
expect(presentation).toBeDefined();
|
|
68
71
|
});
|
|
@@ -164,15 +167,19 @@ describe('index', () => {
|
|
|
164
167
|
},
|
|
165
168
|
);
|
|
166
169
|
|
|
167
|
-
const presentation = await sdjwt.present(
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
const presentation = await sdjwt.present(
|
|
171
|
+
credential,
|
|
172
|
+
{ foo: true },
|
|
173
|
+
{
|
|
174
|
+
kb: {
|
|
175
|
+
payload: {
|
|
176
|
+
aud: '',
|
|
177
|
+
iat: 1,
|
|
178
|
+
nonce: '342',
|
|
179
|
+
},
|
|
173
180
|
},
|
|
174
181
|
},
|
|
175
|
-
|
|
182
|
+
);
|
|
176
183
|
|
|
177
184
|
try {
|
|
178
185
|
await sdjwt.verify(presentation);
|
|
@@ -236,15 +243,19 @@ describe('index', () => {
|
|
|
236
243
|
},
|
|
237
244
|
);
|
|
238
245
|
|
|
239
|
-
const presentation = await sdjwt.present(
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
246
|
+
const presentation = await sdjwt.present(
|
|
247
|
+
credential,
|
|
248
|
+
{ foo: true },
|
|
249
|
+
{
|
|
250
|
+
kb: {
|
|
251
|
+
payload: {
|
|
252
|
+
aud: '1',
|
|
253
|
+
iat: 1,
|
|
254
|
+
nonce: '342',
|
|
255
|
+
},
|
|
245
256
|
},
|
|
246
257
|
},
|
|
247
|
-
|
|
258
|
+
);
|
|
248
259
|
|
|
249
260
|
const results = await sdjwt.verify(presentation, ['foo'], true);
|
|
250
261
|
expect(results).toBeDefined();
|
|
@@ -342,15 +353,19 @@ describe('index', () => {
|
|
|
342
353
|
},
|
|
343
354
|
);
|
|
344
355
|
|
|
345
|
-
const presentation = await sdjwt.present(
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
356
|
+
const presentation = await sdjwt.present(
|
|
357
|
+
credential,
|
|
358
|
+
{ foo: true },
|
|
359
|
+
{
|
|
360
|
+
kb: {
|
|
361
|
+
payload: {
|
|
362
|
+
aud: '1',
|
|
363
|
+
iat: 1,
|
|
364
|
+
nonce: '342',
|
|
365
|
+
},
|
|
351
366
|
},
|
|
352
367
|
},
|
|
353
|
-
|
|
368
|
+
);
|
|
354
369
|
try {
|
|
355
370
|
const results = await sdjwt.verify(presentation, ['foo'], true);
|
|
356
371
|
} catch (e) {
|
|
@@ -382,15 +397,19 @@ describe('index', () => {
|
|
|
382
397
|
},
|
|
383
398
|
);
|
|
384
399
|
try {
|
|
385
|
-
const presentation = await sdjwt.present(
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
400
|
+
const presentation = await sdjwt.present(
|
|
401
|
+
credential,
|
|
402
|
+
{ foo: true },
|
|
403
|
+
{
|
|
404
|
+
kb: {
|
|
405
|
+
payload: {
|
|
406
|
+
aud: '1',
|
|
407
|
+
iat: 1,
|
|
408
|
+
nonce: '342',
|
|
409
|
+
},
|
|
391
410
|
},
|
|
392
411
|
},
|
|
393
|
-
|
|
412
|
+
);
|
|
394
413
|
} catch (e) {
|
|
395
414
|
expect(e).toBeDefined();
|
|
396
415
|
}
|
|
@@ -420,15 +439,19 @@ describe('index', () => {
|
|
|
420
439
|
},
|
|
421
440
|
);
|
|
422
441
|
|
|
423
|
-
const presentation = await sdjwt.present(
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
442
|
+
const presentation = await sdjwt.present(
|
|
443
|
+
credential,
|
|
444
|
+
{ foo: true },
|
|
445
|
+
{
|
|
446
|
+
kb: {
|
|
447
|
+
payload: {
|
|
448
|
+
aud: '1',
|
|
449
|
+
iat: 1,
|
|
450
|
+
nonce: '342',
|
|
451
|
+
},
|
|
429
452
|
},
|
|
430
453
|
},
|
|
431
|
-
|
|
454
|
+
);
|
|
432
455
|
try {
|
|
433
456
|
const results = await sdjwt.verify(presentation, ['foo'], true);
|
|
434
457
|
} catch (e) {
|
|
@@ -459,15 +482,19 @@ describe('index', () => {
|
|
|
459
482
|
},
|
|
460
483
|
);
|
|
461
484
|
|
|
462
|
-
const presentation = sdjwt.present(
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
485
|
+
const presentation = sdjwt.present(
|
|
486
|
+
credential,
|
|
487
|
+
{ foo: true },
|
|
488
|
+
{
|
|
489
|
+
kb: {
|
|
490
|
+
payload: {
|
|
491
|
+
aud: '1',
|
|
492
|
+
iat: 1,
|
|
493
|
+
nonce: '342',
|
|
494
|
+
},
|
|
468
495
|
},
|
|
469
496
|
},
|
|
470
|
-
|
|
497
|
+
);
|
|
471
498
|
expect(presentation).rejects.toThrow(
|
|
472
499
|
'Key Binding sign algorithm not specified',
|
|
473
500
|
);
|
|
@@ -497,7 +524,7 @@ describe('index', () => {
|
|
|
497
524
|
expect(sdjwt.presentableKeys('')).rejects.toThrow('Hasher not found');
|
|
498
525
|
expect(sdjwt.getClaims('')).rejects.toThrow('Hasher not found');
|
|
499
526
|
expect(() => sdjwt.decode('')).toThrowError('Hasher not found');
|
|
500
|
-
expect(sdjwt.present(credential,
|
|
527
|
+
expect(sdjwt.present(credential, { foo: true })).rejects.toThrow(
|
|
501
528
|
'Hasher not found',
|
|
502
529
|
);
|
|
503
530
|
});
|
|
@@ -525,4 +552,42 @@ describe('index', () => {
|
|
|
525
552
|
expect(keys).toBeDefined();
|
|
526
553
|
expect(keys).toEqual(['foo']);
|
|
527
554
|
});
|
|
555
|
+
|
|
556
|
+
test('present all disclosures with kb jwt', async () => {
|
|
557
|
+
const { signer } = createSignerVerifier();
|
|
558
|
+
const sdjwt = new SDJwtInstance<SdJwtPayload>({
|
|
559
|
+
signer,
|
|
560
|
+
kbSigner: signer,
|
|
561
|
+
hasher: digest,
|
|
562
|
+
saltGenerator: generateSalt,
|
|
563
|
+
signAlg: 'EdDSA',
|
|
564
|
+
kbSignAlg: 'EdDSA',
|
|
565
|
+
});
|
|
566
|
+
const credential = await sdjwt.issue(
|
|
567
|
+
{
|
|
568
|
+
foo: 'bar',
|
|
569
|
+
iss: 'Issuer',
|
|
570
|
+
iat: new Date().getTime(),
|
|
571
|
+
vct: '',
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
_sd: ['foo'],
|
|
575
|
+
},
|
|
576
|
+
);
|
|
577
|
+
|
|
578
|
+
const presentation = await sdjwt.present(credential, undefined, {
|
|
579
|
+
kb: {
|
|
580
|
+
payload: {
|
|
581
|
+
aud: '1',
|
|
582
|
+
iat: 1,
|
|
583
|
+
nonce: '342',
|
|
584
|
+
},
|
|
585
|
+
},
|
|
586
|
+
});
|
|
587
|
+
|
|
588
|
+
const decoded = await sdjwt.decode(presentation);
|
|
589
|
+
expect(decoded.jwt).toBeDefined();
|
|
590
|
+
expect(decoded.disclosures).toBeDefined();
|
|
591
|
+
expect(decoded.kbJwt).toBeDefined();
|
|
592
|
+
});
|
|
528
593
|
});
|
package/test/app-e2e.spec.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import Crypto from 'node:crypto';
|
|
2
2
|
import { SDJwtInstance, SdJwtPayload } from '../src';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
DisclosureFrame,
|
|
5
|
+
PresentationFrame,
|
|
6
|
+
Signer,
|
|
7
|
+
Verifier,
|
|
8
|
+
} from '@sd-jwt/types';
|
|
4
9
|
import fs from 'fs';
|
|
5
10
|
import path from 'path';
|
|
6
11
|
import { describe, expect, test } from 'vitest';
|
|
@@ -105,7 +110,10 @@ describe('App', () => {
|
|
|
105
110
|
'id',
|
|
106
111
|
]);
|
|
107
112
|
|
|
108
|
-
const presentationFrame =
|
|
113
|
+
const presentationFrame = {
|
|
114
|
+
firstname: true,
|
|
115
|
+
id: true,
|
|
116
|
+
};
|
|
109
117
|
const presentedSDJwt = await sdjwt.present(encodedSdjwt, presentationFrame);
|
|
110
118
|
expect(presentedSDJwt).toBeDefined();
|
|
111
119
|
|
|
@@ -215,7 +223,7 @@ async function JSONtest(filename: string) {
|
|
|
215
223
|
|
|
216
224
|
const presentedSDJwt = await sdjwt.present(
|
|
217
225
|
encodedSdjwt,
|
|
218
|
-
test.
|
|
226
|
+
test.presentationFrames,
|
|
219
227
|
);
|
|
220
228
|
|
|
221
229
|
expect(presentedSDJwt).toBeDefined();
|
|
@@ -236,7 +244,7 @@ async function JSONtest(filename: string) {
|
|
|
236
244
|
type TestJson = {
|
|
237
245
|
claims: SdJwtPayload;
|
|
238
246
|
disclosureFrame: DisclosureFrame<SdJwtPayload>;
|
|
239
|
-
|
|
247
|
+
presentationFrames: PresentationFrame<SdJwtPayload>;
|
|
240
248
|
presenatedClaims: object;
|
|
241
249
|
requiredClaimKeys: string[];
|
|
242
250
|
};
|
|
@@ -7,14 +7,16 @@
|
|
|
7
7
|
"_sd": [0, 1, 2, 3, 4, 5]
|
|
8
8
|
}
|
|
9
9
|
},
|
|
10
|
-
"
|
|
11
|
-
"data_types
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
"presentationFrames": {
|
|
11
|
+
"data_types": {
|
|
12
|
+
"0": true,
|
|
13
|
+
"1": true,
|
|
14
|
+
"2": true,
|
|
15
|
+
"3": true,
|
|
16
|
+
"4": true,
|
|
17
|
+
"5": true
|
|
18
|
+
}
|
|
19
|
+
},
|
|
18
20
|
"presenatedClaims": {
|
|
19
21
|
"data_types": [null, 42, 3.14, "foo", ["Test"], { "foo": "bar" }]
|
|
20
22
|
},
|
package/test/array_full_sd.json
CHANGED
package/test/array_in_sd.json
CHANGED
|
@@ -12,7 +12,16 @@
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"
|
|
15
|
+
"presentationFrames": {
|
|
16
|
+
"nested_array": {
|
|
17
|
+
"0": {
|
|
18
|
+
"0": true
|
|
19
|
+
},
|
|
20
|
+
"1": {
|
|
21
|
+
"1": true
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
16
25
|
"presenatedClaims": {
|
|
17
26
|
"nested_array": [["foo"], ["qux"]]
|
|
18
27
|
},
|
package/test/array_of_nulls.json
CHANGED
|
@@ -28,7 +28,14 @@
|
|
|
28
28
|
"_sd": ["foo"]
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
|
-
"
|
|
31
|
+
"presentationFrames": {
|
|
32
|
+
"addresses": {
|
|
33
|
+
"1": true
|
|
34
|
+
},
|
|
35
|
+
"array_with_one_sd_object": {
|
|
36
|
+
"foo": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
32
39
|
"presenatedClaims": {
|
|
33
40
|
"addresses": [
|
|
34
41
|
{
|
|
@@ -25,12 +25,20 @@
|
|
|
25
25
|
"_sd": [0, 1]
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
-
"
|
|
29
|
-
"array_with_recursive_sd
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
"presentationFrames": {
|
|
29
|
+
"array_with_recursive_sd": {
|
|
30
|
+
"1": {
|
|
31
|
+
"baz": true
|
|
32
|
+
},
|
|
33
|
+
"2": {
|
|
34
|
+
"1": true
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"test2": {
|
|
38
|
+
"0": true,
|
|
39
|
+
"1": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
34
42
|
"presenatedClaims": {
|
|
35
43
|
"array_with_recursive_sd": [
|
|
36
44
|
"boring",
|
package/test/complex.json
CHANGED
package/test/header_mod.json
CHANGED
|
@@ -24,7 +24,11 @@
|
|
|
24
24
|
"birthdate"
|
|
25
25
|
]
|
|
26
26
|
},
|
|
27
|
-
"
|
|
27
|
+
"presentationFrames": {
|
|
28
|
+
"given_name": true,
|
|
29
|
+
"family_name": true,
|
|
30
|
+
"address": true
|
|
31
|
+
},
|
|
28
32
|
"presenatedClaims": {
|
|
29
33
|
"given_name": "John",
|
|
30
34
|
"family_name": "Deo",
|
|
@@ -24,7 +24,11 @@
|
|
|
24
24
|
"birthdate"
|
|
25
25
|
]
|
|
26
26
|
},
|
|
27
|
-
"
|
|
27
|
+
"presentationFrames": {
|
|
28
|
+
"given_name": true,
|
|
29
|
+
"family_name": true,
|
|
30
|
+
"address": true
|
|
31
|
+
},
|
|
28
32
|
"presenatedClaims": {
|
|
29
33
|
"given_name": "John",
|
|
30
34
|
"family_name": "Deo",
|
package/test/key_binding.json
CHANGED
|
@@ -24,7 +24,11 @@
|
|
|
24
24
|
"birthdate"
|
|
25
25
|
]
|
|
26
26
|
},
|
|
27
|
-
"
|
|
27
|
+
"presentationFrames": {
|
|
28
|
+
"given_name": true,
|
|
29
|
+
"family_name": true,
|
|
30
|
+
"address": true
|
|
31
|
+
},
|
|
28
32
|
"presenatedClaims": {
|
|
29
33
|
"given_name": "John",
|
|
30
34
|
"family_name": "Deo",
|
package/test/no_sd.json
CHANGED
|
@@ -25,15 +25,17 @@
|
|
|
25
25
|
]
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
|
-
"
|
|
29
|
-
"value_Data_types
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
"presentationFrames": {
|
|
29
|
+
"value_Data_types": {
|
|
30
|
+
"test_null": true,
|
|
31
|
+
"test_int": true,
|
|
32
|
+
"test_float": true,
|
|
33
|
+
"test_str": true,
|
|
34
|
+
"test_bool": true,
|
|
35
|
+
"test_arr": true,
|
|
36
|
+
"test_object": true
|
|
37
|
+
}
|
|
38
|
+
},
|
|
37
39
|
"presenatedClaims": {
|
|
38
40
|
"value_Data_types": {
|
|
39
41
|
"test_null": null,
|
package/test/recursions.json
CHANGED
|
@@ -50,23 +50,42 @@
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
},
|
|
53
|
-
"
|
|
54
|
-
"foo
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
53
|
+
"presentationFrames": {
|
|
54
|
+
"foo": {
|
|
55
|
+
"1": true
|
|
56
|
+
},
|
|
57
|
+
"bar": {
|
|
58
|
+
"green": true
|
|
59
|
+
},
|
|
60
|
+
"qux": {
|
|
61
|
+
"0": {
|
|
62
|
+
"0": true,
|
|
63
|
+
"1": true
|
|
64
|
+
},
|
|
65
|
+
"1": {
|
|
66
|
+
"0": true,
|
|
67
|
+
"1": true
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"baz": {
|
|
71
|
+
"0": {
|
|
72
|
+
"0": true,
|
|
73
|
+
"1": true
|
|
74
|
+
},
|
|
75
|
+
"1": {
|
|
76
|
+
"0": true,
|
|
77
|
+
"1": true
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
"animals": {
|
|
81
|
+
"snake": {
|
|
82
|
+
"age": true
|
|
83
|
+
},
|
|
84
|
+
"bird": {
|
|
85
|
+
"age": true
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
},
|
|
70
89
|
"presenatedClaims": {
|
|
71
90
|
"foo": ["two"],
|
|
72
91
|
"bar": {
|