@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.js
CHANGED
|
@@ -57,16 +57,19 @@ var __async = (__this, __arguments, generator) => {
|
|
|
57
57
|
// src/index.ts
|
|
58
58
|
var src_exports = {};
|
|
59
59
|
__export(src_exports, {
|
|
60
|
+
FlattenJSON: () => FlattenJSON,
|
|
61
|
+
GeneralJSON: () => GeneralJSON,
|
|
60
62
|
Jwt: () => Jwt,
|
|
61
63
|
KBJwt: () => KBJwt,
|
|
62
64
|
SDJwt: () => SDJwt,
|
|
65
|
+
SDJwtGeneralJSONInstance: () => SDJwtGeneralJSONInstance,
|
|
63
66
|
SDJwtInstance: () => SDJwtInstance,
|
|
64
67
|
createDecoy: () => createDecoy,
|
|
65
68
|
listKeys: () => listKeys,
|
|
66
69
|
pack: () => pack
|
|
67
70
|
});
|
|
68
71
|
module.exports = __toCommonJS(src_exports);
|
|
69
|
-
var
|
|
72
|
+
var import_utils7 = require("@sd-jwt/utils");
|
|
70
73
|
|
|
71
74
|
// src/jwt.ts
|
|
72
75
|
var import_utils = require("@sd-jwt/utils");
|
|
@@ -257,6 +260,17 @@ var SDJwt = class _SDJwt {
|
|
|
257
260
|
});
|
|
258
261
|
}
|
|
259
262
|
present(presentFrame, hasher) {
|
|
263
|
+
return __async(this, null, function* () {
|
|
264
|
+
const disclosures = yield this.getPresentDisclosures(presentFrame, hasher);
|
|
265
|
+
const presentSDJwt = new _SDJwt({
|
|
266
|
+
jwt: this.jwt,
|
|
267
|
+
disclosures,
|
|
268
|
+
kbJwt: this.kbJwt
|
|
269
|
+
});
|
|
270
|
+
return presentSDJwt.encodeSDJwt();
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
getPresentDisclosures(presentFrame, hasher) {
|
|
260
274
|
return __async(this, null, function* () {
|
|
261
275
|
var _a;
|
|
262
276
|
if (!((_a = this.jwt) == null ? void 0 : _a.payload) || !this.disclosures) {
|
|
@@ -272,12 +286,7 @@ var SDJwt = class _SDJwt {
|
|
|
272
286
|
);
|
|
273
287
|
const keys = presentFrame ? (0, import_present.transformPresentationFrame)(presentFrame) : yield this.presentableKeys(hasher);
|
|
274
288
|
const disclosures = keys.map((k) => hashmap[disclosureKeymap[k]]).filter((d) => d !== void 0);
|
|
275
|
-
|
|
276
|
-
jwt: this.jwt,
|
|
277
|
-
disclosures,
|
|
278
|
-
kbJwt: this.kbJwt
|
|
279
|
-
});
|
|
280
|
-
return presentSDJwt.encodeSDJwt();
|
|
289
|
+
return disclosures;
|
|
281
290
|
});
|
|
282
291
|
}
|
|
283
292
|
encodeSDJwt() {
|
|
@@ -426,8 +435,168 @@ var pack = (claims, disclosureFrame, hash, saltGenerator) => __async(void 0, nul
|
|
|
426
435
|
});
|
|
427
436
|
|
|
428
437
|
// src/index.ts
|
|
429
|
-
var
|
|
438
|
+
var import_types5 = require("@sd-jwt/types");
|
|
439
|
+
var import_decode5 = require("@sd-jwt/decode");
|
|
440
|
+
|
|
441
|
+
// src/flattenJSON.ts
|
|
442
|
+
var import_utils5 = require("@sd-jwt/utils");
|
|
430
443
|
var import_decode3 = require("@sd-jwt/decode");
|
|
444
|
+
var import_types3 = require("@sd-jwt/types");
|
|
445
|
+
var FlattenJSON = class _FlattenJSON {
|
|
446
|
+
constructor(data) {
|
|
447
|
+
this.disclosures = data.disclosures;
|
|
448
|
+
this.kb_jwt = data.kb_jwt;
|
|
449
|
+
this.payload = data.jwtData.payload;
|
|
450
|
+
this.signature = data.jwtData.signature;
|
|
451
|
+
this.protected = data.jwtData.protected;
|
|
452
|
+
}
|
|
453
|
+
static fromEncode(encodedSdJwt) {
|
|
454
|
+
const { jwt, disclosures, kbJwt } = (0, import_decode3.splitSdJwt)(encodedSdJwt);
|
|
455
|
+
const { 0: protectedHeader, 1: payload, 2: signature } = jwt.split(".");
|
|
456
|
+
if (!protectedHeader || !payload || !signature) {
|
|
457
|
+
throw new import_utils5.SDJWTException("Invalid JWT");
|
|
458
|
+
}
|
|
459
|
+
return new _FlattenJSON({
|
|
460
|
+
jwtData: {
|
|
461
|
+
protected: protectedHeader,
|
|
462
|
+
payload,
|
|
463
|
+
signature
|
|
464
|
+
},
|
|
465
|
+
disclosures,
|
|
466
|
+
kb_jwt: kbJwt
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
static fromSerialized(json) {
|
|
470
|
+
return new _FlattenJSON({
|
|
471
|
+
jwtData: {
|
|
472
|
+
protected: json.protected,
|
|
473
|
+
payload: json.payload,
|
|
474
|
+
signature: json.signature
|
|
475
|
+
},
|
|
476
|
+
disclosures: json.header.disclosures,
|
|
477
|
+
kb_jwt: json.header.kb_jwt
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
toJson() {
|
|
481
|
+
return {
|
|
482
|
+
payload: this.payload,
|
|
483
|
+
signature: this.signature,
|
|
484
|
+
protected: this.protected,
|
|
485
|
+
header: {
|
|
486
|
+
disclosures: this.disclosures,
|
|
487
|
+
kb_jwt: this.kb_jwt
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
toEncoded() {
|
|
492
|
+
var _a;
|
|
493
|
+
const jwt = `${this.protected}.${this.payload}.${this.signature}`;
|
|
494
|
+
const disclosures = this.disclosures.join(import_types3.SD_SEPARATOR);
|
|
495
|
+
const kb_jwt = (_a = this.kb_jwt) != null ? _a : "";
|
|
496
|
+
return [jwt, disclosures, kb_jwt].join(import_types3.SD_SEPARATOR);
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
// src/generalJSON.ts
|
|
501
|
+
var import_utils6 = require("@sd-jwt/utils");
|
|
502
|
+
var import_decode4 = require("@sd-jwt/decode");
|
|
503
|
+
var import_types4 = require("@sd-jwt/types");
|
|
504
|
+
var GeneralJSON = class _GeneralJSON {
|
|
505
|
+
constructor(data) {
|
|
506
|
+
this.payload = data.payload;
|
|
507
|
+
this.disclosures = data.disclosures;
|
|
508
|
+
this.kb_jwt = data.kb_jwt;
|
|
509
|
+
this.signatures = data.signatures;
|
|
510
|
+
}
|
|
511
|
+
static fromEncode(encodedSdJwt) {
|
|
512
|
+
const { jwt, disclosures, kbJwt } = (0, import_decode4.splitSdJwt)(encodedSdJwt);
|
|
513
|
+
const { 0: protectedHeader, 1: payload, 2: signature } = jwt.split(".");
|
|
514
|
+
if (!protectedHeader || !payload || !signature) {
|
|
515
|
+
throw new import_utils6.SDJWTException("Invalid JWT");
|
|
516
|
+
}
|
|
517
|
+
return new _GeneralJSON({
|
|
518
|
+
payload,
|
|
519
|
+
disclosures,
|
|
520
|
+
kb_jwt: kbJwt,
|
|
521
|
+
signatures: [
|
|
522
|
+
{
|
|
523
|
+
protected: protectedHeader,
|
|
524
|
+
signature
|
|
525
|
+
}
|
|
526
|
+
]
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
static fromSerialized(json) {
|
|
530
|
+
var _a, _b, _c;
|
|
531
|
+
if (!json.signatures[0]) {
|
|
532
|
+
throw new import_utils6.SDJWTException("Invalid JSON");
|
|
533
|
+
}
|
|
534
|
+
const disclosures = (_b = (_a = json.signatures[0].header) == null ? void 0 : _a.disclosures) != null ? _b : [];
|
|
535
|
+
const kb_jwt = (_c = json.signatures[0].header) == null ? void 0 : _c.kb_jwt;
|
|
536
|
+
return new _GeneralJSON({
|
|
537
|
+
payload: json.payload,
|
|
538
|
+
disclosures,
|
|
539
|
+
kb_jwt,
|
|
540
|
+
signatures: json.signatures.map((s) => {
|
|
541
|
+
var _a2;
|
|
542
|
+
return {
|
|
543
|
+
protected: s.protected,
|
|
544
|
+
signature: s.signature,
|
|
545
|
+
kid: (_a2 = s.header) == null ? void 0 : _a2.kid
|
|
546
|
+
};
|
|
547
|
+
})
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
toJson() {
|
|
551
|
+
return {
|
|
552
|
+
payload: this.payload,
|
|
553
|
+
signatures: this.signatures.map((s, i) => {
|
|
554
|
+
if (i !== 0) {
|
|
555
|
+
return {
|
|
556
|
+
header: {
|
|
557
|
+
kid: s.kid
|
|
558
|
+
},
|
|
559
|
+
protected: s.protected,
|
|
560
|
+
signature: s.signature
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
return {
|
|
564
|
+
header: {
|
|
565
|
+
disclosures: this.disclosures,
|
|
566
|
+
kid: s.kid,
|
|
567
|
+
kb_jwt: this.kb_jwt
|
|
568
|
+
},
|
|
569
|
+
protected: s.protected,
|
|
570
|
+
signature: s.signature
|
|
571
|
+
};
|
|
572
|
+
})
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
toEncoded(index) {
|
|
576
|
+
var _a;
|
|
577
|
+
if (index < 0 || index >= this.signatures.length) {
|
|
578
|
+
throw new import_utils6.SDJWTException("Index out of bounds");
|
|
579
|
+
}
|
|
580
|
+
const { protected: protectedHeader, signature } = this.signatures[index];
|
|
581
|
+
const disclosures = this.disclosures.join(import_types4.SD_SEPARATOR);
|
|
582
|
+
const kb_jwt = (_a = this.kb_jwt) != null ? _a : "";
|
|
583
|
+
const jwt = `${protectedHeader}.${this.payload}.${signature}`;
|
|
584
|
+
return [jwt, disclosures, kb_jwt].join(import_types4.SD_SEPARATOR);
|
|
585
|
+
}
|
|
586
|
+
addSignature(protectedHeader, signer, kid) {
|
|
587
|
+
return __async(this, null, function* () {
|
|
588
|
+
const header = (0, import_utils6.base64urlEncode)(JSON.stringify(protectedHeader));
|
|
589
|
+
const signature = yield signer(`${header}.${this.payload}`);
|
|
590
|
+
this.signatures.push({
|
|
591
|
+
protected: header,
|
|
592
|
+
signature,
|
|
593
|
+
kid
|
|
594
|
+
});
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
// src/index.ts
|
|
431
600
|
var _SDJwtInstance = class _SDJwtInstance {
|
|
432
601
|
constructor(userConfig) {
|
|
433
602
|
this.userConfig = {};
|
|
@@ -438,15 +607,15 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
438
607
|
createKBJwt(options, sdHash) {
|
|
439
608
|
return __async(this, null, function* () {
|
|
440
609
|
if (!this.userConfig.kbSigner) {
|
|
441
|
-
throw new
|
|
610
|
+
throw new import_utils7.SDJWTException("Key Binding Signer not found");
|
|
442
611
|
}
|
|
443
612
|
if (!this.userConfig.kbSignAlg) {
|
|
444
|
-
throw new
|
|
613
|
+
throw new import_utils7.SDJWTException("Key Binding sign algorithm not specified");
|
|
445
614
|
}
|
|
446
615
|
const { payload } = options;
|
|
447
616
|
const kbJwt = new KBJwt({
|
|
448
617
|
header: {
|
|
449
|
-
typ:
|
|
618
|
+
typ: import_types5.KB_JWT_TYP,
|
|
450
619
|
alg: this.userConfig.kbSignAlg
|
|
451
620
|
},
|
|
452
621
|
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
@@ -458,7 +627,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
458
627
|
SignJwt(jwt) {
|
|
459
628
|
return __async(this, null, function* () {
|
|
460
629
|
if (!this.userConfig.signer) {
|
|
461
|
-
throw new
|
|
630
|
+
throw new import_utils7.SDJWTException("Signer not found");
|
|
462
631
|
}
|
|
463
632
|
yield jwt.sign(this.userConfig.signer);
|
|
464
633
|
return jwt;
|
|
@@ -467,7 +636,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
467
636
|
VerifyJwt(jwt) {
|
|
468
637
|
return __async(this, null, function* () {
|
|
469
638
|
if (!this.userConfig.verifier) {
|
|
470
|
-
throw new
|
|
639
|
+
throw new import_utils7.SDJWTException("Verifier not found");
|
|
471
640
|
}
|
|
472
641
|
return jwt.verify(this.userConfig.verifier);
|
|
473
642
|
});
|
|
@@ -476,13 +645,13 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
476
645
|
return __async(this, null, function* () {
|
|
477
646
|
var _a, _b;
|
|
478
647
|
if (!this.userConfig.hasher) {
|
|
479
|
-
throw new
|
|
648
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
480
649
|
}
|
|
481
650
|
if (!this.userConfig.saltGenerator) {
|
|
482
|
-
throw new
|
|
651
|
+
throw new import_utils7.SDJWTException("SaltGenerator not found");
|
|
483
652
|
}
|
|
484
653
|
if (!this.userConfig.signAlg) {
|
|
485
|
-
throw new
|
|
654
|
+
throw new import_utils7.SDJWTException("sign alogrithm not specified");
|
|
486
655
|
}
|
|
487
656
|
if (disclosureFrame) {
|
|
488
657
|
this.validateReservedFields(disclosureFrame);
|
|
@@ -525,12 +694,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
525
694
|
return __async(this, null, function* () {
|
|
526
695
|
var _a;
|
|
527
696
|
if (!this.userConfig.hasher) {
|
|
528
|
-
throw new
|
|
697
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
529
698
|
}
|
|
530
699
|
const hasher = this.userConfig.hasher;
|
|
531
700
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
532
701
|
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
|
|
533
|
-
throw new
|
|
702
|
+
throw new import_utils7.SDJWTException("Payload not found");
|
|
534
703
|
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
535
704
|
presentationFrame,
|
|
536
705
|
hasher
|
|
@@ -553,19 +722,19 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
553
722
|
verify(encodedSDJwt, requiredClaimKeys, requireKeyBindings) {
|
|
554
723
|
return __async(this, null, function* () {
|
|
555
724
|
if (!this.userConfig.hasher) {
|
|
556
|
-
throw new
|
|
725
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
557
726
|
}
|
|
558
727
|
const hasher = this.userConfig.hasher;
|
|
559
728
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
560
729
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
561
|
-
throw new
|
|
730
|
+
throw new import_utils7.SDJWTException("Invalid SD JWT");
|
|
562
731
|
}
|
|
563
732
|
const { payload, header } = yield this.validate(encodedSDJwt);
|
|
564
733
|
if (requiredClaimKeys) {
|
|
565
734
|
const keys = yield sdjwt.keys(hasher);
|
|
566
735
|
const missingKeys = requiredClaimKeys.filter((k) => !keys.includes(k));
|
|
567
736
|
if (missingKeys.length > 0) {
|
|
568
|
-
throw new
|
|
737
|
+
throw new import_utils7.SDJWTException(
|
|
569
738
|
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
570
739
|
);
|
|
571
740
|
}
|
|
@@ -574,10 +743,10 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
574
743
|
return { payload, header };
|
|
575
744
|
}
|
|
576
745
|
if (!sdjwt.kbJwt) {
|
|
577
|
-
throw new
|
|
746
|
+
throw new import_utils7.SDJWTException("Key Binding JWT not exist");
|
|
578
747
|
}
|
|
579
748
|
if (!this.userConfig.kbVerifier) {
|
|
580
|
-
throw new
|
|
749
|
+
throw new import_utils7.SDJWTException("Key Binding Verifier not found");
|
|
581
750
|
}
|
|
582
751
|
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
583
752
|
verifier: this.userConfig.kbVerifier,
|
|
@@ -598,7 +767,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
598
767
|
hasher
|
|
599
768
|
);
|
|
600
769
|
if (sdHashStr !== sdHashfromKb) {
|
|
601
|
-
throw new
|
|
770
|
+
throw new import_utils7.SDJWTException("Invalid sd_hash in Key Binding JWT");
|
|
602
771
|
}
|
|
603
772
|
return { payload, header, kb };
|
|
604
773
|
});
|
|
@@ -606,11 +775,11 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
606
775
|
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
607
776
|
return __async(this, null, function* () {
|
|
608
777
|
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
609
|
-
throw new
|
|
778
|
+
throw new import_utils7.SDJWTException("Invalid SD JWT");
|
|
610
779
|
}
|
|
611
|
-
const { _sd_alg } = (0,
|
|
780
|
+
const { _sd_alg } = (0, import_decode5.getSDAlgAndPayload)(sdjwt.jwt.payload);
|
|
612
781
|
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
613
|
-
const sdHashStr = (0,
|
|
782
|
+
const sdHashStr = (0, import_utils7.uint8ArrayToBase64Url)(sdHash);
|
|
614
783
|
return sdHashStr;
|
|
615
784
|
});
|
|
616
785
|
}
|
|
@@ -619,12 +788,12 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
619
788
|
validate(encodedSDJwt) {
|
|
620
789
|
return __async(this, null, function* () {
|
|
621
790
|
if (!this.userConfig.hasher) {
|
|
622
|
-
throw new
|
|
791
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
623
792
|
}
|
|
624
793
|
const hasher = this.userConfig.hasher;
|
|
625
794
|
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
626
795
|
if (!sdjwt.jwt) {
|
|
627
|
-
throw new
|
|
796
|
+
throw new import_utils7.SDJWTException("Invalid SD JWT");
|
|
628
797
|
}
|
|
629
798
|
const verifiedPayloads = yield this.VerifyJwt(sdjwt.jwt);
|
|
630
799
|
const claims = yield sdjwt.getClaims(hasher);
|
|
@@ -639,14 +808,14 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
639
808
|
}
|
|
640
809
|
decode(endcodedSDJwt) {
|
|
641
810
|
if (!this.userConfig.hasher) {
|
|
642
|
-
throw new
|
|
811
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
643
812
|
}
|
|
644
813
|
return SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
645
814
|
}
|
|
646
815
|
keys(endcodedSDJwt) {
|
|
647
816
|
return __async(this, null, function* () {
|
|
648
817
|
if (!this.userConfig.hasher) {
|
|
649
|
-
throw new
|
|
818
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
650
819
|
}
|
|
651
820
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
652
821
|
return sdjwt.keys(this.userConfig.hasher);
|
|
@@ -655,7 +824,7 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
655
824
|
presentableKeys(endcodedSDJwt) {
|
|
656
825
|
return __async(this, null, function* () {
|
|
657
826
|
if (!this.userConfig.hasher) {
|
|
658
|
-
throw new
|
|
827
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
659
828
|
}
|
|
660
829
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
661
830
|
return sdjwt.presentableKeys(this.userConfig.hasher);
|
|
@@ -664,20 +833,299 @@ var _SDJwtInstance = class _SDJwtInstance {
|
|
|
664
833
|
getClaims(endcodedSDJwt) {
|
|
665
834
|
return __async(this, null, function* () {
|
|
666
835
|
if (!this.userConfig.hasher) {
|
|
667
|
-
throw new
|
|
836
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
668
837
|
}
|
|
669
838
|
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
670
839
|
return sdjwt.getClaims(this.userConfig.hasher);
|
|
671
840
|
});
|
|
672
841
|
}
|
|
842
|
+
toFlattenJSON(endcodedSDJwt) {
|
|
843
|
+
return FlattenJSON.fromEncode(endcodedSDJwt);
|
|
844
|
+
}
|
|
845
|
+
toGeneralJSON(endcodedSDJwt) {
|
|
846
|
+
return GeneralJSON.fromEncode(endcodedSDJwt);
|
|
847
|
+
}
|
|
673
848
|
};
|
|
674
849
|
_SDJwtInstance.DEFAULT_hashAlg = "sha-256";
|
|
675
850
|
var SDJwtInstance = _SDJwtInstance;
|
|
851
|
+
var SDJwtGeneralJSONInstance = class {
|
|
852
|
+
constructor(userConfig) {
|
|
853
|
+
this.userConfig = {};
|
|
854
|
+
if (userConfig) {
|
|
855
|
+
this.userConfig = userConfig;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
createKBJwt(options, sdHash) {
|
|
859
|
+
return __async(this, null, function* () {
|
|
860
|
+
if (!this.userConfig.kbSigner) {
|
|
861
|
+
throw new import_utils7.SDJWTException("Key Binding Signer not found");
|
|
862
|
+
}
|
|
863
|
+
if (!this.userConfig.kbSignAlg) {
|
|
864
|
+
throw new import_utils7.SDJWTException("Key Binding sign algorithm not specified");
|
|
865
|
+
}
|
|
866
|
+
const { payload } = options;
|
|
867
|
+
const kbJwt = new KBJwt({
|
|
868
|
+
header: {
|
|
869
|
+
typ: import_types5.KB_JWT_TYP,
|
|
870
|
+
alg: this.userConfig.kbSignAlg
|
|
871
|
+
},
|
|
872
|
+
payload: __spreadProps(__spreadValues({}, payload), { sd_hash: sdHash })
|
|
873
|
+
});
|
|
874
|
+
yield kbJwt.sign(this.userConfig.kbSigner);
|
|
875
|
+
return kbJwt;
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
encodeObj(obj) {
|
|
879
|
+
return (0, import_utils7.base64urlEncode)(JSON.stringify(obj));
|
|
880
|
+
}
|
|
881
|
+
issue(payload, disclosureFrame, options) {
|
|
882
|
+
return __async(this, null, function* () {
|
|
883
|
+
var _a;
|
|
884
|
+
if (!this.userConfig.hasher) {
|
|
885
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
886
|
+
}
|
|
887
|
+
if (!this.userConfig.saltGenerator) {
|
|
888
|
+
throw new import_utils7.SDJWTException("SaltGenerator not found");
|
|
889
|
+
}
|
|
890
|
+
if (disclosureFrame) {
|
|
891
|
+
this.validateReservedFields(disclosureFrame);
|
|
892
|
+
}
|
|
893
|
+
const hasher = this.userConfig.hasher;
|
|
894
|
+
const hashAlg = (_a = this.userConfig.hashAlg) != null ? _a : SDJwtInstance.DEFAULT_hashAlg;
|
|
895
|
+
const { packedClaims, disclosures } = yield pack(
|
|
896
|
+
payload,
|
|
897
|
+
disclosureFrame,
|
|
898
|
+
{ hasher, alg: hashAlg },
|
|
899
|
+
this.userConfig.saltGenerator
|
|
900
|
+
);
|
|
901
|
+
const encodedDisclosures = disclosures.map((d) => d.encode());
|
|
902
|
+
const encodedSDJwtPayload = this.encodeObj(__spreadProps(__spreadValues({}, packedClaims), {
|
|
903
|
+
_sd_alg: disclosureFrame ? hashAlg : void 0
|
|
904
|
+
}));
|
|
905
|
+
const signatures = yield Promise.all(
|
|
906
|
+
options.sigs.map((s) => __async(this, null, function* () {
|
|
907
|
+
const { signer, alg, kid, header } = s;
|
|
908
|
+
const protectedHeader = __spreadValues({ typ: this.type, alg, kid }, header);
|
|
909
|
+
const encodedProtectedHeader = this.encodeObj(protectedHeader);
|
|
910
|
+
const signature = yield signer(
|
|
911
|
+
`${encodedProtectedHeader}.${encodedSDJwtPayload}`
|
|
912
|
+
);
|
|
913
|
+
return {
|
|
914
|
+
protected: encodedProtectedHeader,
|
|
915
|
+
kid,
|
|
916
|
+
signature
|
|
917
|
+
};
|
|
918
|
+
}))
|
|
919
|
+
);
|
|
920
|
+
const generalJson = new GeneralJSON({
|
|
921
|
+
payload: encodedSDJwtPayload,
|
|
922
|
+
disclosures: encodedDisclosures,
|
|
923
|
+
signatures
|
|
924
|
+
});
|
|
925
|
+
return generalJson;
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Validates if the disclosureFrame contains any reserved fields. If so it will throw an error.
|
|
930
|
+
* @param disclosureFrame
|
|
931
|
+
* @returns
|
|
932
|
+
*/
|
|
933
|
+
validateReservedFields(disclosureFrame) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
present(generalJSON, presentationFrame, options) {
|
|
937
|
+
return __async(this, null, function* () {
|
|
938
|
+
var _a;
|
|
939
|
+
if (!this.userConfig.hasher) {
|
|
940
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
941
|
+
}
|
|
942
|
+
const hasher = this.userConfig.hasher;
|
|
943
|
+
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
944
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
945
|
+
if (!((_a = sdjwt.jwt) == null ? void 0 : _a.payload))
|
|
946
|
+
throw new import_utils7.SDJWTException("Payload not found");
|
|
947
|
+
const disclosures = yield sdjwt.getPresentDisclosures(
|
|
948
|
+
presentationFrame,
|
|
949
|
+
hasher
|
|
950
|
+
);
|
|
951
|
+
const encodedDisclosures = disclosures.map((d) => d.encode());
|
|
952
|
+
const presentedGeneralJSON = new GeneralJSON({
|
|
953
|
+
payload: generalJSON.payload,
|
|
954
|
+
disclosures: encodedDisclosures,
|
|
955
|
+
signatures: generalJSON.signatures
|
|
956
|
+
});
|
|
957
|
+
if (!(options == null ? void 0 : options.kb)) {
|
|
958
|
+
return presentedGeneralJSON;
|
|
959
|
+
}
|
|
960
|
+
const presentSdJwtWithoutKb = yield sdjwt.present(
|
|
961
|
+
presentationFrame,
|
|
962
|
+
hasher
|
|
963
|
+
);
|
|
964
|
+
const sdHashStr = yield this.calculateSDHash(
|
|
965
|
+
presentSdJwtWithoutKb,
|
|
966
|
+
sdjwt,
|
|
967
|
+
hasher
|
|
968
|
+
);
|
|
969
|
+
const kbJwt = yield this.createKBJwt(options.kb, sdHashStr);
|
|
970
|
+
const encodedKbJwt = kbJwt.encodeJwt();
|
|
971
|
+
presentedGeneralJSON.kb_jwt = encodedKbJwt;
|
|
972
|
+
return presentedGeneralJSON;
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
// This function is for verifying the SD JWT
|
|
976
|
+
// If requiredClaimKeys is provided, it will check if the required claim keys are presentation in the SD JWT
|
|
977
|
+
// If requireKeyBindings is true, it will check if the key binding JWT is presentation and verify it
|
|
978
|
+
verify(generalJSON, requiredClaimKeys, requireKeyBindings) {
|
|
979
|
+
return __async(this, null, function* () {
|
|
980
|
+
if (!this.userConfig.hasher) {
|
|
981
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
982
|
+
}
|
|
983
|
+
const hasher = this.userConfig.hasher;
|
|
984
|
+
const { payload, headers } = yield this.validate(generalJSON);
|
|
985
|
+
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
986
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
987
|
+
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
988
|
+
throw new import_utils7.SDJWTException("Invalid SD JWT");
|
|
989
|
+
}
|
|
990
|
+
if (requiredClaimKeys) {
|
|
991
|
+
const keys = yield sdjwt.keys(hasher);
|
|
992
|
+
const missingKeys = requiredClaimKeys.filter((k) => !keys.includes(k));
|
|
993
|
+
if (missingKeys.length > 0) {
|
|
994
|
+
throw new import_utils7.SDJWTException(
|
|
995
|
+
`Missing required claim keys: ${missingKeys.join(", ")}`
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
if (!requireKeyBindings) {
|
|
1000
|
+
return { payload, headers };
|
|
1001
|
+
}
|
|
1002
|
+
if (!sdjwt.kbJwt) {
|
|
1003
|
+
throw new import_utils7.SDJWTException("Key Binding JWT not exist");
|
|
1004
|
+
}
|
|
1005
|
+
if (!this.userConfig.kbVerifier) {
|
|
1006
|
+
throw new import_utils7.SDJWTException("Key Binding Verifier not found");
|
|
1007
|
+
}
|
|
1008
|
+
const kb = yield sdjwt.kbJwt.verifyKB({
|
|
1009
|
+
verifier: this.userConfig.kbVerifier,
|
|
1010
|
+
payload
|
|
1011
|
+
});
|
|
1012
|
+
if (!kb) {
|
|
1013
|
+
throw new Error("signature is not valid");
|
|
1014
|
+
}
|
|
1015
|
+
const sdHashfromKb = kb.payload.sd_hash;
|
|
1016
|
+
const sdjwtWithoutKb = new SDJwt({
|
|
1017
|
+
jwt: sdjwt.jwt,
|
|
1018
|
+
disclosures: sdjwt.disclosures
|
|
1019
|
+
});
|
|
1020
|
+
const presentSdJwtWithoutKb = sdjwtWithoutKb.encodeSDJwt();
|
|
1021
|
+
const sdHashStr = yield this.calculateSDHash(
|
|
1022
|
+
presentSdJwtWithoutKb,
|
|
1023
|
+
sdjwt,
|
|
1024
|
+
hasher
|
|
1025
|
+
);
|
|
1026
|
+
if (sdHashStr !== sdHashfromKb) {
|
|
1027
|
+
throw new import_utils7.SDJWTException("Invalid sd_hash in Key Binding JWT");
|
|
1028
|
+
}
|
|
1029
|
+
return { payload, headers, kb };
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
calculateSDHash(presentSdJwtWithoutKb, sdjwt, hasher) {
|
|
1033
|
+
return __async(this, null, function* () {
|
|
1034
|
+
if (!sdjwt.jwt || !sdjwt.jwt.payload) {
|
|
1035
|
+
throw new import_utils7.SDJWTException("Invalid SD JWT");
|
|
1036
|
+
}
|
|
1037
|
+
const { _sd_alg } = (0, import_decode5.getSDAlgAndPayload)(sdjwt.jwt.payload);
|
|
1038
|
+
const sdHash = yield hasher(presentSdJwtWithoutKb, _sd_alg);
|
|
1039
|
+
const sdHashStr = (0, import_utils7.uint8ArrayToBase64Url)(sdHash);
|
|
1040
|
+
return sdHashStr;
|
|
1041
|
+
});
|
|
1042
|
+
}
|
|
1043
|
+
// This function is for validating the SD JWT
|
|
1044
|
+
// Just checking signature and return its the claims
|
|
1045
|
+
validate(generalJSON) {
|
|
1046
|
+
return __async(this, null, function* () {
|
|
1047
|
+
if (!this.userConfig.hasher) {
|
|
1048
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
1049
|
+
}
|
|
1050
|
+
if (!this.userConfig.verifier) {
|
|
1051
|
+
throw new import_utils7.SDJWTException("Verifier not found");
|
|
1052
|
+
}
|
|
1053
|
+
const hasher = this.userConfig.hasher;
|
|
1054
|
+
const verifier = this.userConfig.verifier;
|
|
1055
|
+
const { payload, signatures } = generalJSON;
|
|
1056
|
+
const results = yield Promise.all(
|
|
1057
|
+
signatures.map((s) => __async(this, null, function* () {
|
|
1058
|
+
const { protected: encodedHeader, signature } = s;
|
|
1059
|
+
const verified2 = yield verifier(
|
|
1060
|
+
`${encodedHeader}.${payload}`,
|
|
1061
|
+
signature
|
|
1062
|
+
);
|
|
1063
|
+
const header = JSON.parse((0, import_utils7.base64urlDecode)(encodedHeader));
|
|
1064
|
+
return { verified: verified2, header };
|
|
1065
|
+
}))
|
|
1066
|
+
);
|
|
1067
|
+
const verified = results.every((r) => r.verified);
|
|
1068
|
+
if (!verified) {
|
|
1069
|
+
throw new import_utils7.SDJWTException("Signature is not valid");
|
|
1070
|
+
}
|
|
1071
|
+
const encodedSDJwt = generalJSON.toEncoded(0);
|
|
1072
|
+
const sdjwt = yield SDJwt.fromEncode(encodedSDJwt, hasher);
|
|
1073
|
+
if (!sdjwt.jwt) {
|
|
1074
|
+
throw new import_utils7.SDJWTException("Invalid SD JWT");
|
|
1075
|
+
}
|
|
1076
|
+
const claims = yield sdjwt.getClaims(hasher);
|
|
1077
|
+
return { payload: claims, headers: results.map((r) => r.header) };
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
config(newConfig) {
|
|
1081
|
+
this.userConfig = __spreadValues(__spreadValues({}, this.userConfig), newConfig);
|
|
1082
|
+
}
|
|
1083
|
+
encode(sdJwt, index) {
|
|
1084
|
+
return sdJwt.toEncoded(index);
|
|
1085
|
+
}
|
|
1086
|
+
decode(endcodedSDJwt) {
|
|
1087
|
+
return GeneralJSON.fromEncode(endcodedSDJwt);
|
|
1088
|
+
}
|
|
1089
|
+
keys(generalSdjwt) {
|
|
1090
|
+
return __async(this, null, function* () {
|
|
1091
|
+
if (!this.userConfig.hasher) {
|
|
1092
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
1093
|
+
}
|
|
1094
|
+
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1095
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
1096
|
+
return sdjwt.keys(this.userConfig.hasher);
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
presentableKeys(generalSdjwt) {
|
|
1100
|
+
return __async(this, null, function* () {
|
|
1101
|
+
if (!this.userConfig.hasher) {
|
|
1102
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
1103
|
+
}
|
|
1104
|
+
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1105
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
1106
|
+
return sdjwt.presentableKeys(this.userConfig.hasher);
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
getClaims(generalSdjwt) {
|
|
1110
|
+
return __async(this, null, function* () {
|
|
1111
|
+
if (!this.userConfig.hasher) {
|
|
1112
|
+
throw new import_utils7.SDJWTException("Hasher not found");
|
|
1113
|
+
}
|
|
1114
|
+
const endcodedSDJwt = generalSdjwt.toEncoded(0);
|
|
1115
|
+
const sdjwt = yield SDJwt.fromEncode(endcodedSDJwt, this.userConfig.hasher);
|
|
1116
|
+
return sdjwt.getClaims(this.userConfig.hasher);
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
SDJwtGeneralJSONInstance.DEFAULT_hashAlg = "sha-256";
|
|
676
1121
|
// Annotate the CommonJS export names for ESM import in node:
|
|
677
1122
|
0 && (module.exports = {
|
|
1123
|
+
FlattenJSON,
|
|
1124
|
+
GeneralJSON,
|
|
678
1125
|
Jwt,
|
|
679
1126
|
KBJwt,
|
|
680
1127
|
SDJwt,
|
|
1128
|
+
SDJwtGeneralJSONInstance,
|
|
681
1129
|
SDJwtInstance,
|
|
682
1130
|
createDecoy,
|
|
683
1131
|
listKeys,
|