@sd-jwt/core 0.7.2 → 0.8.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 +11 -0
- package/dist/index.d.mts +142 -2
- package/dist/index.d.ts +142 -2
- package/dist/index.js +481 -33
- package/dist/index.mjs +479 -29
- package/package.json +7 -7
- package/src/flattenJSON.ts +90 -0
- package/src/generalJSON.ts +140 -0
- package/src/index.ts +350 -3
- package/src/sdjwt.ts +14 -6
- package/src/test/flattenJSON.spec.ts +56 -0
- package/src/test/generalJSON.spec.ts +124 -0
package/dist/index.mjs
CHANGED
|
@@ -39,7 +39,12 @@ var __async = (__this, __arguments, generator) => {
|
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
// src/index.ts
|
|
42
|
-
import {
|
|
42
|
+
import {
|
|
43
|
+
base64urlDecode,
|
|
44
|
+
base64urlEncode as base64urlEncode3,
|
|
45
|
+
SDJWTException as SDJWTException6,
|
|
46
|
+
uint8ArrayToBase64Url as uint8ArrayToBase64Url2
|
|
47
|
+
} from "@sd-jwt/utils";
|
|
43
48
|
|
|
44
49
|
// src/jwt.ts
|
|
45
50
|
import { base64urlEncode, SDJWTException } from "@sd-jwt/utils";
|
|
@@ -237,6 +242,17 @@ var SDJwt = class _SDJwt {
|
|
|
237
242
|
});
|
|
238
243
|
}
|
|
239
244
|
present(presentFrame, hasher) {
|
|
245
|
+
return __async(this, null, function* () {
|
|
246
|
+
const disclosures = yield this.getPresentDisclosures(presentFrame, hasher);
|
|
247
|
+
const presentSDJwt = new _SDJwt({
|
|
248
|
+
jwt: this.jwt,
|
|
249
|
+
disclosures,
|
|
250
|
+
kbJwt: this.kbJwt
|
|
251
|
+
});
|
|
252
|
+
return presentSDJwt.encodeSDJwt();
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
getPresentDisclosures(presentFrame, hasher) {
|
|
240
256
|
return __async(this, null, function* () {
|
|
241
257
|
var _a;
|
|
242
258
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
@@ -252,12 +268,7 @@ var SDJwt = class _SDJwt {
|
|
|
252
268
|
);
|
|
253
269
|
const keys = presentFrame ? transformPresentationFrame(presentFrame) : yield this.presentableKeys(hasher);
|
|
254
270
|
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
255
|
-
|
|
256
|
-
jwt: this.jwt,
|
|
257
|
-
disclosures,
|
|
258
|
-
kbJwt: this.kbJwt
|
|
259
|
-
});
|
|
260
|
-
return presentSDJwt.encodeSDJwt();
|
|
271
|
+
return disclosures;
|
|
261
272
|
});
|
|
262
273
|
}
|
|
263
274
|
encodeSDJwt() {
|
|
@@ -410,6 +421,166 @@ import {
|
|
|
410
421
|
KB_JWT_TYP as KB_JWT_TYP2
|
|
411
422
|
} from "@sd-jwt/types";
|
|
412
423
|
import { getSDAlgAndPayload as getSDAlgAndPayload2 } from "@sd-jwt/decode";
|
|
424
|
+
|
|
425
|
+
// src/flattenJSON.ts
|
|
426
|
+
import { SDJWTException as SDJWTException4 } from "@sd-jwt/utils";
|
|
427
|
+
import { splitSdJwt } from "@sd-jwt/decode";
|
|
428
|
+
import { SD_SEPARATOR as SD_SEPARATOR2 } from "@sd-jwt/types";
|
|
429
|
+
var FlattenJSON = class _FlattenJSON {
|
|
430
|
+
constructor(data) {
|
|
431
|
+
this.disclosures = data.disclosures;
|
|
432
|
+
this.kb_jwt = data.kb_jwt;
|
|
433
|
+
this.payload = data.jwtData.payload;
|
|
434
|
+
this.signature = data.jwtData.signature;
|
|
435
|
+
this.protected = data.jwtData.protected;
|
|
436
|
+
}
|
|
437
|
+
static fromEncode(encodedSdJwt) {
|
|
438
|
+
const { jwt, disclosures, kbJwt } = splitSdJwt(encodedSdJwt);
|
|
439
|
+
const { 0: protectedHeader, 1: payload, 2: signature } = jwt.split(".");
|
|
440
|
+
if (!protectedHeader || !payload || !signature) {
|
|
441
|
+
throw new SDJWTException4("Invalid JWT");
|
|
442
|
+
}
|
|
443
|
+
return new _FlattenJSON({
|
|
444
|
+
jwtData: {
|
|
445
|
+
protected: protectedHeader,
|
|
446
|
+
payload,
|
|
447
|
+
signature
|
|
448
|
+
},
|
|
449
|
+
disclosures,
|
|
450
|
+
kb_jwt: kbJwt
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
static fromSerialized(json) {
|
|
454
|
+
return new _FlattenJSON({
|
|
455
|
+
jwtData: {
|
|
456
|
+
protected: json.protected,
|
|
457
|
+
payload: json.payload,
|
|
458
|
+
signature: json.signature
|
|
459
|
+
},
|
|
460
|
+
disclosures: json.header.disclosures,
|
|
461
|
+
kb_jwt: json.header.kb_jwt
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
toJson() {
|
|
465
|
+
return {
|
|
466
|
+
payload: this.payload,
|
|
467
|
+
signature: this.signature,
|
|
468
|
+
protected: this.protected,
|
|
469
|
+
header: {
|
|
470
|
+
disclosures: this.disclosures,
|
|
471
|
+
kb_jwt: this.kb_jwt
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
toEncoded() {
|
|
476
|
+
var _a;
|
|
477
|
+
const jwt = `${this.protected}.${this.payload}.${this.signature}`;
|
|
478
|
+
const disclosures = this.disclosures.join(SD_SEPARATOR2);
|
|
479
|
+
const kb_jwt = (_a = this.kb_jwt) != null ? _a : "";
|
|
480
|
+
return [jwt, disclosures, kb_jwt].join(SD_SEPARATOR2);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// src/generalJSON.ts
|
|
485
|
+
import { base64urlEncode as base64urlEncode2, SDJWTException as SDJWTException5 } from "@sd-jwt/utils";
|
|
486
|
+
import { splitSdJwt as splitSdJwt2 } from "@sd-jwt/decode";
|
|
487
|
+
import { SD_SEPARATOR as SD_SEPARATOR3 } from "@sd-jwt/types";
|
|
488
|
+
var GeneralJSON = class _GeneralJSON {
|
|
489
|
+
constructor(data) {
|
|
490
|
+
this.payload = data.payload;
|
|
491
|
+
this.disclosures = data.disclosures;
|
|
492
|
+
this.kb_jwt = data.kb_jwt;
|
|
493
|
+
this.signatures = data.signatures;
|
|
494
|
+
}
|
|
495
|
+
static fromEncode(encodedSdJwt) {
|
|
496
|
+
const { jwt, disclosures, kbJwt } = splitSdJwt2(encodedSdJwt);
|
|
497
|
+
const { 0: protectedHeader, 1: payload, 2: signature } = jwt.split(".");
|
|
498
|
+
if (!protectedHeader || !payload || !signature) {
|
|
499
|
+
throw new SDJWTException5("Invalid JWT");
|
|
500
|
+
}
|
|
501
|
+
return new _GeneralJSON({
|
|
502
|
+
payload,
|
|
503
|
+
disclosures,
|
|
504
|
+
kb_jwt: kbJwt,
|
|
505
|
+
signatures: [
|
|
506
|
+
{
|
|
507
|
+
protected: protectedHeader,
|
|
508
|
+
signature
|
|
509
|
+
}
|
|
510
|
+
]
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
static fromSerialized(json) {
|
|
514
|
+
var _a, _b, _c;
|
|
515
|
+
if (!json.signatures[0]) {
|
|
516
|
+
throw new SDJWTException5("Invalid JSON");
|
|
517
|
+
}
|
|
518
|
+
const disclosures = (_b = (_a = json.signatures[0].header) == null ? void 0 : _a.disclosures) != null ? _b : [];
|
|
519
|
+
const kb_jwt = (_c = json.signatures[0].header) == null ? void 0 : _c.kb_jwt;
|
|
520
|
+
return new _GeneralJSON({
|
|
521
|
+
payload: json.payload,
|
|
522
|
+
disclosures,
|
|
523
|
+
kb_jwt,
|
|
524
|
+
signatures: json.signatures.map((s) => {
|
|
525
|
+
var _a2;
|
|
526
|
+
return {
|
|
527
|
+
protected: s.protected,
|
|
528
|
+
signature: s.signature,
|
|
529
|
+
kid: (_a2 = s.header) == null ? void 0 : _a2.kid
|
|
530
|
+
};
|
|
531
|
+
})
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
toJson() {
|
|
535
|
+
return {
|
|
536
|
+
payload: this.payload,
|
|
537
|
+
signatures: this.signatures.map((s, i) => {
|
|
538
|
+
if (i !== 0) {
|
|
539
|
+
return {
|
|
540
|
+
header: {
|
|
541
|
+
kid: s.kid
|
|
542
|
+
},
|
|
543
|
+
protected: s.protected,
|
|
544
|
+
signature: s.signature
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
return {
|
|
548
|
+
header: {
|
|
549
|
+
disclosures: this.disclosures,
|
|
550
|
+
kid: s.kid,
|
|
551
|
+
kb_jwt: this.kb_jwt
|
|
552
|
+
},
|
|
553
|
+
protected: s.protected,
|
|
554
|
+
signature: s.signature
|
|
555
|
+
};
|
|
556
|
+
})
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
toEncoded(index) {
|
|
560
|
+
var _a;
|
|
561
|
+
if (index < 0 || index >= this.signatures.length) {
|
|
562
|
+
throw new SDJWTException5("Index out of bounds");
|
|
563
|
+
}
|
|
564
|
+
const { protected: protectedHeader, signature } = this.signatures[index];
|
|
565
|
+
const disclosures = this.disclosures.join(SD_SEPARATOR3);
|
|
566
|
+
const kb_jwt = (_a = this.kb_jwt) != null ? _a : "";
|
|
567
|
+
const jwt = `${protectedHeader}.${this.payload}.${signature}`;
|
|
568
|
+
return [jwt, disclosures, kb_jwt].join(SD_SEPARATOR3);
|
|
569
|
+
}
|
|
570
|
+
addSignature(protectedHeader, signer, kid) {
|
|
571
|
+
return __async(this, null, function* () {
|
|
572
|
+
const header = base64urlEncode2(JSON.stringify(protectedHeader));
|
|
573
|
+
const signature = yield signer(`${header}.${this.payload}`);
|
|
574
|
+
this.signatures.push({
|
|
575
|
+
protected: header,
|
|
576
|
+
signature,
|
|
577
|
+
kid
|
|
578
|
+
});
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
// src/index.ts
|
|
413
584
|
var _SDJwtInstance = class _SDJwtInstance {
|
|
414
585
|
constructor(userConfig) {
|
|
415
586
|
this.userConfig = {};
|
|
@@ -420,10 +591,10 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
420
591
|
createKBJwt(options, sdHash) {
|
|
421
592
|
return __async(this, null, function* () {
|
|
422
593
|
if (!this.userConfig.kbSigner) {
|
|
423
|
-
throw new
|
|
594
|
+
throw new SDJWTException6("Key Binding Signer not found");
|
|
424
595
|
}
|
|
425
596
|
if (!this.userConfig.kbSignAlg) {
|
|
426
|
-
throw new
|
|
597
|
+
throw new SDJWTException6("Key Binding sign algorithm not specified");
|
|
427
598
|
}
|
|
428
599
|
const { payload } = options;
|
|
429
600
|
const kbJwt = new KBJwt({
|
|
@@ -440,7 +611,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
440
611
|
SignJwt(jwt) {
|
|
441
612
|
return __async(this, null, function* () {
|
|
442
613
|
if (!this.userConfig.signer) {
|
|
443
|
-
throw new
|
|
614
|
+
throw new SDJWTException6("Signer not found");
|
|
444
615
|
}
|
|
445
616
|
yield jwt.sign(this.userConfig.signer);
|
|
446
617
|
return jwt;
|
|
@@ -449,7 +620,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
449
620
|
VerifyJwt(jwt) {
|
|
450
621
|
return __async(this, null, function* () {
|
|
451
622
|
if (!this.userConfig.verifier) {
|
|
452
|
-
throw new
|
|
623
|
+
throw new SDJWTException6("Verifier not found");
|
|
453
624
|
}
|
|
454
625
|
return jwt.verify(this.userConfig.verifier);
|
|
455
626
|
});
|
|
@@ -458,13 +629,13 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
458
629
|
return __async(this, null, function* () {
|
|
459
630
|
var _a, _b;
|
|
460
631
|
if (!this.userConfig.hasher) {
|
|
461
|
-
throw new
|
|
632
|
+
throw new SDJWTException6("Hasher not found");
|
|
462
633
|
}
|
|
463
634
|
if (!this.userConfig.saltGenerator) {
|
|
464
|
-
throw new
|
|
635
|
+
throw new SDJWTException6("SaltGenerator not found");
|
|
465
636
|
}
|
|
466
637
|
if (!this.userConfig.signAlg) {
|
|
467
|
-
throw new
|
|
638
|
+
throw new SDJWTException6("sign alogrithm not specified");
|
|
468
639
|
}
|
|
469
640
|
if (disclosureFrame) {
|
|
470
641
|
this.validateReservedFields(disclosureFrame);
|
|
@@ -507,12 +678,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
507
678
|
return __async(this, null, function* () {
|
|
508
679
|
var _a;
|
|
509
680
|
if (!this.userConfig.hasher) {
|
|
510
|
-
throw new
|
|
681
|
+
throw new SDJWTException6("Hasher not found");
|
|
511
682
|
}
|
|
512
683
|
const hasher = this.userConfig.hasher;
|
|
513
684
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
514
685
|
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
|
|
515
|
-
throw new
|
|
686
|
+
throw new SDJWTException6("Payload not found");
|
|
516
687
|
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
517
688
|
presentationFrame,
|
|
518
689
|
hasher
|
|
@@ -535,19 +706,19 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
535
706
|
verify(encodedSDJwt, requiredClaimKeys, requireKeyBindings) {
|
|
536
707
|
return __async(this, null, function* () {
|
|
537
708
|
if (!this.userConfig.hasher) {
|
|
538
|
-
throw new
|
|
709
|
+
throw new SDJWTException6("Hasher not found");
|
|
539
710
|
}
|
|
540
711
|
const hasher = this.userConfig.hasher;
|
|
541
712
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
542
713
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
543
|
-
throw new
|
|
714
|
+
throw new SDJWTException6("Invalid SD JWT");
|
|
544
715
|
}
|
|
545
716
|
const { payload, header } = yield this.validate(encodedSDJwt);
|
|
546
717
|
if (requiredClaimKeys) {
|
|
547
718
|
const keys = yield sdjwt.keys(hasher);
|
|
548
719
|
const missingKeys = requiredClaimKeys.filter((k) => !keys.includes(k));
|
|
549
720
|
if (missingKeys.length > 0) {
|
|
550
|
-
throw new
|
|
721
|
+
throw new SDJWTException6(
|
|
551
722
|
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
552
723
|
);
|
|
553
724
|
}
|
|
@@ -556,10 +727,10 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
556
727
|
return { payload, header };
|
|
557
728
|
}
|
|
558
729
|
if (!sdjwt.kbJwt) {
|
|
559
|
-
throw new
|
|
730
|
+
throw new SDJWTException6("Key Binding JWT not exist");
|
|
560
731
|
}
|
|
561
732
|
if (!this.userConfig.kbVerifier) {
|
|
562
|
-
throw new
|
|
733
|
+
throw new SDJWTException6("Key Binding Verifier not found");
|
|
563
734
|
}
|
|
564
735
|
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
565
736
|
verifier: this.userConfig.kbVerifier,
|
|
@@ -580,7 +751,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
580
751
|
hasher
|
|
581
752
|
);
|
|
582
753
|
if (sdHashStr !== sdHashfromKb) {
|
|
583
|
-
throw new
|
|
754
|
+
throw new SDJWTException6("Invalid sd_hash in Key Binding JWT");
|
|
584
755
|
}
|
|
585
756
|
return { payload, header, kb };
|
|
586
757
|
});
|
|
@@ -588,7 +759,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
588
759
|
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
589
760
|
return __async(this, null, function* () {
|
|
590
761
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
591
|
-
throw new
|
|
762
|
+
throw new SDJWTException6("Invalid SD JWT");
|
|
592
763
|
}
|
|
593
764
|
const { _sd_alg } = getSDAlgAndPayload2(sdjwt.jwt.payload);
|
|
594
765
|
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
@@ -601,12 +772,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
601
772
|
validate(encodedSDJwt) {
|
|
602
773
|
return __async(this, null, function* () {
|
|
603
774
|
if (!this.userConfig.hasher) {
|
|
604
|
-
throw new
|
|
775
|
+
throw new SDJWTException6("Hasher not found");
|
|
605
776
|
}
|
|
606
777
|
const hasher = this.userConfig.hasher;
|
|
607
778
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
608
779
|
if (!sdjwt.jwt) {
|
|
609
|
-
throw new
|
|
780
|
+
throw new SDJWTException6("Invalid SD JWT");
|
|
610
781
|
}
|
|
611
782
|
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt);
|
|
612
783
|
const claims = yield sdjwt.getClaims(hasher);
|
|
@@ -621,14 +792,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
621
792
|
}
|
|
622
793
|
decode(endcodedSDJwt) {
|
|
623
794
|
if (!this.userConfig.hasher) {
|
|
624
|
-
throw new
|
|
795
|
+
throw new SDJWTException6("Hasher not found");
|
|
625
796
|
}
|
|
626
797
|
return SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
627
798
|
}
|
|
628
799
|
keys(endcodedSDJwt) {
|
|
629
800
|
return __async(this, null, function* () {
|
|
630
801
|
if (!this.userConfig.hasher) {
|
|
631
|
-
throw new
|
|
802
|
+
throw new SDJWTException6("Hasher not found");
|
|
632
803
|
}
|
|
633
804
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
634
805
|
return sdjwt.keys(this.userConfig.hasher);
|
|
@@ -637,7 +808,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
637
808
|
presentableKeys(endcodedSDJwt) {
|
|
638
809
|
return __async(this, null, function* () {
|
|
639
810
|
if (!this.userConfig.hasher) {
|
|
640
|
-
throw new
|
|
811
|
+
throw new SDJWTException6("Hasher not found");
|
|
641
812
|
}
|
|
642
813
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
643
814
|
return sdjwt.presentableKeys(this.userConfig.hasher);
|
|
@@ -646,19 +817,298 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
646
817
|
getClaims(endcodedSDJwt) {
|
|
647
818
|
return __async(this, null, function* () {
|
|
648
819
|
if (!this.userConfig.hasher) {
|
|
649
|
-
throw new
|
|
820
|
+
throw new SDJWTException6("Hasher not found");
|
|
650
821
|
}
|
|
651
822
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
652
823
|
return sdjwt.getClaims(this.userConfig.hasher);
|
|
653
824
|
});
|
|
654
825
|
}
|
|
826
|
+
toFlattenJSON(endcodedSDJwt) {
|
|
827
|
+
return FlattenJSON.fromEncode(endcodedSDJwt);
|
|
828
|
+
}
|
|
829
|
+
toGeneralJSON(endcodedSDJwt) {
|
|
830
|
+
return GeneralJSON.fromEncode(endcodedSDJwt);
|
|
831
|
+
}
|
|
655
832
|
};
|
|
656
833
|
_SDJwtInstance.DEFAULT_hashAlg = "sha-256";
|
|
657
834
|
var SDJwtInstance = _SDJwtInstance;
|
|
835
|
+
var SDJwtGeneralJSONInstance = class {
|
|
836
|
+
constructor(userConfig) {
|
|
837
|
+
this.userConfig = {};
|
|
838
|
+
if (userConfig) {
|
|
839
|
+
this.userConfig = userConfig;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
createKBJwt(options, sdHash) {
|
|
843
|
+
return __async(this, null, function* () {
|
|
844
|
+
if (!this.userConfig.kbSigner) {
|
|
845
|
+
throw new SDJWTException6("Key Binding Signer not found");
|
|
846
|
+
}
|
|
847
|
+
if (!this.userConfig.kbSignAlg) {
|
|
848
|
+
throw new SDJWTException6("Key Binding sign algorithm not specified");
|
|
849
|
+
}
|
|
850
|
+
const { payload } = options;
|
|
851
|
+
const kbJwt = new KBJwt({
|
|
852
|
+
header: {
|
|
853
|
+
typ: KB_JWT_TYP2,
|
|
854
|
+
alg: this.userConfig.kbSignAlg
|
|
855
|
+
},
|
|
856
|
+
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
857
|
+
});
|
|
858
|
+
yield kbJwt.sign(this.userConfig.kbSigner);
|
|
859
|
+
return kbJwt;
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
encodeObj(obj) {
|
|
863
|
+
return base64urlEncode3(JSON.stringify(obj));
|
|
864
|
+
}
|
|
865
|
+
issue(payload, disclosureFrame, options) {
|
|
866
|
+
return __async(this, null, function* () {
|
|
867
|
+
var _a;
|
|
868
|
+
if (!this.userConfig.hasher) {
|
|
869
|
+
throw new SDJWTException6("Hasher not found");
|
|
870
|
+
}
|
|
871
|
+
if (!this.userConfig.saltGenerator) {
|
|
872
|
+
throw new SDJWTException6("SaltGenerator not found");
|
|
873
|
+
}
|
|
874
|
+
if (disclosureFrame) {
|
|
875
|
+
this.validateReservedFields(disclosureFrame);
|
|
876
|
+
}
|
|
877
|
+
const hasher = this.userConfig.hasher;
|
|
878
|
+
const hashAlg = (_a = this.userConfig.hashAlg) != null ? _a : SDJwtInstance.DEFAULT_hashAlg;
|
|
879
|
+
const { packedClaims, disclosures } = yield pack(
|
|
880
|
+
payload,
|
|
881
|
+
disclosureFrame,
|
|
882
|
+
{ hasher, alg: hashAlg },
|
|
883
|
+
this.userConfig.saltGenerator
|
|
884
|
+
);
|
|
885
|
+
const encodedDisclosures = disclosures.map((d) => d.encode());
|
|
886
|
+
const encodedSDJwtPayload = this.encodeObj(__spreadProps(__spreadValues({}, packedClaims), {
|
|
887
|
+
_sd_alg: disclosureFrame ? hashAlg : void 0
|
|
888
|
+
}));
|
|
889
|
+
const signatures = yield Promise.all(
|
|
890
|
+
options.sigs.map((s) => __async(this, null, function* () {
|
|
891
|
+
const { signer, alg, kid, header } = s;
|
|
892
|
+
const protectedHeader = __spreadValues({ typ: this.type, alg, kid }, header);
|
|
893
|
+
const encodedProtectedHeader = this.encodeObj(protectedHeader);
|
|
894
|
+
const signature = yield signer(
|
|
895
|
+
`${encodedProtectedHeader}.${encodedSDJwtPayload}`
|
|
896
|
+
);
|
|
897
|
+
return {
|
|
898
|
+
protected: encodedProtectedHeader,
|
|
899
|
+
kid,
|
|
900
|
+
signature
|
|
901
|
+
};
|
|
902
|
+
}))
|
|
903
|
+
);
|
|
904
|
+
const generalJson = new GeneralJSON({
|
|
905
|
+
payload: encodedSDJwtPayload,
|
|
906
|
+
disclosures: encodedDisclosures,
|
|
907
|
+
signatures
|
|
908
|
+
});
|
|
909
|
+
return generalJson;
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* Validates if the disclosureFrame contains any reserved fields. If so it will throw an error.
|
|
914
|
+
* @param disclosureFrame
|
|
915
|
+
* @returns
|
|
916
|
+
*/
|
|
917
|
+
validateReservedFields(disclosureFrame) {
|
|
918
|
+
return;
|
|
919
|
+
}
|
|
920
|
+
present(generalJSON, presentationFrame, options) {
|
|
921
|
+
return __async(this, null, function* () {
|
|
922
|
+
var _a;
|
|
923
|
+
if (!this.userConfig.hasher) {
|
|
924
|
+
throw new SDJWTException6("Hasher not found");
|
|
925
|
+
}
|
|
926
|
+
const hasher = this.userConfig.hasher;
|
|
927
|
+
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
928
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
929
|
+
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
|
|
930
|
+
throw new SDJWTException6("Payload not found");
|
|
931
|
+
const disclosures = yield sdjwt.getPresentDisclosures(
|
|
932
|
+
presentationFrame,
|
|
933
|
+
hasher
|
|
934
|
+
);
|
|
935
|
+
const encodedDisclosures = disclosures.map((d) => d.encode());
|
|
936
|
+
const presentedGeneralJSON = new GeneralJSON({
|
|
937
|
+
payload: generalJSON.payload,
|
|
938
|
+
disclosures: encodedDisclosures,
|
|
939
|
+
signatures: generalJSON.signatures
|
|
940
|
+
});
|
|
941
|
+
if (!(options == null ? void 0 : options.kb)) {
|
|
942
|
+
return presentedGeneralJSON;
|
|
943
|
+
}
|
|
944
|
+
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
945
|
+
presentationFrame,
|
|
946
|
+
hasher
|
|
947
|
+
);
|
|
948
|
+
const sdHashStr = yield this.calculateSDHash(
|
|
949
|
+
presentSdJwtWithoutKb,
|
|
950
|
+
sdjwt,
|
|
951
|
+
hasher
|
|
952
|
+
);
|
|
953
|
+
const kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
|
|
954
|
+
const encodedKbJwt = kbJwt.encodeJwt();
|
|
955
|
+
presentedGeneralJSON.kb_jwt = encodedKbJwt;
|
|
956
|
+
return presentedGeneralJSON;
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
// This function is for verifying the SD JWT
|
|
960
|
+
// If requiredClaimKeys is provided, it will check if the required claim keys are presentation in the SD JWT
|
|
961
|
+
// If requireKeyBindings is true, it will check if the key binding JWT is presentation and verify it
|
|
962
|
+
verify(generalJSON, requiredClaimKeys, requireKeyBindings) {
|
|
963
|
+
return __async(this, null, function* () {
|
|
964
|
+
if (!this.userConfig.hasher) {
|
|
965
|
+
throw new SDJWTException6("Hasher not found");
|
|
966
|
+
}
|
|
967
|
+
const hasher = this.userConfig.hasher;
|
|
968
|
+
const { payload, headers } = yield this.validate(generalJSON);
|
|
969
|
+
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
970
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
971
|
+
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
972
|
+
throw new SDJWTException6("Invalid SD JWT");
|
|
973
|
+
}
|
|
974
|
+
if (requiredClaimKeys) {
|
|
975
|
+
const keys = yield sdjwt.keys(hasher);
|
|
976
|
+
const missingKeys = requiredClaimKeys.filter((k) => !keys.includes(k));
|
|
977
|
+
if (missingKeys.length > 0) {
|
|
978
|
+
throw new SDJWTException6(
|
|
979
|
+
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
if (!requireKeyBindings) {
|
|
984
|
+
return { payload, headers };
|
|
985
|
+
}
|
|
986
|
+
if (!sdjwt.kbJwt) {
|
|
987
|
+
throw new SDJWTException6("Key Binding JWT not exist");
|
|
988
|
+
}
|
|
989
|
+
if (!this.userConfig.kbVerifier) {
|
|
990
|
+
throw new SDJWTException6("Key Binding Verifier not found");
|
|
991
|
+
}
|
|
992
|
+
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
993
|
+
verifier: this.userConfig.kbVerifier,
|
|
994
|
+
payload
|
|
995
|
+
});
|
|
996
|
+
if (!kb) {
|
|
997
|
+
throw new Error("signature is not valid");
|
|
998
|
+
}
|
|
999
|
+
const sdHashfromKb = kb.payload.sd_hash;
|
|
1000
|
+
const sdjwtWithoutKb = new SDJwt({
|
|
1001
|
+
jwt: sdjwt.jwt,
|
|
1002
|
+
disclosures: sdjwt.disclosures
|
|
1003
|
+
});
|
|
1004
|
+
const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
|
|
1005
|
+
const sdHashStr = yield this.calculateSDHash(
|
|
1006
|
+
presentSdJwtWithoutKb,
|
|
1007
|
+
sdjwt,
|
|
1008
|
+
hasher
|
|
1009
|
+
);
|
|
1010
|
+
if (sdHashStr !== sdHashfromKb) {
|
|
1011
|
+
throw new SDJWTException6("Invalid sd_hash in Key Binding JWT");
|
|
1012
|
+
}
|
|
1013
|
+
return { payload, headers, kb };
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
1017
|
+
return __async(this, null, function* () {
|
|
1018
|
+
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1019
|
+
throw new SDJWTException6("Invalid SD JWT");
|
|
1020
|
+
}
|
|
1021
|
+
const { _sd_alg } = getSDAlgAndPayload2(sdjwt.jwt.payload);
|
|
1022
|
+
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
1023
|
+
const sdHashStr = uint8ArrayToBase64Url2(sdHash);
|
|
1024
|
+
return sdHashStr;
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
// This function is for validating the SD JWT
|
|
1028
|
+
// Just checking signature and return its the claims
|
|
1029
|
+
validate(generalJSON) {
|
|
1030
|
+
return __async(this, null, function* () {
|
|
1031
|
+
if (!this.userConfig.hasher) {
|
|
1032
|
+
throw new SDJWTException6("Hasher not found");
|
|
1033
|
+
}
|
|
1034
|
+
if (!this.userConfig.verifier) {
|
|
1035
|
+
throw new SDJWTException6("Verifier not found");
|
|
1036
|
+
}
|
|
1037
|
+
const hasher = this.userConfig.hasher;
|
|
1038
|
+
const verifier = this.userConfig.verifier;
|
|
1039
|
+
const { payload, signatures } = generalJSON;
|
|
1040
|
+
const results = yield Promise.all(
|
|
1041
|
+
signatures.map((s) => __async(this, null, function* () {
|
|
1042
|
+
const { protected: encodedHeader, signature } = s;
|
|
1043
|
+
const verified2 = yield verifier(
|
|
1044
|
+
`${encodedHeader}.${payload}`,
|
|
1045
|
+
signature
|
|
1046
|
+
);
|
|
1047
|
+
const header = JSON.parse(base64urlDecode(encodedHeader));
|
|
1048
|
+
return { verified: verified2, header };
|
|
1049
|
+
}))
|
|
1050
|
+
);
|
|
1051
|
+
const verified = results.every((r) => r.verified);
|
|
1052
|
+
if (!verified) {
|
|
1053
|
+
throw new SDJWTException6("Signature is not valid");
|
|
1054
|
+
}
|
|
1055
|
+
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
1056
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1057
|
+
if (!sdjwt.jwt) {
|
|
1058
|
+
throw new SDJWTException6("Invalid SD JWT");
|
|
1059
|
+
}
|
|
1060
|
+
const claims = yield sdjwt.getClaims(hasher);
|
|
1061
|
+
return { payload: claims, headers: results.map((r) => r.header) };
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
config(newConfig) {
|
|
1065
|
+
this.userConfig = __spreadValues(__spreadValues({}, this.userConfig), newConfig);
|
|
1066
|
+
}
|
|
1067
|
+
encode(sdJwt, index) {
|
|
1068
|
+
return sdJwt.toEncoded(index);
|
|
1069
|
+
}
|
|
1070
|
+
decode(endcodedSDJwt) {
|
|
1071
|
+
return GeneralJSON.fromEncode(endcodedSDJwt);
|
|
1072
|
+
}
|
|
1073
|
+
keys(generalSdjwt) {
|
|
1074
|
+
return __async(this, null, function* () {
|
|
1075
|
+
if (!this.userConfig.hasher) {
|
|
1076
|
+
throw new SDJWTException6("Hasher not found");
|
|
1077
|
+
}
|
|
1078
|
+
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1079
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
1080
|
+
return sdjwt.keys(this.userConfig.hasher);
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
presentableKeys(generalSdjwt) {
|
|
1084
|
+
return __async(this, null, function* () {
|
|
1085
|
+
if (!this.userConfig.hasher) {
|
|
1086
|
+
throw new SDJWTException6("Hasher not found");
|
|
1087
|
+
}
|
|
1088
|
+
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1089
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
1090
|
+
return sdjwt.presentableKeys(this.userConfig.hasher);
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
getClaims(generalSdjwt) {
|
|
1094
|
+
return __async(this, null, function* () {
|
|
1095
|
+
if (!this.userConfig.hasher) {
|
|
1096
|
+
throw new SDJWTException6("Hasher not found");
|
|
1097
|
+
}
|
|
1098
|
+
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1099
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
1100
|
+
return sdjwt.getClaims(this.userConfig.hasher);
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
};
|
|
1104
|
+
SDJwtGeneralJSONInstance.DEFAULT_hashAlg = "sha-256";
|
|
658
1105
|
export {
|
|
1106
|
+
FlattenJSON,
|
|
1107
|
+
GeneralJSON,
|
|
659
1108
|
Jwt,
|
|
660
1109
|
KBJwt,
|
|
661
1110
|
SDJwt,
|
|
1111
|
+
SDJwtGeneralJSONInstance,
|
|
662
1112
|
SDJwtInstance,
|
|
663
1113
|
createDecoy,
|
|
664
1114
|
listKeys,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sd-jwt/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "sd-jwt draft 7 implementation in typescript",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -38,13 +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.8.0"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@sd-jwt/decode": "0.
|
|
45
|
-
"@sd-jwt/present": "0.
|
|
46
|
-
"@sd-jwt/types": "0.
|
|
47
|
-
"@sd-jwt/utils": "0.
|
|
44
|
+
"@sd-jwt/decode": "0.8.0",
|
|
45
|
+
"@sd-jwt/present": "0.8.0",
|
|
46
|
+
"@sd-jwt/types": "0.8.0",
|
|
47
|
+
"@sd-jwt/utils": "0.8.0"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"esm"
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "0d9742cd87d643079c7828ac3689d39ac4f6f21d"
|
|
66
66
|
}
|