@blamejs/pki 0.8.58 → 0.8.59
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/lib/acme.js +38 -23
- package/lib/asn1-der.js +16 -5
- package/lib/cmc-build.js +4 -1
- package/lib/cmp-build.js +10 -1
- package/lib/cms-decrypt.js +6 -2
- package/lib/cms-verify.js +3 -3
- package/lib/crl-sign.js +3 -3
- package/lib/ct.js +10 -1
- package/lib/est.js +43 -23
- package/lib/guard-identifier.js +1 -1
- package/lib/key.js +11 -7
- package/lib/path-validate.js +5 -5
- package/lib/pki-build.js +4 -4
- package/lib/sign-scheme.js +4 -4
- package/lib/webcrypto.js +5 -5
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,23 @@ All notable changes to `@blamejs/pki` are documented here. The format
|
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this
|
|
5
5
|
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## v0.8.59 — 2026-10-07
|
|
8
|
+
|
|
9
|
+
Render an object identifier, match a header name and read a media type through operations a replacement cannot answer.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- The check that holds these modules to captured operations now counts a method reached through an index, not only one reached through a call. It is the same receiver one bracket over, and the earlier form could not see it: two live copies in the RFC 5280 policy-mapping walk, where the copy becomes a node's expected policy set, were found by other means.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- An object identifier is rendered to its dotted form through operations bound when the module loaded, and its arcs are collected by defining each index rather than by appending to the array. Three different replacements each decided that string, which is the value `pki.oid` resolves, which selects a signature algorithm and which names an extension: a replaced integer conversion made the content octets of `1.2.3` render as `1.3.4`, and an accessor inherited at the first index of every array took each arc as it was collected and made the same octets render as `0.1.3`. Appending stores at an index, and a store consults the prototype chain for a setter, so a list this build assembles is now built by defining its indexes.
|
|
18
|
+
- A media type is read on the delimiter character and folded through a captured conversion, in `pki.acme`, `pki.cmp` and `pki.ct`. The token decides which parser a response body is handed to, and it was produced by splitting, trimming and folding through live operations. Splitting is now a character scan, which this toolkit requires in its libraries because a separator's own split hook is part of that operation.
|
|
19
|
+
- `pki.est` reads a content-type parameter through captured operations, and collects the segments it searches by defining each index. That is where the RFC 7030 multipart boundary comes from, so the value decides where a multi-part response is divided: measured, a header declaring `boundary=wire` yielded `forged`, both through a replaced append and through an accessor inherited at an array index. The name comparison that selects a parameter, the slicing that extracts it and the quote stripping around it were each live, as were the name and value of every header on a part, which is where a part's own content type comes from: measured, a part declaring `application/pkcs8` was read as `application/pkcs7-mime` carrying `smime-type=certs-only`. Its two case-insensitive header lookups are folded through the capture on both sides of the comparison.
|
|
20
|
+
- `pki.acme` parses a Link header through captured operations: the header is divided into links, each link into parameters, and the target cut out of its angle brackets, all through operations bound when the module loaded. The relation decides whether a header names a resource the client will follow and the target is the URL it would fetch, and both were produced by methods read off the live prototype: measured, a header stating one alternate chain resolved to a different URL.
|
|
21
|
+
- `pki.cmc.build` selects which request arm a message carries through a selection that reads each candidate once and builds its own result, rather than through a method that is both read off the prototype and specified to construct its result through a replaceable protocol.
|
|
22
|
+
- The algorithm, extension and criticality tables that `pki.path.validate`, `pki.cms`, `pki.crl`, `pki.key`, `pki.webcrypto`, `pki.x509` and the signature-scheme registry build when they load are built through captured walks, so a replacement installed before a module loads cannot decide which rows exist.
|
|
23
|
+
|
|
7
24
|
## v0.8.58 — 2026-10-07
|
|
8
25
|
|
|
9
26
|
Connect under the trust anchors, the address and the identity check the request named, not the ones a second read answers with.
|
package/lib/acme.js
CHANGED
|
@@ -88,6 +88,7 @@ var _sortI = intrinsic.sort;
|
|
|
88
88
|
var _objectKeys = intrinsic.keys;
|
|
89
89
|
var _lower = intrinsic.toLowerCase;
|
|
90
90
|
var _StringI = intrinsic.String;
|
|
91
|
+
var _acmeTrim = intrinsic.uncurry(String.prototype.trim);
|
|
91
92
|
var _stringify = intrinsic.stringify;
|
|
92
93
|
var _push = intrinsic.push;
|
|
93
94
|
var _pop = intrinsic.pop;
|
|
@@ -98,6 +99,7 @@ var _split = intrinsic.uncurry(String.prototype.split);
|
|
|
98
99
|
var _parseIntI = intrinsic.parseInt;
|
|
99
100
|
var _numToString = intrinsic.numberToString;
|
|
100
101
|
var _strSlice = intrinsic.uncurry(String.prototype.slice);
|
|
102
|
+
var _charAtA = intrinsic.uncurry(String.prototype.charAt);
|
|
101
103
|
var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
|
|
102
104
|
var _charAt = intrinsic.uncurry(String.prototype.charAt);
|
|
103
105
|
var pkgVersion = require("../package.json").version;
|
|
@@ -1707,61 +1709,71 @@ function _hasCtlOctet(s) {
|
|
|
1707
1709
|
}
|
|
1708
1710
|
|
|
1709
1711
|
function _splitLinkValues(s) {
|
|
1712
|
+
/** @internal The header is cut through the captured operations, the same as the parameters below:
|
|
1713
|
+
* each piece becomes a link whose relation decides whether this client follows it. */
|
|
1710
1714
|
var out = [], start = 0, inAngle = false, inQuote = false;
|
|
1711
1715
|
for (var i = 0; i < s.length; i++) {
|
|
1712
|
-
var ch = s
|
|
1716
|
+
var ch = _charAtA(s, i);
|
|
1713
1717
|
if (inQuote) { if (ch === "\\") { i++; continue; } if (ch === "\"") inQuote = false; continue; }
|
|
1714
1718
|
if (ch === "\"") { inQuote = true; continue; }
|
|
1715
1719
|
if (ch === "<") inAngle = true;
|
|
1716
1720
|
else if (ch === ">") inAngle = false;
|
|
1717
|
-
else if (ch === "," && !inAngle) {
|
|
1721
|
+
else if (ch === "," && !inAngle) { intrinsic.append(out, _strSlice(s, start, i)); start = i + 1; }
|
|
1718
1722
|
}
|
|
1719
1723
|
if (inQuote || inAngle) throw E("acme/bad-link", "the Link header has an unterminated quote or angle bracket (RFC 8288)");
|
|
1720
|
-
|
|
1724
|
+
intrinsic.append(out, _strSlice(s, start));
|
|
1721
1725
|
return out;
|
|
1722
1726
|
}
|
|
1723
1727
|
function _splitLinkParams(rest) {
|
|
1724
1728
|
var parts = [], start = 0, inQuote = false;
|
|
1725
1729
|
for (var i = 0; i < rest.length; i++) {
|
|
1726
|
-
var ch = rest
|
|
1730
|
+
var ch = _charAtA(rest, i);
|
|
1727
1731
|
if (inQuote) { if (ch === "\\") { i++; continue; } if (ch === "\"") inQuote = false; continue; }
|
|
1728
1732
|
if (ch === "\"") inQuote = true;
|
|
1729
|
-
else if (ch === ";") {
|
|
1733
|
+
else if (ch === ";") { intrinsic.append(parts, _strSlice(rest, start, i)); start = i + 1; }
|
|
1730
1734
|
}
|
|
1731
|
-
|
|
1735
|
+
intrinsic.append(parts, _strSlice(rest, start));
|
|
1732
1736
|
var out = [];
|
|
1733
1737
|
for (var j = 0; j < parts.length; j++) {
|
|
1734
1738
|
var p = _trimOWS(parts[j]);
|
|
1735
1739
|
if (p === "") { if (j === 0) continue; throw E("acme/bad-link", "an empty Link parameter (a ';' with no parameter) is malformed (RFC 8288): " + JSON.stringify(rest)); }
|
|
1736
|
-
|
|
1737
|
-
|
|
1740
|
+
/** @internal The parameter name and value are cut and folded through the captured operations.
|
|
1741
|
+
* A Link parameter is what names the relation this client follows, and read off the prototype a
|
|
1742
|
+
* replacement chose it: measured, a header stating `rel=next` parsed as `alternate`. */
|
|
1743
|
+
var eq = intrinsic.stringIndexOf(p, "=");
|
|
1744
|
+
var name = _lower(eq === -1 ? p : _trimOWS(_strSlice(p, 0, eq)));
|
|
1738
1745
|
if (!pkix.allCharsIn(name, _LINK_TOKEN_TABLE)) throw E("acme/bad-link", "a Link parameter name must be a token (RFC 8288 / RFC 7230): " + JSON.stringify(p));
|
|
1739
|
-
if (eq === -1) {
|
|
1740
|
-
var v = _trimOWS(p
|
|
1741
|
-
if (v.length >= 2 && v
|
|
1742
|
-
var inner = v
|
|
1746
|
+
if (eq === -1) { intrinsic.append(out, { name: name, value: "", hasValue: false }); continue; }
|
|
1747
|
+
var v = _trimOWS(_strSlice(p, eq + 1));
|
|
1748
|
+
if (v.length >= 2 && _charAtA(v, 0) === "\"" && _charAtA(v, v.length - 1) === "\"") {
|
|
1749
|
+
var inner = _strSlice(v, 1, -1);
|
|
1743
1750
|
if (!_isValidQuotedInterior(inner)) throw E("acme/bad-link", "a quoted Link parameter value is malformed (an unescaped quote or dangling backslash, RFC 7230): " + JSON.stringify(p));
|
|
1744
1751
|
v = _unescapeQuotedPair(inner);
|
|
1745
1752
|
} else if (!pkix.allCharsIn(v, _LINK_TOKEN_TABLE)) {
|
|
1746
1753
|
throw E("acme/bad-link", "an unquoted Link parameter value must be a non-empty token (RFC 8288 / RFC 7230): " + JSON.stringify(p));
|
|
1747
1754
|
}
|
|
1748
|
-
|
|
1755
|
+
intrinsic.append(out, { name: name, value: v, hasValue: true });
|
|
1749
1756
|
}
|
|
1750
1757
|
return out;
|
|
1751
1758
|
}
|
|
1752
1759
|
function _relHas(rel, relName) {
|
|
1753
|
-
|
|
1754
|
-
|
|
1760
|
+
/** @internal The relation names are scanned on the delimiter CHARACTER, which hard rule 11 requires
|
|
1761
|
+
* in lib/, and each token is folded through the captured conversion: the match decides whether a
|
|
1762
|
+
* Link header names the resource this client then follows. */
|
|
1763
|
+
var toks = intrinsic.splitChar(_StringI(rel), 32);
|
|
1764
|
+
for (var i = 0; i < toks.length; i++) { if (_lower(toks[i]) === relName) return true; }
|
|
1755
1765
|
return false;
|
|
1756
1766
|
}
|
|
1757
1767
|
function _parseLinkValue(raw) {
|
|
1758
1768
|
var s = _trimOWS(raw);
|
|
1759
1769
|
if (s === "") return null;
|
|
1760
|
-
var gt =
|
|
1761
|
-
if (s
|
|
1770
|
+
var gt = intrinsic.stringIndexOf(s, ">");
|
|
1771
|
+
if (_charAtA(s, 0) !== "<" || gt === -1) throw E("acme/bad-link", "a Link value must be <URI-Reference> with parameters (RFC 8288): " + JSON.stringify(raw));
|
|
1762
1772
|
var rest = _stripLeadingOWS(s, gt + 1);
|
|
1763
|
-
if (rest !== "" && rest
|
|
1764
|
-
|
|
1773
|
+
if (rest !== "" && _charAtA(rest, 0) !== ";") throw E("acme/bad-link", "a Link value's parameters must be introduced by ';' (RFC 8288): " + JSON.stringify(raw));
|
|
1774
|
+
/** @internal The target this client may follow is cut through the captured operation: read off the
|
|
1775
|
+
* prototype, a replacement decided the URL a Link header resolves to. */
|
|
1776
|
+
var uri = _strSlice(s, 1, gt);
|
|
1765
1777
|
if (_linkUriInvalid(uri)) throw E("acme/bad-link", "a Link URI-Reference contains a character, percent-escape, or encoded dot-segment not permitted by RFC 3986: " + JSON.stringify(raw));
|
|
1766
1778
|
var params = _splitLinkParams(rest), rel = "", relSeen = false, anchor = null, anchorSeen = false;
|
|
1767
1779
|
for (var i = 0; i < params.length; i++) {
|
|
@@ -1780,14 +1792,16 @@ function _parseLinkRelation(headers, base, relName, opts) {
|
|
|
1780
1792
|
var raw = null;
|
|
1781
1793
|
var hNames = guard.identifier.optionNames(headers);
|
|
1782
1794
|
for (var hi = 0; hi < hNames.length; hi++) {
|
|
1783
|
-
if (hNames[hi]
|
|
1795
|
+
if (_lower(hNames[hi]) === "link") { raw = headers[hNames[hi]]; break; }
|
|
1784
1796
|
}
|
|
1785
1797
|
if (raw == null) return [];
|
|
1786
1798
|
var baseUrl = new _URL(base), baseOrigin = _urlOrigin(baseUrl), baseHref = _urlHref(baseUrl);
|
|
1787
1799
|
var baseKey = _dedupKey(baseHref);
|
|
1788
|
-
var fields =
|
|
1800
|
+
var fields = intrinsic.isArray(raw) ? raw : [raw], out = [], seen = intrinsic.create(null), distinctCount = 0, totalBytes = 0;
|
|
1789
1801
|
for (var fi = 0; fi < fields.length; fi++) {
|
|
1790
|
-
|
|
1802
|
+
/** @internal The header field is converted through the capture: read through the live global, a
|
|
1803
|
+
* replacement supplied the whole Link header and with it the target this client resolves. */
|
|
1804
|
+
var field = _StringI(fields[fi]);
|
|
1791
1805
|
totalBytes += field.length + 1;
|
|
1792
1806
|
if (totalBytes > LINK_HEADER_MAX_BYTES) throw E("acme/bad-link", "the Link header(s) exceed the " + LINK_HEADER_MAX_BYTES + "-byte aggregate cap (RFC 8288, CWE-770)");
|
|
1793
1807
|
if (_hasCtlOctet(field)) throw E("acme/bad-link", "a Link header must not contain control octets (RFC 9110 field-value)");
|
|
@@ -2202,7 +2216,8 @@ function client(directoryUrl, opts) {
|
|
|
2202
2216
|
function _pollAuthorization(url, budget) { return _poll("authorization", url, budget); }
|
|
2203
2217
|
|
|
2204
2218
|
function _readCertChain(res) {
|
|
2205
|
-
var
|
|
2219
|
+
var ctParts = intrinsic.splitChar(_StringI(res.headers["content-type"] || ""), 59);
|
|
2220
|
+
var ctToken = _lower(_acmeTrim(ctParts.length ? ctParts[0] : ""));
|
|
2206
2221
|
if (ctToken !== "application/pem-certificate-chain") throw E("acme/bad-certificate-chain", "the certificate download returned an unexpected media type " + JSON.stringify(ctToken) + " (expected application/pem-certificate-chain, RFC 8555 sec. 7.4.2)");
|
|
2207
2222
|
var chain = _splitPemChain(_bodyText(res));
|
|
2208
2223
|
return { certificate: chain[0], chain: chain.slice(1), certificates: chain };
|
package/lib/asn1-der.js
CHANGED
|
@@ -566,8 +566,16 @@ function decodeOidContent(buf) {
|
|
|
566
566
|
"OBJECT IDENTIFIER carries more than " + constants.LIMITS.OID_MAX_SUBIDENTIFIERS + " sub-identifiers");
|
|
567
567
|
}
|
|
568
568
|
var value = 0n;
|
|
569
|
-
|
|
570
|
-
|
|
569
|
+
/** @internal The arc is accumulated through the captured conversion. Read off the global, a
|
|
570
|
+
* replacement decides the sub-identifier, and therefore the dotted string every algorithm and
|
|
571
|
+
* extension decision in this toolkit is made on: measured, the same two bytes rendered as
|
|
572
|
+
* `1.2.3` and as `1.2.4`. */
|
|
573
|
+
for (var k = arcStart; k <= i; k++) value = value * 128n + intrinsic.BigInt(buf[k] & 0x7f);
|
|
574
|
+
/** @internal `append`, not a captured `push`: appending with `push` STORES at the index, and a
|
|
575
|
+
* store walks the prototype chain for a setter, so an accessor installed at
|
|
576
|
+
* `Array.prototype[0]` took the arc and answered with another. `append` defines the index on
|
|
577
|
+
* the array itself. */
|
|
578
|
+
intrinsic.append(arcs, value);
|
|
571
579
|
arcStart = i + 1;
|
|
572
580
|
}
|
|
573
581
|
}
|
|
@@ -577,9 +585,12 @@ function decodeOidContent(buf) {
|
|
|
577
585
|
if (first < 40n) { a1 = 0n; a2 = first; }
|
|
578
586
|
else if (first < 80n) { a1 = 1n; a2 = first - 40n; }
|
|
579
587
|
else { a1 = 2n; a2 = first - 80n; }
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
588
|
+
/** @internal Each arc is rendered through the captured conversion. Read off the prototype, the
|
|
589
|
+
* value that becomes the dotted identifier is whatever a replacement returns, and the identifier
|
|
590
|
+
* is what every algorithm and extension decision in this toolkit is made on. */
|
|
591
|
+
var out = [intrinsic.bigIntToString(a1, 10), intrinsic.bigIntToString(a2, 10)];
|
|
592
|
+
for (var j = 1; j < arcs.length; j++) intrinsic.append(out, intrinsic.bigIntToString(arcs[j], 10));
|
|
593
|
+
return intrinsic.join(out, ".");
|
|
583
594
|
}
|
|
584
595
|
|
|
585
596
|
function _decodeText(buf, encoding) {
|
package/lib/cmc-build.js
CHANGED
|
@@ -173,7 +173,10 @@ function fixedRequestId(req, index) {
|
|
|
173
173
|
return "unknown field " + JSON.stringify(k) + " on request " + index +
|
|
174
174
|
" -- a request names one of tcr / crm / orm, and optionally bodyPartID";
|
|
175
175
|
});
|
|
176
|
-
|
|
176
|
+
/** @internal `selectList`, not the live `filter`: the selection decides which request arm this
|
|
177
|
+
* message carries, and `Array.prototype.filter` is both read off the prototype and specified to
|
|
178
|
+
* build its result through the species constructor. */
|
|
179
|
+
var arms = intrinsic.selectList(["tcr", "crm", "orm"], function (k) { return req[k] != null; });
|
|
177
180
|
if (arms.length !== 1) {
|
|
178
181
|
throw E("cmc/bad-input",
|
|
179
182
|
"each request names exactly one of tcr / crm / orm, got " + (arms.length ? arms.join(" + ") : "none") +
|
package/lib/cmp-build.js
CHANGED
|
@@ -29,6 +29,7 @@ var cmp = require("./schema-cmp");
|
|
|
29
29
|
var crmf = require("./crmf-sign");
|
|
30
30
|
var schemaCrmf = require("./schema-crmf");
|
|
31
31
|
var intrinsic = require("./guard-intrinsic");
|
|
32
|
+
var _strTrim = intrinsic.uncurry(String.prototype.trim);
|
|
32
33
|
/** @internal The promise a signature self-check is awaited through, built from the constructor captured
|
|
33
34
|
* at load. `Promise.resolve` builds from its RECEIVER, so reading the global binding at the call hands
|
|
34
35
|
* the construction to whatever that binding holds, and one settling without awaiting its argument runs
|
|
@@ -1012,7 +1013,15 @@ function _tlsForTransfer(opts) {
|
|
|
1012
1013
|
return guard.identifier.pickSettings(opts.tls, TLS_SETTINGS);
|
|
1013
1014
|
}
|
|
1014
1015
|
|
|
1015
|
-
|
|
1016
|
+
/** @internal The media type is read through the captured operations, and on the delimiter CHARACTER
|
|
1017
|
+
* rather than through `split`, which hard rule 11 bans in lib/ because the separator's own
|
|
1018
|
+
* `Symbol.split` is part of that operation. The token decides which parser a response body is
|
|
1019
|
+
* handed to. */
|
|
1020
|
+
function _ctypeToken(headers) {
|
|
1021
|
+
var raw = intrinsic.String((headers || {})["content-type"] || "");
|
|
1022
|
+
var parts = intrinsic.splitChar(raw, 59);
|
|
1023
|
+
return intrinsic.toLowerCase(_strTrim(parts.length ? parts[0] : ""));
|
|
1024
|
+
}
|
|
1016
1025
|
function _isPkixcmp(headers) { var t = _ctypeToken(headers); return t === PKIXCMP || t === PKIXCMP_POLL; }
|
|
1017
1026
|
|
|
1018
1027
|
/** @internal The sentinel is added at the one exit rather than at each `return`, so a branch added
|
package/lib/cms-decrypt.js
CHANGED
|
@@ -631,9 +631,13 @@ var HASH_W3C = intrinsic.create(null); HASH_W3C[O("sha1")] = "SHA-1"; HASH_W3C[O
|
|
|
631
631
|
function _hashW3c(o) { if (!HASH_W3C[o]) throw _err("cms/unsupported-algorithm", "unsupported OAEP hash " + o); return HASH_W3C[o]; }
|
|
632
632
|
|
|
633
633
|
var X963_HASH = intrinsic.create(null);
|
|
634
|
-
[["dhSinglePass-stdDH-sha1kdf-scheme", "SHA-1"], ["dhSinglePass-stdDH-sha224kdf-scheme", "SHA-224"], ["dhSinglePass-stdDH-sha256kdf-scheme", "SHA-256"], ["dhSinglePass-stdDH-sha384kdf-scheme", "SHA-384"], ["dhSinglePass-stdDH-sha512kdf-scheme", "SHA-512"],
|
|
634
|
+
var _X963_ROWS = [["dhSinglePass-stdDH-sha1kdf-scheme", "SHA-1"], ["dhSinglePass-stdDH-sha224kdf-scheme", "SHA-224"], ["dhSinglePass-stdDH-sha256kdf-scheme", "SHA-256"], ["dhSinglePass-stdDH-sha384kdf-scheme", "SHA-384"], ["dhSinglePass-stdDH-sha512kdf-scheme", "SHA-512"],
|
|
635
635
|
["dhSinglePass-cofactorDH-sha1kdf-scheme", "SHA-1"], ["dhSinglePass-cofactorDH-sha224kdf-scheme", "SHA-224"], ["dhSinglePass-cofactorDH-sha256kdf-scheme", "SHA-256"], ["dhSinglePass-cofactorDH-sha384kdf-scheme", "SHA-384"], ["dhSinglePass-cofactorDH-sha512kdf-scheme", "SHA-512"]
|
|
636
|
-
]
|
|
636
|
+
];
|
|
637
|
+
/** @internal The registry is built through the captured walk. The method is read off the live
|
|
638
|
+
* prototype at the moment it runs even where the receiver is a literal, and these rows decide which
|
|
639
|
+
* hash a key-agreement recipient's KDF uses. */
|
|
640
|
+
intrinsic.forEach(_X963_ROWS, function (r) { X963_HASH[O(r[0])] = r[1]; });
|
|
637
641
|
function _x963Hash(scheme) { if (!X963_HASH[scheme]) throw _err("cms/unsupported-algorithm", "unsupported kari key-agreement scheme " + scheme); return X963_HASH[scheme]; }
|
|
638
642
|
function _kariWrap(kea) {
|
|
639
643
|
var params = asn1.decode(kea.parameters);
|
package/lib/cms-verify.js
CHANGED
|
@@ -126,9 +126,9 @@ var SIG_SCHEME = intrinsic.assign(intrinsic.create(null), {
|
|
|
126
126
|
ecdsaWithSHA384: { kind: "ec", hash: "SHA-384", params: "absent" },
|
|
127
127
|
ecdsaWithSHA512: { kind: "ec", hash: "SHA-512", params: "absent" },
|
|
128
128
|
});
|
|
129
|
-
["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
130
|
-
|
|
131
|
-
]
|
|
129
|
+
intrinsic.forEach(["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
130
|
+
"shake-128s", "shake-128f", "shake-192s", "shake-192f", "shake-256s", "shake-256f"
|
|
131
|
+
], function (s) { SIG_SCHEME["id-slh-dsa-" + s] = { kind: "slhdsa", name: "SLH-DSA-" + intrinsic.toUpperCase(s), params: "absent", sameKeyOid: true, digest: SLHDSA_BY_OID[oid.byName("id-slh-dsa-" + s)].digest }; });
|
|
132
132
|
function _isDerNull(p) { return guard.der.isNull(p); }
|
|
133
133
|
function _algParamsOk(shape, p) { return shape === "null" ? _isDerNull(p) : (p === null || p === undefined); }
|
|
134
134
|
var EC_CURVE = intrinsic.create(null);
|
package/lib/crl-sign.js
CHANGED
|
@@ -108,8 +108,8 @@ var KNOWN_REVOKED_KEYS = intrinsic.assign(intrinsic.create(null), {
|
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
var REQUIRED_CRITICALITY = intrinsic.create(null);
|
|
111
|
-
[["cRLNumber", false], ["authorityKeyIdentifier", false], ["freshestCRL", false], ["authorityInfoAccess", false],
|
|
112
|
-
["issuingDistributionPoint", true], ["deltaCRLIndicator", true]]
|
|
111
|
+
intrinsic.forEach([["cRLNumber", false], ["authorityKeyIdentifier", false], ["freshestCRL", false], ["authorityInfoAccess", false],
|
|
112
|
+
["issuingDistributionPoint", true], ["deltaCRLIndicator", true]], function (r) { REQUIRED_CRITICALITY[O(r[0])] = r[1]; });
|
|
113
113
|
|
|
114
114
|
var REQUIRED_ENTRY_CRITICALITY = intrinsic.create(null);
|
|
115
115
|
(function () {
|
|
@@ -199,7 +199,7 @@ var _PRE_ENCODED_IDP_SCHEMA = pkix.issuingDistributionPoint("crl/bad-idp");
|
|
|
199
199
|
function _validatePreEncodedIdp(inner) {
|
|
200
200
|
if (!inner.children || !inner.children.length) throw _err("crl/bad-idp", "pre-encoded issuingDistributionPoint MUST NOT be empty (RFC 5280 sec. 5.2.5)");
|
|
201
201
|
var f = schema.walk(_PRE_ENCODED_IDP_SCHEMA, inner, NS).fields;
|
|
202
|
-
["onlyContainsUserCerts", "onlyContainsCACerts", "onlyContainsAttributeCerts"]
|
|
202
|
+
intrinsic.forEach(["onlyContainsUserCerts", "onlyContainsCACerts", "onlyContainsAttributeCerts"], function (name) {
|
|
203
203
|
if (f[name].present && f[name].value !== true) throw _err("crl/bad-idp", "pre-encoded issuingDistributionPoint " + name + " encodes its DEFAULT FALSE, which DER omits (X.690 sec. 11.5)");
|
|
204
204
|
});
|
|
205
205
|
if (f.indirectCRL.present) throw _err("crl/bad-idp", _INDIRECT_IDP_DEFERRED);
|
package/lib/ct.js
CHANGED
|
@@ -63,6 +63,7 @@ var _bufToString = intrinsic.bufToString;
|
|
|
63
63
|
var _bufferCompare = intrinsic.compare;
|
|
64
64
|
var _subarray = intrinsic.subarray;
|
|
65
65
|
var _toLowerCase = intrinsic.toLowerCase;
|
|
66
|
+
var _ctTrim = intrinsic.uncurry(String.prototype.trim);
|
|
66
67
|
var _bufCopy = intrinsic.uncurry(Buffer.prototype.copy);
|
|
67
68
|
var _writeU64BE = intrinsic.uncurry(Buffer.prototype.writeBigUInt64BE);
|
|
68
69
|
var _searchSet = intrinsic.uncurry(URLSearchParams.prototype.set);
|
|
@@ -1230,7 +1231,15 @@ function _assertTransport(opts) {
|
|
|
1230
1231
|
"(request) => Promise<{ status, headers, body }>");
|
|
1231
1232
|
}
|
|
1232
1233
|
|
|
1233
|
-
|
|
1234
|
+
/** @internal The media type is read through the captured operations, and on the delimiter CHARACTER
|
|
1235
|
+
* rather than through `split`, which hard rule 11 bans in lib/ because the separator's own
|
|
1236
|
+
* `Symbol.split` is part of that operation. The token decides which parser a log's response body is
|
|
1237
|
+
* handed to. */
|
|
1238
|
+
function _fetchCtypeToken(headers) {
|
|
1239
|
+
var raw = intrinsic.String((headers || {})["content-type"] || "");
|
|
1240
|
+
var parts = intrinsic.splitChar(raw, 59);
|
|
1241
|
+
return _toLowerCase(_ctTrim(parts.length ? parts[0] : ""));
|
|
1242
|
+
}
|
|
1234
1243
|
|
|
1235
1244
|
function _parseHttpsUrl(u, label) {
|
|
1236
1245
|
var parsed;
|
package/lib/est.js
CHANGED
|
@@ -76,6 +76,9 @@ var intrinsic = require("./guard-intrinsic");
|
|
|
76
76
|
var _charCodeAt = intrinsic.uncurry(String.prototype.charCodeAt);
|
|
77
77
|
var _strSlice = intrinsic.uncurry(String.prototype.slice);
|
|
78
78
|
var _toLowerCase = intrinsic.uncurry(String.prototype.toLowerCase);
|
|
79
|
+
var _estTrim = intrinsic.uncurry(String.prototype.trim);
|
|
80
|
+
var _estCharAt = intrinsic.uncurry(String.prototype.charAt);
|
|
81
|
+
var _estIndexOf = intrinsic.stringIndexOf;
|
|
79
82
|
/** @internal Each verb gates its body on a resolved promise and returns its refusals as rejected ones,
|
|
80
83
|
* and both build from the RECEIVER, so reading the global binding at the call decides whether the body
|
|
81
84
|
* runs and whether a refusal stays a refusal. Taken at load. */
|
|
@@ -250,7 +253,7 @@ function _isMultipartMixedPrefix(ct) {
|
|
|
250
253
|
}
|
|
251
254
|
|
|
252
255
|
function _multipartBoundary(contentType) {
|
|
253
|
-
var ct =
|
|
256
|
+
var ct = _stringOf(contentType || "");
|
|
254
257
|
if (!_isMultipartMixedPrefix(ct)) return null;
|
|
255
258
|
var bp = _ctParam(ct, "boundary");
|
|
256
259
|
if (bp.duplicated) {
|
|
@@ -356,12 +359,16 @@ function splitMultipartMixed(body, contentType) {
|
|
|
356
359
|
var lines = _splitCrlf(_unfoldHeaders(rawHeaders));
|
|
357
360
|
for (var li = 0; li < lines.length; li++) {
|
|
358
361
|
var line = lines[li];
|
|
359
|
-
|
|
360
|
-
|
|
362
|
+
/** @internal A part's header name and value are cut, trimmed and folded through the captured
|
|
363
|
+
* operations. One of those headers is the part's own content type, which selects the reader
|
|
364
|
+
* its body goes to: measured, a part stating `application/pkcs8` was read as
|
|
365
|
+
* `application/pkcs7-mime` with a `smime-type` of `certs-only`. */
|
|
366
|
+
var col = _estIndexOf(line, ":");
|
|
367
|
+
if (col > 0) headers[_toLowerCase(_estTrim(_strSlice(line, 0, col)))] = _estTrim(_strSlice(line, col + 1));
|
|
361
368
|
}
|
|
362
369
|
var partCt = headers["content-type"] || "";
|
|
363
370
|
if (_ciStartsWith(partCt, "MULTIPART/")) throw E("est/bad-multipart", "a nested multipart part is not permitted");
|
|
364
|
-
|
|
371
|
+
intrinsic.append(parts, { headers: headers, contentType: partCt, body: partBody });
|
|
365
372
|
}
|
|
366
373
|
return parts;
|
|
367
374
|
}
|
|
@@ -457,29 +464,37 @@ function _recipientMatches(recipientInfos, opts) {
|
|
|
457
464
|
return false;
|
|
458
465
|
}
|
|
459
466
|
|
|
467
|
+
/** @internal The segments are collected through the captured append. Read off the prototype, a
|
|
468
|
+
* replacement decides which segments a parameter is then looked for in, and one of those parameters
|
|
469
|
+
* is the multipart boundary a response body is divided on: measured, a `boundary=wire` header
|
|
470
|
+
* yielded `forged`. */
|
|
460
471
|
function _splitContentTypeParams(s) {
|
|
461
472
|
var segs = [], cur = "", inQuote = false;
|
|
462
473
|
for (var i = 0; i < s.length; i++) {
|
|
463
|
-
var ch = s
|
|
474
|
+
var ch = _estCharAt(s, i);
|
|
464
475
|
if (ch === '"') { inQuote = !inQuote; cur += ch; }
|
|
465
|
-
else if (ch === ";" && !inQuote) {
|
|
476
|
+
else if (ch === ";" && !inQuote) { intrinsic.append(segs, cur); cur = ""; }
|
|
466
477
|
else cur += ch;
|
|
467
478
|
}
|
|
468
|
-
|
|
479
|
+
intrinsic.append(segs, cur);
|
|
469
480
|
return segs;
|
|
470
481
|
}
|
|
471
482
|
|
|
472
483
|
function _ctParam(contentType, name) {
|
|
473
|
-
var segs = _splitContentTypeParams(
|
|
484
|
+
var segs = _splitContentTypeParams(_stringOf(contentType || ""));
|
|
474
485
|
var value = null, count = 0;
|
|
486
|
+
/** @internal Each parameter is read through the captured operations. The name decides which
|
|
487
|
+
* parameter this is, and the value it returns is the one a caller acts on: for the RFC 7030
|
|
488
|
+
* multipart boundary, it is where a response body is split. */
|
|
475
489
|
for (var i = 1; i < segs.length; i++) {
|
|
476
|
-
var
|
|
490
|
+
var seg = segs[i];
|
|
491
|
+
var eq = _estIndexOf(seg, "=");
|
|
477
492
|
if (eq === -1) continue;
|
|
478
|
-
if (
|
|
493
|
+
if (_toLowerCase(_estTrim(_strSlice(seg, 0, eq))) !== name) continue;
|
|
479
494
|
count++;
|
|
480
495
|
if (count > 1) continue;
|
|
481
|
-
var val =
|
|
482
|
-
if (val.length >= 2 && val
|
|
496
|
+
var val = _estTrim(_strSlice(seg, eq + 1));
|
|
497
|
+
if (val.length >= 2 && _estCharAt(val, 0) === '"' && _estCharAt(val, val.length - 1) === '"') val = _strSlice(val, 1, -1);
|
|
483
498
|
value = val;
|
|
484
499
|
}
|
|
485
500
|
return { value: value, duplicated: count > 1 };
|
|
@@ -501,12 +516,15 @@ function _mediaType(seg) {
|
|
|
501
516
|
return _toLowerCase(_strSlice(seg, a, b));
|
|
502
517
|
}
|
|
503
518
|
|
|
519
|
+
/** @internal The media type and the S/MIME type are produced through the captured conversions. The
|
|
520
|
+
* media type selects which reader a part's body goes to, and read through the live global `String`
|
|
521
|
+
* a replacement chose it: measured, `text/plain` arrived as `application/pkcs8`. */
|
|
504
522
|
function _partMediaType(contentType) {
|
|
505
|
-
var segs = _splitContentTypeParams(
|
|
523
|
+
var segs = _splitContentTypeParams(_stringOf(contentType || ""));
|
|
506
524
|
var st = _ctParam(contentType, "smime-type");
|
|
507
525
|
return {
|
|
508
526
|
media: _mediaType(segs[0]),
|
|
509
|
-
smimeType: st.value === null ? null : st.value
|
|
527
|
+
smimeType: st.value === null ? null : _toLowerCase(st.value),
|
|
510
528
|
ambiguous: st.duplicated,
|
|
511
529
|
};
|
|
512
530
|
}
|
|
@@ -1279,7 +1297,7 @@ function _requestBinding(der) {
|
|
|
1279
1297
|
var body = cmcFmt.parse(der);
|
|
1280
1298
|
var ids = [];
|
|
1281
1299
|
var paths = [];
|
|
1282
|
-
[body.requests, body.controls, body.cmsSequence, body.otherMsgs]
|
|
1300
|
+
intrinsic.forEach([body.requests, body.controls, body.cmsSequence, body.otherMsgs], function (list) {
|
|
1283
1301
|
(list || []).forEach(function (el) {
|
|
1284
1302
|
if (el && el.bodyPartID != null) { ids.push(el.bodyPartID); paths.push([el.bodyPartID]); }
|
|
1285
1303
|
});
|
|
@@ -1325,7 +1343,7 @@ function _collectNestedPaths(list, prefix, out, depth) {
|
|
|
1325
1343
|
catch (_e) { /* allow:swallow-unverified the outer request must itself parse for this to run, which already rejects a malformed nested ContentInfo; a payload that survives that and still fails to read back lands on the same no-path refusal the non-pkiData route below takes, which the vectors drive */ return; }
|
|
1326
1344
|
if (!inner || inner.kind !== "pkiData") return;
|
|
1327
1345
|
var path = prefix.concat([el.bodyPartID]);
|
|
1328
|
-
[inner.requests, inner.controls, inner.cmsSequence, inner.otherMsgs]
|
|
1346
|
+
intrinsic.forEach([inner.requests, inner.controls, inner.cmsSequence, inner.otherMsgs], function (l) {
|
|
1329
1347
|
(l || []).forEach(function (e2) { if (e2 && e2.bodyPartID != null) out.push(path.concat([e2.bodyPartID])); });
|
|
1330
1348
|
});
|
|
1331
1349
|
_collectNestedPaths(inner.cmsSequence, path, out, depth + 1);
|
|
@@ -1405,7 +1423,7 @@ function _fullcmcResult(res, opts, wanted, sent) {
|
|
|
1405
1423
|
}
|
|
1406
1424
|
var smimeType = pt200.smimeType;
|
|
1407
1425
|
if (smimeType === "certs-only") {
|
|
1408
|
-
var unecho = ["transactionId", "senderNonce", "dataReturn"]
|
|
1426
|
+
var unecho = intrinsic.selectList(["transactionId", "senderNonce", "dataReturn"], function (k) {
|
|
1409
1427
|
return sent[k] != null;
|
|
1410
1428
|
});
|
|
1411
1429
|
if (unecho.length) {
|
|
@@ -1731,21 +1749,23 @@ function _assertConfidentialCipher(res) {
|
|
|
1731
1749
|
|
|
1732
1750
|
function _ciHeaderList(headers, name) {
|
|
1733
1751
|
headers = headers || {};
|
|
1734
|
-
|
|
1752
|
+
/** @internal The header NAME a value is selected under is folded through the captured conversion on
|
|
1753
|
+
* both sides of the comparison: the match decides which header this response is read from. */
|
|
1754
|
+
var lname = _toLowerCase(name), keys = guard.identifier.optionNames(headers), parts = [];
|
|
1735
1755
|
for (var i = 0; i < keys.length; i++) {
|
|
1736
|
-
if (keys[i]
|
|
1756
|
+
if (_toLowerCase(keys[i]) !== lname) continue;
|
|
1737
1757
|
var v = headers[keys[i]];
|
|
1738
1758
|
if (v == null) continue;
|
|
1739
|
-
|
|
1759
|
+
intrinsic.append(parts, intrinsic.isArray(v) ? intrinsic.join(v, ", ") : _stringOf(v));
|
|
1740
1760
|
}
|
|
1741
|
-
return parts.length ?
|
|
1761
|
+
return parts.length ? intrinsic.join(parts, ", ") : null;
|
|
1742
1762
|
}
|
|
1743
1763
|
|
|
1744
1764
|
function _ciHeader(headers, name) {
|
|
1745
1765
|
headers = headers || {};
|
|
1746
|
-
var lname = name
|
|
1766
|
+
var lname = _toLowerCase(name), keys = guard.identifier.optionNames(headers), found = null, n = 0;
|
|
1747
1767
|
for (var i = 0; i < keys.length; i++) {
|
|
1748
|
-
if (keys[i]
|
|
1768
|
+
if (_toLowerCase(keys[i]) !== lname) continue;
|
|
1749
1769
|
n += 1;
|
|
1750
1770
|
if (n === 1) found = headers[keys[i]];
|
|
1751
1771
|
}
|
package/lib/guard-identifier.js
CHANGED
|
@@ -257,7 +257,7 @@ var _CONCRETE_TYPED_MEMBERS = ["BYTES_PER_ELEMENT"];
|
|
|
257
257
|
var _BUFFER_PROTO_MEMBERS = ["parent", "offset"];
|
|
258
258
|
|
|
259
259
|
var _ARRAY_MEMBERS = _ARRAY_PROTO_MEMBERS;
|
|
260
|
-
var _REGEXP_MEMBERS = ["lastIndex"]
|
|
260
|
+
var _REGEXP_MEMBERS = intrinsic.concatList(["lastIndex"], _REGEXP_PROTO_MEMBERS);
|
|
261
261
|
var _VIEW_MEMBERS = _TYPED_PROTO_MEMBERS.concat(_CONCRETE_TYPED_MEMBERS);
|
|
262
262
|
var _BUFFER_KIND_MEMBERS = _VIEW_MEMBERS.concat(_BUFFER_PROTO_MEMBERS);
|
|
263
263
|
var _DATAVIEW_MEMBERS = _DATAVIEW_PROTO_MEMBERS;
|
package/lib/key.js
CHANGED
|
@@ -48,6 +48,10 @@ var _floor = intrinsic.floor;
|
|
|
48
48
|
var _isFinite = intrinsic.isFinite;
|
|
49
49
|
var _String = intrinsic.String;
|
|
50
50
|
var _toUpperCase = intrinsic.toUpperCase;
|
|
51
|
+
/** @internal The walk over an array LITERAL is captured too. The receiver is the literal rather than
|
|
52
|
+
* a caller's value, but the method is still read off the live prototype at the moment it runs, and a
|
|
53
|
+
* replacement decides which rows of a registry this module builds. */
|
|
54
|
+
var _forEach = intrinsic.forEach;
|
|
51
55
|
var _strIndexOf = intrinsic.stringIndexOf;
|
|
52
56
|
|
|
53
57
|
var b = asn1.build;
|
|
@@ -60,13 +64,13 @@ function _err(code, msg, cause) { return new KeyError(code, msg, cause); }
|
|
|
60
64
|
var CIPHER_NAME = _assign(_create(null), { "aes-128-cbc": "aes128-CBC", "aes-192-cbc": "aes192-CBC", "aes-256-cbc": "aes256-CBC" });
|
|
61
65
|
|
|
62
66
|
var INFER_ALG = _create(null);
|
|
63
|
-
["Ed25519", "Ed448", "X25519", "X448"]
|
|
64
|
-
[["id-ml-dsa-44", "ML-DSA-44"], ["id-ml-dsa-65", "ML-DSA-65"], ["id-ml-dsa-87", "ML-DSA-87"],
|
|
65
|
-
|
|
66
|
-
]
|
|
67
|
-
["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
68
|
-
|
|
69
|
-
]
|
|
67
|
+
_forEach(["Ed25519", "Ed448", "X25519", "X448"], function (n) { INFER_ALG[O(n)] = { name: n }; });
|
|
68
|
+
_forEach([["id-ml-dsa-44", "ML-DSA-44"], ["id-ml-dsa-65", "ML-DSA-65"], ["id-ml-dsa-87", "ML-DSA-87"],
|
|
69
|
+
["id-ml-kem-512", "ML-KEM-512"], ["id-ml-kem-768", "ML-KEM-768"], ["id-ml-kem-1024", "ML-KEM-1024"]
|
|
70
|
+
], function (r) { INFER_ALG[O(r[0])] = { name: r[1] }; });
|
|
71
|
+
_forEach(["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
72
|
+
"shake-128s", "shake-128f", "shake-192s", "shake-192f", "shake-256s", "shake-256f"
|
|
73
|
+
], function (s) { INFER_ALG[O("id-slh-dsa-" + s)] = { name: _toUpperCase("SLH-DSA-" + s) }; });
|
|
70
74
|
|
|
71
75
|
function _isCryptoKey(x) { return webcrypto.isCryptoKeyLike(x); }
|
|
72
76
|
function _algName(a) { return typeof a === "string" ? a : (a && a.name); }
|
package/lib/path-validate.js
CHANGED
|
@@ -179,9 +179,9 @@ _sig("Ed448", { name: "Ed448" }, { name: "Ed448" }, "absent", false, true);
|
|
|
179
179
|
_sig("id-ml-dsa-44", { name: "ML-DSA-44" }, { name: "ML-DSA-44" }, "absent", false, true);
|
|
180
180
|
_sig("id-ml-dsa-65", { name: "ML-DSA-65" }, { name: "ML-DSA-65" }, "absent", false, true);
|
|
181
181
|
_sig("id-ml-dsa-87", { name: "ML-DSA-87" }, { name: "ML-DSA-87" }, "absent", false, true);
|
|
182
|
-
["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
183
|
-
|
|
184
|
-
]
|
|
182
|
+
intrinsic.forEach(["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
183
|
+
"shake-128s", "shake-128f", "shake-192s", "shake-192f", "shake-256s", "shake-256f"
|
|
184
|
+
], function (set) {
|
|
185
185
|
var wc = "SLH-DSA-" + set.toUpperCase();
|
|
186
186
|
_sig("id-slh-dsa-" + set, { name: wc }, { name: wc }, "absent", false, true);
|
|
187
187
|
});
|
|
@@ -304,7 +304,7 @@ function compositeKeyUsageCheck(cert) {
|
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
var STATEFUL_HBS_OIDS = intrinsic.create(null);
|
|
307
|
-
["id-alg-hss-lms-hashsig", "id-alg-xmss-hashsig", "id-alg-xmssmt-hashsig"]
|
|
307
|
+
intrinsic.forEach(["id-alg-hss-lms-hashsig", "id-alg-xmss-hashsig", "id-alg-xmssmt-hashsig"], function (n) { STATEFUL_HBS_OIDS[oid.byName(n)] = true; });
|
|
308
308
|
|
|
309
309
|
/** @internal RFC 9802 sec. 6 states the rule twice, and the two differ: a certification authority's
|
|
310
310
|
* certificate may assert keyCertSign, an end entity's may not. Both must assert at least one of the values
|
|
@@ -404,7 +404,7 @@ function statefulHbsKeyUsageCheck(cert, isCa) {
|
|
|
404
404
|
}
|
|
405
405
|
|
|
406
406
|
var ML_KEM_OIDS = intrinsic.create(null);
|
|
407
|
-
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"]
|
|
407
|
+
intrinsic.forEach(["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"], function (n) { ML_KEM_OIDS[oid.byName(n)] = true; });
|
|
408
408
|
|
|
409
409
|
function kemKeyUsageCheck(cert) {
|
|
410
410
|
var ku;
|
package/lib/pki-build.js
CHANGED
|
@@ -359,8 +359,8 @@ var ATV_TYPE = intrinsic.assign(intrinsic.create(null), {
|
|
|
359
359
|
* pre-encoded value for one of them must be a member. An attribute with no published short
|
|
360
360
|
* name has a syntax this toolkit does not claim to know, and its value stays opaque. */
|
|
361
361
|
var DIRECTORY_STRING_TAGS = intrinsic.assign(intrinsic.create(null), {});
|
|
362
|
-
[asn1.TAGS.TELETEX_STRING, asn1.TAGS.PRINTABLE_STRING, asn1.TAGS.UNIVERSAL_STRING,
|
|
363
|
-
asn1.TAGS.UTF8_STRING, asn1.TAGS.BMP_STRING]
|
|
362
|
+
intrinsic.forEach([asn1.TAGS.TELETEX_STRING, asn1.TAGS.PRINTABLE_STRING, asn1.TAGS.UNIVERSAL_STRING,
|
|
363
|
+
asn1.TAGS.UTF8_STRING, asn1.TAGS.BMP_STRING], function (t) { DIRECTORY_STRING_TAGS[t] = 1; });
|
|
364
364
|
|
|
365
365
|
var KU_BIT = intrinsic.assign(intrinsic.create(null), {
|
|
366
366
|
digitalSignature: 0, nonRepudiation: 1, contentCommitment: 1, keyEncipherment: 2,
|
|
@@ -396,12 +396,12 @@ var SDA_ATTR_KEYS = intrinsic.assign(intrinsic.create(null), { type: 1, values:
|
|
|
396
396
|
* statement's set is refused rather than ignored: a misspelled field would otherwise be dropped and
|
|
397
397
|
* the certificate would carry a statement the caller did not write. */
|
|
398
398
|
var QC_INFO_KEYS = intrinsic.create(null);
|
|
399
|
-
[["qcType", { types: 1 }], ["qcIdentMethod", { methods: 1 }],
|
|
399
|
+
intrinsic.forEach([["qcType", { types: 1 }], ["qcIdentMethod", { methods: 1 }],
|
|
400
400
|
["qcCClegislation", { countries: 1 }], ["qcQSCDlegislation", { countries: 1 }],
|
|
401
401
|
["qcRetentionPeriod", { years: 1 }], ["qcLimitValue", { currency: 1, amount: 1, exponent: 1 }],
|
|
402
402
|
["qcPDS", { locations: 1 }],
|
|
403
403
|
["qcsPkixQCSyntaxV1", { semanticsIdentifier: 1, nameRegistrationAuthorities: 1 }],
|
|
404
|
-
["qcsPkixQCSyntaxV2", { semanticsIdentifier: 1, nameRegistrationAuthorities: 1 }]]
|
|
404
|
+
["qcsPkixQCSyntaxV2", { semanticsIdentifier: 1, nameRegistrationAuthorities: 1 }]], function (r) {
|
|
405
405
|
QC_INFO_KEYS[oid.byName(r[0])] = intrinsic.assign(intrinsic.create(null), r[1]);
|
|
406
406
|
});
|
|
407
407
|
var QC_PDS_LOCATION_KEYS = intrinsic.assign(intrinsic.create(null), { url: 1, language: 1 });
|
package/lib/sign-scheme.js
CHANGED
|
@@ -69,10 +69,10 @@ function mldsaDigestSuitable(mlName, md) {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
var SLHDSA_BY_OID = intrinsic.create(null);
|
|
72
|
-
[["sha2-128s", "sha256"], ["sha2-128f", "sha256"], ["sha2-192s", "sha512"], ["sha2-192f", "sha512"],
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
]
|
|
72
|
+
intrinsic.forEach([["sha2-128s", "sha256"], ["sha2-128f", "sha256"], ["sha2-192s", "sha512"], ["sha2-192f", "sha512"],
|
|
73
|
+
["sha2-256s", "sha512"], ["sha2-256f", "sha512"], ["shake-128s", "shake128"], ["shake-128f", "shake128"],
|
|
74
|
+
["shake-192s", "shake256"], ["shake-192f", "shake256"], ["shake-256s", "shake256"], ["shake-256f", "shake256"]
|
|
75
|
+
], function (r) { SLHDSA_BY_OID[O("id-slh-dsa-" + r[0])] = { wc: "SLH-DSA-" + _toUpperCase(r[0]), digest: r[1] }; });
|
|
76
76
|
|
|
77
77
|
function _algId(name, shape) { return shape === "null" ? b.sequence([b.oid(O(name)), b.nullValue()]) : b.sequence([b.oid(O(name))]); }
|
|
78
78
|
function _pssAlgId(digestName) {
|
package/lib/webcrypto.js
CHANGED
|
@@ -176,9 +176,9 @@ var ML_DSA_NODE = intrinsic.assign(intrinsic.create(null), { "ML-DSA-44": "ml-ds
|
|
|
176
176
|
var ML_KEM_NODE = intrinsic.assign(intrinsic.create(null), { "ML-KEM-512": "ml-kem-512", "ML-KEM-768": "ml-kem-768", "ML-KEM-1024": "ml-kem-1024" });
|
|
177
177
|
|
|
178
178
|
var SLH_DSA_NODE = intrinsic.create(null);
|
|
179
|
-
["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
180
|
-
|
|
181
|
-
]
|
|
179
|
+
_forEach(["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
180
|
+
"shake-128s", "shake-128f", "shake-192s", "shake-192f", "shake-256s", "shake-256f"
|
|
181
|
+
], function (s) { SLH_DSA_NODE["SLH-DSA-" + _toUpperCase(s)] = "slh-dsa-" + s; });
|
|
182
182
|
|
|
183
183
|
var SIGN_VERIFY_NAMES = intrinsic.create(null);
|
|
184
184
|
["RSASSA-PKCS1-V1_5", "RSA-PSS", "ECDSA", "ED25519", "ED448", "HMAC"]
|
|
@@ -868,7 +868,7 @@ function _nodeKey(fn, who) {
|
|
|
868
868
|
}
|
|
869
869
|
|
|
870
870
|
var ML_KEM_INNER = intrinsic.create(null);
|
|
871
|
-
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"]
|
|
871
|
+
_forEach(["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"], function (n) {
|
|
872
872
|
var row = oid.kemParams(n);
|
|
873
873
|
ML_KEM_INNER[oid.byName(n)] = { ek: row.ek, dk: row.dk };
|
|
874
874
|
});
|
|
@@ -1010,7 +1010,7 @@ var IMPORT_KEY_TYPE = intrinsic.assign(intrinsic.create(null), {
|
|
|
1010
1010
|
"ED25519": _typeSet(["ed25519"]), "ED448": _typeSet(["ed448"]),
|
|
1011
1011
|
"X25519": _typeSet(["x25519"]), "X448": _typeSet(["x448"]),
|
|
1012
1012
|
});
|
|
1013
|
-
[ML_DSA_NODE, ML_KEM_NODE, SLH_DSA_NODE]
|
|
1013
|
+
_forEach([ML_DSA_NODE, ML_KEM_NODE, SLH_DSA_NODE], function (m) {
|
|
1014
1014
|
_forEach(_keys(m), function (webName) { IMPORT_KEY_TYPE[webName] = _typeSet([m[webName]]); });
|
|
1015
1015
|
});
|
|
1016
1016
|
function _algFromImport(name, alg, keyObject) {
|
package/package.json
CHANGED
package/sbom.cdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
|
|
3
3
|
"bomFormat": "CycloneDX",
|
|
4
4
|
"specVersion": "1.5",
|
|
5
|
-
"serialNumber": "urn:uuid:
|
|
5
|
+
"serialNumber": "urn:uuid:2b5749b0-053a-41de-947c-63a7a8df8028",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-10-
|
|
8
|
+
"timestamp": "2026-10-07T05:12:27.182Z",
|
|
9
9
|
"lifecycles": [
|
|
10
10
|
{
|
|
11
11
|
"phase": "build"
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"component": {
|
|
22
|
-
"bom-ref": "@blamejs/pki@0.8.
|
|
22
|
+
"bom-ref": "@blamejs/pki@0.8.59",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "pki",
|
|
25
|
-
"version": "0.8.
|
|
25
|
+
"version": "0.8.59",
|
|
26
26
|
"scope": "required",
|
|
27
27
|
"author": "blamejs contributors",
|
|
28
28
|
"description": "Pure-JavaScript PKI toolkit that owns its stack — X.509, ASN.1/DER, CMS, PQC-first.",
|
|
29
|
-
"purl": "pkg:npm/%40blamejs/pki@0.8.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/pki@0.8.59",
|
|
30
30
|
"properties": [],
|
|
31
31
|
"externalReferences": [
|
|
32
32
|
{
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"components": [],
|
|
55
55
|
"dependencies": [
|
|
56
56
|
{
|
|
57
|
-
"ref": "@blamejs/pki@0.8.
|
|
57
|
+
"ref": "@blamejs/pki@0.8.59",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|