@openeudi/openid4vp 0.11.1 → 0.13.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 +140 -4
- package/dist/index.cjs +742 -113
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +165 -8
- package/dist/index.d.ts +165 -8
- package/dist/index.js +741 -115
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
-
import { X509Certificate, SubjectKeyIdentifierExtension,
|
|
2
|
+
import { X509Certificate, SubjectKeyIdentifierExtension, BasicConstraintsExtension, KeyUsagesExtension, KeyUsageFlags as KeyUsageFlags$1, ExtendedKeyUsageExtension, AuthorityKeyIdentifierExtension, SubjectAlternativeNameExtension, Name as Name$1 } from '@peculiar/x509';
|
|
3
3
|
import { v4 } from 'uuid';
|
|
4
4
|
import { SignJWT, importX509, decodeProtectedHeader, jwtVerify, importJWK, compactDecrypt } from 'jose';
|
|
5
5
|
import { Encoder, Tag } from 'cbor-x';
|
|
@@ -24,7 +24,7 @@ var init_reflect_polyfill = __esm({
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
// src/errors.ts
|
|
27
|
-
var InvalidSignatureError, ExpiredCredentialError, UnsupportedFormatError, MalformedCredentialError, NonceValidationError, HaipValidationError, OpenID4VPError, TrustAnchorNotFoundError, CertificateChainError, RevokedCertificateError, RevocationCheckFailedError, LotlFetchError, LotlSignatureError, SignedRequestBuildError, UnsupportedJweError, DecryptionFailedError, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError;
|
|
27
|
+
var InvalidSignatureError, ExpiredCredentialError, UnsupportedFormatError, MalformedCredentialError, NonceValidationError, HaipValidationError, OpenID4VPError, TrustAnchorNotFoundError, CertificateChainError, RevokedCertificateError, RevocationCheckFailedError, LotlFetchError, LotlSignatureError, LotlConfigurationError, SignedRequestBuildError, UnsupportedJweError, DecryptionFailedError, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, GuardedFetchError;
|
|
28
28
|
var init_errors = __esm({
|
|
29
29
|
"src/errors.ts"() {
|
|
30
30
|
init_reflect_polyfill();
|
|
@@ -121,6 +121,9 @@ var init_errors = __esm({
|
|
|
121
121
|
LotlSignatureError = class extends OpenID4VPError {
|
|
122
122
|
code = "lotl_signature_invalid";
|
|
123
123
|
};
|
|
124
|
+
LotlConfigurationError = class extends OpenID4VPError {
|
|
125
|
+
code = "lotl_configuration_invalid";
|
|
126
|
+
};
|
|
124
127
|
SignedRequestBuildError = class extends OpenID4VPError {
|
|
125
128
|
code;
|
|
126
129
|
constructor(code, message) {
|
|
@@ -168,6 +171,16 @@ var init_errors = __esm({
|
|
|
168
171
|
this.presentationCount = presentationCount;
|
|
169
172
|
}
|
|
170
173
|
};
|
|
174
|
+
GuardedFetchError = class extends OpenID4VPError {
|
|
175
|
+
code = "guarded_fetch_rejected";
|
|
176
|
+
reason;
|
|
177
|
+
url;
|
|
178
|
+
constructor(reason, message, options) {
|
|
179
|
+
super(message, { cause: options.cause });
|
|
180
|
+
this.reason = reason;
|
|
181
|
+
this.url = options.url;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
171
184
|
}
|
|
172
185
|
});
|
|
173
186
|
|
|
@@ -6564,7 +6577,7 @@ function dnIsUnder(childDn, subtreeDn) {
|
|
|
6564
6577
|
}
|
|
6565
6578
|
return true;
|
|
6566
6579
|
}
|
|
6567
|
-
var NAME_CONSTRAINTS_OID, DEFAULT_ALGORITHMS, ChainBuilder;
|
|
6580
|
+
var NAME_CONSTRAINTS_OID, ISO_18013_5_DS_EKU, DEFAULT_MAX_CHAIN_LENGTH, DEFAULT_MAX_SIGNATURE_CHECKS, searchAborts, DEFAULT_ALGORITHMS, ChainBuilder;
|
|
6568
6581
|
var init_ChainBuilder = __esm({
|
|
6569
6582
|
"src/trust/ChainBuilder.ts"() {
|
|
6570
6583
|
init_reflect_polyfill();
|
|
@@ -6573,6 +6586,10 @@ var init_ChainBuilder = __esm({
|
|
|
6573
6586
|
init_errors();
|
|
6574
6587
|
init_x509_utils();
|
|
6575
6588
|
NAME_CONSTRAINTS_OID = "2.5.29.30";
|
|
6589
|
+
ISO_18013_5_DS_EKU = "1.0.18013.5.1.2";
|
|
6590
|
+
DEFAULT_MAX_CHAIN_LENGTH = 5;
|
|
6591
|
+
DEFAULT_MAX_SIGNATURE_CHECKS = 32;
|
|
6592
|
+
searchAborts = /* @__PURE__ */ new WeakSet();
|
|
6576
6593
|
DEFAULT_ALGORITHMS = [
|
|
6577
6594
|
"ES256",
|
|
6578
6595
|
"ES384",
|
|
@@ -6595,62 +6612,130 @@ var init_ChainBuilder = __esm({
|
|
|
6595
6612
|
* optionally using additional intermediates. Returns the ordered chain
|
|
6596
6613
|
* (leaf → anchor). Throws `CertificateChainError` on any validation
|
|
6597
6614
|
* failure.
|
|
6615
|
+
*
|
|
6616
|
+
* Trust is by presence in the anchor set and is established ONLY by (a) the
|
|
6617
|
+
* leaf being byte-identical to an anchor, or (b) a verified signature by an
|
|
6618
|
+
* anchor's key on the last certificate of the path. Subject/Issuer DN
|
|
6619
|
+
* equality is used to select candidates, never to conclude trust
|
|
6620
|
+
* (GHSA-4c2f-96cf-f5fc).
|
|
6621
|
+
*
|
|
6622
|
+
* The search is depth-first and backtracks: when several intermediates share
|
|
6623
|
+
* a Subject DN — a re-issued certificate next to its expired predecessor, or
|
|
6624
|
+
* cross-signed copies under different roots — a candidate that fails a check
|
|
6625
|
+
* or leads nowhere does not end the search. The result therefore does not
|
|
6626
|
+
* depend on the order of `intermediates`. Work is bounded by
|
|
6627
|
+
* `maxChainLength` and `maxSignatureChecks`.
|
|
6598
6628
|
*/
|
|
6599
|
-
async build(leaf, anchors, intermediates = []) {
|
|
6600
|
-
const
|
|
6629
|
+
async build(leaf, anchors, intermediates = [], context = {}) {
|
|
6630
|
+
const search = {
|
|
6631
|
+
remaining: this.opts.maxSignatureChecks ?? DEFAULT_MAX_SIGNATURE_CHECKS
|
|
6632
|
+
};
|
|
6633
|
+
let lastFailure;
|
|
6601
6634
|
for (const anchor of anchors) {
|
|
6635
|
+
search.specific = void 0;
|
|
6636
|
+
search.fallback = void 0;
|
|
6602
6637
|
try {
|
|
6603
|
-
|
|
6638
|
+
const chain = await this.tryBuild(leaf, anchor, intermediates, context, search);
|
|
6639
|
+
if (chain) return chain;
|
|
6640
|
+
lastFailure = search.specific ?? search.fallback;
|
|
6604
6641
|
} catch (err) {
|
|
6605
|
-
|
|
6642
|
+
if (searchAborts.has(err)) throw err;
|
|
6643
|
+
lastFailure = err;
|
|
6606
6644
|
}
|
|
6607
6645
|
}
|
|
6608
|
-
|
|
6609
|
-
if (last instanceof CertificateChainError) throw last;
|
|
6646
|
+
if (lastFailure instanceof CertificateChainError) throw lastFailure;
|
|
6610
6647
|
throw new CertificateChainError("no valid chain to any anchor", {
|
|
6611
6648
|
reason: "signature",
|
|
6612
|
-
cause:
|
|
6649
|
+
cause: lastFailure
|
|
6613
6650
|
});
|
|
6614
6651
|
}
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
this.
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6652
|
+
/** Search for a path from `leaf` that closes at `anchor`. */
|
|
6653
|
+
async tryBuild(leaf, anchor, intermediates, context, search) {
|
|
6654
|
+
this.checkPerCert(leaf, context);
|
|
6655
|
+
if (certificatesEqual(leaf, anchor)) {
|
|
6656
|
+
this.checkLeafKeyUsage(leaf, "generic");
|
|
6657
|
+
return [leaf];
|
|
6658
|
+
}
|
|
6659
|
+
const profile = this.opts.profile ?? "generic";
|
|
6660
|
+
this.checkLeafKeyUsage(leaf, profile);
|
|
6661
|
+
this.checkLeafExtendedKeyUsage(leaf, profile);
|
|
6662
|
+
const pool = intermediates.filter(
|
|
6663
|
+
(c) => !certificatesEqual(c, anchor) && !certificatesEqual(c, leaf)
|
|
6664
|
+
);
|
|
6665
|
+
return this.extendPath([leaf], anchor, pool, context, search);
|
|
6666
|
+
}
|
|
6667
|
+
/**
|
|
6668
|
+
* Try to complete `chain` (leaf first) to `anchor`. Returns the completed
|
|
6669
|
+
* chain, or `undefined` when no extension of this prefix works — failures
|
|
6670
|
+
* are recorded on `search` so the caller can report the most specific one.
|
|
6671
|
+
* Throws only to abandon the whole search (signature budget exhausted).
|
|
6672
|
+
*/
|
|
6673
|
+
async extendPath(chain, anchor, pool, context, search) {
|
|
6674
|
+
const leaf = chain[0];
|
|
6675
|
+
const current = chain[chain.length - 1];
|
|
6676
|
+
const maxLength = this.opts.maxChainLength ?? DEFAULT_MAX_CHAIN_LENGTH;
|
|
6677
|
+
if (chain.length + 1 > maxLength) {
|
|
6678
|
+
search.specific = new CertificateChainError(
|
|
6679
|
+
`chain from ${leaf.subject} exceeds the maximum length of ${maxLength} certificates`,
|
|
6680
|
+
{ reason: "path_length" }
|
|
6681
|
+
);
|
|
6682
|
+
return void 0;
|
|
6683
|
+
}
|
|
6684
|
+
const nonLeafDepth = chain.length - 1;
|
|
6685
|
+
if (current.issuer === anchor.subject) {
|
|
6686
|
+
try {
|
|
6687
|
+
await this.closeAtAnchor(current, anchor, nonLeafDepth, context, search);
|
|
6688
|
+
const closed = [...chain, anchor];
|
|
6689
|
+
this.checkNameConstraints(leaf, closed.slice(1));
|
|
6690
|
+
return closed;
|
|
6691
|
+
} catch (err) {
|
|
6692
|
+
if (searchAborts.has(err)) throw err;
|
|
6693
|
+
search.specific = err;
|
|
6637
6694
|
}
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6695
|
+
}
|
|
6696
|
+
const candidates = pool.filter(
|
|
6697
|
+
(c) => c.subject === current.issuer && !chain.some((x) => certificatesEqual(x, c))
|
|
6698
|
+
);
|
|
6699
|
+
let verified = 0;
|
|
6700
|
+
for (const candidate of candidates) {
|
|
6701
|
+
if (!await this.signatureVerifies(current, candidate, search)) continue;
|
|
6702
|
+
verified++;
|
|
6703
|
+
try {
|
|
6704
|
+
this.checkPerCert(candidate, context);
|
|
6705
|
+
this.checkCaAndPathLen(candidate, nonLeafDepth);
|
|
6706
|
+
this.checkAkiSkiMatch(current, candidate);
|
|
6707
|
+
} catch (err) {
|
|
6708
|
+
search.specific = err;
|
|
6709
|
+
continue;
|
|
6710
|
+
}
|
|
6711
|
+
const found = await this.extendPath([...chain, candidate], anchor, pool, context, search);
|
|
6712
|
+
if (found) return found;
|
|
6713
|
+
}
|
|
6714
|
+
search.fallback = new CertificateChainError(
|
|
6715
|
+
candidates.length > 0 && verified === 0 ? `signature verification failed for ${current.subject}` : `no issuer certificate found for ${current.subject}`,
|
|
6716
|
+
{ reason: "signature" }
|
|
6717
|
+
);
|
|
6718
|
+
return void 0;
|
|
6719
|
+
}
|
|
6720
|
+
async closeAtAnchor(current, anchor, nonLeafDepth, context, search) {
|
|
6721
|
+
this.checkPerCert(anchor, context);
|
|
6722
|
+
this.checkCaAndPathLen(anchor, nonLeafDepth);
|
|
6723
|
+
this.checkAkiSkiMatch(current, anchor);
|
|
6724
|
+
this.spendSignatureCheck(search);
|
|
6725
|
+
await this.verifySignature(current, anchor);
|
|
6726
|
+
}
|
|
6727
|
+
/** Charge one signature verification to the search, or abandon it. */
|
|
6728
|
+
spendSignatureCheck(search) {
|
|
6729
|
+
if (search.remaining <= 0) {
|
|
6730
|
+
const limit = this.opts.maxSignatureChecks ?? DEFAULT_MAX_SIGNATURE_CHECKS;
|
|
6731
|
+
const err = new CertificateChainError(
|
|
6732
|
+
`certificate path search exceeded ${limit} signature checks`,
|
|
6733
|
+
{ reason: "path_length" }
|
|
6650
6734
|
);
|
|
6735
|
+
searchAborts.add(err);
|
|
6736
|
+
throw err;
|
|
6651
6737
|
}
|
|
6652
|
-
|
|
6653
|
-
return chain;
|
|
6738
|
+
search.remaining--;
|
|
6654
6739
|
}
|
|
6655
6740
|
/**
|
|
6656
6741
|
* Enforce nameConstraints asserted by any CA above the leaf against the
|
|
@@ -6699,7 +6784,7 @@ var init_ChainBuilder = __esm({
|
|
|
6699
6784
|
}
|
|
6700
6785
|
}
|
|
6701
6786
|
checkCaAndPathLen(cert, nonLeafDepth) {
|
|
6702
|
-
this.checkCaKeyUsage(cert);
|
|
6787
|
+
this.checkCaKeyUsage(cert, this.opts.profile ?? "generic");
|
|
6703
6788
|
const bc = cert.getExtension(BasicConstraintsExtension);
|
|
6704
6789
|
if (!bc || !bc.ca) {
|
|
6705
6790
|
throw new CertificateChainError(
|
|
@@ -6714,9 +6799,17 @@ var init_ChainBuilder = __esm({
|
|
|
6714
6799
|
);
|
|
6715
6800
|
}
|
|
6716
6801
|
}
|
|
6717
|
-
checkLeafKeyUsage(leaf) {
|
|
6802
|
+
checkLeafKeyUsage(leaf, profile) {
|
|
6718
6803
|
const ext = leaf.getExtension(KeyUsagesExtension);
|
|
6719
|
-
if (!ext)
|
|
6804
|
+
if (!ext) {
|
|
6805
|
+
if (profile === "iso18013-5") {
|
|
6806
|
+
throw new CertificateChainError(
|
|
6807
|
+
`document signer ${leaf.subject} has no keyUsage extension (ISO 18013-5 requires digitalSignature)`,
|
|
6808
|
+
{ reason: "key_usage" }
|
|
6809
|
+
);
|
|
6810
|
+
}
|
|
6811
|
+
return;
|
|
6812
|
+
}
|
|
6720
6813
|
if ((ext.usages & KeyUsageFlags$1.digitalSignature) === 0) {
|
|
6721
6814
|
throw new CertificateChainError(
|
|
6722
6815
|
`leaf ${leaf.subject} does not assert digitalSignature key usage`,
|
|
@@ -6724,9 +6817,28 @@ var init_ChainBuilder = __esm({
|
|
|
6724
6817
|
);
|
|
6725
6818
|
}
|
|
6726
6819
|
}
|
|
6727
|
-
|
|
6820
|
+
checkLeafExtendedKeyUsage(leaf, profile) {
|
|
6821
|
+
if (profile !== "iso18013-5") return;
|
|
6822
|
+
const ext = leaf.getExtension(ExtendedKeyUsageExtension);
|
|
6823
|
+
const usages = (ext?.usages ?? []).map(String);
|
|
6824
|
+
if (!usages.includes(ISO_18013_5_DS_EKU)) {
|
|
6825
|
+
throw new CertificateChainError(
|
|
6826
|
+
`document signer ${leaf.subject} lacks extended key usage ${ISO_18013_5_DS_EKU} (id-mdl-kp-mdlDS)`,
|
|
6827
|
+
{ reason: "extended_key_usage" }
|
|
6828
|
+
);
|
|
6829
|
+
}
|
|
6830
|
+
}
|
|
6831
|
+
checkCaKeyUsage(cert, profile) {
|
|
6728
6832
|
const ext = cert.getExtension(KeyUsagesExtension);
|
|
6729
|
-
if (!ext)
|
|
6833
|
+
if (!ext) {
|
|
6834
|
+
if (profile === "iso18013-5") {
|
|
6835
|
+
throw new CertificateChainError(
|
|
6836
|
+
`CA ${cert.subject} has no keyUsage extension (ISO 18013-5 requires keyCertSign)`,
|
|
6837
|
+
{ reason: "key_usage" }
|
|
6838
|
+
);
|
|
6839
|
+
}
|
|
6840
|
+
return;
|
|
6841
|
+
}
|
|
6730
6842
|
if ((ext.usages & KeyUsageFlags$1.keyCertSign) === 0) {
|
|
6731
6843
|
throw new CertificateChainError(
|
|
6732
6844
|
`CA ${cert.subject} does not assert keyCertSign key usage`,
|
|
@@ -6747,30 +6859,46 @@ var init_ChainBuilder = __esm({
|
|
|
6747
6859
|
);
|
|
6748
6860
|
}
|
|
6749
6861
|
}
|
|
6862
|
+
/**
|
|
6863
|
+
* Signature check used to select among DN-matching candidates. Never throws
|
|
6864
|
+
* on a bad signature; throws only when the search budget is exhausted.
|
|
6865
|
+
*/
|
|
6866
|
+
async signatureVerifies(child, issuer, search) {
|
|
6867
|
+
this.spendSignatureCheck(search);
|
|
6868
|
+
try {
|
|
6869
|
+
return await child.verify({ publicKey: issuer.publicKey, signatureOnly: true });
|
|
6870
|
+
} catch {
|
|
6871
|
+
return false;
|
|
6872
|
+
}
|
|
6873
|
+
}
|
|
6750
6874
|
async verifySignature(child, issuer) {
|
|
6751
6875
|
const ok = await child.verify({ publicKey: issuer.publicKey, signatureOnly: true });
|
|
6752
6876
|
if (!ok) {
|
|
6753
6877
|
throw new CertificateChainError(`signature verification failed for ${child.subject}`, { reason: "signature" });
|
|
6754
6878
|
}
|
|
6755
6879
|
}
|
|
6756
|
-
checkPerCert(cert) {
|
|
6757
|
-
this.
|
|
6880
|
+
checkPerCert(cert, context = {}) {
|
|
6881
|
+
const now = (this.opts.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
6882
|
+
this.checkValidity(cert, now, "");
|
|
6883
|
+
if (context.issuedAt) {
|
|
6884
|
+
this.checkValidity(cert, context.issuedAt, ` at issuance time ${context.issuedAt.toISOString()}`);
|
|
6885
|
+
}
|
|
6758
6886
|
this.checkAlgorithm(cert);
|
|
6759
6887
|
}
|
|
6760
|
-
checkValidity(cert) {
|
|
6761
|
-
const
|
|
6888
|
+
checkValidity(cert, at, label) {
|
|
6889
|
+
const time = at.getTime();
|
|
6762
6890
|
const skewMs = (this.opts.clockSkewTolerance ?? 60) * 1e3;
|
|
6763
6891
|
const notBefore = cert.notBefore.getTime();
|
|
6764
6892
|
const notAfter = cert.notAfter.getTime();
|
|
6765
|
-
if (
|
|
6893
|
+
if (time + skewMs < notBefore) {
|
|
6766
6894
|
throw new CertificateChainError(
|
|
6767
|
-
`certificate ${cert.subject} not yet valid (notBefore=${cert.notBefore.toISOString()})`,
|
|
6895
|
+
`certificate ${cert.subject} not yet valid${label} (notBefore=${cert.notBefore.toISOString()})`,
|
|
6768
6896
|
{ reason: "validity" }
|
|
6769
6897
|
);
|
|
6770
6898
|
}
|
|
6771
|
-
if (
|
|
6899
|
+
if (time - skewMs > notAfter) {
|
|
6772
6900
|
throw new CertificateChainError(
|
|
6773
|
-
`certificate ${cert.subject} expired (notAfter=${cert.notAfter.toISOString()})`,
|
|
6901
|
+
`certificate ${cert.subject} expired${label} (notAfter=${cert.notAfter.toISOString()})`,
|
|
6774
6902
|
{ reason: "validity" }
|
|
6775
6903
|
);
|
|
6776
6904
|
}
|
|
@@ -6817,6 +6945,349 @@ var init_ecdsa_util = __esm({
|
|
|
6817
6945
|
}
|
|
6818
6946
|
});
|
|
6819
6947
|
|
|
6948
|
+
// src/http/ip-address.ts
|
|
6949
|
+
function parseIPv4(input) {
|
|
6950
|
+
const parts = input.split(".");
|
|
6951
|
+
if (parts.length !== 4) return void 0;
|
|
6952
|
+
const bytes = [];
|
|
6953
|
+
for (const part of parts) {
|
|
6954
|
+
if (!/^\d{1,3}$/.test(part)) return void 0;
|
|
6955
|
+
const value = Number(part);
|
|
6956
|
+
if (value > 255) return void 0;
|
|
6957
|
+
bytes.push(value);
|
|
6958
|
+
}
|
|
6959
|
+
return bytes;
|
|
6960
|
+
}
|
|
6961
|
+
function parseIPv6(input) {
|
|
6962
|
+
const address = input.split("%")[0];
|
|
6963
|
+
if (!address.includes(":")) return void 0;
|
|
6964
|
+
let head = address;
|
|
6965
|
+
let embeddedV4;
|
|
6966
|
+
const lastColon = address.lastIndexOf(":");
|
|
6967
|
+
const tail = address.slice(lastColon + 1);
|
|
6968
|
+
if (tail.includes(".")) {
|
|
6969
|
+
embeddedV4 = parseIPv4(tail);
|
|
6970
|
+
if (!embeddedV4) return void 0;
|
|
6971
|
+
head = address.slice(0, lastColon + 1) + "0:0";
|
|
6972
|
+
}
|
|
6973
|
+
const doubleColon = head.split("::");
|
|
6974
|
+
if (doubleColon.length > 2) return void 0;
|
|
6975
|
+
const toGroups = (s) => s === "" ? [] : s.split(":");
|
|
6976
|
+
const left = toGroups(doubleColon[0]);
|
|
6977
|
+
const right = doubleColon.length === 2 ? toGroups(doubleColon[1]) : [];
|
|
6978
|
+
const missing = 8 - left.length - right.length;
|
|
6979
|
+
if (doubleColon.length === 2 ? missing < 1 : missing !== 0) return void 0;
|
|
6980
|
+
const groups = [...left, ...Array(doubleColon.length === 2 ? missing : 0).fill("0"), ...right];
|
|
6981
|
+
const bytes = [];
|
|
6982
|
+
for (const group of groups) {
|
|
6983
|
+
if (!/^[0-9a-fA-F]{1,4}$/.test(group)) return void 0;
|
|
6984
|
+
const value = parseInt(group, 16);
|
|
6985
|
+
bytes.push(value >> 8, value & 255);
|
|
6986
|
+
}
|
|
6987
|
+
if (embeddedV4) bytes.splice(12, 4, ...embeddedV4);
|
|
6988
|
+
return bytes;
|
|
6989
|
+
}
|
|
6990
|
+
function inPrefix(bytes, prefix, bits) {
|
|
6991
|
+
for (let i = 0; i < bits; i++) {
|
|
6992
|
+
const byte = i >> 3;
|
|
6993
|
+
const mask = 128 >> (i & 7);
|
|
6994
|
+
if ((bytes[byte] & mask) !== ((prefix[byte] ?? 0) & mask)) return false;
|
|
6995
|
+
}
|
|
6996
|
+
return true;
|
|
6997
|
+
}
|
|
6998
|
+
function isPublicV4(bytes) {
|
|
6999
|
+
return !BLOCKED_V4.some(([prefix, bits]) => inPrefix(bytes, prefix, bits));
|
|
7000
|
+
}
|
|
7001
|
+
function isPublicV6(bytes) {
|
|
7002
|
+
const first10Zero = bytes.slice(0, 10).every((b) => b === 0);
|
|
7003
|
+
if (first10Zero && bytes[10] === 0 && bytes[11] === 0) {
|
|
7004
|
+
const v4 = bytes.slice(12);
|
|
7005
|
+
if (v4.slice(0, 3).every((b) => b === 0)) return false;
|
|
7006
|
+
return isPublicV4(v4);
|
|
7007
|
+
}
|
|
7008
|
+
if (first10Zero && bytes[10] === 255 && bytes[11] === 255) return isPublicV4(bytes.slice(12));
|
|
7009
|
+
if (inPrefix(bytes, [0, 100, 255, 155], 96)) return isPublicV4(bytes.slice(12));
|
|
7010
|
+
if (inPrefix(bytes, [32, 2], 16)) return isPublicV4(bytes.slice(2, 6));
|
|
7011
|
+
return !BLOCKED_V6.some(([prefix, bits]) => inPrefix(bytes, prefix, bits));
|
|
7012
|
+
}
|
|
7013
|
+
function isPublicIpAddress(ip) {
|
|
7014
|
+
const v4 = parseIPv4(ip);
|
|
7015
|
+
if (v4) return isPublicV4(v4);
|
|
7016
|
+
const v6 = parseIPv6(ip);
|
|
7017
|
+
if (v6) return isPublicV6(v6);
|
|
7018
|
+
return false;
|
|
7019
|
+
}
|
|
7020
|
+
function isIpLiteral(host) {
|
|
7021
|
+
return parseIPv4(host) !== void 0 || parseIPv6(host) !== void 0;
|
|
7022
|
+
}
|
|
7023
|
+
var BLOCKED_V4, BLOCKED_V6;
|
|
7024
|
+
var init_ip_address = __esm({
|
|
7025
|
+
"src/http/ip-address.ts"() {
|
|
7026
|
+
init_reflect_polyfill();
|
|
7027
|
+
BLOCKED_V4 = [
|
|
7028
|
+
[[0, 0, 0, 0], 8],
|
|
7029
|
+
[[10, 0, 0, 0], 8],
|
|
7030
|
+
[[100, 64, 0, 0], 10],
|
|
7031
|
+
[[127, 0, 0, 0], 8],
|
|
7032
|
+
[[169, 254, 0, 0], 16],
|
|
7033
|
+
[[172, 16, 0, 0], 12],
|
|
7034
|
+
[[192, 0, 0, 0], 24],
|
|
7035
|
+
[[192, 0, 2, 0], 24],
|
|
7036
|
+
[[192, 88, 99, 0], 24],
|
|
7037
|
+
[[192, 168, 0, 0], 16],
|
|
7038
|
+
[[198, 18, 0, 0], 15],
|
|
7039
|
+
[[198, 51, 100, 0], 24],
|
|
7040
|
+
[[203, 0, 113, 0], 24],
|
|
7041
|
+
[[224, 0, 0, 0], 4],
|
|
7042
|
+
[[240, 0, 0, 0], 4]
|
|
7043
|
+
];
|
|
7044
|
+
BLOCKED_V6 = [
|
|
7045
|
+
[[1, 0], 64],
|
|
7046
|
+
// 100::/64 discard-only
|
|
7047
|
+
[[32, 1, 0, 0], 32],
|
|
7048
|
+
// 2001::/32 Teredo (embeds an obfuscated IPv4)
|
|
7049
|
+
[[32, 1, 13, 184], 32],
|
|
7050
|
+
// 2001:db8::/32 documentation
|
|
7051
|
+
[[252], 7],
|
|
7052
|
+
// fc00::/7 unique local (incl. fd00:ec2::254 metadata)
|
|
7053
|
+
[[254, 128], 10],
|
|
7054
|
+
// fe80::/10 link-local
|
|
7055
|
+
[[254, 192], 10],
|
|
7056
|
+
// fec0::/10 deprecated site-local
|
|
7057
|
+
[[255], 8]
|
|
7058
|
+
// ff00::/8 multicast
|
|
7059
|
+
];
|
|
7060
|
+
}
|
|
7061
|
+
});
|
|
7062
|
+
|
|
7063
|
+
// src/http/guarded-fetch.ts
|
|
7064
|
+
function loadDns() {
|
|
7065
|
+
dnsModule ??= (async () => {
|
|
7066
|
+
try {
|
|
7067
|
+
const specifier = "node:dns";
|
|
7068
|
+
const mod = await import(
|
|
7069
|
+
/* webpackIgnore: true */
|
|
7070
|
+
/* @vite-ignore */
|
|
7071
|
+
specifier
|
|
7072
|
+
);
|
|
7073
|
+
return mod.promises ?? mod.default?.promises;
|
|
7074
|
+
} catch {
|
|
7075
|
+
return void 0;
|
|
7076
|
+
}
|
|
7077
|
+
})();
|
|
7078
|
+
return dnsModule;
|
|
7079
|
+
}
|
|
7080
|
+
function toError(err) {
|
|
7081
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
7082
|
+
}
|
|
7083
|
+
function createGuardedFetcher(options = {}) {
|
|
7084
|
+
const allowHttp = options.allowHttp ?? false;
|
|
7085
|
+
const allowPrivate = options.allowPrivateNetworks ?? false;
|
|
7086
|
+
const maxRedirects = options.maxRedirects ?? GUARDED_FETCH_DEFAULTS.maxRedirects;
|
|
7087
|
+
const timeoutMs = options.timeoutMs ?? GUARDED_FETCH_DEFAULTS.timeoutMs;
|
|
7088
|
+
const maxBytes = options.maxResponseBytes ?? GUARDED_FETCH_DEFAULTS.maxResponseBytes;
|
|
7089
|
+
const lookup = options.lookup ?? defaultLookup;
|
|
7090
|
+
const transport = options.fetch ?? ((url, init) => globalThis.fetch(url, init));
|
|
7091
|
+
return async (input, init = {}) => {
|
|
7092
|
+
const controller = new AbortController();
|
|
7093
|
+
const timer = setTimeout(() => {
|
|
7094
|
+
controller.abort(
|
|
7095
|
+
new GuardedFetchError("timeout", `request to ${input} exceeded ${timeoutMs} ms`, { url: input })
|
|
7096
|
+
);
|
|
7097
|
+
}, timeoutMs);
|
|
7098
|
+
const callerSignal = init.signal ?? void 0;
|
|
7099
|
+
const onCallerAbort = () => controller.abort(callerSignal?.reason);
|
|
7100
|
+
if (callerSignal?.aborted) onCallerAbort();
|
|
7101
|
+
else callerSignal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
7102
|
+
const aborted = new Promise((_, reject) => {
|
|
7103
|
+
const fail = () => reject(toError(controller.signal.reason));
|
|
7104
|
+
if (controller.signal.aborted) fail();
|
|
7105
|
+
else controller.signal.addEventListener("abort", fail, { once: true });
|
|
7106
|
+
});
|
|
7107
|
+
aborted.catch(() => {
|
|
7108
|
+
});
|
|
7109
|
+
const race = (p) => Promise.race([p, aborted]);
|
|
7110
|
+
try {
|
|
7111
|
+
let url = await race(validateTarget(input, void 0));
|
|
7112
|
+
let method = (init.method ?? "GET").toUpperCase();
|
|
7113
|
+
let body = init.body;
|
|
7114
|
+
const headers = new Headers(init.headers);
|
|
7115
|
+
for (let hop = 0; ; hop++) {
|
|
7116
|
+
const response = await race(
|
|
7117
|
+
transport(url.href, { ...init, method, body, headers, redirect: "manual", signal: controller.signal })
|
|
7118
|
+
);
|
|
7119
|
+
if (response.type === "opaqueredirect") {
|
|
7120
|
+
throw new GuardedFetchError(
|
|
7121
|
+
"invalid_redirect",
|
|
7122
|
+
`redirect from ${url.href} cannot be inspected by this transport`,
|
|
7123
|
+
{ url: url.href }
|
|
7124
|
+
);
|
|
7125
|
+
}
|
|
7126
|
+
if (!REDIRECT_STATUSES.has(response.status)) {
|
|
7127
|
+
const bytes = await readBounded(response, url.href, maxBytes, race);
|
|
7128
|
+
return new Response(NULL_BODY_STATUSES.has(response.status) ? null : bytes, {
|
|
7129
|
+
status: response.status,
|
|
7130
|
+
statusText: response.statusText,
|
|
7131
|
+
headers: response.headers
|
|
7132
|
+
});
|
|
7133
|
+
}
|
|
7134
|
+
await response.body?.cancel().catch(() => {
|
|
7135
|
+
});
|
|
7136
|
+
if (hop >= maxRedirects) {
|
|
7137
|
+
throw new GuardedFetchError(
|
|
7138
|
+
"too_many_redirects",
|
|
7139
|
+
`more than ${maxRedirects} redirects starting at ${input}`,
|
|
7140
|
+
{ url: url.href }
|
|
7141
|
+
);
|
|
7142
|
+
}
|
|
7143
|
+
const location = response.headers.get("location");
|
|
7144
|
+
if (!location) {
|
|
7145
|
+
throw new GuardedFetchError(
|
|
7146
|
+
"invalid_redirect",
|
|
7147
|
+
`HTTP ${response.status} from ${url.href} has no Location header`,
|
|
7148
|
+
{ url: url.href }
|
|
7149
|
+
);
|
|
7150
|
+
}
|
|
7151
|
+
let next;
|
|
7152
|
+
try {
|
|
7153
|
+
next = new URL(location, url);
|
|
7154
|
+
} catch (err) {
|
|
7155
|
+
throw new GuardedFetchError("invalid_redirect", `unparseable Location from ${url.href}`, {
|
|
7156
|
+
url: url.href,
|
|
7157
|
+
cause: toError(err)
|
|
7158
|
+
});
|
|
7159
|
+
}
|
|
7160
|
+
const nextUrl = await race(validateTarget(next.href, url));
|
|
7161
|
+
if (response.status === 303 || (response.status === 301 || response.status === 302) && method === "POST") {
|
|
7162
|
+
if (method !== "HEAD") method = "GET";
|
|
7163
|
+
body = void 0;
|
|
7164
|
+
for (const h of BODY_HEADERS) headers.delete(h);
|
|
7165
|
+
}
|
|
7166
|
+
if (nextUrl.origin !== url.origin) {
|
|
7167
|
+
for (const h of CROSS_ORIGIN_STRIPPED_HEADERS) headers.delete(h);
|
|
7168
|
+
}
|
|
7169
|
+
url = nextUrl;
|
|
7170
|
+
}
|
|
7171
|
+
} catch (err) {
|
|
7172
|
+
if (controller.signal.aborted) throw toError(controller.signal.reason);
|
|
7173
|
+
throw err;
|
|
7174
|
+
} finally {
|
|
7175
|
+
clearTimeout(timer);
|
|
7176
|
+
callerSignal?.removeEventListener("abort", onCallerAbort);
|
|
7177
|
+
}
|
|
7178
|
+
};
|
|
7179
|
+
async function validateTarget(raw, previous) {
|
|
7180
|
+
let url;
|
|
7181
|
+
try {
|
|
7182
|
+
url = new URL(raw);
|
|
7183
|
+
} catch (err) {
|
|
7184
|
+
throw new GuardedFetchError("invalid_url", `not an absolute URL: ${raw}`, { url: raw, cause: toError(err) });
|
|
7185
|
+
}
|
|
7186
|
+
if (url.protocol !== "https:" && !(allowHttp && url.protocol === "http:")) {
|
|
7187
|
+
throw new GuardedFetchError("insecure_scheme", `refusing ${url.protocol} URL ${url.href}: HTTPS is required`, {
|
|
7188
|
+
url: url.href
|
|
7189
|
+
});
|
|
7190
|
+
}
|
|
7191
|
+
if (previous?.protocol === "https:" && url.protocol !== "https:") {
|
|
7192
|
+
throw new GuardedFetchError("insecure_scheme", `refusing https -> http redirect to ${url.href}`, {
|
|
7193
|
+
url: url.href
|
|
7194
|
+
});
|
|
7195
|
+
}
|
|
7196
|
+
if (allowPrivate) return url;
|
|
7197
|
+
const host = url.hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
7198
|
+
if (host === "localhost" || host.endsWith(".localhost")) {
|
|
7199
|
+
throw new GuardedFetchError("private_address", `refusing loopback host ${host}`, { url: url.href });
|
|
7200
|
+
}
|
|
7201
|
+
if (isIpLiteral(host)) {
|
|
7202
|
+
if (!isPublicIpAddress(host)) {
|
|
7203
|
+
throw new GuardedFetchError("private_address", `refusing non-public address ${host}`, { url: url.href });
|
|
7204
|
+
}
|
|
7205
|
+
return url;
|
|
7206
|
+
}
|
|
7207
|
+
let addresses;
|
|
7208
|
+
try {
|
|
7209
|
+
addresses = await lookup(host);
|
|
7210
|
+
} catch (err) {
|
|
7211
|
+
throw new GuardedFetchError("dns_resolution_failed", `could not resolve ${host}`, {
|
|
7212
|
+
url: url.href,
|
|
7213
|
+
cause: toError(err)
|
|
7214
|
+
});
|
|
7215
|
+
}
|
|
7216
|
+
if (addresses === void 0) return url;
|
|
7217
|
+
if (addresses.length === 0) {
|
|
7218
|
+
throw new GuardedFetchError("dns_resolution_failed", `${host} resolved to no addresses`, {
|
|
7219
|
+
url: url.href
|
|
7220
|
+
});
|
|
7221
|
+
}
|
|
7222
|
+
const blocked = addresses.find((a) => !isPublicIpAddress(a));
|
|
7223
|
+
if (blocked !== void 0) {
|
|
7224
|
+
throw new GuardedFetchError("private_address", `${host} resolves to non-public address ${blocked}`, {
|
|
7225
|
+
url: url.href
|
|
7226
|
+
});
|
|
7227
|
+
}
|
|
7228
|
+
return url;
|
|
7229
|
+
}
|
|
7230
|
+
}
|
|
7231
|
+
async function readBounded(response, url, maxBytes, race) {
|
|
7232
|
+
const tooLarge = () => new GuardedFetchError("response_too_large", `response from ${url} exceeds ${maxBytes} bytes`, { url });
|
|
7233
|
+
const declared = response.headers.get("content-length");
|
|
7234
|
+
if (declared !== null && Number(declared) > maxBytes) {
|
|
7235
|
+
await response.body?.cancel().catch(() => {
|
|
7236
|
+
});
|
|
7237
|
+
throw tooLarge();
|
|
7238
|
+
}
|
|
7239
|
+
if (!response.body) return null;
|
|
7240
|
+
const reader = response.body.getReader();
|
|
7241
|
+
const chunks = [];
|
|
7242
|
+
let total = 0;
|
|
7243
|
+
try {
|
|
7244
|
+
for (; ; ) {
|
|
7245
|
+
const { done, value } = await race(reader.read());
|
|
7246
|
+
if (done) break;
|
|
7247
|
+
total += value.byteLength;
|
|
7248
|
+
if (total > maxBytes) throw tooLarge();
|
|
7249
|
+
chunks.push(value);
|
|
7250
|
+
}
|
|
7251
|
+
} catch (err) {
|
|
7252
|
+
reader.cancel().catch(() => {
|
|
7253
|
+
});
|
|
7254
|
+
throw err;
|
|
7255
|
+
}
|
|
7256
|
+
const out = new Uint8Array(new ArrayBuffer(total));
|
|
7257
|
+
let offset = 0;
|
|
7258
|
+
for (const chunk of chunks) {
|
|
7259
|
+
out.set(chunk, offset);
|
|
7260
|
+
offset += chunk.byteLength;
|
|
7261
|
+
}
|
|
7262
|
+
return out;
|
|
7263
|
+
}
|
|
7264
|
+
function createDefaultTrustFetcher() {
|
|
7265
|
+
return createGuardedFetcher({ allowHttp: true });
|
|
7266
|
+
}
|
|
7267
|
+
var GUARDED_FETCH_DEFAULTS, REDIRECT_STATUSES, NULL_BODY_STATUSES, CROSS_ORIGIN_STRIPPED_HEADERS, BODY_HEADERS, dnsModule, defaultLookup;
|
|
7268
|
+
var init_guarded_fetch = __esm({
|
|
7269
|
+
"src/http/guarded-fetch.ts"() {
|
|
7270
|
+
init_reflect_polyfill();
|
|
7271
|
+
init_errors();
|
|
7272
|
+
init_ip_address();
|
|
7273
|
+
GUARDED_FETCH_DEFAULTS = {
|
|
7274
|
+
maxRedirects: 3,
|
|
7275
|
+
timeoutMs: 15e3,
|
|
7276
|
+
maxResponseBytes: 16 * 1024 * 1024
|
|
7277
|
+
};
|
|
7278
|
+
REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
7279
|
+
NULL_BODY_STATUSES = /* @__PURE__ */ new Set([101, 103, 204, 205, 304]);
|
|
7280
|
+
CROSS_ORIGIN_STRIPPED_HEADERS = ["authorization", "cookie", "proxy-authorization"];
|
|
7281
|
+
BODY_HEADERS = ["content-type", "content-length", "content-encoding", "content-language", "content-location"];
|
|
7282
|
+
defaultLookup = async (hostname) => {
|
|
7283
|
+
const dns = await loadDns();
|
|
7284
|
+
if (!dns) return void 0;
|
|
7285
|
+
const records = await dns.lookup(hostname, { all: true, verbatim: true });
|
|
7286
|
+
return records.map((r) => r.address);
|
|
7287
|
+
};
|
|
7288
|
+
}
|
|
7289
|
+
});
|
|
7290
|
+
|
|
6820
7291
|
// src/trust/CrlFetcher.ts
|
|
6821
7292
|
function normalizeCrl(parsed, der) {
|
|
6822
7293
|
const thisUpdate = parsed.tbsCertList.thisUpdate.getTime();
|
|
@@ -6852,11 +7323,12 @@ var init_CrlFetcher = __esm({
|
|
|
6852
7323
|
init_es2015();
|
|
6853
7324
|
init_es20152();
|
|
6854
7325
|
init_ecdsa_util();
|
|
7326
|
+
init_guarded_fetch();
|
|
6855
7327
|
CrlFetcher = class {
|
|
6856
7328
|
fetcher;
|
|
6857
7329
|
cache;
|
|
6858
7330
|
constructor(opts = {}) {
|
|
6859
|
-
this.fetcher = opts.fetcher ??
|
|
7331
|
+
this.fetcher = opts.fetcher ?? createDefaultTrustFetcher();
|
|
6860
7332
|
this.cache = opts.cache;
|
|
6861
7333
|
}
|
|
6862
7334
|
async fetchAndParse(url) {
|
|
@@ -7588,12 +8060,13 @@ var init_OcspClient = __esm({
|
|
|
7588
8060
|
init_es20152();
|
|
7589
8061
|
init_ChainBuilder();
|
|
7590
8062
|
init_ecdsa_util();
|
|
8063
|
+
init_guarded_fetch();
|
|
7591
8064
|
DEFAULT_MAX_RESPONSE_AGE_MS = 7 * 24 * 3600 * 1e3;
|
|
7592
8065
|
OcspClient = class {
|
|
7593
8066
|
fetcher;
|
|
7594
8067
|
cache;
|
|
7595
8068
|
constructor(opts = {}) {
|
|
7596
|
-
this.fetcher = opts.fetcher ??
|
|
8069
|
+
this.fetcher = opts.fetcher ?? createDefaultTrustFetcher();
|
|
7597
8070
|
this.cache = opts.cache;
|
|
7598
8071
|
}
|
|
7599
8072
|
/**
|
|
@@ -8059,7 +8532,9 @@ var init_ProvenanceResolver = __esm({
|
|
|
8059
8532
|
// src/trust/TrustEvaluator.ts
|
|
8060
8533
|
var TrustEvaluator_exports = {};
|
|
8061
8534
|
__export(TrustEvaluator_exports, {
|
|
8062
|
-
|
|
8535
|
+
MAX_CREDENTIAL_CERTIFICATES: () => MAX_CREDENTIAL_CERTIFICATES,
|
|
8536
|
+
TrustEvaluator: () => TrustEvaluator,
|
|
8537
|
+
evaluateCredentialIssuer: () => evaluateCredentialIssuer
|
|
8063
8538
|
});
|
|
8064
8539
|
function deriveHint(leaf) {
|
|
8065
8540
|
const aki = leaf.getExtension(AuthorityKeyIdentifierExtension);
|
|
@@ -8070,6 +8545,13 @@ function deriveHint(leaf) {
|
|
|
8070
8545
|
aki: akiBytes
|
|
8071
8546
|
};
|
|
8072
8547
|
}
|
|
8548
|
+
function deriveSelfHint(cert) {
|
|
8549
|
+
const skiHex = getSkiHex(cert);
|
|
8550
|
+
return {
|
|
8551
|
+
issuer: cert.subject,
|
|
8552
|
+
aki: skiHex ? hexToBytes(skiHex) : void 0
|
|
8553
|
+
};
|
|
8554
|
+
}
|
|
8073
8555
|
function hexToBytes(s) {
|
|
8074
8556
|
const clean = s.replace(/[^0-9a-f]/gi, "");
|
|
8075
8557
|
const out = new Uint8Array(clean.length / 2);
|
|
@@ -8101,7 +8583,31 @@ async function resolveProvenance(store, anchor) {
|
|
|
8101
8583
|
return void 0;
|
|
8102
8584
|
}
|
|
8103
8585
|
}
|
|
8104
|
-
|
|
8586
|
+
async function evaluateCredentialIssuer(input) {
|
|
8587
|
+
const [signerDer, ...rest] = input.chain;
|
|
8588
|
+
if (!signerDer) {
|
|
8589
|
+
throw new MalformedCredentialError("Missing issuer certificate");
|
|
8590
|
+
}
|
|
8591
|
+
if (input.chain.length > MAX_CREDENTIAL_CERTIFICATES) {
|
|
8592
|
+
throw new MalformedCredentialError(
|
|
8593
|
+
`x5c/x5chain carries ${input.chain.length} certificates; at most ${MAX_CREDENTIAL_CERTIFICATES} are accepted`
|
|
8594
|
+
);
|
|
8595
|
+
}
|
|
8596
|
+
const parse = (bytes, position) => {
|
|
8597
|
+
try {
|
|
8598
|
+
return new X509Certificate(bytes);
|
|
8599
|
+
} catch (err) {
|
|
8600
|
+
throw new MalformedCredentialError(
|
|
8601
|
+
`Invalid certificate at x5c/x5chain position ${position}: ${err.message}`
|
|
8602
|
+
);
|
|
8603
|
+
}
|
|
8604
|
+
};
|
|
8605
|
+
const leaf = parse(signerDer, 0);
|
|
8606
|
+
const intermediates = rest.map((bytes, i) => parse(bytes, i + 1));
|
|
8607
|
+
const { chain, issuedAt, ...evaluatorOptions } = input;
|
|
8608
|
+
return new TrustEvaluator(evaluatorOptions).evaluate(leaf, { intermediates, issuedAt });
|
|
8609
|
+
}
|
|
8610
|
+
var TrustEvaluator, MAX_CREDENTIAL_CERTIFICATES;
|
|
8105
8611
|
var init_TrustEvaluator = __esm({
|
|
8106
8612
|
"src/trust/TrustEvaluator.ts"() {
|
|
8107
8613
|
init_reflect_polyfill();
|
|
@@ -8127,13 +8633,10 @@ var init_TrustEvaluator = __esm({
|
|
|
8127
8633
|
revocationChecker;
|
|
8128
8634
|
async evaluate(leaf, context = {}) {
|
|
8129
8635
|
const hint = deriveHint(leaf);
|
|
8130
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8131
8636
|
const anchors = [];
|
|
8132
8637
|
const pushUnique = (batch) => {
|
|
8133
8638
|
for (const a of batch) {
|
|
8134
|
-
|
|
8135
|
-
if (seen.has(key)) continue;
|
|
8136
|
-
seen.add(key);
|
|
8639
|
+
if (anchors.some((x) => certificatesEqual(x.certificate, a.certificate))) continue;
|
|
8137
8640
|
anchors.push(a);
|
|
8138
8641
|
}
|
|
8139
8642
|
};
|
|
@@ -8141,6 +8644,7 @@ var init_TrustEvaluator = __esm({
|
|
|
8141
8644
|
for (const inter of context.intermediates ?? []) {
|
|
8142
8645
|
pushUnique(await this.trustStore.getAnchors(deriveHint(inter)));
|
|
8143
8646
|
}
|
|
8647
|
+
pushUnique(await this.trustStore.getAnchors(deriveSelfHint(leaf)));
|
|
8144
8648
|
if (anchors.length === 0) {
|
|
8145
8649
|
throw new TrustAnchorNotFoundError(
|
|
8146
8650
|
`no trust anchor for issuer=${hint.issuer ?? "(none)"}`
|
|
@@ -8150,7 +8654,8 @@ var init_TrustEvaluator = __esm({
|
|
|
8150
8654
|
const chain = await this.chainBuilder.build(
|
|
8151
8655
|
leaf,
|
|
8152
8656
|
anchorCerts,
|
|
8153
|
-
context.intermediates ?? []
|
|
8657
|
+
context.intermediates ?? [],
|
|
8658
|
+
{ issuedAt: context.issuedAt }
|
|
8154
8659
|
);
|
|
8155
8660
|
const terminusCert = chain[chain.length - 1];
|
|
8156
8661
|
const anchor = anchors.find(
|
|
@@ -8190,6 +8695,7 @@ var init_TrustEvaluator = __esm({
|
|
|
8190
8695
|
};
|
|
8191
8696
|
}
|
|
8192
8697
|
};
|
|
8698
|
+
MAX_CREDENTIAL_CERTIFICATES = 10;
|
|
8193
8699
|
}
|
|
8194
8700
|
});
|
|
8195
8701
|
|
|
@@ -8422,6 +8928,33 @@ function buildHaipQuery(input) {
|
|
|
8422
8928
|
}
|
|
8423
8929
|
return { credentials: [credential] };
|
|
8424
8930
|
}
|
|
8931
|
+
function buildCredentialSetQuery(input) {
|
|
8932
|
+
if (input.options.length === 0) {
|
|
8933
|
+
throw new HaipValidationError(
|
|
8934
|
+
"EMPTY_OPTIONS",
|
|
8935
|
+
"a credential set must offer at least one option"
|
|
8936
|
+
);
|
|
8937
|
+
}
|
|
8938
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8939
|
+
for (const option of input.options) {
|
|
8940
|
+
if (seen.has(option.credentialId)) {
|
|
8941
|
+
throw new HaipValidationError(
|
|
8942
|
+
"DUPLICATE_CREDENTIAL_ID",
|
|
8943
|
+
`credential '${option.credentialId}' is declared by more than one option; credential ids must be unique for credential_sets to reference them`,
|
|
8944
|
+
option.credentialId
|
|
8945
|
+
);
|
|
8946
|
+
}
|
|
8947
|
+
seen.add(option.credentialId);
|
|
8948
|
+
}
|
|
8949
|
+
const credentials = input.options.map((option) => buildHaipQuery(option).credentials[0]);
|
|
8950
|
+
const credentialSet = {
|
|
8951
|
+
options: input.options.map((option) => [option.credentialId])
|
|
8952
|
+
};
|
|
8953
|
+
if (input.required === false) {
|
|
8954
|
+
credentialSet.required = false;
|
|
8955
|
+
}
|
|
8956
|
+
return { credentials, credential_sets: [credentialSet] };
|
|
8957
|
+
}
|
|
8425
8958
|
var HAIP_FORMATS = /* @__PURE__ */ new Set(["dc+sd-jwt", "mso_mdoc"]);
|
|
8426
8959
|
function validateHaipQuery(query) {
|
|
8427
8960
|
if (!query.credentials || query.credentials.length === 0) {
|
|
@@ -8437,46 +8970,86 @@ function validateHaipQuery(query) {
|
|
|
8437
8970
|
);
|
|
8438
8971
|
}
|
|
8439
8972
|
for (const credential of query.credentials) {
|
|
8440
|
-
|
|
8973
|
+
validateCredential(credential);
|
|
8974
|
+
}
|
|
8975
|
+
}
|
|
8976
|
+
function validateCredential(credential) {
|
|
8977
|
+
if (!HAIP_FORMATS.has(credential.format)) {
|
|
8978
|
+
throw new HaipValidationError(
|
|
8979
|
+
"UNSUPPORTED_FORMAT",
|
|
8980
|
+
`credential '${credential.id}' uses unsupported format '${credential.format}' (allowed: dc+sd-jwt, mso_mdoc)`,
|
|
8981
|
+
credential.id
|
|
8982
|
+
);
|
|
8983
|
+
}
|
|
8984
|
+
if (credential.format === "dc+sd-jwt") {
|
|
8985
|
+
const vctValues = credential.meta?.vct_values;
|
|
8986
|
+
if (!vctValues || vctValues.length === 0) {
|
|
8441
8987
|
throw new HaipValidationError(
|
|
8442
|
-
"
|
|
8443
|
-
`credential '${credential.id}'
|
|
8988
|
+
"MISSING_SDJWT_META",
|
|
8989
|
+
`credential '${credential.id}' with format 'dc+sd-jwt' must set meta.vct_values`,
|
|
8444
8990
|
credential.id
|
|
8445
8991
|
);
|
|
8446
8992
|
}
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
throw new HaipValidationError(
|
|
8451
|
-
"MISSING_SDJWT_META",
|
|
8452
|
-
`credential '${credential.id}' with format 'dc+sd-jwt' must set meta.vct_values`,
|
|
8453
|
-
credential.id
|
|
8454
|
-
);
|
|
8455
|
-
}
|
|
8456
|
-
}
|
|
8457
|
-
if (credential.format === "mso_mdoc") {
|
|
8458
|
-
if (typeof credential.meta?.doctype_value !== "string") {
|
|
8459
|
-
throw new HaipValidationError(
|
|
8460
|
-
"MISSING_MDOC_META",
|
|
8461
|
-
`credential '${credential.id}' with format 'mso_mdoc' must set meta.doctype_value`,
|
|
8462
|
-
credential.id
|
|
8463
|
-
);
|
|
8464
|
-
}
|
|
8465
|
-
}
|
|
8466
|
-
if (!credential.claims || credential.claims.length === 0) {
|
|
8993
|
+
}
|
|
8994
|
+
if (credential.format === "mso_mdoc") {
|
|
8995
|
+
if (typeof credential.meta?.doctype_value !== "string") {
|
|
8467
8996
|
throw new HaipValidationError(
|
|
8468
|
-
"
|
|
8469
|
-
`credential '${credential.id}'
|
|
8997
|
+
"MISSING_MDOC_META",
|
|
8998
|
+
`credential '${credential.id}' with format 'mso_mdoc' must set meta.doctype_value`,
|
|
8470
8999
|
credential.id
|
|
8471
9000
|
);
|
|
8472
9001
|
}
|
|
8473
|
-
|
|
9002
|
+
}
|
|
9003
|
+
if (!credential.claims || credential.claims.length === 0) {
|
|
9004
|
+
throw new HaipValidationError(
|
|
9005
|
+
"NO_CLAIMS",
|
|
9006
|
+
`credential '${credential.id}' must declare at least one claim`,
|
|
9007
|
+
credential.id
|
|
9008
|
+
);
|
|
9009
|
+
}
|
|
9010
|
+
if (credential.claim_sets !== void 0) {
|
|
9011
|
+
throw new HaipValidationError(
|
|
9012
|
+
"CLAIM_SETS_DISALLOWED",
|
|
9013
|
+
`credential '${credential.id}' uses claim_sets, not permitted in HAIP-minimal`,
|
|
9014
|
+
credential.id
|
|
9015
|
+
);
|
|
9016
|
+
}
|
|
9017
|
+
}
|
|
9018
|
+
function validateCredentialSetQuery(query) {
|
|
9019
|
+
if (!query.credentials || query.credentials.length === 0) {
|
|
9020
|
+
throw new HaipValidationError(
|
|
9021
|
+
"EMPTY_QUERY",
|
|
9022
|
+
"query.credentials must have at least one entry"
|
|
9023
|
+
);
|
|
9024
|
+
}
|
|
9025
|
+
if (!query.credential_sets || query.credential_sets.length === 0) {
|
|
9026
|
+
throw new HaipValidationError(
|
|
9027
|
+
"MISSING_CREDENTIAL_SETS",
|
|
9028
|
+
"a credential-set query must declare at least one credential_sets entry"
|
|
9029
|
+
);
|
|
9030
|
+
}
|
|
9031
|
+
for (const credential of query.credentials) {
|
|
9032
|
+
validateCredential(credential);
|
|
9033
|
+
}
|
|
9034
|
+
const declaredIds = new Set(query.credentials.map((c) => c.id));
|
|
9035
|
+
for (const credentialSet of query.credential_sets) {
|
|
9036
|
+
if (!credentialSet.options || credentialSet.options.length === 0) {
|
|
8474
9037
|
throw new HaipValidationError(
|
|
8475
|
-
"
|
|
8476
|
-
|
|
8477
|
-
credential.id
|
|
9038
|
+
"EMPTY_OPTIONS",
|
|
9039
|
+
"a credential set must offer at least one option"
|
|
8478
9040
|
);
|
|
8479
9041
|
}
|
|
9042
|
+
for (const option of credentialSet.options) {
|
|
9043
|
+
for (const id of option) {
|
|
9044
|
+
if (!declaredIds.has(id)) {
|
|
9045
|
+
throw new HaipValidationError(
|
|
9046
|
+
"UNKNOWN_OPTION_REFERENCE",
|
|
9047
|
+
`credential_sets option references '${id}', which is not declared in query.credentials`,
|
|
9048
|
+
id
|
|
9049
|
+
);
|
|
9050
|
+
}
|
|
9051
|
+
}
|
|
9052
|
+
}
|
|
8480
9053
|
}
|
|
8481
9054
|
}
|
|
8482
9055
|
function isHaipQuery(query) {
|
|
@@ -8914,6 +9487,14 @@ function bytesEqual3(a, b) {
|
|
|
8914
9487
|
}
|
|
8915
9488
|
return true;
|
|
8916
9489
|
}
|
|
9490
|
+
function peekMsoSigned(payload) {
|
|
9491
|
+
try {
|
|
9492
|
+
const signed = decodeMso(payload).validityInfo.signed;
|
|
9493
|
+
return Number.isFinite(signed.getTime()) ? signed : void 0;
|
|
9494
|
+
} catch {
|
|
9495
|
+
return void 0;
|
|
9496
|
+
}
|
|
9497
|
+
}
|
|
8917
9498
|
function derToPem(der) {
|
|
8918
9499
|
let binary = "";
|
|
8919
9500
|
for (const b of der) binary += String.fromCharCode(b);
|
|
@@ -9074,17 +9655,17 @@ var MdocParser = class {
|
|
|
9074
9655
|
}
|
|
9075
9656
|
let trustResult;
|
|
9076
9657
|
if (options.trustStore) {
|
|
9077
|
-
const {
|
|
9078
|
-
|
|
9658
|
+
const { evaluateCredentialIssuer: evaluateCredentialIssuer2 } = await Promise.resolve().then(() => (init_TrustEvaluator(), TrustEvaluator_exports));
|
|
9659
|
+
trustResult = await evaluateCredentialIssuer2({
|
|
9660
|
+
chain: cose.x5chain,
|
|
9661
|
+
profile: "iso18013-5",
|
|
9662
|
+
issuedAt: peekMsoSigned(cose.payload),
|
|
9079
9663
|
trustStore: options.trustStore,
|
|
9080
9664
|
revocationPolicy: options.revocationPolicy ?? "skip",
|
|
9081
9665
|
fetcher: options.fetcher,
|
|
9082
9666
|
cache: options.cache,
|
|
9083
9667
|
clockSkewTolerance: options.clockSkewTolerance
|
|
9084
9668
|
});
|
|
9085
|
-
const { X509Certificate: X509Certificate9 } = await import('@peculiar/x509');
|
|
9086
|
-
const leaf = new X509Certificate9(issuerCertBytes);
|
|
9087
|
-
trustResult = await evaluator.evaluate(leaf);
|
|
9088
9669
|
} else {
|
|
9089
9670
|
if (options.trustedCertificates.length === 0) {
|
|
9090
9671
|
if (options.skipTrustCheck !== true) {
|
|
@@ -9233,6 +9814,13 @@ var MdocParser = class {
|
|
|
9233
9814
|
init_reflect_polyfill();
|
|
9234
9815
|
init_errors();
|
|
9235
9816
|
var DEFAULT_ALLOWED_ALGORITHMS2 = ["ES256", "ES384", "ES512"];
|
|
9817
|
+
var SD_JWT_VC_TYP = "dc+sd-jwt";
|
|
9818
|
+
var LEGACY_SD_JWT_VC_TYP = "vc+sd-jwt";
|
|
9819
|
+
function normalizeTyp(typ) {
|
|
9820
|
+
if (typeof typ !== "string") return void 0;
|
|
9821
|
+
const lower = typ.toLowerCase();
|
|
9822
|
+
return lower.startsWith("application/") ? lower.slice("application/".length) : lower;
|
|
9823
|
+
}
|
|
9236
9824
|
var sha256Hasher = async (data, _alg) => {
|
|
9237
9825
|
const encoder2 = new TextEncoder();
|
|
9238
9826
|
const input = typeof data === "string" ? encoder2.encode(data) : data;
|
|
@@ -9345,6 +9933,18 @@ var SdJwtParser = class {
|
|
|
9345
9933
|
if (typeof alg !== "string" || !allowedAlgorithms.includes(alg)) {
|
|
9346
9934
|
return invalidResult(`Unsupported algorithm: ${alg}`);
|
|
9347
9935
|
}
|
|
9936
|
+
const typ = normalizeTyp(header.typ);
|
|
9937
|
+
if (typ === LEGACY_SD_JWT_VC_TYP) {
|
|
9938
|
+
if (options.allowLegacyVcSdJwtTyp !== true) {
|
|
9939
|
+
return invalidResult(
|
|
9940
|
+
`Legacy SD-JWT VC typ '${LEGACY_SD_JWT_VC_TYP}' is not accepted (removed in draft-ietf-oauth-sd-jwt-vc-19; expected '${SD_JWT_VC_TYP}'). Set allowLegacyVcSdJwtTyp to accept it during migration.`
|
|
9941
|
+
);
|
|
9942
|
+
}
|
|
9943
|
+
} else if (typ !== SD_JWT_VC_TYP) {
|
|
9944
|
+
return invalidResult(
|
|
9945
|
+
`Unsupported SD-JWT VC typ: ${header.typ === void 0 ? "(missing)" : String(header.typ)} (expected '${SD_JWT_VC_TYP}')`
|
|
9946
|
+
);
|
|
9947
|
+
}
|
|
9348
9948
|
const x5cArray = header.x5c;
|
|
9349
9949
|
const hasX5c = Array.isArray(x5cArray) && x5cArray.length > 0 && typeof x5cArray[0] === "string";
|
|
9350
9950
|
let issuerKey;
|
|
@@ -9414,17 +10014,22 @@ var SdJwtParser = class {
|
|
|
9414
10014
|
};
|
|
9415
10015
|
let trustResult;
|
|
9416
10016
|
if (issuerCertBytes === void 0) ; else if (options.trustStore) {
|
|
9417
|
-
const {
|
|
9418
|
-
const
|
|
10017
|
+
const { evaluateCredentialIssuer: evaluateCredentialIssuer2 } = await Promise.resolve().then(() => (init_TrustEvaluator(), TrustEvaluator_exports));
|
|
10018
|
+
const x5cRest = x5cArray.slice(1);
|
|
10019
|
+
if (!x5cRest.every((entry) => typeof entry === "string")) {
|
|
10020
|
+
throw new MalformedCredentialError("x5c entries must be base64 strings");
|
|
10021
|
+
}
|
|
10022
|
+
const iat = payload["iat"];
|
|
10023
|
+
trustResult = await evaluateCredentialIssuer2({
|
|
10024
|
+
chain: [issuerCertBytes, ...x5cRest.map((entry) => base64ToBytes(entry))],
|
|
10025
|
+
profile: "generic",
|
|
10026
|
+
issuedAt: typeof iat === "number" && Number.isFinite(iat) ? new Date(iat * 1e3) : void 0,
|
|
9419
10027
|
trustStore: options.trustStore,
|
|
9420
10028
|
revocationPolicy: options.revocationPolicy ?? "skip",
|
|
9421
10029
|
fetcher: options.fetcher,
|
|
9422
10030
|
cache: options.cache,
|
|
9423
10031
|
clockSkewTolerance: options.clockSkewTolerance
|
|
9424
10032
|
});
|
|
9425
|
-
const { X509Certificate: X509Certificate9 } = await import('@peculiar/x509');
|
|
9426
|
-
const leaf = new X509Certificate9(issuerCertBytes);
|
|
9427
|
-
trustResult = await evaluator.evaluate(leaf);
|
|
9428
10033
|
} else {
|
|
9429
10034
|
if (options.trustedCertificates.length === 0) {
|
|
9430
10035
|
if (options.skipTrustCheck !== true) {
|
|
@@ -9860,6 +10465,9 @@ var InMemoryCache = class {
|
|
|
9860
10465
|
}
|
|
9861
10466
|
};
|
|
9862
10467
|
|
|
10468
|
+
// src/index.ts
|
|
10469
|
+
init_guarded_fetch();
|
|
10470
|
+
|
|
9863
10471
|
// src/trust/index.ts
|
|
9864
10472
|
init_reflect_polyfill();
|
|
9865
10473
|
|
|
@@ -9907,14 +10515,10 @@ var CompositeTrustStore = class {
|
|
|
9907
10515
|
const results = await Promise.all(
|
|
9908
10516
|
this.stores.map((store) => store.getAnchors(hint))
|
|
9909
10517
|
);
|
|
9910
|
-
const seen = /* @__PURE__ */ new Set();
|
|
9911
10518
|
const out = [];
|
|
9912
10519
|
for (const batch of results) {
|
|
9913
10520
|
for (const anchor of batch) {
|
|
9914
|
-
|
|
9915
|
-
const key = ski ?? anchor.certificate.serialNumber;
|
|
9916
|
-
if (seen.has(key)) continue;
|
|
9917
|
-
seen.add(key);
|
|
10521
|
+
if (out.some((a) => certificatesEqual(a.certificate, anchor.certificate))) continue;
|
|
9918
10522
|
out.push(anchor);
|
|
9919
10523
|
}
|
|
9920
10524
|
}
|
|
@@ -9946,6 +10550,7 @@ function bytesToHex3(bytes) {
|
|
|
9946
10550
|
|
|
9947
10551
|
// src/trust/LotlTrustStore.ts
|
|
9948
10552
|
init_reflect_polyfill();
|
|
10553
|
+
init_errors();
|
|
9949
10554
|
|
|
9950
10555
|
// src/trust/lotl-signing-anchors.ts
|
|
9951
10556
|
init_reflect_polyfill();
|
|
@@ -10007,13 +10612,15 @@ var EU_LOTL_SIGNING_ANCHORS = Object.freeze(
|
|
|
10007
10612
|
// src/trust/LotlFetcher.ts
|
|
10008
10613
|
init_reflect_polyfill();
|
|
10009
10614
|
init_errors();
|
|
10615
|
+
init_guarded_fetch();
|
|
10010
10616
|
var XMLDSIG_NS = "http://www.w3.org/2000/09/xmldsig#";
|
|
10011
10617
|
var LotlFetcher = class {
|
|
10012
10618
|
fetcher;
|
|
10013
10619
|
constructor(opts = {}) {
|
|
10014
|
-
this.fetcher = opts.fetcher ??
|
|
10620
|
+
this.fetcher = opts.fetcher ?? createDefaultTrustFetcher();
|
|
10015
10621
|
}
|
|
10016
10622
|
async fetchSigned(url, signingAnchors) {
|
|
10623
|
+
assertCryptoEngineRegistered();
|
|
10017
10624
|
let xmlText;
|
|
10018
10625
|
try {
|
|
10019
10626
|
const response = await this.fetcher(url, { method: "GET" });
|
|
@@ -10066,6 +10673,22 @@ var LotlFetcher = class {
|
|
|
10066
10673
|
);
|
|
10067
10674
|
}
|
|
10068
10675
|
};
|
|
10676
|
+
function assertCryptoEngineRegistered() {
|
|
10677
|
+
let engine;
|
|
10678
|
+
try {
|
|
10679
|
+
engine = xmldsig.Application.crypto;
|
|
10680
|
+
} catch (err) {
|
|
10681
|
+
throw new LotlConfigurationError(
|
|
10682
|
+
`no xmldsigjs crypto engine registered \u2014 trusted-list signatures cannot be verified. Call xmldsig.Application.setEngine('NodeJS', new Crypto()) (e.g. from @peculiar/webcrypto) once at startup, before using LotlTrustStore. Underlying error: ${err instanceof Error ? err.message : String(err)}`,
|
|
10683
|
+
{ cause: err instanceof Error ? err : void 0 }
|
|
10684
|
+
);
|
|
10685
|
+
}
|
|
10686
|
+
if (!engine) {
|
|
10687
|
+
throw new LotlConfigurationError(
|
|
10688
|
+
"no xmldsigjs crypto engine registered \u2014 trusted-list signatures cannot be verified. Call xmldsig.Application.setEngine('NodeJS', new Crypto()) (e.g. from @peculiar/webcrypto) once at startup, before using LotlTrustStore."
|
|
10689
|
+
);
|
|
10690
|
+
}
|
|
10691
|
+
}
|
|
10069
10692
|
async function verifyAgainst(doc, sigEl, anchor) {
|
|
10070
10693
|
try {
|
|
10071
10694
|
const signed = new xmldsig.SignedXml(doc);
|
|
@@ -10213,6 +10836,7 @@ function parsePointer(el) {
|
|
|
10213
10836
|
|
|
10214
10837
|
// src/trust/NationalTlResolver.ts
|
|
10215
10838
|
init_reflect_polyfill();
|
|
10839
|
+
init_errors();
|
|
10216
10840
|
var TSL_NS2 = "http://uri.etsi.org/02231/v2#";
|
|
10217
10841
|
var NationalTlResolver = class {
|
|
10218
10842
|
constructor(opts) {
|
|
@@ -10228,6 +10852,7 @@ var NationalTlResolver = class {
|
|
|
10228
10852
|
);
|
|
10229
10853
|
return parseNationalTl(doc, pointer.country);
|
|
10230
10854
|
} catch (err) {
|
|
10855
|
+
if (err instanceof LotlConfigurationError) throw err;
|
|
10231
10856
|
console.warn(
|
|
10232
10857
|
`[openid4vp] national TL for ${pointer.country} failed: ${err.message}`
|
|
10233
10858
|
);
|
|
@@ -10406,6 +11031,7 @@ var LotlTrustStore = class {
|
|
|
10406
11031
|
};
|
|
10407
11032
|
return this.snapshot;
|
|
10408
11033
|
} catch (err) {
|
|
11034
|
+
if (err instanceof LotlConfigurationError) throw err;
|
|
10409
11035
|
if (this.snapshot) {
|
|
10410
11036
|
console.warn(
|
|
10411
11037
|
`[openid4vp] LOTL refresh failed; serving cached snapshot (${err.message})`
|
|
@@ -10453,7 +11079,7 @@ function equalBytes(a, b) {
|
|
|
10453
11079
|
|
|
10454
11080
|
// src/index.ts
|
|
10455
11081
|
init_errors();
|
|
10456
|
-
var VERSION = "0.
|
|
11082
|
+
var VERSION = "0.13.0";
|
|
10457
11083
|
/*! Bundled license information:
|
|
10458
11084
|
|
|
10459
11085
|
pvtsutils/build/index.es.js:
|
|
@@ -10523,6 +11149,6 @@ asn1js/build/index.es.js:
|
|
|
10523
11149
|
*)
|
|
10524
11150
|
*/
|
|
10525
11151
|
|
|
10526
|
-
export { CertificateChainError, CompositeTrustStore, DecryptionFailedError, ExpiredCredentialError, HAIP_DOCTYPE_NAMESPACES, HaipValidationError, InMemoryCache, InvalidSignatureError, LotlFetchError, LotlSignatureError, LotlTrustStore, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, SignedRequestBuildError, StaticTrustStore, TrustAnchorNotFoundError, UnsupportedFormatError, UnsupportedJweError, VERSION, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
|
|
11152
|
+
export { CertificateChainError, CompositeTrustStore, DecryptionFailedError, ExpiredCredentialError, GUARDED_FETCH_DEFAULTS, GuardedFetchError, HAIP_DOCTYPE_NAMESPACES, HaipValidationError, InMemoryCache, InvalidSignatureError, LotlConfigurationError, LotlFetchError, LotlSignatureError, LotlTrustStore, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, SignedRequestBuildError, StaticTrustStore, TrustAnchorNotFoundError, UnsupportedFormatError, UnsupportedJweError, VERSION, buildCredentialSetQuery, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createGuardedFetcher, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateCredentialSetQuery, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
|
|
10527
11153
|
//# sourceMappingURL=index.js.map
|
|
10528
11154
|
//# sourceMappingURL=index.js.map
|