@openeudi/openid4vp 0.5.0 → 0.7.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/README.md +93 -1
- package/dist/index.cjs +371 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -2
- package/dist/index.d.ts +103 -2
- package/dist/index.js +369 -90
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { X509Certificate, SubjectKeyIdentifierExtension, X509Certificates, BasicConstraintsExtension, KeyUsagesExtension, KeyUsageFlags as KeyUsageFlags$1, AuthorityKeyIdentifierExtension, SubjectAlternativeNameExtension, ExtendedKeyUsageExtension, Name as Name$1 } from '@peculiar/x509';
|
|
2
2
|
import { v4 } from 'uuid';
|
|
3
|
+
import { SignJWT, importX509, decodeProtectedHeader, jwtVerify, importJWK, compactDecrypt } from 'jose';
|
|
3
4
|
import { Encoder, Tag } from 'cbor-x';
|
|
4
|
-
import { importX509, decodeProtectedHeader, jwtVerify, importJWK } from 'jose';
|
|
5
5
|
import { splitSdJwt, decodeSdJwt, getClaims } from '@sd-jwt/decode';
|
|
6
6
|
import { matchQuery, buildSubmission } from '@openeudi/dcql';
|
|
7
7
|
export { DcqlMatchError, DcqlValidationError } from '@openeudi/dcql';
|
|
@@ -19,7 +19,7 @@ var __export = (target, all) => {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
// src/errors.ts
|
|
22
|
-
var InvalidSignatureError, ExpiredCredentialError, UnsupportedFormatError, MalformedCredentialError, NonceValidationError, HaipValidationError, OpenID4VPError, TrustAnchorNotFoundError, CertificateChainError, RevokedCertificateError, RevocationCheckFailedError, LotlFetchError, LotlSignatureError;
|
|
22
|
+
var InvalidSignatureError, ExpiredCredentialError, UnsupportedFormatError, MalformedCredentialError, NonceValidationError, HaipValidationError, OpenID4VPError, TrustAnchorNotFoundError, CertificateChainError, RevokedCertificateError, RevocationCheckFailedError, LotlFetchError, LotlSignatureError, SignedRequestBuildError, UnsupportedJweError, DecryptionFailedError, MissingDecryptionKeyError, MultipleCredentialsNotSupportedError;
|
|
23
23
|
var init_errors = __esm({
|
|
24
24
|
"src/errors.ts"() {
|
|
25
25
|
InvalidSignatureError = class extends Error {
|
|
@@ -115,6 +115,47 @@ var init_errors = __esm({
|
|
|
115
115
|
LotlSignatureError = class extends OpenID4VPError {
|
|
116
116
|
code = "lotl_signature_invalid";
|
|
117
117
|
};
|
|
118
|
+
SignedRequestBuildError = class extends OpenID4VPError {
|
|
119
|
+
code;
|
|
120
|
+
constructor(code, message) {
|
|
121
|
+
super(message);
|
|
122
|
+
this.code = code;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
UnsupportedJweError = class extends OpenID4VPError {
|
|
126
|
+
code = "unsupported_jwe";
|
|
127
|
+
alg;
|
|
128
|
+
enc;
|
|
129
|
+
constructor(alg, enc) {
|
|
130
|
+
super(`Unsupported JWE algorithms: alg=${alg}, enc=${enc}`);
|
|
131
|
+
this.alg = alg;
|
|
132
|
+
this.enc = enc;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
DecryptionFailedError = class extends OpenID4VPError {
|
|
136
|
+
code = "decryption_failed";
|
|
137
|
+
constructor(message = "Failed to decrypt authorization response", options) {
|
|
138
|
+
super(message, options);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
MissingDecryptionKeyError = class extends OpenID4VPError {
|
|
142
|
+
code = "missing_decryption_key";
|
|
143
|
+
constructor(message = "decryptionKey is required to verify a direct_post.jwt response") {
|
|
144
|
+
super(message);
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
MultipleCredentialsNotSupportedError = class extends OpenID4VPError {
|
|
148
|
+
code = "multi_credential_unsupported";
|
|
149
|
+
entryCount;
|
|
150
|
+
presentationCount;
|
|
151
|
+
constructor(entryCount, presentationCount) {
|
|
152
|
+
super(
|
|
153
|
+
`Multi-credential presentations are not yet supported: ${entryCount} queryId entries, ${presentationCount} presentations`
|
|
154
|
+
);
|
|
155
|
+
this.entryCount = entryCount;
|
|
156
|
+
this.presentationCount = presentationCount;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
118
159
|
}
|
|
119
160
|
});
|
|
120
161
|
|
|
@@ -610,6 +651,9 @@ __export(index_es_exports, {
|
|
|
610
651
|
Choice: () => Choice,
|
|
611
652
|
Constructed: () => Constructed,
|
|
612
653
|
DATE: () => DATE,
|
|
654
|
+
DEFAULT_MAX_CONTENT_LENGTH: () => DEFAULT_MAX_CONTENT_LENGTH,
|
|
655
|
+
DEFAULT_MAX_DEPTH: () => DEFAULT_MAX_DEPTH,
|
|
656
|
+
DEFAULT_MAX_NODES: () => DEFAULT_MAX_NODES,
|
|
613
657
|
DateTime: () => DateTime,
|
|
614
658
|
Duration: () => Duration,
|
|
615
659
|
EndOfContent: () => EndOfContent,
|
|
@@ -704,7 +748,7 @@ function HexBlock(BaseClass) {
|
|
|
704
748
|
this.isHexOnly = (_b = params.isHexOnly) !== null && _b !== void 0 ? _b : false;
|
|
705
749
|
this.valueHexView = params.valueHex ? BufferSourceConverter.toUint8Array(params.valueHex) : EMPTY_VIEW;
|
|
706
750
|
}
|
|
707
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
751
|
+
fromBER(inputBuffer, inputOffset, inputLength, _context) {
|
|
708
752
|
const view = inputBuffer instanceof ArrayBuffer ? new Uint8Array(inputBuffer) : inputBuffer;
|
|
709
753
|
if (!checkBufferParams(this, view, inputOffset, inputLength)) {
|
|
710
754
|
return -1;
|
|
@@ -748,6 +792,49 @@ function prepareIndefiniteForm(baseBlock) {
|
|
|
748
792
|
}
|
|
749
793
|
return !!((_a2 = baseBlock.lenBlock) === null || _a2 === void 0 ? void 0 : _a2.isIndefiniteForm);
|
|
750
794
|
}
|
|
795
|
+
function createFromBerContext(options = {}) {
|
|
796
|
+
var _a2, _b, _c;
|
|
797
|
+
return {
|
|
798
|
+
depth: 0,
|
|
799
|
+
maxDepth: (_a2 = options.maxDepth) !== null && _a2 !== void 0 ? _a2 : DEFAULT_MAX_DEPTH,
|
|
800
|
+
nodesCount: 0,
|
|
801
|
+
maxNodes: (_b = options.maxNodes) !== null && _b !== void 0 ? _b : DEFAULT_MAX_NODES,
|
|
802
|
+
maxContentLength: (_c = options.maxContentLength) !== null && _c !== void 0 ? _c : DEFAULT_MAX_CONTENT_LENGTH
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
function createErrorResult(error) {
|
|
806
|
+
const result = new BaseBlock({}, ValueBlock);
|
|
807
|
+
result.error = error;
|
|
808
|
+
return {
|
|
809
|
+
offset: -1,
|
|
810
|
+
result
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
function checkNodesLimit(context) {
|
|
814
|
+
context.nodesCount += 1;
|
|
815
|
+
if (context.nodesCount > context.maxNodes) {
|
|
816
|
+
return MAX_NODES_EXCEEDED_ERROR;
|
|
817
|
+
}
|
|
818
|
+
return void 0;
|
|
819
|
+
}
|
|
820
|
+
function checkContentLengthLimit(inputLength, context) {
|
|
821
|
+
if (inputLength > context.maxContentLength) {
|
|
822
|
+
return MAX_CONTENT_LENGTH_EXCEEDED_ERROR;
|
|
823
|
+
}
|
|
824
|
+
return void 0;
|
|
825
|
+
}
|
|
826
|
+
function localFromBERWithChildContext(inputBuffer, inputOffset, inputLength, context) {
|
|
827
|
+
const childDepth = context.depth + 1;
|
|
828
|
+
if (childDepth > context.maxDepth) {
|
|
829
|
+
return createErrorResult(MAX_DEPTH_EXCEEDED_ERROR);
|
|
830
|
+
}
|
|
831
|
+
context.depth = childDepth;
|
|
832
|
+
try {
|
|
833
|
+
return localFromBER(inputBuffer, inputOffset, inputLength, context);
|
|
834
|
+
} finally {
|
|
835
|
+
context.depth -= 1;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
751
838
|
function localChangeType(inputObject, newType) {
|
|
752
839
|
if (inputObject instanceof newType) {
|
|
753
840
|
return inputObject;
|
|
@@ -759,7 +846,7 @@ function localChangeType(inputObject, newType) {
|
|
|
759
846
|
newObject.valueBeforeDecodeView = inputObject.valueBeforeDecodeView;
|
|
760
847
|
return newObject;
|
|
761
848
|
}
|
|
762
|
-
function localFromBER(inputBuffer, inputOffset = 0, inputLength = inputBuffer.length) {
|
|
849
|
+
function localFromBER(inputBuffer, inputOffset = 0, inputLength = inputBuffer.length, context = createFromBerContext()) {
|
|
763
850
|
const incomingOffset = inputOffset;
|
|
764
851
|
let returnObject = new BaseBlock({}, ValueBlock);
|
|
765
852
|
const baseBlock = new LocalBaseBlock();
|
|
@@ -778,6 +865,14 @@ function localFromBER(inputBuffer, inputOffset = 0, inputLength = inputBuffer.le
|
|
|
778
865
|
result: returnObject
|
|
779
866
|
};
|
|
780
867
|
}
|
|
868
|
+
const nodesLimitError = checkNodesLimit(context);
|
|
869
|
+
if (nodesLimitError) {
|
|
870
|
+
returnObject.error = nodesLimitError;
|
|
871
|
+
return {
|
|
872
|
+
offset: -1,
|
|
873
|
+
result: returnObject
|
|
874
|
+
};
|
|
875
|
+
}
|
|
781
876
|
let resultOffset = returnObject.idBlock.fromBER(inputBuffer, inputOffset, inputLength);
|
|
782
877
|
if (returnObject.idBlock.warnings.length) {
|
|
783
878
|
returnObject.warnings.concat(returnObject.idBlock.warnings);
|
|
@@ -804,6 +899,15 @@ function localFromBER(inputBuffer, inputOffset = 0, inputLength = inputBuffer.le
|
|
|
804
899
|
}
|
|
805
900
|
inputOffset = resultOffset;
|
|
806
901
|
inputLength -= returnObject.lenBlock.blockLength;
|
|
902
|
+
const valueLength = returnObject.lenBlock.isIndefiniteForm ? inputLength : returnObject.lenBlock.length;
|
|
903
|
+
const contentLengthError = checkContentLengthLimit(valueLength, context);
|
|
904
|
+
if (contentLengthError) {
|
|
905
|
+
returnObject.error = contentLengthError;
|
|
906
|
+
return {
|
|
907
|
+
offset: -1,
|
|
908
|
+
result: returnObject
|
|
909
|
+
};
|
|
910
|
+
}
|
|
807
911
|
if (!returnObject.idBlock.isConstructed && returnObject.lenBlock.isIndefiniteForm) {
|
|
808
912
|
returnObject.error = "Indefinite length form used for primitive encoding form";
|
|
809
913
|
return {
|
|
@@ -942,14 +1046,14 @@ function localFromBER(inputBuffer, inputOffset = 0, inputLength = inputBuffer.le
|
|
|
942
1046
|
}
|
|
943
1047
|
}
|
|
944
1048
|
returnObject = localChangeType(returnObject, newASN1Type);
|
|
945
|
-
resultOffset = returnObject.fromBER(inputBuffer, inputOffset,
|
|
1049
|
+
resultOffset = returnObject.fromBER(inputBuffer, inputOffset, valueLength, context);
|
|
946
1050
|
returnObject.valueBeforeDecodeView = inputBuffer.subarray(incomingOffset, incomingOffset + returnObject.blockLength);
|
|
947
1051
|
return {
|
|
948
1052
|
offset: resultOffset,
|
|
949
1053
|
result: returnObject
|
|
950
1054
|
};
|
|
951
1055
|
}
|
|
952
|
-
function fromBER(inputBuffer) {
|
|
1056
|
+
function fromBER(inputBuffer, options = {}) {
|
|
953
1057
|
if (!inputBuffer.byteLength) {
|
|
954
1058
|
const result = new BaseBlock({}, ValueBlock);
|
|
955
1059
|
result.error = "Input buffer has zero length";
|
|
@@ -958,7 +1062,7 @@ function fromBER(inputBuffer) {
|
|
|
958
1062
|
result
|
|
959
1063
|
};
|
|
960
1064
|
}
|
|
961
|
-
return localFromBER(BufferSourceConverter.toUint8Array(inputBuffer).slice(), 0, inputBuffer.byteLength);
|
|
1065
|
+
return localFromBER(BufferSourceConverter.toUint8Array(inputBuffer).slice(), 0, inputBuffer.byteLength, createFromBerContext(options));
|
|
962
1066
|
}
|
|
963
1067
|
function checkLen(indefiniteLength, length) {
|
|
964
1068
|
if (indefiniteLength) {
|
|
@@ -1364,7 +1468,7 @@ function verifySchema(inputBuffer, inputSchema) {
|
|
|
1364
1468
|
}
|
|
1365
1469
|
return compareSchema(asn1.result, asn1.result, inputSchema);
|
|
1366
1470
|
}
|
|
1367
|
-
var ViewWriter, powers2, digitsString, NAME, VALUE_HEX_VIEW, IS_HEX_ONLY, ID_BLOCK, TAG_CLASS, TAG_NUMBER, IS_CONSTRUCTED, FROM_BER, TO_BER, LOCAL, EMPTY_STRING, EMPTY_BUFFER, EMPTY_VIEW, END_OF_CONTENT_NAME, OCTET_STRING_NAME, BIT_STRING_NAME, LocalBaseBlock, ValueBlock, LocalIdentificationBlock, LocalLengthBlock, typeStore, BaseBlock, BaseStringBlock, LocalPrimitiveValueBlock, _a$w, Primitive, LocalConstructedValueBlock, _a$v, Constructed, LocalEndOfContentValueBlock, _a$u, EndOfContent, _a$t, Null, LocalBooleanValueBlock, _a$s, Boolean2, LocalOctetStringValueBlock, _a$r, OctetString, LocalBitStringValueBlock, _a$q, BitString, _a$p, LocalIntegerValueBlock, _a$o, Integer, _a$n, Enumerated, LocalSidValueBlock, LocalObjectIdentifierValueBlock, _a$m, ObjectIdentifier, LocalRelativeSidValueBlock, LocalRelativeObjectIdentifierValueBlock, _a$l, RelativeObjectIdentifier, _a$k, Sequence, _a$j, Set2, LocalStringValueBlock, LocalSimpleStringValueBlock, LocalSimpleStringBlock, LocalUtf8StringValueBlock, _a$i, Utf8String, LocalBmpStringValueBlock, _a$h, BmpString, LocalUniversalStringValueBlock, _a$g, UniversalString, _a$f, NumericString, _a$e, PrintableString, _a$d, TeletexString, _a$c, VideotexString, _a$b, IA5String, _a$a, GraphicString, _a$9, VisibleString, _a$8, GeneralString, _a$7, CharacterString, _a$6, UTCTime, _a$5, GeneralizedTime, _a$4, DATE, _a$3, TimeOfDay, _a$2, DateTime, _a$1, Duration, _a, TIME, Any, Choice, Repeated, RawData;
|
|
1471
|
+
var ViewWriter, powers2, digitsString, NAME, VALUE_HEX_VIEW, IS_HEX_ONLY, ID_BLOCK, TAG_CLASS, TAG_NUMBER, IS_CONSTRUCTED, FROM_BER, TO_BER, LOCAL, EMPTY_STRING, EMPTY_BUFFER, EMPTY_VIEW, END_OF_CONTENT_NAME, OCTET_STRING_NAME, BIT_STRING_NAME, LocalBaseBlock, ValueBlock, LocalIdentificationBlock, LocalLengthBlock, typeStore, BaseBlock, BaseStringBlock, LocalPrimitiveValueBlock, _a$w, Primitive, DEFAULT_MAX_DEPTH, DEFAULT_MAX_NODES, DEFAULT_MAX_CONTENT_LENGTH, MAX_DEPTH_EXCEEDED_ERROR, MAX_NODES_EXCEEDED_ERROR, MAX_CONTENT_LENGTH_EXCEEDED_ERROR, LocalConstructedValueBlock, _a$v, Constructed, LocalEndOfContentValueBlock, _a$u, EndOfContent, _a$t, Null, LocalBooleanValueBlock, _a$s, Boolean2, LocalOctetStringValueBlock, _a$r, OctetString, LocalBitStringValueBlock, _a$q, BitString, _a$p, LocalIntegerValueBlock, _a$o, Integer, _a$n, Enumerated, LocalSidValueBlock, LocalObjectIdentifierValueBlock, _a$m, ObjectIdentifier, LocalRelativeSidValueBlock, LocalRelativeObjectIdentifierValueBlock, _a$l, RelativeObjectIdentifier, _a$k, Sequence, _a$j, Set2, LocalStringValueBlock, LocalSimpleStringValueBlock, LocalSimpleStringBlock, LocalUtf8StringValueBlock, _a$i, Utf8String, LocalBmpStringValueBlock, _a$h, BmpString, LocalUniversalStringValueBlock, _a$g, UniversalString, _a$f, NumericString, _a$e, PrintableString, _a$d, TeletexString, _a$c, VideotexString, _a$b, IA5String, _a$a, GraphicString, _a$9, VisibleString, _a$8, GeneralString, _a$7, CharacterString, _a$6, UTCTime, _a$5, GeneralizedTime, _a$4, DATE, _a$3, TimeOfDay, _a$2, DateTime, _a$1, Duration, _a, TIME, Any, Choice, Repeated, RawData;
|
|
1368
1472
|
var init_index_es2 = __esm({
|
|
1369
1473
|
"node_modules/asn1js/build/index.es.js"() {
|
|
1370
1474
|
init_index_es();
|
|
@@ -1426,7 +1530,7 @@ var init_index_es2 = __esm({
|
|
|
1426
1530
|
};
|
|
1427
1531
|
LocalBaseBlock.NAME = "baseBlock";
|
|
1428
1532
|
ValueBlock = class extends LocalBaseBlock {
|
|
1429
|
-
fromBER(_inputBuffer, _inputOffset, _inputLength) {
|
|
1533
|
+
fromBER(_inputBuffer, _inputOffset, _inputLength, _context) {
|
|
1430
1534
|
throw TypeError("User need to make a specific function in a class which extends 'ValueBlock'");
|
|
1431
1535
|
}
|
|
1432
1536
|
toBER(_sizeOnly, _writer) {
|
|
@@ -1539,31 +1643,21 @@ var init_index_es2 = __esm({
|
|
|
1539
1643
|
this.tagNumber = tagNumberMask;
|
|
1540
1644
|
this.blockLength = 1;
|
|
1541
1645
|
} else {
|
|
1542
|
-
let count =
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
intTagNumberBuffer[count - 1] = intBuffer[count] & 127;
|
|
1547
|
-
count++;
|
|
1548
|
-
if (count >= intBuffer.length) {
|
|
1646
|
+
let count = 0;
|
|
1647
|
+
while (true) {
|
|
1648
|
+
const tagByteIndex = count + 1;
|
|
1649
|
+
if (tagByteIndex >= intBuffer.length) {
|
|
1549
1650
|
this.error = "End of input reached before message was fully decoded";
|
|
1550
1651
|
return -1;
|
|
1551
1652
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
for (let i = 0; i < intTagNumberBuffer.length; i++)
|
|
1556
|
-
tempBufferView2[i] = intTagNumberBuffer[i];
|
|
1557
|
-
intTagNumberBuffer = this.valueHexView = new Uint8Array(tagNumberBufferMaxLength);
|
|
1558
|
-
}
|
|
1653
|
+
count++;
|
|
1654
|
+
if ((intBuffer[tagByteIndex] & 128) === 0)
|
|
1655
|
+
break;
|
|
1559
1656
|
}
|
|
1560
1657
|
this.blockLength = count + 1;
|
|
1561
|
-
intTagNumberBuffer
|
|
1562
|
-
const tempBufferView = new Uint8Array(count);
|
|
1658
|
+
const intTagNumberBuffer = this.valueHexView = new Uint8Array(count);
|
|
1563
1659
|
for (let i = 0; i < count; i++)
|
|
1564
|
-
|
|
1565
|
-
intTagNumberBuffer = this.valueHexView = new Uint8Array(count);
|
|
1566
|
-
intTagNumberBuffer.set(tempBufferView);
|
|
1660
|
+
intTagNumberBuffer[i] = intBuffer[i + 1] & 127;
|
|
1567
1661
|
if (this.blockLength <= 9)
|
|
1568
1662
|
this.tagNumber = utilFromBase(intTagNumberBuffer, 7);
|
|
1569
1663
|
else {
|
|
@@ -1713,8 +1807,8 @@ var init_index_es2 = __esm({
|
|
|
1713
1807
|
this.lenBlock = new LocalLengthBlock(parameters);
|
|
1714
1808
|
this.valueBlock = valueBlockType ? new valueBlockType(parameters) : new ValueBlock(parameters);
|
|
1715
1809
|
}
|
|
1716
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
1717
|
-
const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm ? inputLength : this.lenBlock.length);
|
|
1810
|
+
fromBER(inputBuffer, inputOffset, inputLength, context) {
|
|
1811
|
+
const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm ? inputLength : this.lenBlock.length, context);
|
|
1718
1812
|
if (resultOffset === -1) {
|
|
1719
1813
|
this.error = this.valueBlock.error;
|
|
1720
1814
|
return resultOffset;
|
|
@@ -1838,14 +1932,21 @@ var init_index_es2 = __esm({
|
|
|
1838
1932
|
typeStore.Primitive = _a$w;
|
|
1839
1933
|
})();
|
|
1840
1934
|
Primitive.NAME = "PRIMITIVE";
|
|
1935
|
+
DEFAULT_MAX_DEPTH = 100;
|
|
1936
|
+
DEFAULT_MAX_NODES = 1e4;
|
|
1937
|
+
DEFAULT_MAX_CONTENT_LENGTH = 16 * 1024 * 1024;
|
|
1938
|
+
MAX_DEPTH_EXCEEDED_ERROR = "Maximum ASN.1 nesting depth exceeded";
|
|
1939
|
+
MAX_NODES_EXCEEDED_ERROR = "Maximum ASN.1 node count exceeded";
|
|
1940
|
+
MAX_CONTENT_LENGTH_EXCEEDED_ERROR = "Maximum ASN.1 content length exceeded";
|
|
1841
1941
|
LocalConstructedValueBlock = class extends ValueBlock {
|
|
1842
1942
|
constructor({ value = [], isIndefiniteForm = false, ...parameters } = {}) {
|
|
1843
1943
|
super(parameters);
|
|
1844
1944
|
this.value = value;
|
|
1845
1945
|
this.isIndefiniteForm = isIndefiniteForm;
|
|
1846
1946
|
}
|
|
1847
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
1947
|
+
fromBER(inputBuffer, inputOffset, inputLength, context) {
|
|
1848
1948
|
const view = BufferSourceConverter.toUint8Array(inputBuffer);
|
|
1949
|
+
const parseContext = context !== null && context !== void 0 ? context : createFromBerContext();
|
|
1849
1950
|
if (!checkBufferParams(this, view, inputOffset, inputLength)) {
|
|
1850
1951
|
return -1;
|
|
1851
1952
|
}
|
|
@@ -1856,7 +1957,7 @@ var init_index_es2 = __esm({
|
|
|
1856
1957
|
}
|
|
1857
1958
|
let currentOffset = inputOffset;
|
|
1858
1959
|
while (checkLen(this.isIndefiniteForm, inputLength) > 0) {
|
|
1859
|
-
const returnObject =
|
|
1960
|
+
const returnObject = localFromBERWithChildContext(view, currentOffset, inputLength, parseContext);
|
|
1860
1961
|
if (returnObject.offset === -1) {
|
|
1861
1962
|
this.error = returnObject.result.error;
|
|
1862
1963
|
this.warnings.concat(returnObject.result.warnings);
|
|
@@ -1907,9 +2008,9 @@ var init_index_es2 = __esm({
|
|
|
1907
2008
|
super(parameters, LocalConstructedValueBlock);
|
|
1908
2009
|
this.idBlock.isConstructed = true;
|
|
1909
2010
|
}
|
|
1910
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
2011
|
+
fromBER(inputBuffer, inputOffset, inputLength, context) {
|
|
1911
2012
|
this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
|
|
1912
|
-
const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm ? inputLength : this.lenBlock.length);
|
|
2013
|
+
const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, this.lenBlock.isIndefiniteForm ? inputLength : this.lenBlock.length, context);
|
|
1913
2014
|
if (resultOffset === -1) {
|
|
1914
2015
|
this.error = this.valueBlock.error;
|
|
1915
2016
|
return resultOffset;
|
|
@@ -2072,11 +2173,11 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
2072
2173
|
super(parameters);
|
|
2073
2174
|
this.isConstructed = isConstructed;
|
|
2074
2175
|
}
|
|
2075
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
2176
|
+
fromBER(inputBuffer, inputOffset, inputLength, context) {
|
|
2076
2177
|
let resultOffset = 0;
|
|
2077
2178
|
if (this.isConstructed) {
|
|
2078
2179
|
this.isHexOnly = false;
|
|
2079
|
-
resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
|
|
2180
|
+
resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength, context);
|
|
2080
2181
|
if (resultOffset === -1)
|
|
2081
2182
|
return resultOffset;
|
|
2082
2183
|
for (let i = 0; i < this.value.length; i++) {
|
|
@@ -2132,7 +2233,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
2132
2233
|
this.idBlock.tagClass = 1;
|
|
2133
2234
|
this.idBlock.tagNumber = 4;
|
|
2134
2235
|
}
|
|
2135
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
2236
|
+
fromBER(inputBuffer, inputOffset, inputLength, context) {
|
|
2136
2237
|
this.valueBlock.isConstructed = this.idBlock.isConstructed;
|
|
2137
2238
|
this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
|
|
2138
2239
|
if (inputLength === 0) {
|
|
@@ -2147,7 +2248,8 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
2147
2248
|
const buf = view.subarray(inputOffset, inputOffset + inputLength);
|
|
2148
2249
|
try {
|
|
2149
2250
|
if (buf.byteLength) {
|
|
2150
|
-
const
|
|
2251
|
+
const parseContext = context !== null && context !== void 0 ? context : createFromBerContext();
|
|
2252
|
+
const asn = localFromBERWithChildContext(buf, 0, buf.byteLength, parseContext);
|
|
2151
2253
|
if (asn.offset !== -1 && asn.offset === inputLength) {
|
|
2152
2254
|
this.valueBlock.value = [asn.result];
|
|
2153
2255
|
}
|
|
@@ -2155,7 +2257,7 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
2155
2257
|
} catch {
|
|
2156
2258
|
}
|
|
2157
2259
|
}
|
|
2158
|
-
return super.fromBER(inputBuffer, inputOffset, inputLength);
|
|
2260
|
+
return super.fromBER(inputBuffer, inputOffset, inputLength, context);
|
|
2159
2261
|
}
|
|
2160
2262
|
onAsciiEncoding() {
|
|
2161
2263
|
if (this.valueBlock.isConstructed || this.valueBlock.value && this.valueBlock.value.length) {
|
|
@@ -2190,13 +2292,13 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
2190
2292
|
this.isConstructed = isConstructed;
|
|
2191
2293
|
this.blockLength = this.valueHexView.byteLength;
|
|
2192
2294
|
}
|
|
2193
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
2295
|
+
fromBER(inputBuffer, inputOffset, inputLength, context) {
|
|
2194
2296
|
if (!inputLength) {
|
|
2195
2297
|
return inputOffset;
|
|
2196
2298
|
}
|
|
2197
2299
|
let resultOffset = -1;
|
|
2198
2300
|
if (this.isConstructed) {
|
|
2199
|
-
resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength);
|
|
2301
|
+
resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength, context);
|
|
2200
2302
|
if (resultOffset === -1)
|
|
2201
2303
|
return resultOffset;
|
|
2202
2304
|
for (const value of this.value) {
|
|
@@ -2236,7 +2338,8 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
2236
2338
|
const buf = intBuffer.subarray(1);
|
|
2237
2339
|
try {
|
|
2238
2340
|
if (buf.byteLength) {
|
|
2239
|
-
const
|
|
2341
|
+
const parseContext = context !== null && context !== void 0 ? context : createFromBerContext();
|
|
2342
|
+
const asn = localFromBERWithChildContext(buf, 0, buf.byteLength, parseContext);
|
|
2240
2343
|
if (asn.offset !== -1 && asn.offset === inputLength - 1) {
|
|
2241
2344
|
this.value = [asn.result];
|
|
2242
2345
|
}
|
|
@@ -2292,10 +2395,10 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
2292
2395
|
this.idBlock.tagClass = 1;
|
|
2293
2396
|
this.idBlock.tagNumber = 3;
|
|
2294
2397
|
}
|
|
2295
|
-
fromBER(inputBuffer, inputOffset, inputLength) {
|
|
2398
|
+
fromBER(inputBuffer, inputOffset, inputLength, context) {
|
|
2296
2399
|
this.valueBlock.isConstructed = this.idBlock.isConstructed;
|
|
2297
2400
|
this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
|
|
2298
|
-
return super.fromBER(inputBuffer, inputOffset, inputLength);
|
|
2401
|
+
return super.fromBER(inputBuffer, inputOffset, inputLength, context);
|
|
2299
2402
|
}
|
|
2300
2403
|
onAsciiEncoding() {
|
|
2301
2404
|
if (this.valueBlock.isConstructed || this.valueBlock.value && this.valueBlock.value.length) {
|
|
@@ -7962,6 +8065,135 @@ function createAuthorizationRequest(input, query) {
|
|
|
7962
8065
|
};
|
|
7963
8066
|
}
|
|
7964
8067
|
|
|
8068
|
+
// src/signed-authorization.ts
|
|
8069
|
+
init_errors();
|
|
8070
|
+
var DEFAULT_SUPPORTED_ENC_VALUES = ["A128GCM", "A256GCM"];
|
|
8071
|
+
var SUPPORTED_SIGNING_ALGS = /* @__PURE__ */ new Set(["ES256", "ES384", "RS256"]);
|
|
8072
|
+
async function createSignedAuthorizationRequest(input, query) {
|
|
8073
|
+
if (input.certificateChain.length === 0) {
|
|
8074
|
+
throw new SignedRequestBuildError(
|
|
8075
|
+
"empty_cert_chain",
|
|
8076
|
+
"certificateChain must contain at least the leaf certificate"
|
|
8077
|
+
);
|
|
8078
|
+
}
|
|
8079
|
+
const signingAlg = input.signingAlgorithm ?? "ES256";
|
|
8080
|
+
if (!SUPPORTED_SIGNING_ALGS.has(signingAlg)) {
|
|
8081
|
+
throw new SignedRequestBuildError(
|
|
8082
|
+
"unsupported_signing_alg",
|
|
8083
|
+
`signingAlgorithm ${signingAlg} is not supported (expected ES256/ES384/RS256)`
|
|
8084
|
+
);
|
|
8085
|
+
}
|
|
8086
|
+
if (!input.vpFormatsSupported || Object.keys(input.vpFormatsSupported).length === 0) {
|
|
8087
|
+
throw new SignedRequestBuildError(
|
|
8088
|
+
"missing_vp_formats",
|
|
8089
|
+
"vpFormatsSupported is required and must be non-empty"
|
|
8090
|
+
);
|
|
8091
|
+
}
|
|
8092
|
+
const leafCert = new X509Certificate(toArrayBuffer(input.certificateChain[0]));
|
|
8093
|
+
const sanDnsNames = extractDnsNames(leafCert);
|
|
8094
|
+
if (!sanDnsNames.includes(input.hostname)) {
|
|
8095
|
+
throw new SignedRequestBuildError(
|
|
8096
|
+
"hostname_cert_mismatch",
|
|
8097
|
+
`leaf cert SAN DNSName values [${sanDnsNames.join(", ")}] do not include hostname "${input.hostname}"`
|
|
8098
|
+
);
|
|
8099
|
+
}
|
|
8100
|
+
const signerPublicSpki = new Uint8Array(
|
|
8101
|
+
await crypto.subtle.exportKey("spki", input.signer.publicKey)
|
|
8102
|
+
);
|
|
8103
|
+
const leafSpki = new Uint8Array(leafCert.publicKey.rawData);
|
|
8104
|
+
if (!bytesEqual(signerPublicSpki, leafSpki)) {
|
|
8105
|
+
throw new SignedRequestBuildError(
|
|
8106
|
+
"signing_key_cert_mismatch",
|
|
8107
|
+
"signer.publicKey SPKI does not match leaf certificate SPKI"
|
|
8108
|
+
);
|
|
8109
|
+
}
|
|
8110
|
+
const responseMode = input.responseMode ?? "direct_post.jwt";
|
|
8111
|
+
if (responseMode === "direct_post.jwt") {
|
|
8112
|
+
if (!input.encryptionKey?.publicJwk) {
|
|
8113
|
+
throw new SignedRequestBuildError(
|
|
8114
|
+
"missing_encryption_jwk",
|
|
8115
|
+
"direct_post.jwt response mode requires encryptionKey.publicJwk"
|
|
8116
|
+
);
|
|
8117
|
+
}
|
|
8118
|
+
if (!input.encryptionKey.publicJwk.alg) {
|
|
8119
|
+
throw new SignedRequestBuildError(
|
|
8120
|
+
"missing_encryption_alg",
|
|
8121
|
+
"encryptionKey.publicJwk must carry alg (OpenID4VP 1.0 \xA78.3)"
|
|
8122
|
+
);
|
|
8123
|
+
}
|
|
8124
|
+
}
|
|
8125
|
+
const state = input.state ?? v4();
|
|
8126
|
+
const clientId = `x509_san_dns:${input.hostname}`;
|
|
8127
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
8128
|
+
const clientMetadata = {
|
|
8129
|
+
vp_formats_supported: input.vpFormatsSupported
|
|
8130
|
+
};
|
|
8131
|
+
if (responseMode === "direct_post.jwt" && input.encryptionKey) {
|
|
8132
|
+
const enc = input.encryptionKey.supportedEncValues;
|
|
8133
|
+
if (enc !== void 0 && enc.length === 0) {
|
|
8134
|
+
throw new SignedRequestBuildError(
|
|
8135
|
+
"empty_supported_enc_values",
|
|
8136
|
+
"encryptionKey.supportedEncValues must not be empty (omit to use defaults [A128GCM, A256GCM])"
|
|
8137
|
+
);
|
|
8138
|
+
}
|
|
8139
|
+
const jwk = { ...input.encryptionKey.publicJwk, use: "enc" };
|
|
8140
|
+
clientMetadata.jwks = { keys: [jwk] };
|
|
8141
|
+
clientMetadata.encrypted_response_enc_values_supported = enc ?? [...DEFAULT_SUPPORTED_ENC_VALUES];
|
|
8142
|
+
}
|
|
8143
|
+
const payload = {
|
|
8144
|
+
iss: clientId,
|
|
8145
|
+
aud: "https://self-issued.me/v2",
|
|
8146
|
+
response_type: "vp_token",
|
|
8147
|
+
response_mode: responseMode,
|
|
8148
|
+
client_id: clientId,
|
|
8149
|
+
response_uri: input.responseUri,
|
|
8150
|
+
nonce: input.nonce,
|
|
8151
|
+
state,
|
|
8152
|
+
dcql_query: query,
|
|
8153
|
+
client_metadata: clientMetadata,
|
|
8154
|
+
iat: now,
|
|
8155
|
+
exp: now + 120
|
|
8156
|
+
};
|
|
8157
|
+
const x5c = input.certificateChain.map((der) => bytesToBase64(der));
|
|
8158
|
+
const jws = await new SignJWT(payload).setProtectedHeader({ typ: "oauth-authz-req+jwt", alg: signingAlg, x5c }).sign(input.signer.privateKey);
|
|
8159
|
+
const uriParams = new URLSearchParams({
|
|
8160
|
+
client_id: clientId,
|
|
8161
|
+
request_uri: input.requestUri
|
|
8162
|
+
});
|
|
8163
|
+
return {
|
|
8164
|
+
uri: `openid4vp://authorize?${uriParams.toString()}`,
|
|
8165
|
+
requestObject: jws,
|
|
8166
|
+
dcqlQuery: query,
|
|
8167
|
+
nonce: input.nonce,
|
|
8168
|
+
state
|
|
8169
|
+
};
|
|
8170
|
+
}
|
|
8171
|
+
function extractDnsNames(cert) {
|
|
8172
|
+
const SAN_OID = "2.5.29.17";
|
|
8173
|
+
const ext = cert.extensions.find((e) => e.type === SAN_OID);
|
|
8174
|
+
if (!ext) return [];
|
|
8175
|
+
const names = ext.names;
|
|
8176
|
+
const items = names?.items ?? [];
|
|
8177
|
+
return items.filter((e) => e.type === "dns").map((e) => e.value);
|
|
8178
|
+
}
|
|
8179
|
+
function bytesEqual(a, b) {
|
|
8180
|
+
if (a.length !== b.length) return false;
|
|
8181
|
+
for (let i = 0; i < a.length; i++) {
|
|
8182
|
+
if (a[i] !== b[i]) return false;
|
|
8183
|
+
}
|
|
8184
|
+
return true;
|
|
8185
|
+
}
|
|
8186
|
+
function bytesToBase64(bytes) {
|
|
8187
|
+
let s = "";
|
|
8188
|
+
for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
|
|
8189
|
+
return btoa(s);
|
|
8190
|
+
}
|
|
8191
|
+
function toArrayBuffer(bytes) {
|
|
8192
|
+
const out = new ArrayBuffer(bytes.byteLength);
|
|
8193
|
+
new Uint8Array(out).set(bytes);
|
|
8194
|
+
return out;
|
|
8195
|
+
}
|
|
8196
|
+
|
|
7965
8197
|
// src/haip.ts
|
|
7966
8198
|
init_errors();
|
|
7967
8199
|
var HAIP_DOCTYPE_NAMESPACES = {
|
|
@@ -8188,7 +8420,7 @@ async function computeItemDigest(itemBytes, digestAlgorithm) {
|
|
|
8188
8420
|
const buf = await crypto.subtle.digest(digestAlgorithm, new Uint8Array(itemBytes));
|
|
8189
8421
|
return new Uint8Array(buf);
|
|
8190
8422
|
}
|
|
8191
|
-
function
|
|
8423
|
+
function bytesEqual2(a, b) {
|
|
8192
8424
|
if (a.length !== b.length) return false;
|
|
8193
8425
|
for (let i = 0; i < a.length; i++) {
|
|
8194
8426
|
if (a[i] !== b[i]) return false;
|
|
@@ -8234,7 +8466,7 @@ async function verifyAllDigests(nameSpaces, mso) {
|
|
|
8234
8466
|
if (!expectedDigest) {
|
|
8235
8467
|
throw new MalformedCredentialError(`digestID ${digestID} missing from MSO valueDigests[${ns}]`);
|
|
8236
8468
|
}
|
|
8237
|
-
if (!
|
|
8469
|
+
if (!bytesEqual2(hash, expectedDigest)) {
|
|
8238
8470
|
throw new MalformedCredentialError(`digest mismatch for ns=${ns} digestID=${digestID}`);
|
|
8239
8471
|
}
|
|
8240
8472
|
}
|
|
@@ -8353,7 +8585,7 @@ init_errors();
|
|
|
8353
8585
|
var decoder4 = new Encoder({ mapsAsObjects: false, useRecords: false });
|
|
8354
8586
|
var encoder = new Encoder({ mapsAsObjects: false, useRecords: false });
|
|
8355
8587
|
var DEFAULT_ALLOWED_ALGORITHMS = ["ES256", "ES384", "ES512"];
|
|
8356
|
-
function
|
|
8588
|
+
function bytesEqual3(a, b) {
|
|
8357
8589
|
if (a.length !== b.length) return false;
|
|
8358
8590
|
for (let i = 0; i < a.length; i++) {
|
|
8359
8591
|
if (a[i] !== b[i]) return false;
|
|
@@ -8489,8 +8721,8 @@ var MdocParser = class {
|
|
|
8489
8721
|
cache: options.cache,
|
|
8490
8722
|
clockSkewTolerance: options.clockSkewTolerance
|
|
8491
8723
|
});
|
|
8492
|
-
const { X509Certificate:
|
|
8493
|
-
const leaf = new
|
|
8724
|
+
const { X509Certificate: X509Certificate9 } = await import('@peculiar/x509');
|
|
8725
|
+
const leaf = new X509Certificate9(issuerCertBytes);
|
|
8494
8726
|
trustResult = await evaluator.evaluate(leaf);
|
|
8495
8727
|
} else {
|
|
8496
8728
|
if (options.trustedCertificates.length === 0) {
|
|
@@ -8500,7 +8732,7 @@ var MdocParser = class {
|
|
|
8500
8732
|
);
|
|
8501
8733
|
}
|
|
8502
8734
|
} else {
|
|
8503
|
-
const trusted = options.trustedCertificates.some((t) =>
|
|
8735
|
+
const trusted = options.trustedCertificates.some((t) => bytesEqual3(t, issuerCertBytes));
|
|
8504
8736
|
if (!trusted) {
|
|
8505
8737
|
return {
|
|
8506
8738
|
valid: false,
|
|
@@ -8615,7 +8847,7 @@ function base64ToBytes(base64) {
|
|
|
8615
8847
|
}
|
|
8616
8848
|
return bytes;
|
|
8617
8849
|
}
|
|
8618
|
-
function
|
|
8850
|
+
function bytesEqual4(a, b) {
|
|
8619
8851
|
if (a.length !== b.length) return false;
|
|
8620
8852
|
for (let i = 0; i < a.length; i++) {
|
|
8621
8853
|
if (a[i] !== b[i]) return false;
|
|
@@ -8738,8 +8970,8 @@ var SdJwtParser = class {
|
|
|
8738
8970
|
cache: options.cache,
|
|
8739
8971
|
clockSkewTolerance: options.clockSkewTolerance
|
|
8740
8972
|
});
|
|
8741
|
-
const { X509Certificate:
|
|
8742
|
-
const leaf = new
|
|
8973
|
+
const { X509Certificate: X509Certificate9 } = await import('@peculiar/x509');
|
|
8974
|
+
const leaf = new X509Certificate9(issuerCertBytes);
|
|
8743
8975
|
trustResult = await evaluator.evaluate(leaf);
|
|
8744
8976
|
} else {
|
|
8745
8977
|
if (options.trustedCertificates.length === 0) {
|
|
@@ -8749,7 +8981,7 @@ var SdJwtParser = class {
|
|
|
8749
8981
|
);
|
|
8750
8982
|
}
|
|
8751
8983
|
} else {
|
|
8752
|
-
const isTrusted = options.trustedCertificates.some((trusted) =>
|
|
8984
|
+
const isTrusted = options.trustedCertificates.some((trusted) => bytesEqual4(trusted, issuerCertBytes));
|
|
8753
8985
|
if (!isTrusted) {
|
|
8754
8986
|
return invalidResult("Issuer certificate is not trusted");
|
|
8755
8987
|
}
|
|
@@ -8846,42 +9078,48 @@ async function parsePresentation(vpToken, options) {
|
|
|
8846
9078
|
error: "Unsupported credential format"
|
|
8847
9079
|
};
|
|
8848
9080
|
}
|
|
8849
|
-
|
|
8850
|
-
|
|
8851
|
-
|
|
8852
|
-
|
|
8853
|
-
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8857
|
-
|
|
8858
|
-
|
|
8859
|
-
|
|
9081
|
+
|
|
9082
|
+
// src/decrypt-response.ts
|
|
9083
|
+
init_errors();
|
|
9084
|
+
var SUPPORTED_ALG = "ECDH-ES";
|
|
9085
|
+
var SUPPORTED_ENC = /* @__PURE__ */ new Set(["A128GCM", "A256GCM"]);
|
|
9086
|
+
async function decryptAuthorizationResponse(jwe, privateKey) {
|
|
9087
|
+
let header;
|
|
9088
|
+
try {
|
|
9089
|
+
header = decodeProtectedHeader(jwe);
|
|
9090
|
+
} catch (err) {
|
|
9091
|
+
throw new DecryptionFailedError("Malformed JWE header", {
|
|
9092
|
+
cause: err
|
|
9093
|
+
});
|
|
8860
9094
|
}
|
|
8861
|
-
|
|
8862
|
-
|
|
8863
|
-
|
|
9095
|
+
const alg = typeof header.alg === "string" ? header.alg : "";
|
|
9096
|
+
const enc = typeof header.enc === "string" ? header.enc : "";
|
|
9097
|
+
if (alg !== SUPPORTED_ALG || !SUPPORTED_ENC.has(enc)) {
|
|
9098
|
+
throw new UnsupportedJweError(alg, enc);
|
|
8864
9099
|
}
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
const
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
9100
|
+
let plaintext;
|
|
9101
|
+
try {
|
|
9102
|
+
const result = await compactDecrypt(jwe, privateKey);
|
|
9103
|
+
plaintext = result.plaintext;
|
|
9104
|
+
} catch (err) {
|
|
9105
|
+
throw new DecryptionFailedError(void 0, { cause: err });
|
|
9106
|
+
}
|
|
9107
|
+
try {
|
|
9108
|
+
const text = new TextDecoder().decode(plaintext);
|
|
9109
|
+
return JSON.parse(text);
|
|
9110
|
+
} catch (err) {
|
|
9111
|
+
throw new DecryptionFailedError("Decrypted plaintext is not valid JSON", {
|
|
9112
|
+
cause: err
|
|
9113
|
+
});
|
|
8871
9114
|
}
|
|
8872
|
-
if (hasDetail) return "missing_claims";
|
|
8873
|
-
return "no_credential_found";
|
|
8874
|
-
}
|
|
8875
|
-
function refineUnmatched(query, decoded, match) {
|
|
8876
|
-
if (match.unmatched.length === 0) return match;
|
|
8877
|
-
const refined = match.unmatched.map((entry) => {
|
|
8878
|
-
const credentialQuery = query.credentials.find((c) => c.id === entry.queryId);
|
|
8879
|
-
if (!credentialQuery) return entry;
|
|
8880
|
-
const specific = classifyMismatch(credentialQuery, decoded, entry.detail !== void 0);
|
|
8881
|
-
return { ...entry, reason: specific };
|
|
8882
|
-
});
|
|
8883
|
-
return { ...match, unmatched: refined };
|
|
8884
9115
|
}
|
|
9116
|
+
|
|
9117
|
+
// src/verify.ts
|
|
9118
|
+
init_errors();
|
|
9119
|
+
var INTERNAL_TO_DCQL_FORMAT = {
|
|
9120
|
+
"sd-jwt-vc": "dc+sd-jwt",
|
|
9121
|
+
mdoc: "mso_mdoc"
|
|
9122
|
+
};
|
|
8885
9123
|
async function verifyPresentation(vpToken, query, options) {
|
|
8886
9124
|
const parsed = await parsePresentation(vpToken, options);
|
|
8887
9125
|
const dcqlFormat = INTERNAL_TO_DCQL_FORMAT[parsed.format] ?? parsed.format;
|
|
@@ -8900,8 +9138,7 @@ async function verifyPresentation(vpToken, query, options) {
|
|
|
8900
9138
|
if (parsed.trust?.trustedAuthorityIds && parsed.trust.trustedAuthorityIds.length > 0) {
|
|
8901
9139
|
decoded.trusted_authority_ids = [...parsed.trust.trustedAuthorityIds];
|
|
8902
9140
|
}
|
|
8903
|
-
const
|
|
8904
|
-
const match = refineUnmatched(query, decoded, rawMatch);
|
|
9141
|
+
const match = matchQuery(query, [decoded]);
|
|
8905
9142
|
const submission = match.satisfied ? buildSubmission(query, match) : null;
|
|
8906
9143
|
return {
|
|
8907
9144
|
parsed,
|
|
@@ -8910,6 +9147,48 @@ async function verifyPresentation(vpToken, query, options) {
|
|
|
8910
9147
|
valid: parsed.valid && match.satisfied
|
|
8911
9148
|
};
|
|
8912
9149
|
}
|
|
9150
|
+
function isEncryptedResponse(x) {
|
|
9151
|
+
return typeof x === "object" && x !== null && "response" in x && typeof x.response === "string" && Object.keys(x).length === 1;
|
|
9152
|
+
}
|
|
9153
|
+
function isAuthorizationResponse(x) {
|
|
9154
|
+
return typeof x === "object" && x !== null && "vp_token" in x && typeof x.vp_token === "object" && x.vp_token !== null;
|
|
9155
|
+
}
|
|
9156
|
+
async function verifyAuthorizationResponse(envelope, query, options) {
|
|
9157
|
+
if (isEncryptedResponse(envelope)) {
|
|
9158
|
+
if (!options.decryptionKey) {
|
|
9159
|
+
throw new MissingDecryptionKeyError();
|
|
9160
|
+
}
|
|
9161
|
+
const decrypted = await decryptAuthorizationResponse(
|
|
9162
|
+
envelope.response,
|
|
9163
|
+
options.decryptionKey
|
|
9164
|
+
);
|
|
9165
|
+
return verifyAuthorizationResponse(decrypted, query, options);
|
|
9166
|
+
}
|
|
9167
|
+
if (!isAuthorizationResponse(envelope)) {
|
|
9168
|
+
throw new TypeError("envelope must contain vp_token as a JSON object per OpenID4VP 1.0 \xA78.1");
|
|
9169
|
+
}
|
|
9170
|
+
const vpToken = envelope.vp_token;
|
|
9171
|
+
const queryIds = Object.keys(vpToken);
|
|
9172
|
+
if (queryIds.length === 0) {
|
|
9173
|
+
throw new TypeError("vp_token cannot be empty per OpenID4VP 1.0 \xA78.1");
|
|
9174
|
+
}
|
|
9175
|
+
for (const id of queryIds) {
|
|
9176
|
+
if (!Array.isArray(vpToken[id])) {
|
|
9177
|
+
throw new TypeError(
|
|
9178
|
+
`vp_token entry "${id}" must be an array of presentations per OpenID4VP 1.0 \xA78.1`
|
|
9179
|
+
);
|
|
9180
|
+
}
|
|
9181
|
+
}
|
|
9182
|
+
const presentationCount = queryIds.reduce(
|
|
9183
|
+
(sum, id) => sum + vpToken[id].length,
|
|
9184
|
+
0
|
|
9185
|
+
);
|
|
9186
|
+
if (queryIds.length > 1 || presentationCount > 1) {
|
|
9187
|
+
throw new MultipleCredentialsNotSupportedError(queryIds.length, presentationCount);
|
|
9188
|
+
}
|
|
9189
|
+
const presentation = vpToken[queryIds[0]][0];
|
|
9190
|
+
return verifyPresentation(presentation, query, options);
|
|
9191
|
+
}
|
|
8913
9192
|
|
|
8914
9193
|
// src/index.ts
|
|
8915
9194
|
init_errors();
|
|
@@ -9521,7 +9800,7 @@ function equalBytes(a, b) {
|
|
|
9521
9800
|
|
|
9522
9801
|
// src/index.ts
|
|
9523
9802
|
init_errors();
|
|
9524
|
-
var VERSION = "0.
|
|
9803
|
+
var VERSION = "0.7.0";
|
|
9525
9804
|
/*! Bundled license information:
|
|
9526
9805
|
|
|
9527
9806
|
pvtsutils/build/index.es.js:
|
|
@@ -9591,6 +9870,6 @@ asn1js/build/index.es.js:
|
|
|
9591
9870
|
*)
|
|
9592
9871
|
*/
|
|
9593
9872
|
|
|
9594
|
-
export { CertificateChainError, CompositeTrustStore, ExpiredCredentialError, HAIP_DOCTYPE_NAMESPACES, HaipValidationError, InMemoryCache, InvalidSignatureError, LotlFetchError, LotlSignatureError, LotlTrustStore, MalformedCredentialError, MdocParser, NonceValidationError, OpenID4VPError, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, StaticTrustStore, TrustAnchorNotFoundError, UnsupportedFormatError, VERSION, buildHaipQuery, createAuthorizationRequest, isHaipQuery, parsePresentation, validateHaipQuery, verifyPresentation };
|
|
9873
|
+
export { CertificateChainError, CompositeTrustStore, DecryptionFailedError, ExpiredCredentialError, HAIP_DOCTYPE_NAMESPACES, HaipValidationError, InMemoryCache, InvalidSignatureError, LotlFetchError, LotlSignatureError, LotlTrustStore, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, SignedRequestBuildError, StaticTrustStore, TrustAnchorNotFoundError, UnsupportedFormatError, UnsupportedJweError, VERSION, buildHaipQuery, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
|
|
9595
9874
|
//# sourceMappingURL=index.js.map
|
|
9596
9875
|
//# sourceMappingURL=index.js.map
|