@sd-jwt/core 0.3.2-next.74 → 0.3.2-next.76

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/dist/index.d.mts CHANGED
@@ -91,6 +91,7 @@ declare class SDJwtInstance {
91
91
  header: _sd_jwt_types.kbHeader;
92
92
  };
93
93
  }>;
94
+ private calculateSDHash;
94
95
  validate(encodedSDJwt: string): Promise<{
95
96
  payload: unknown;
96
97
  header: Record<string, unknown>;
package/dist/index.d.ts CHANGED
@@ -91,6 +91,7 @@ declare class SDJwtInstance {
91
91
  header: _sd_jwt_types.kbHeader;
92
92
  };
93
93
  }>;
94
+ private calculateSDHash;
94
95
  validate(encodedSDJwt: string): Promise<{
95
96
  payload: unknown;
96
97
  header: Record<string, unknown>;
package/dist/index.js CHANGED
@@ -403,6 +403,7 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
403
403
 
404
404
  // src/index.ts
405
405
  var import_types2 = require("@sd-jwt/types");
406
+ var import_decode3 = require("@sd-jwt/decode");
406
407
  var _SDJwtInstance = class _SDJwtInstance {
407
408
  constructor(userConfig) {
408
409
  this.userConfig = {};
@@ -410,7 +411,7 @@ var _SDJwtInstance = class _SDJwtInstance {
410
411
  this.userConfig = userConfig;
411
412
  }
412
413
  }
413
- createKBJwt(options) {
414
+ createKBJwt(options, sdHash) {
414
415
  return __async(this, null, function* () {
415
416
  if (!this.userConfig.kbSigner) {
416
417
  throw new import_utils5.SDJWTException("Key Binding Signer not found");
@@ -424,7 +425,7 @@ var _SDJwtInstance = class _SDJwtInstance {
424
425
  typ: import_types2.KB_JWT_TYP,
425
426
  alg: this.userConfig.kbSignAlg
426
427
  },
427
- payload
428
+ payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
428
429
  });
429
430
  yield kbJwt.sign(this.userConfig.kbSigner);
430
431
  return kbJwt;
@@ -474,7 +475,7 @@ var _SDJwtInstance = class _SDJwtInstance {
474
475
  const jwt = new Jwt({
475
476
  header,
476
477
  payload: __spreadProps(__spreadValues({}, packedClaims), {
477
- _sd_alg: hashAlg
478
+ _sd_alg: disclosureFrame ? hashAlg : void 0
478
479
  })
479
480
  });
480
481
  yield this.SignJwt(jwt);
@@ -487,6 +488,7 @@ var _SDJwtInstance = class _SDJwtInstance {
487
488
  }
488
489
  present(encodedSDJwt, presentationKeys, options) {
489
490
  return __async(this, null, function* () {
491
+ var _a;
490
492
  if (!presentationKeys)
491
493
  return encodedSDJwt;
492
494
  if (!this.userConfig.hasher) {
@@ -494,8 +496,21 @@ var _SDJwtInstance = class _SDJwtInstance {
494
496
  }
495
497
  const hasher = this.userConfig.hasher;
496
498
  const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
497
- const kbJwt = (options == null ? void 0 : options.kb) ? yield this.createKBJwt(options.kb) : void 0;
498
- sdjwt.kbJwt = kbJwt;
499
+ if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
500
+ throw new import_utils5.SDJWTException("Payload not found");
501
+ const presentSdJwtWithoutKb = yield sdjwt.present(
502
+ presentationKeys.sort(),
503
+ hasher
504
+ );
505
+ if (!(options == null ? void 0 : options.kb)) {
506
+ return presentSdJwtWithoutKb;
507
+ }
508
+ const sdHashStr = yield this.calculateSDHash(
509
+ presentSdJwtWithoutKb,
510
+ sdjwt,
511
+ hasher
512
+ );
513
+ sdjwt.kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
499
514
  return sdjwt.present(presentationKeys.sort(), hasher);
500
515
  });
501
516
  }
@@ -509,7 +524,7 @@ var _SDJwtInstance = class _SDJwtInstance {
509
524
  }
510
525
  const hasher = this.userConfig.hasher;
511
526
  const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
512
- if (!sdjwt.jwt) {
527
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
513
528
  throw new import_utils5.SDJWTException("Invalid SD JWT");
514
529
  }
515
530
  const { payload, header } = yield this.validate(encodedSDJwt);
@@ -532,9 +547,34 @@ var _SDJwtInstance = class _SDJwtInstance {
532
547
  throw new import_utils5.SDJWTException("Key Binding Verifier not found");
533
548
  }
534
549
  const kb = yield sdjwt.kbJwt.verify(this.userConfig.kbVerifier);
550
+ const sdHashfromKb = kb.payload.sd_hash;
551
+ const sdjwtWithoutKb = new SDJwt({
552
+ jwt: sdjwt.jwt,
553
+ disclosures: sdjwt.disclosures
554
+ });
555
+ const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
556
+ const sdHashStr = yield this.calculateSDHash(
557
+ presentSdJwtWithoutKb,
558
+ sdjwt,
559
+ hasher
560
+ );
561
+ if (sdHashStr !== sdHashfromKb) {
562
+ throw new import_utils5.SDJWTException("Invalid sd_hash in Key Binding JWT");
563
+ }
535
564
  return { payload, header, kb };
536
565
  });
537
566
  }
567
+ calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
568
+ return __async(this, null, function* () {
569
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
570
+ throw new import_utils5.SDJWTException("Invalid SD JWT");
571
+ }
572
+ const { _sd_alg } = (0, import_decode3.getSDAlgAndPayload)(sdjwt.jwt.payload);
573
+ const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
574
+ const sdHashStr = (0, import_utils5.Uint8ArrayToBase64Url)(sdHash);
575
+ return sdHashStr;
576
+ });
577
+ }
538
578
  // This function is for validating the SD JWT
539
579
  // Just checking signature and return its the claims
540
580
  validate(encodedSDJwt) {
package/dist/index.mjs CHANGED
@@ -42,7 +42,7 @@ var __async = (__this, __arguments, generator) => {
42
42
  };
43
43
 
44
44
  // src/index.ts
45
- import { SDJWTException as SDJWTException4 } from "@sd-jwt/utils";
45
+ import { SDJWTException as SDJWTException4, Uint8ArrayToBase64Url as Uint8ArrayToBase64Url2 } from "@sd-jwt/utils";
46
46
 
47
47
  // src/jwt.ts
48
48
  import { Base64urlEncode, SDJWTException } from "@sd-jwt/utils";
@@ -381,9 +381,10 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
381
381
 
382
382
  // src/index.ts
383
383
  import {
384
- KB_JWT_TYP,
384
+ KB_JWT_TYP as KB_JWT_TYP2,
385
385
  SD_JWT_TYP
386
386
  } from "@sd-jwt/types";
387
+ import { getSDAlgAndPayload as getSDAlgAndPayload2 } from "@sd-jwt/decode";
387
388
  var _SDJwtInstance = class _SDJwtInstance {
388
389
  constructor(userConfig) {
389
390
  this.userConfig = {};
@@ -391,7 +392,7 @@ var _SDJwtInstance = class _SDJwtInstance {
391
392
  this.userConfig = userConfig;
392
393
  }
393
394
  }
394
- createKBJwt(options) {
395
+ createKBJwt(options, sdHash) {
395
396
  return __async(this, null, function* () {
396
397
  if (!this.userConfig.kbSigner) {
397
398
  throw new SDJWTException4("Key Binding Signer not found");
@@ -402,10 +403,10 @@ var _SDJwtInstance = class _SDJwtInstance {
402
403
  const { payload } = options;
403
404
  const kbJwt = new KBJwt({
404
405
  header: {
405
- typ: KB_JWT_TYP,
406
+ typ: KB_JWT_TYP2,
406
407
  alg: this.userConfig.kbSignAlg
407
408
  },
408
- payload
409
+ payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
409
410
  });
410
411
  yield kbJwt.sign(this.userConfig.kbSigner);
411
412
  return kbJwt;
@@ -455,7 +456,7 @@ var _SDJwtInstance = class _SDJwtInstance {
455
456
  const jwt = new Jwt({
456
457
  header,
457
458
  payload: __spreadProps(__spreadValues({}, packedClaims), {
458
- _sd_alg: hashAlg
459
+ _sd_alg: disclosureFrame ? hashAlg : void 0
459
460
  })
460
461
  });
461
462
  yield this.SignJwt(jwt);
@@ -468,6 +469,7 @@ var _SDJwtInstance = class _SDJwtInstance {
468
469
  }
469
470
  present(encodedSDJwt, presentationKeys, options) {
470
471
  return __async(this, null, function* () {
472
+ var _a;
471
473
  if (!presentationKeys)
472
474
  return encodedSDJwt;
473
475
  if (!this.userConfig.hasher) {
@@ -475,8 +477,21 @@ var _SDJwtInstance = class _SDJwtInstance {
475
477
  }
476
478
  const hasher = this.userConfig.hasher;
477
479
  const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
478
- const kbJwt = (options == null ? void 0 : options.kb) ? yield this.createKBJwt(options.kb) : void 0;
479
- sdjwt.kbJwt = kbJwt;
480
+ if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
481
+ throw new SDJWTException4("Payload not found");
482
+ const presentSdJwtWithoutKb = yield sdjwt.present(
483
+ presentationKeys.sort(),
484
+ hasher
485
+ );
486
+ if (!(options == null ? void 0 : options.kb)) {
487
+ return presentSdJwtWithoutKb;
488
+ }
489
+ const sdHashStr = yield this.calculateSDHash(
490
+ presentSdJwtWithoutKb,
491
+ sdjwt,
492
+ hasher
493
+ );
494
+ sdjwt.kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
480
495
  return sdjwt.present(presentationKeys.sort(), hasher);
481
496
  });
482
497
  }
@@ -490,7 +505,7 @@ var _SDJwtInstance = class _SDJwtInstance {
490
505
  }
491
506
  const hasher = this.userConfig.hasher;
492
507
  const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
493
- if (!sdjwt.jwt) {
508
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
494
509
  throw new SDJWTException4("Invalid SD JWT");
495
510
  }
496
511
  const { payload, header } = yield this.validate(encodedSDJwt);
@@ -513,9 +528,34 @@ var _SDJwtInstance = class _SDJwtInstance {
513
528
  throw new SDJWTException4("Key Binding Verifier not found");
514
529
  }
515
530
  const kb = yield sdjwt.kbJwt.verify(this.userConfig.kbVerifier);
531
+ const sdHashfromKb = kb.payload.sd_hash;
532
+ const sdjwtWithoutKb = new SDJwt({
533
+ jwt: sdjwt.jwt,
534
+ disclosures: sdjwt.disclosures
535
+ });
536
+ const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
537
+ const sdHashStr = yield this.calculateSDHash(
538
+ presentSdJwtWithoutKb,
539
+ sdjwt,
540
+ hasher
541
+ );
542
+ if (sdHashStr !== sdHashfromKb) {
543
+ throw new SDJWTException4("Invalid sd_hash in Key Binding JWT");
544
+ }
516
545
  return { payload, header, kb };
517
546
  });
518
547
  }
548
+ calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
549
+ return __async(this, null, function* () {
550
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
551
+ throw new SDJWTException4("Invalid SD JWT");
552
+ }
553
+ const { _sd_alg } = getSDAlgAndPayload2(sdjwt.jwt.payload);
554
+ const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
555
+ const sdHashStr = Uint8ArrayToBase64Url2(sdHash);
556
+ return sdHashStr;
557
+ });
558
+ }
519
559
  // This function is for validating the SD JWT
520
560
  // Just checking signature and return its the claims
521
561
  validate(encodedSDJwt) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sd-jwt/core",
3
- "version": "0.3.2-next.74+d503996",
3
+ "version": "0.3.2-next.76+270ba1b",
4
4
  "description": "sd-jwt draft 7 implementation in typescript",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -39,12 +39,12 @@
39
39
  },
40
40
  "license": "Apache-2.0",
41
41
  "devDependencies": {
42
- "@sd-jwt/crypto-nodejs": "0.3.2-next.74+d503996"
42
+ "@sd-jwt/crypto-nodejs": "0.3.2-next.76+270ba1b"
43
43
  },
44
44
  "dependencies": {
45
- "@sd-jwt/decode": "0.3.2-next.74+d503996",
46
- "@sd-jwt/types": "0.3.2-next.74+d503996",
47
- "@sd-jwt/utils": "0.3.2-next.74+d503996"
45
+ "@sd-jwt/decode": "0.3.2-next.76+270ba1b",
46
+ "@sd-jwt/types": "0.3.2-next.76+270ba1b",
47
+ "@sd-jwt/utils": "0.3.2-next.76+270ba1b"
48
48
  },
49
49
  "publishConfig": {
50
50
  "access": "public"
@@ -62,5 +62,5 @@
62
62
  "esm"
63
63
  ]
64
64
  },
65
- "gitHead": "d5039962a53cb1b55a28dc956d71eab865c05917"
65
+ "gitHead": "270ba1b51bde3fd8c4f2dc7d9eaf09e1225c7873"
66
66
  }
package/src/index.ts CHANGED
@@ -1,15 +1,17 @@
1
- import { SDJWTException } from '@sd-jwt/utils';
1
+ import { SDJWTException, Uint8ArrayToBase64Url } from '@sd-jwt/utils';
2
2
  import { Jwt } from './jwt';
3
3
  import { KBJwt } from './kbjwt';
4
4
  import { SDJwt, pack } from './sdjwt';
5
5
  import {
6
6
  DisclosureFrame,
7
+ Hasher,
7
8
  KBOptions,
8
9
  KB_JWT_TYP,
9
10
  SDJWTCompact,
10
11
  SDJWTConfig,
11
12
  SD_JWT_TYP,
12
13
  } from '@sd-jwt/types';
14
+ import { getSDAlgAndPayload } from '@sd-jwt/decode';
13
15
 
14
16
  export * from './sdjwt';
15
17
  export * from './kbjwt';
@@ -27,20 +29,24 @@ export class SDJwtInstance {
27
29
  }
28
30
  }
29
31
 
30
- private async createKBJwt(options: KBOptions): Promise<KBJwt> {
32
+ private async createKBJwt(
33
+ options: KBOptions,
34
+ sdHash: string,
35
+ ): Promise<KBJwt> {
31
36
  if (!this.userConfig.kbSigner) {
32
37
  throw new SDJWTException('Key Binding Signer not found');
33
38
  }
34
39
  if (!this.userConfig.kbSignAlg) {
35
40
  throw new SDJWTException('Key Binding sign algorithm not specified');
36
41
  }
42
+
37
43
  const { payload } = options;
38
44
  const kbJwt = new KBJwt({
39
45
  header: {
40
46
  typ: KB_JWT_TYP,
41
47
  alg: this.userConfig.kbSignAlg,
42
48
  },
43
- payload,
49
+ payload: { ...payload, sd_hash: sdHash },
44
50
  });
45
51
 
46
52
  await kbJwt.sign(this.userConfig.kbSigner);
@@ -100,7 +106,7 @@ export class SDJwtInstance {
100
106
  header,
101
107
  payload: {
102
108
  ...packedClaims,
103
- _sd_alg: hashAlg,
109
+ _sd_alg: disclosureFrame ? hashAlg : undefined,
104
110
  },
105
111
  });
106
112
  await this.SignJwt(jwt);
@@ -127,9 +133,24 @@ export class SDJwtInstance {
127
133
  const hasher = this.userConfig.hasher;
128
134
 
129
135
  const sdjwt = await SDJwt.fromEncode(encodedSDJwt, hasher);
130
- const kbJwt = options?.kb ? await this.createKBJwt(options.kb) : undefined;
131
- sdjwt.kbJwt = kbJwt;
132
136
 
137
+ if (!sdjwt.jwt?.payload) throw new SDJWTException('Payload not found');
138
+ const presentSdJwtWithoutKb = await sdjwt.present(
139
+ presentationKeys.sort(),
140
+ hasher,
141
+ );
142
+
143
+ if (!options?.kb) {
144
+ return presentSdJwtWithoutKb;
145
+ }
146
+
147
+ const sdHashStr = await this.calculateSDHash(
148
+ presentSdJwtWithoutKb,
149
+ sdjwt,
150
+ hasher,
151
+ );
152
+
153
+ sdjwt.kbJwt = await this.createKBJwt(options.kb, sdHashStr);
133
154
  return sdjwt.present(presentationKeys.sort(), hasher);
134
155
  }
135
156
 
@@ -147,7 +168,7 @@ export class SDJwtInstance {
147
168
  const hasher = this.userConfig.hasher;
148
169
 
149
170
  const sdjwt = await SDJwt.fromEncode(encodedSDJwt, hasher);
150
- if (!sdjwt.jwt) {
171
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
151
172
  throw new SDJWTException('Invalid SD JWT');
152
173
  }
153
174
  const { payload, header } = await this.validate(encodedSDJwt);
@@ -173,9 +194,40 @@ export class SDJwtInstance {
173
194
  throw new SDJWTException('Key Binding Verifier not found');
174
195
  }
175
196
  const kb = await sdjwt.kbJwt.verify(this.userConfig.kbVerifier);
197
+ const sdHashfromKb = kb.payload.sd_hash;
198
+ const sdjwtWithoutKb = new SDJwt({
199
+ jwt: sdjwt.jwt,
200
+ disclosures: sdjwt.disclosures,
201
+ });
202
+
203
+ const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
204
+ const sdHashStr = await this.calculateSDHash(
205
+ presentSdJwtWithoutKb,
206
+ sdjwt,
207
+ hasher,
208
+ );
209
+
210
+ if (sdHashStr !== sdHashfromKb) {
211
+ throw new SDJWTException('Invalid sd_hash in Key Binding JWT');
212
+ }
213
+
176
214
  return { payload, header, kb };
177
215
  }
178
216
 
217
+ private async calculateSDHash(
218
+ presentSdJwtWithoutKb: string,
219
+ sdjwt: SDJwt,
220
+ hasher: Hasher,
221
+ ) {
222
+ if (!sdjwt.jwt || !sdjwt.jwt.payload) {
223
+ throw new SDJWTException('Invalid SD JWT');
224
+ }
225
+ const { _sd_alg } = getSDAlgAndPayload(sdjwt.jwt.payload);
226
+ const sdHash = await hasher(presentSdJwtWithoutKb, _sd_alg);
227
+ const sdHashStr = Uint8ArrayToBase64Url(sdHash);
228
+ return sdHashStr;
229
+ }
230
+
179
231
  // This function is for validating the SD JWT
180
232
  // Just checking signature and return its the claims
181
233
  public async validate(encodedSDJwt: string) {
package/src/sdjwt.ts CHANGED
@@ -6,12 +6,15 @@ import {
6
6
  DisclosureFrame,
7
7
  Hasher,
8
8
  HasherAndAlg,
9
+ KBOptions,
10
+ KB_JWT_TYP,
9
11
  SDJWTCompact,
10
12
  SD_DECOY,
11
13
  SD_DIGEST,
12
14
  SD_LIST_KEY,
13
15
  SD_SEPARATOR,
14
16
  SaltGenerator,
17
+ Signer,
15
18
  kbHeader,
16
19
  kbPayload,
17
20
  } from '@sd-jwt/types';
@@ -52,7 +52,6 @@ describe('index', () => {
52
52
  const presentation = await sdjwt.present(credential, ['foo'], {
53
53
  kb: {
54
54
  payload: {
55
- sd_hash: 'sha-256',
56
55
  aud: '1',
57
56
  iat: 1,
58
57
  nonce: '342',
@@ -154,8 +153,7 @@ describe('index', () => {
154
153
  const presentation = await sdjwt.present(credential, ['foo'], {
155
154
  kb: {
156
155
  payload: {
157
- sd_hash: '',
158
- aud: '1',
156
+ aud: '',
159
157
  iat: 1,
160
158
  nonce: '342',
161
159
  },
@@ -194,7 +192,6 @@ describe('index', () => {
194
192
  const presentation = await sdjwt.present(credential, ['foo'], {
195
193
  kb: {
196
194
  payload: {
197
- sd_hash: 'sha-256',
198
195
  aud: '1',
199
196
  iat: 1,
200
197
  nonce: '342',
@@ -289,7 +286,6 @@ describe('index', () => {
289
286
  const presentation = await sdjwt.present(credential, ['foo'], {
290
287
  kb: {
291
288
  payload: {
292
- sd_hash: 'sha-256',
293
289
  aud: '1',
294
290
  iat: 1,
295
291
  nonce: '342',
@@ -327,7 +323,6 @@ describe('index', () => {
327
323
  const presentation = await sdjwt.present(credential, ['foo'], {
328
324
  kb: {
329
325
  payload: {
330
- sd_hash: 'sha-256',
331
326
  aud: '1',
332
327
  iat: 1,
333
328
  nonce: '342',
@@ -363,7 +358,6 @@ describe('index', () => {
363
358
  const presentation = await sdjwt.present(credential, ['foo'], {
364
359
  kb: {
365
360
  payload: {
366
- sd_hash: 'sha-256',
367
361
  aud: '1',
368
362
  iat: 1,
369
363
  nonce: '342',