@blamejs/pki 0.6.40 → 0.6.42
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 +25 -0
- package/README.md +1 -1
- package/lib/acme.js +24 -13
- package/lib/asn1-der.js +5 -5
- package/lib/attrcert-sign.js +14 -14
- package/lib/cbor-det.js +2 -2
- package/lib/cmc-build.js +16 -16
- package/lib/cmc-verify.js +5 -5
- package/lib/cmp-build.js +29 -19
- package/lib/cmp-session.js +21 -16
- package/lib/cmp-verify.js +4 -4
- package/lib/cms-decrypt.js +8 -8
- package/lib/cms-encrypt.js +22 -22
- package/lib/cms-sign.js +17 -17
- package/lib/cms-verify.js +6 -6
- package/lib/composite-kem.js +1 -1
- package/lib/composite-sig.js +4 -4
- package/lib/constants.js +13 -9
- package/lib/crl-sign.js +17 -17
- package/lib/crmf-sign.js +11 -11
- package/lib/csr-sign.js +2 -2
- package/lib/ct.js +19 -11
- package/lib/edwards-point.js +2 -2
- package/lib/est.js +74 -43
- package/lib/guard-async.js +17 -1
- package/lib/guard-bytes.js +2 -2
- package/lib/guard-compress.js +5 -5
- package/lib/guard-identifier.js +45 -1
- package/lib/guard-name.js +272 -1
- package/lib/guard-time.js +3 -1
- package/lib/hpke.js +10 -10
- package/lib/http-digest.js +2 -2
- package/lib/http-transport.js +3 -3
- package/lib/inspect.js +9 -9
- package/lib/jose.js +14 -14
- package/lib/key.js +7 -7
- package/lib/lint.js +6 -4
- package/lib/merkle.js +2 -2
- package/lib/mime.js +2 -2
- package/lib/ocsp-verify.js +1 -1
- package/lib/ocsp.js +5 -5
- package/lib/oid.js +3 -3
- package/lib/path-validate.js +50 -120
- package/lib/pbes2.js +2 -2
- package/lib/pkcs12-build.js +15 -15
- package/lib/pki-build.js +2 -2
- package/lib/scep.js +47 -16
- package/lib/schema-all.js +1 -1
- package/lib/schema-attrcert.js +4 -3
- package/lib/schema-c509.js +23 -23
- package/lib/schema-cmc.js +6 -6
- package/lib/schema-cmp.js +3 -3
- package/lib/schema-cms.js +15 -8
- package/lib/schema-crmf.js +1 -1
- package/lib/schema-csr.js +1 -1
- package/lib/schema-engine.js +2 -1
- package/lib/schema-pkcs12.js +1 -1
- package/lib/schema-pkix.js +3 -0
- package/lib/schema-tsp.js +2 -2
- package/lib/shbs.js +2 -2
- package/lib/sign-scheme.js +9 -9
- package/lib/sigstore.js +9 -8
- package/lib/smime.js +12 -12
- package/lib/tls-cert-compress.js +6 -6
- package/lib/trust.js +179 -10
- package/lib/tsp-sign.js +11 -11
- package/lib/validator-attcert.js +2 -2
- package/lib/validator-cose.js +5 -5
- package/lib/validator-sig.js +3 -3
- package/lib/validator-tpm.js +5 -4
- package/lib/webauthn.js +12 -12
- package/lib/webcrypto.js +22 -14
- package/lib/x509-sign.js +8 -8
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,31 @@ 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.6.42 — 2026-09-06
|
|
8
|
+
|
|
9
|
+
A trust anchor carries the namespace a root program trusts a root for, so a certificate outside it is refused even where the root certificate states no such limit.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- pki.trust.anchor(entry, opts) accepts opts.nameConstraints, the namespace a root program applies to a root outside any extension the root certificate carries. It is a { permitted, excluded } pair of { tag, base } subtrees, the shape pki.path.validate takes for opts.initialPermittedSubtrees, and validate seeds it as the RFC 5280 section 6.1.1(h)(i) initial value: it intersects with each certificate's own nameConstraints so a leaf must satisfy both, and an excluded subtree rejects a name whatever the permitted set says. A verdict reports it at anchorConstraints.nameConstraintsApplied. The subtrees are copied out of the caller's object, so changing that object afterwards leaves the namespace an anchor already vouches for unchanged. An overlay naming no subtree, one carrying a malformed subtree, and one supplying its subtrees through an accessor are each refused with trust/bad-input, since carrying any of them would widen the namespace the operator asked to restrict.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- pki.path.validate refuses a subtree in opts.initialPermittedSubtrees, opts.initialExcludedSubtrees, or a trust anchor's nameConstraints whose base is outside the form its tag names, with path/bad-input. Tag 1 is a mailbox, a host name, or a host name written as a subtree with a leading dot, and a mailbox may name its domain as a bracketed IPv4 or IPv6 address literal; tags 2 and 6 are host names, and a tag-6 base is the dotted host a certificate's URI is compared by rather than a URI; tag 4 names at least one relative name, with dotted-decimal object identifier types and string values; tag 7 is 8 bytes for IPv4 or 32 for IPv6. A host name is labels of letters, digits and hyphens, with a hyphen at neither edge of a label, 63 characters to a label and 253 to the name. An anchor whose nameConstraints names no subtree at all is refused the same way. Such a base previously reached the comparison, where it either matched every name, so a permitted subtree restricted nothing, or matched none, so an excluded subtree kept nothing out. A certificate's own nameConstraints extension is unaffected and is compared as the certificate wrote it.
|
|
18
|
+
|
|
19
|
+
## v0.6.41 — 2026-09-05
|
|
20
|
+
|
|
21
|
+
A lookup table answers from its own entries, so a name taken off the wire cannot resolve to something the table never registered.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Every object the toolkit publishes as a table carries no prototype: pki.C.TIME, pki.C.BYTES, pki.C.LIMITS, pki.C.NAMES and each name table under it, pki.asn1.TAGS, pki.asn1.build, pki.cbor.build, pki.ct.HASH_ALGORITHMS, pki.ct.SIGNATURE_ALGORITHMS, pki.hpke.suites, pki.path.PROCESSED_EXTENSIONS and pki.path.TARGET_UNPROCESSED_IF_CRITICAL. The same holds for a map a verb returns that is keyed by names it read, rather than by a fixed set of fields. Among them: the results of pki.oid.all, pki.est.paths and pki.scep.parseCapabilities, the headers on a pki.transport response and on each part pki.est.splitMultipartMixed returns, the counts map on a pki.lint.certificate result, the extensions map on a pki.sigstore.verifyBundle identity, and the purposes map on each anchor from pki.trust.parseCertdata, pki.trust.parseCcadbCsv and pki.trust.anchor. A result read by a fixed set of field names keeps the prototype it had, which covers parsed certificates, decoded WebAuthn authenticator data, CMS recipient identifiers and the other parse records. Reading an entry, calling a member, listing the keys, spreading, destructuring and serializing to JSON are unchanged; calling an Object.prototype method on the object itself, such as table.hasOwnProperty(name), no longer works, so use Object.hasOwn(table, name).
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- A lookup table carries no prototype, so a name the wire supplies resolves to an entry the table registered or to nothing. Two verbs were reachable: pki.webauthn.verify selected a verifier the table never held for an attestation naming constructor, toString or another Object.prototype member as its format, and pki.schema.c509.parse accepted a certificate whose subject-public-key algorithm named such a member instead of throwing c509/unknown-algorithm. The same change applies to the signature-scheme, content-encryption, key-agreement, extension-decoder and status-name registries.
|
|
30
|
+
- Every verb that takes an injected opts.transport names the option when the value is not callable, refusing it with the module's own bad-input code at the door, before the message or the certificate is read. This covers all eighteen: the six pki.est verbs, the seven pki.scep verbs, pki.acme.client, pki.cmp.transfer, pki.cmp.session, pki.ct.fetchLogList and pki.path.build. Previously most of them let the value reach the call site, where the operator got a bare TypeError naming no option. A falsy transport and an explicit null are refused the same way. Either had been read as no transport supplied and replaced with the default network client, so a caller that believed it had injected a transport reached the CA instead, which is the case worth upgrading for. Only an option no lookup finds falls back, so a defaults object carrying the transport on its prototype still works. A value that passes for callable and then throws when it is called, which is what a class constructor does, is reported as that verb's typed error too, rather than escaping as a TypeError.
|
|
31
|
+
|
|
7
32
|
## v0.6.40 — 2026-09-05
|
|
8
33
|
|
|
9
34
|
Every verify verdict now reaches its caller as the object the verb built, and a list the toolkit assembles carries the entries the toolkit put in it.
|
package/README.md
CHANGED
|
@@ -245,7 +245,7 @@ comment blocks, is at [pkijs.com](https://pkijs.com).
|
|
|
245
245
|
| `pki.ocsp` | Online Certificate Status Protocol (RFC 6960), both the responder and relying-party surface. `buildRequest(query, opts)` builds an OCSPRequest for one or more `{ cert, issuer }` pairs, with the CertID hashed under SHA-1 by default per the RFC 5019 lightweight profile or under SHA-2, plus an optional RFC 9654 nonce and an optional requestor signature. `sign(responseData, responder, opts)` produces a signed BasicOCSPResponse over the exact `ResponseData` DER, from the issuing CA directly or a delegated responder, under any `pki.cms.sign` key including the post-quantum ML-DSA and SLH-DSA sets, with `good`, `revoked` (reason and time), or `unknown` per-certificate status. `buildErrorResponse(status)` produces the unsigned §2.3 error (`tryLater`, `unauthorized`, and the rest). `verify(response, opts)` verifies a response fail-closed against the same hardened gates `pki.path.ocspChecker` runs: the CertID binding, responder authorization (the issuing CA, or a CA-issued delegate bearing id-kp-OCSPSigning and id-pkix-ocsp-nocheck and passing the full out-of-path certificate gates), the signature over `tbsResponseDataBytes`, currency against `thisUpdate` and `nextUpdate`, and the request-nonce echo. It returns `{ status: "good" / "revoked" / "unknown", ... }` and never silently accepts. `verifyRequest(request, opts)` is the responder-side inverse of `buildRequest`: it verifies a client's signed request (RFC 6960 §4.1.1) under the requestor certificate the request carries, trying each embedded certificate since the field is unordered, and reports `signed`, `signatureValid`, every certificate whose key verified (`signerCerts`, so a key carried under an expired certificate beside its renewal is not hidden behind ordering) with the first one's decoded subject, the full embedded certificate bag (`certs`, including intermediates for path building), and the request's CertIDs; an unsigned request is reported with `signed: false` rather than refused. Transport-free — `buildRequest`, `sign`, `buildErrorResponse`, `verify`, `verifyRequest` |
|
|
246
246
|
| `pki.ct` | Certificate Transparency (RFC 6962). `parseSctList` decodes the `SignedCertificateTimestampList` a certificate or OCSP response carries, a TLS-presentation-language payload inside the §3.3 double DER wrap, into per-SCT log id, exact `timestamp` (BigInt), named signature algorithm, and raw signature. `reconstructSignedData` rebuilds the exact `digitally-signed` preimage, and `verifySct` verifies an SCT signature against a log's public key, routing an ECDSA signature through the strict DER-conformance gate and verifying through the crypto engine, resolving true or false and throwing a typed error on a structural fault. On the producing side, `encodeSctList` builds the extension value byte for byte as the exact inverse of `parseSctList`, and `signSct` performs a log's signing step. For trust, `parseLogList` ingests the CT log-list JSON into constraint-carrying trusted logs, recomputing each log's id as SHA-256 of its key and refusing a disagreeing id (a swapped key, §3.2) and decoding the state and temporal-interval constraints; `verifySctWithLogList` resolves the log key from an SCT's log id, enforces the state (usable, qualified, and readonly trusted; retired only before retirement; pending and rejected refused) and the temporal-interval window, then delegates the signature check to `verifySct`. `verifyLogListSignature(json, signature, publicKey)` verifies the detached `log_list.sig` over the raw log-list bytes against a caller-pinned signer key (RSASSA-PKCS1-v1.5/SHA-256 and an EC P-256 arm, with forgeable-key defenses failing closed), cross-checked against `openssl dgst`. `fetchLogList(opts)` turns that chain into a live client: it GETs the `log_list.json` and its detached `log_list.sig` over `pki.transport`, verifies the detached signature over the raw fetched bytes against a caller-pinned distributor key before parsing, so an unverified document is never parsed, read, cached, or surfaced, then ingests the same bytes through `parseLogList` and returns the trusted-log set plus the surfaced `version` and `timestamp`. Above the per-SCT layer, `verifySctList` renders a certificate-level verdict over every SCT a certificate carries (§3.3), reporting how many distinct trusted logs verified an SCT (so a duplicated SCT cannot inflate the count) and from how many distinct trusted operators against a caller's CT policy (`minScts` and `minOperators`, both defaulting to the RFC floor of one), where a policy shortfall is a verdict and a per-SCT failure is a recorded row rather than a thrown call; `x509CertEntry` reconstructs the precertificate log entry from a final certificate by removing the SCT-list extension from its TBSCertificate as byte surgery, so its embedded SCTs verify end to end (§3.2). The toolkit bakes in no vendor URL or key, TLS trust is explicit with `rejectUnauthorized` always on, each response is size-capped before the trust chain, and the transport is injectable so the whole path is testable offline — `parseSctList`, `reconstructSignedData`, `verifySct`, `encodeSctList`, `signSct`, `parseLogList`, `verifySctWithLogList`, `verifySctList`, `x509CertEntry`, `verifyLogListSignature`, `fetchLogList` |
|
|
247
247
|
| `pki.merkle` | Merkle-tree proof verification (RFC 6962 / RFC 9162). `leafHash`, `nodeHash`, and `emptyRootHash` build the domain-separated (0x00 leaf, 0x01 node) SHA-256 tree hashes. `verifyInclusion` folds an audit proof back to a root, and `verifyConsistency` reconstructs both the old and new root, which is the append-only guarantee; each is constant-time-compared to a trusted checkpoint root. Fail-closed on bad geometry, sync hashing, transport-free — `leafHash`, `nodeHash`, `emptyRootHash`, `verifyInclusion`, `verifyConsistency` |
|
|
248
|
-
| `pki.trust` | Mozilla and CCADB trust-store ingestion. `parseCertdata` reads the NSS `certdata.txt` object stream and `parseCcadbCsv` the CCADB CSV export, both into one constraint-carrying anchor shape: the per-purpose trust bits, where only `CKT_NSS_TRUSTED_DELEGATOR` grants, and the per-purpose distrust-after dates the bare root list omits. Certificate and trust objects pair by byte-exact issuer and serial rather than adjacency and are cross-checked against the parsed DER, so metadata cannot attach to the wrong root. `anchor()` hands an entry to `pki.path.validate({ trustAnchors, checkPurpose })
|
|
248
|
+
| `pki.trust` | Mozilla and CCADB trust-store ingestion. `parseCertdata` reads the NSS `certdata.txt` object stream and `parseCcadbCsv` the CCADB CSV export, both into one constraint-carrying anchor shape: the per-purpose trust bits, where only `CKT_NSS_TRUSTED_DELEGATOR` grants, and the per-purpose distrust-after dates the bare root list omits. Certificate and trust objects pair by byte-exact issuer and serial rather than adjacency and are cross-checked against the parsed DER, so metadata cannot attach to the wrong root. `anchor()` hands an entry to `pki.path.validate({ trustAnchors, checkPurpose })`, and `anchor(entry, { nameConstraints })` attaches the namespace a root program trusts a root for when that is narrower than the root certificate states, a `{ permitted, excluded }` pair of `{ tag, base }` subtrees that `validate` seeds as the RFC 5280 §6.1.1(h)(i) initial value, intersecting with each certificate's own constraints. Offline, fail-closed, bounded — `parseCertdata`, `parseCcadbCsv`, `anchor` |
|
|
249
249
|
| `pki.shbs` | Stateful hash-based signature verification: HSS/LMS (RFC 8554), carried in X.509 by RFC 9802 and in CMS by RFC 9708, profiled by NIST SP 800-208 for CNSA 2.0 firmware signing. `verify` checks an HSS signature, where every level must pass, and `verifyLms` a single-tree LMS, over the raw public-key and signature blobs the parsers already surface. Pure public-input SHA-256 and SHAKE256 hashing, a data-driven typecode registry, and bounds-before-slice reads; a malformed blob throws a typed `ShbsError` while a well-formed but wrong signature returns `false`. Verification only by design, since stateful signing needs atomic one-time-key state that belongs in an HSM — `verify`, `verifyLms` |
|
|
250
250
|
| `pki.hpke` | Hybrid Public Key Encryption (RFC 9180), the encrypt-to-a-public-key primitive behind TLS ECH, MLS, and OHTTP. `setupS` and `setupR` establish a sender or recipient context (KEM encapsulation plus the HKDF key schedule); the context's `seal` and `open` AEAD-encrypt with a sequence-counter nonce, and `export` derives further secrets; the module-level `seal` and `open` are single-shot wrappers. DHKEM (P-256, P-521, X25519, X448) by HKDF-SHA256/SHA512 by AES-GCM / ChaCha20Poly1305 / export-only, across all four modes, proven against the RFC 9180 Appendix A vectors. DHKEM(P-384) and HKDF-SHA384 are RFC-registered but Appendix A ships no vector for them, so they fail closed until an authoritative KAT exists. Pure composition over `node:crypto`; ML-KEM and X-Wing are a registry data-row extension pending stable drafts — `suites`, `setupS`, `setupR`, `seal`, `open` |
|
|
251
251
|
| `pki.kem` | Composite ML-KEM key establishment (draft-ietf-lamps-pq-composite-kem), a post-quantum ML-KEM hybridized with a traditional RSA-OAEP, ECDH, X25519, or X448 so the established secret holds if either component is later broken. `encapsulate` turns a recipient's composite `SubjectPublicKeyInfo` into a 256-bit shared secret and a ciphertext; `decapsulate` recovers the same secret from the ciphertext and the composite PKCS#8 private key. Each component KEM runs independently and the two secrets are mixed through a SHA3-256 combiner that binds the traditional ciphertext, the traditional public key, and a per-algorithm label. The twelve algorithms pair ML-KEM-768 and ML-KEM-1024 with RSA-OAEP 2048/3072/4096, ECDH over P-256/P-384/P-521 and brainpoolP256r1/P384r1, X25519, and X448, each verified against the draft Appendix G known-answer vectors; a malformed key or ciphertext, an unsupported algorithm, or a component decapsulation failure throws a typed `KemError` — `encapsulate`, `decapsulate` |
|
package/lib/acme.js
CHANGED
|
@@ -215,14 +215,14 @@ function _isUriString(v) { return _isString(v) && _isUriShape(v); }
|
|
|
215
215
|
|
|
216
216
|
var CRL_REASONS = [0, 1, 2, 3, 4, 5, 6, 8, 9, 10];
|
|
217
217
|
|
|
218
|
-
var KNOWN_CHALLENGE_TYPES = { "http-01": 1, "dns-01": 1, "tls-alpn-01": 1 };
|
|
218
|
+
var KNOWN_CHALLENGE_TYPES = intrinsic.assign(intrinsic.create(null), { "http-01": 1, "dns-01": 1, "tls-alpn-01": 1 });
|
|
219
219
|
|
|
220
|
-
var STATUS = {
|
|
220
|
+
var STATUS = intrinsic.assign(intrinsic.create(null), {
|
|
221
221
|
account: ["valid", "deactivated", "revoked"],
|
|
222
222
|
order: ["pending", "ready", "processing", "valid", "invalid"],
|
|
223
223
|
authorization: ["pending", "valid", "invalid", "deactivated", "expired", "revoked"],
|
|
224
224
|
challenge: ["pending", "processing", "valid", "invalid"],
|
|
225
|
-
};
|
|
225
|
+
});
|
|
226
226
|
|
|
227
227
|
var SPECS = intrinsic.assign(intrinsic.create(null), {
|
|
228
228
|
directory: [
|
|
@@ -627,7 +627,7 @@ var OID_AKI = oid.byName("authorityKeyIdentifier");
|
|
|
627
627
|
var OID_CN = oid.byName("commonName");
|
|
628
628
|
var _extNs = pkix.makeNS("acme", AcmeError, oid);
|
|
629
629
|
var _extDecoders = pkix.certExtensionDecoders(_extNs);
|
|
630
|
-
var _extCtx = { E: function (c, m, cause) { return new AcmeError(c, m, cause); }, oid: oid };
|
|
630
|
+
var _extCtx = intrinsic.assign(intrinsic.create(null), { E: function (c, m, cause) { return new AcmeError(c, m, cause); }, oid: oid });
|
|
631
631
|
|
|
632
632
|
/**
|
|
633
633
|
* @primitive pki.acme.tlsAlpn01Extension
|
|
@@ -726,7 +726,7 @@ async function verifyTlsAlpn01(certDer, token, accountJwk, identifier) {
|
|
|
726
726
|
|
|
727
727
|
|
|
728
728
|
function _outerHeader(o) {
|
|
729
|
-
var h = { alg: o.alg, nonce: o.nonce, url: o.url };
|
|
729
|
+
var h = intrinsic.assign(intrinsic.create(null), { alg: o.alg, nonce: o.nonce, url: o.url });
|
|
730
730
|
if (_hasOwn(o, "kid")) h.kid = o.kid;
|
|
731
731
|
if (_hasOwn(o, "jwk")) h.jwk = o.jwk;
|
|
732
732
|
return h;
|
|
@@ -1778,11 +1778,11 @@ function _parseLinkNext(headers, base) { var m = _parseLinkRelation(headers, bas
|
|
|
1778
1778
|
* var acct = await acme.newAccount({ termsOfServiceAgreed: true });
|
|
1779
1779
|
* var ord = await acme.newOrder({ identifiers: [{ type: "dns", value: "example.org" }] });
|
|
1780
1780
|
*/
|
|
1781
|
-
var _CLIENT_OPTS = {
|
|
1781
|
+
var _CLIENT_OPTS = intrinsic.assign(intrinsic.create(null), {
|
|
1782
1782
|
accountKey: 1, accountJwk: 1, alg: 1, resignKeys: 1, transport: 1, tls: 1, timeout: 1, maxResponseBytes: 1,
|
|
1783
1783
|
maxRedirects: 1, maxNonceRetries: 1, maxPolls: 1, maxTotalWait: 1, sleep: 1, clock: 1, proxy: 1,
|
|
1784
|
-
};
|
|
1785
|
-
var _METHOD_OPTS = {
|
|
1784
|
+
});
|
|
1785
|
+
var _METHOD_OPTS = intrinsic.assign(intrinsic.create(null), {
|
|
1786
1786
|
finalize: { csr: 1, identifiers: 1 },
|
|
1787
1787
|
poll: { maxPolls: 1, maxTotalWait: 1, onRetryAfter: 1 },
|
|
1788
1788
|
download: { expectedSpki: 1, identifiers: 1, requireBinding: 1, selectChain: 1, maxAlternates: 1 },
|
|
@@ -1792,12 +1792,20 @@ var _METHOD_OPTS = {
|
|
|
1792
1792
|
scheduleRenewal: { random: 1, shouldStop: 1, renew: 1, maxChecks: 1, maxWait: 1, longTermRetrySeconds: 1, temporaryBaseSeconds: 1 },
|
|
1793
1793
|
updateAccount: { contact: 1 },
|
|
1794
1794
|
listOrders: { maxPages: 1 },
|
|
1795
|
-
};
|
|
1795
|
+
});
|
|
1796
1796
|
function _gateOpts(bag, whitelist, name) {
|
|
1797
1797
|
bag = guard.identifier.optionsObject(bag, E, "acme/bad-input", "pki.acme " + name + " options");
|
|
1798
1798
|
guard.identifier.assertKnownKeys(bag, whitelist, E, "acme/bad-input", "unknown " + name + " option ");
|
|
1799
1799
|
return bag;
|
|
1800
1800
|
}
|
|
1801
|
+
/** @internal Refused at the door and again where the value is used. The checked value is RETURNED
|
|
1802
|
+
* and it is that one the caller uses: reading the option again would ask a second time, and an
|
|
1803
|
+
* accessor can answer differently on each read. */
|
|
1804
|
+
function _assertTransport(opts) {
|
|
1805
|
+
return guard.identifier.assertCallableOption(opts, "transport", E, "acme/bad-input", "opts.transport",
|
|
1806
|
+
"(request) => Promise<{ status, headers, body }>");
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1801
1809
|
function _resignKeysOf(raw) {
|
|
1802
1810
|
if (raw == null) return null;
|
|
1803
1811
|
if (!_isArrayI(raw) || raw.length === 0) throw E("acme/bad-input", "resignKeys, when set, must be a non-empty array of { alg, key } (RFC 8555 sec. 6.2)");
|
|
@@ -1821,7 +1829,7 @@ function _chooseResign(resignKeys, serverAlgs) {
|
|
|
1821
1829
|
return null;
|
|
1822
1830
|
}
|
|
1823
1831
|
function _jwkForAlg(jwk, alg) {
|
|
1824
|
-
var out =
|
|
1832
|
+
var out = intrinsic.create(null);
|
|
1825
1833
|
var keys = intrinsic.ownKeys(jwk);
|
|
1826
1834
|
for (var i = 0; i < keys.length; i++) { out[keys[i]] = jwk[keys[i]]; }
|
|
1827
1835
|
out.alg = alg;
|
|
@@ -1830,6 +1838,9 @@ function _jwkForAlg(jwk, alg) {
|
|
|
1830
1838
|
function client(directoryUrl, opts) {
|
|
1831
1839
|
opts = guard.identifier.optionsObject(opts, E, "acme/bad-input", "pki.acme.client options");
|
|
1832
1840
|
guard.identifier.assertKnownKeys(opts, _CLIENT_OPTS, E, "acme/bad-input", "unknown pki.acme.client option ");
|
|
1841
|
+
/** @internal Read once, at the door, and carried from here. Asking again would let an option that
|
|
1842
|
+
* answers differently on each read hand back something other than the value that was checked. */
|
|
1843
|
+
var checkedTransport = _assertTransport(opts);
|
|
1833
1844
|
if (!opts.accountKey) throw E("acme/bad-input", "client requires opts.accountKey (the account private key)");
|
|
1834
1845
|
if (!_isObject(opts.accountJwk)) throw E("acme/bad-input", "client requires opts.accountJwk (the account public JWK)");
|
|
1835
1846
|
if (!_isString(opts.alg)) throw E("acme/bad-input", "client requires opts.alg (the account-key JWS alg)");
|
|
@@ -1838,7 +1849,7 @@ function client(directoryUrl, opts) {
|
|
|
1838
1849
|
var accountKey = opts.accountKey, accountJwk = opts.accountJwk, alg = opts.alg;
|
|
1839
1850
|
var resignKeys = _resignKeysOf(opts.resignKeys);
|
|
1840
1851
|
|
|
1841
|
-
var transport =
|
|
1852
|
+
var transport = checkedTransport;
|
|
1842
1853
|
if (!transport) {
|
|
1843
1854
|
var t0 = opts.tls || {};
|
|
1844
1855
|
var hasAnchors = t0.anchors !== undefined && t0.anchors !== null && !(Array.isArray(t0.anchors) && t0.anchors.length === 0);
|
|
@@ -1912,10 +1923,10 @@ function client(directoryUrl, opts) {
|
|
|
1912
1923
|
function _sendFollowing(method, url, headers, body, redirects) {
|
|
1913
1924
|
var reqHeaders = Object.assign({ "user-agent": CLIENT_USER_AGENT }, headers || {});
|
|
1914
1925
|
return guard.async.deferred(function () {
|
|
1915
|
-
return guard.async.
|
|
1926
|
+
return guard.async.invoked(transport, [{ method: method, url: url, headers: reqHeaders, body: body, tls: _tlsFor(url), proxy: budgets.proxy, timeout: budgets.timeout, maxResponseBytes: budgets.maxResponseBytes }], E, "acme/bad-input", "opts.transport");
|
|
1916
1927
|
}).then(function (res) {
|
|
1917
1928
|
res = res || {};
|
|
1918
|
-
var h =
|
|
1929
|
+
var h = intrinsic.create(null);
|
|
1919
1930
|
Object.keys(res.headers || {}).forEach(function (k) { h[k.toLowerCase()] = res.headers[k]; });
|
|
1920
1931
|
var blen = res.body == null ? 0 : (typeof res.body === "string" ? Buffer.byteLength(res.body, "utf8")
|
|
1921
1932
|
: (Buffer.isBuffer(res.body) ? guard.bytes.lengthOf(res.body) : guard.bytes.lengthOf(guard.bytes.source(res.body, E, "acme/bad-response", "the response body"))));
|
package/lib/asn1-der.js
CHANGED
|
@@ -46,7 +46,7 @@ function _asn1Error(c, m) { return new Asn1Error(c, m); }
|
|
|
46
46
|
function _oidErr(c, m) { return new OidError(c, m); }
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
var UNIVERSAL_TYPES = {
|
|
49
|
+
var UNIVERSAL_TYPES = intrinsic.assign(intrinsic.create(null), {
|
|
50
50
|
BOOLEAN: { tag: 0x01, form: "primitive" },
|
|
51
51
|
INTEGER: { tag: 0x02, form: "primitive" },
|
|
52
52
|
BIT_STRING: { tag: 0x03, form: "primitive" },
|
|
@@ -69,9 +69,9 @@ var UNIVERSAL_TYPES = {
|
|
|
69
69
|
UNIVERSAL_STRING: { tag: 0x1c, form: "primitive" },
|
|
70
70
|
CHARACTER_STRING: { tag: 0x1d, form: "constructed" },
|
|
71
71
|
BMP_STRING: { tag: 0x1e, form: "primitive" },
|
|
72
|
-
};
|
|
72
|
+
});
|
|
73
73
|
|
|
74
|
-
var TAGS =
|
|
74
|
+
var TAGS = intrinsic.create(null);
|
|
75
75
|
Object.keys(UNIVERSAL_TYPES).forEach(function (k) { TAGS[k] = UNIVERSAL_TYPES[k].tag; });
|
|
76
76
|
|
|
77
77
|
var CLASS_UNIVERSAL = 0x00;
|
|
@@ -797,7 +797,7 @@ function _utcTimeString(date) {
|
|
|
797
797
|
* pki.asn1.build.utf8("example.com"),
|
|
798
798
|
* ]);
|
|
799
799
|
*/
|
|
800
|
-
var build = {
|
|
800
|
+
var build = intrinsic.assign(intrinsic.create(null), {
|
|
801
801
|
boolean: function (v) { return _universal(TAGS.BOOLEAN, false, Buffer.from([v ? 0xff : 0x00])); },
|
|
802
802
|
integer: function (v) { return _universal(TAGS.INTEGER, false, _intContent(v, "build.integer")); },
|
|
803
803
|
enumerated: function (v) { return _universal(TAGS.ENUMERATED, false, _intContent(v, "build.enumerated")); },
|
|
@@ -873,7 +873,7 @@ var build = {
|
|
|
873
873
|
return encodeTLV(CLASS_CONTEXT, node.constructed, tagNumber, buf.slice(buf.length - node.length));
|
|
874
874
|
},
|
|
875
875
|
raw: function (buf) { return _asBuffer(buf, "build.raw"); },
|
|
876
|
-
};
|
|
876
|
+
});
|
|
877
877
|
intrinsic.freeze(build);
|
|
878
878
|
|
|
879
879
|
function _intContent(v, who) {
|
package/lib/attrcert-sign.js
CHANGED
|
@@ -45,21 +45,21 @@ var _b = pkiBuild.makeBuilder({
|
|
|
45
45
|
NAME_SCHEMA: pkix.name(NS), SPKI_SCHEMA: pkix.spki(NS), EXT_DECODERS: EXT_DECODERS,
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
var KNOWN_SPEC_KEYS = { holder: 1, notBeforeTime: 1, notAfterTime: 1, serialNumber: 1, attributes: 1, extensions: 1 };
|
|
49
|
-
var KNOWN_HOLDER_KEYS = { entityName: 1, baseCertificateID: 1, fromCertificate: 1, objectDigestInfo: 1 };
|
|
50
|
-
var ATTR_OID_NAME = {
|
|
48
|
+
var KNOWN_SPEC_KEYS = intrinsic.assign(intrinsic.create(null), { holder: 1, notBeforeTime: 1, notAfterTime: 1, serialNumber: 1, attributes: 1, extensions: 1 });
|
|
49
|
+
var KNOWN_HOLDER_KEYS = intrinsic.assign(intrinsic.create(null), { entityName: 1, baseCertificateID: 1, fromCertificate: 1, objectDigestInfo: 1 });
|
|
50
|
+
var ATTR_OID_NAME = intrinsic.assign(intrinsic.create(null), {
|
|
51
51
|
role: "role", clearance: "clearance", group: "group", chargingIdentity: "chargingIdentity",
|
|
52
52
|
accessIdentity: "accessIdentity", authenticationInfo: "authenticationInfo",
|
|
53
|
-
};
|
|
54
|
-
var EXT_META = {
|
|
53
|
+
});
|
|
54
|
+
var EXT_META = intrinsic.assign(intrinsic.create(null), {
|
|
55
55
|
auditIdentity: { name: "acAuditIdentity", critical: true },
|
|
56
56
|
targetInformation: { name: "targetInformation", critical: true },
|
|
57
57
|
noRevAvail: { name: "noRevAvail", critical: false },
|
|
58
58
|
aaControls: { name: "aaControls", critical: true },
|
|
59
59
|
acProxying: { name: "acProxying", critical: true },
|
|
60
60
|
authorityKeyIdentifier: { name: "authorityKeyIdentifier", critical: false },
|
|
61
|
-
};
|
|
62
|
-
var REQUIRED_CRITICALITY =
|
|
61
|
+
});
|
|
62
|
+
var REQUIRED_CRITICALITY = intrinsic.create(null);
|
|
63
63
|
Object.keys(EXT_META).forEach(function (k) { REQUIRED_CRITICALITY[O(EXT_META[k].name)] = EXT_META[k].critical; });
|
|
64
64
|
var CLASSLIST_BIT = intrinsic.assign(intrinsic.create(null), { unmarked: 0, unclassified: 1, restricted: 2, confidential: 3, secret: 4, topSecret: 5 });
|
|
65
65
|
|
|
@@ -196,14 +196,14 @@ function _encodeSvceAuthInfo(sai, authInfoAllowed, label) {
|
|
|
196
196
|
return b.sequence(parts);
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
var ATTR_VALUE_ENCODER = {
|
|
199
|
+
var ATTR_VALUE_ENCODER = intrinsic.assign(intrinsic.create(null), {
|
|
200
200
|
role: function (v) { return _encodeRole(v); },
|
|
201
201
|
clearance: function (v) { return _encodeClearance(v); },
|
|
202
202
|
group: function (v) { return _encodeIetfAttrSyntax(v); },
|
|
203
203
|
chargingIdentity: function (v) { return _encodeIetfAttrSyntax(v); },
|
|
204
204
|
authenticationInfo: function (v) { return _encodeSvceAuthInfo(v, true, "authenticationInfo"); },
|
|
205
205
|
accessIdentity: function (v) { return _encodeSvceAuthInfo(v, false, "accessIdentity"); },
|
|
206
|
-
};
|
|
206
|
+
});
|
|
207
207
|
|
|
208
208
|
|
|
209
209
|
function _encodeTarget(t) {
|
|
@@ -252,7 +252,7 @@ function _extensionValue(key, val, aaSpki) {
|
|
|
252
252
|
|
|
253
253
|
|
|
254
254
|
function _buildAttributes(attrSpec) {
|
|
255
|
-
var attrs = [], seen =
|
|
255
|
+
var attrs = [], seen = intrinsic.create(null);
|
|
256
256
|
function add(type, valueTlv) {
|
|
257
257
|
if (seen[type]) throw _err("attrcert/duplicate-attribute", "duplicate " + (oid.name(type) || type) + " attribute (RFC 5755 sec. 4.2.7)");
|
|
258
258
|
seen[type] = true;
|
|
@@ -304,7 +304,7 @@ function _buildExtensions(extSpec, aaSpki) {
|
|
|
304
304
|
if (extSpec == null) return null;
|
|
305
305
|
if (Array.isArray(extSpec)) {
|
|
306
306
|
if (!extSpec.length) return null;
|
|
307
|
-
var seenA =
|
|
307
|
+
var seenA = intrinsic.create(null);
|
|
308
308
|
var exts = extSpec.map(function (e, i) {
|
|
309
309
|
var der = _b.reqDer(e, "extension");
|
|
310
310
|
_b.assertValidExtension(der, i);
|
|
@@ -330,7 +330,7 @@ function _buildExtensions(extSpec, aaSpki) {
|
|
|
330
330
|
guard.identifier.assertKnownKeys(extSpec, EXT_META, _err, "attrcert/bad-input", function (k) {
|
|
331
331
|
return "unknown extension " + JSON.stringify(k) + "; pass a pre-encoded Extension DER via the array form for a custom extension";
|
|
332
332
|
});
|
|
333
|
-
var out = [], seen =
|
|
333
|
+
var out = [], seen = intrinsic.create(null);
|
|
334
334
|
Object.keys(extSpec).forEach(function (k) {
|
|
335
335
|
if (extSpec[k] == null) return;
|
|
336
336
|
var meta = EXT_META[k], eOid = O(meta.name);
|
|
@@ -443,7 +443,7 @@ function _sign(spec, issuer, opts) {
|
|
|
443
443
|
});
|
|
444
444
|
}
|
|
445
445
|
|
|
446
|
-
var KNOWN_VERIFY_OPTS = { time: 1, target: 1, revocationStatus: 1 };
|
|
446
|
+
var KNOWN_VERIFY_OPTS = intrinsic.assign(intrinsic.create(null), { time: 1, target: 1, revocationStatus: 1 });
|
|
447
447
|
var REVOCATION_STATUS = Object.create(null);
|
|
448
448
|
REVOCATION_STATUS.notRevoked = 1;
|
|
449
449
|
REVOCATION_STATUS.revoked = 1;
|
|
@@ -560,7 +560,7 @@ function _checkTargeting(ac, want) {
|
|
|
560
560
|
reason: "this attribute certificate does not name this verifier among its targets (RFC 5755 sec. 4.3.2)" };
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
var SUPPORTED_CRITICAL =
|
|
563
|
+
var SUPPORTED_CRITICAL = intrinsic.create(null);
|
|
564
564
|
SUPPORTED_CRITICAL[O("targetInformation")] = 1;
|
|
565
565
|
SUPPORTED_CRITICAL[O("acAuditIdentity")] = 1;
|
|
566
566
|
|
package/lib/cbor-det.js
CHANGED
|
@@ -645,7 +645,7 @@ function _head(mt, argument, who) {
|
|
|
645
645
|
if (a < 4294967296n) { b = Buffer.alloc(5); b[0] = mtb | 26; b.writeUInt32BE(Number(a), 1); return b; }
|
|
646
646
|
b = Buffer.alloc(9); b[0] = mtb | 27; b.writeBigUInt64BE(a, 1); return b;
|
|
647
647
|
}
|
|
648
|
-
var build = {
|
|
648
|
+
var build = Object.assign(Object.create(null), {
|
|
649
649
|
uint: function (n) { var a = typeof n === "bigint" ? n : BigInt(n); if (a < 0n) throw new CborError("cbor/bad-argument", "build.uint: value must be non-negative"); return _head(0, a, "build.uint"); },
|
|
650
650
|
nint: function (n) { var a = typeof n === "bigint" ? n : BigInt(n); if (a >= 0n) throw new CborError("cbor/bad-argument", "build.nint: value must be negative"); return _head(1, -1n - a, "build.nint"); },
|
|
651
651
|
int: function (n) { var a = typeof n === "bigint" ? n : BigInt(n); return a >= 0n ? _head(0, a, "build.int") : _head(1, -1n - a, "build.int"); },
|
|
@@ -690,7 +690,7 @@ var build = {
|
|
|
690
690
|
return build.tag(1, build.int(secs));
|
|
691
691
|
},
|
|
692
692
|
oid: function (dotted) { return build.tag(111, build.byteString(asn1.encodeOidContent(dotted))); },
|
|
693
|
-
};
|
|
693
|
+
});
|
|
694
694
|
|
|
695
695
|
module.exports = {
|
|
696
696
|
decode: decode,
|
package/lib/cmc-build.js
CHANGED
|
@@ -31,7 +31,7 @@ var OID_IDENTIFICATION = O("id-cmc-identification");
|
|
|
31
31
|
var OID_SHA256 = O("sha256");
|
|
32
32
|
var OID_HMAC_SHA256 = O("hmacWithSHA256");
|
|
33
33
|
|
|
34
|
-
var RENEWAL_FORBIDDEN =
|
|
34
|
+
var RENEWAL_FORBIDDEN = intrinsic.create(null);
|
|
35
35
|
RENEWAL_FORBIDDEN[OID_IDENTIFICATION] = "Identification";
|
|
36
36
|
RENEWAL_FORBIDDEN[O("id-cmc-identityProof")] = "Identity Proof";
|
|
37
37
|
RENEWAL_FORBIDDEN[OID_IDENTITY_PROOF_V2] = "Identity Proof V2";
|
|
@@ -40,11 +40,11 @@ var OID_RESPONSE_BODY = O("id-cmc-responseBody");
|
|
|
40
40
|
|
|
41
41
|
var POP_LINK_RANDOM_BYTES = 64;
|
|
42
42
|
|
|
43
|
-
var KNOWN_SPEC_KEYS = {
|
|
43
|
+
var KNOWN_SPEC_KEYS = intrinsic.assign(intrinsic.create(null), {
|
|
44
44
|
requests: 1, controls: 1, cmsSequence: 1, otherMsgSequence: 1,
|
|
45
45
|
identityProof: 1, popLink: 1, renewal: 1,
|
|
46
46
|
transactionId: 1, senderNonce: 1, dataReturn: 1,
|
|
47
|
-
};
|
|
47
|
+
});
|
|
48
48
|
|
|
49
49
|
var OID_TRANSACTION_ID = O("id-cmc-transactionId");
|
|
50
50
|
var OID_SENDER_NONCE = O("id-cmc-senderNonce");
|
|
@@ -96,10 +96,10 @@ function makeIdAllocator() {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
var KNOWN_REQUEST_KEYS = { tcr: 1, crm: 1, orm: 1, bodyPartID: 1 };
|
|
100
|
-
var KNOWN_CONTROL_KEYS = { type: 1, value: 1 };
|
|
101
|
-
var KNOWN_IDENTITY_PROOF_KEYS = { identity: 1, secret: 1 };
|
|
102
|
-
var KNOWN_POP_LINK_KEYS = { secret: 1 };
|
|
99
|
+
var KNOWN_REQUEST_KEYS = intrinsic.assign(intrinsic.create(null), { tcr: 1, crm: 1, orm: 1, bodyPartID: 1 });
|
|
100
|
+
var KNOWN_CONTROL_KEYS = intrinsic.assign(intrinsic.create(null), { type: 1, value: 1 });
|
|
101
|
+
var KNOWN_IDENTITY_PROOF_KEYS = intrinsic.assign(intrinsic.create(null), { identity: 1, secret: 1 });
|
|
102
|
+
var KNOWN_POP_LINK_KEYS = intrinsic.assign(intrinsic.create(null), { secret: 1 });
|
|
103
103
|
|
|
104
104
|
function fixedRequestId(req, index) {
|
|
105
105
|
if (!req || typeof req !== "object") throw E("cmc/bad-input", "each request must be an object");
|
|
@@ -209,24 +209,24 @@ function _claimRawElement(el, ids, what) {
|
|
|
209
209
|
return der;
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
-
var BINDING_BY_OID =
|
|
212
|
+
var BINDING_BY_OID = intrinsic.create(null);
|
|
213
213
|
BINDING_BY_OID[O("id-cmc-transactionId")] = "transactionId";
|
|
214
214
|
BINDING_BY_OID[O("id-cmc-senderNonce")] = "senderNonce";
|
|
215
215
|
BINDING_BY_OID[O("id-cmc-dataReturn")] = "dataReturn";
|
|
216
216
|
|
|
217
|
-
var BINDING_READER = {
|
|
217
|
+
var BINDING_READER = intrinsic.assign(intrinsic.create(null), {
|
|
218
218
|
transactionId: function (node) { return asn1.read.integer(node); },
|
|
219
219
|
senderNonce: function (node) { return asn1.read.octetString(node); },
|
|
220
220
|
dataReturn: function (node) { return asn1.read.octetString(node); },
|
|
221
|
-
};
|
|
222
|
-
var BINDING_TYPE_NAME = {
|
|
221
|
+
});
|
|
222
|
+
var BINDING_TYPE_NAME = intrinsic.assign(intrinsic.create(null), {
|
|
223
223
|
transactionId: "an INTEGER (RFC 5272 sec. 6.6)",
|
|
224
224
|
senderNonce: "an OCTET STRING (RFC 5272 sec. 6.6)",
|
|
225
225
|
dataReturn: "an OCTET STRING (RFC 5272 sec. 6.4)",
|
|
226
|
-
};
|
|
226
|
+
});
|
|
227
227
|
|
|
228
228
|
function _assertNoDuplicateBinding(callerControls, spec) {
|
|
229
|
-
var seen =
|
|
229
|
+
var seen = intrinsic.create(null);
|
|
230
230
|
callerControls.forEach(function (c) {
|
|
231
231
|
var field = BINDING_BY_OID[_oidOf(c.type)];
|
|
232
232
|
if (!field) return;
|
|
@@ -259,7 +259,7 @@ function _oidOf(v) {
|
|
|
259
259
|
}
|
|
260
260
|
|
|
261
261
|
|
|
262
|
-
var REQUEST_FORBIDDEN_CONTROL =
|
|
262
|
+
var REQUEST_FORBIDDEN_CONTROL = intrinsic.create(null);
|
|
263
263
|
REQUEST_FORBIDDEN_CONTROL[OID_RESPONSE_BODY] =
|
|
264
264
|
"id-cmc-responseBody may appear only in the control sequence of a PKIResponse (RFC 6402 sec. 2.6)";
|
|
265
265
|
REQUEST_FORBIDDEN_CONTROL[O("id-cmc-statusInfo")] =
|
|
@@ -469,7 +469,7 @@ async function _build(spec, signer, opts) {
|
|
|
469
469
|
function _copySigners(signer, owned) {
|
|
470
470
|
function one(s) {
|
|
471
471
|
if (!s || typeof s !== "object") return s;
|
|
472
|
-
var out =
|
|
472
|
+
var out = intrinsic.create(null), k;
|
|
473
473
|
for (k in s) {
|
|
474
474
|
if (!_hasOwn(s, k)) continue;
|
|
475
475
|
out[k] = copyValue(s[k], k === "key");
|
|
@@ -483,7 +483,7 @@ function _copySigners(signer, owned) {
|
|
|
483
483
|
}
|
|
484
484
|
if (Buffer.isBuffer(v) || v instanceof Uint8Array) return _own(Buffer.from(v), true); // allow:byte-source-narrow -- private key bytes (Buffer borrowed / Uint8Array copied+wiped)
|
|
485
485
|
if (!v || typeof v !== "object" || typeof v.type === "string") return v;
|
|
486
|
-
var c =
|
|
486
|
+
var c = intrinsic.create(null), ck;
|
|
487
487
|
for (ck in v) {
|
|
488
488
|
if (!_hasOwn(v, ck)) continue;
|
|
489
489
|
var cv = v[ck];
|
package/lib/cmc-verify.js
CHANGED
|
@@ -40,7 +40,7 @@ var OID_DATA_RETURN = O("id-cmc-dataReturn");
|
|
|
40
40
|
var OID_TRUSTED_ANCHORS = O("id-cmc-trustedAnchors");
|
|
41
41
|
var OID_CONFIRM_CERT_ACCEPTANCE = O("id-cmc-confirmCertAcceptance");
|
|
42
42
|
|
|
43
|
-
var OUTCOME_BY_STATUS = {
|
|
43
|
+
var OUTCOME_BY_STATUS = intrinsic.assign(intrinsic.create(null), {
|
|
44
44
|
success: "issued",
|
|
45
45
|
pending: "pending",
|
|
46
46
|
partial: "pending",
|
|
@@ -48,9 +48,9 @@ var OUTCOME_BY_STATUS = {
|
|
|
48
48
|
popRequired: "pop-required",
|
|
49
49
|
failed: "rejected",
|
|
50
50
|
noSupport: "rejected",
|
|
51
|
-
};
|
|
51
|
+
});
|
|
52
52
|
|
|
53
|
-
var OUTCOME_SEVERITY = { rejected: 4, "pop-required": 3, "confirm-required": 2, pending: 1, issued: 0 };
|
|
53
|
+
var OUTCOME_SEVERITY = intrinsic.assign(intrinsic.create(null), { rejected: 4, "pop-required": 3, "confirm-required": 2, pending: 1, issued: 0 });
|
|
54
54
|
|
|
55
55
|
function _singleValue(control, what) {
|
|
56
56
|
if (control.values.length !== 1) {
|
|
@@ -319,7 +319,7 @@ function _copyAnyBytes(v) {
|
|
|
319
319
|
}
|
|
320
320
|
|
|
321
321
|
function _snapshotSent(sent) {
|
|
322
|
-
var out =
|
|
322
|
+
var out = intrinsic.create(null), k;
|
|
323
323
|
for (k in sent) { if (_hasOwn(sent, k)) out[k] = sent[k]; }
|
|
324
324
|
if (out.transactionId != null) {
|
|
325
325
|
out.transactionIdValue = guard.range.authoredInteger(out.transactionId, E, "cmc/bad-input", "sent.transactionId");
|
|
@@ -331,7 +331,7 @@ function _snapshotSent(sent) {
|
|
|
331
331
|
out.bodyPartPaths = out.bodyPartPaths.map(function (p) { return Array.isArray(p) ? p.slice() : p; });
|
|
332
332
|
}
|
|
333
333
|
if (out.recipient && typeof out.recipient === "object") {
|
|
334
|
-
var r =
|
|
334
|
+
var r = intrinsic.create(null), rk;
|
|
335
335
|
for (rk in out.recipient) {
|
|
336
336
|
if (!_hasOwn(out.recipient, rk)) continue;
|
|
337
337
|
r[rk] = _copyAnyBytes(out.recipient[rk]);
|
package/lib/cmp-build.js
CHANGED
|
@@ -71,10 +71,10 @@ var _b = pkiBuild.makeBuilder({
|
|
|
71
71
|
NAME_SCHEMA: pkix.name(NS), SPKI_SCHEMA: pkix.spki(NS), EXT_DECODERS: EXT_DECODERS,
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
var KNOWN_HEADER_KEYS = {
|
|
74
|
+
var KNOWN_HEADER_KEYS = intrinsic.assign(intrinsic.create(null), {
|
|
75
75
|
sender: 1, recipient: 1, pvno: 1, messageTime: 1, senderKID: 1, recipKID: 1,
|
|
76
76
|
transactionID: 1, senderNonce: 1, recipNonce: 1, freeText: 1, generalInfo: 1,
|
|
77
|
-
};
|
|
77
|
+
});
|
|
78
78
|
var KNOWN_BODY_KEYS = intrinsic.assign(intrinsic.create(null), {
|
|
79
79
|
ir: 1, cr: 1, kur: 1, krr: 1, ccr: 1, p10cr: 1, certConf: 1, pollReq: 1, genm: 1, rr: 1,
|
|
80
80
|
ip: 1, cp: 1, kup: 1, ccp: 1, krp: 1, rp: 1, genp: 1, error: 1, pollRep: 1, pkiconf: 1,
|
|
@@ -87,11 +87,11 @@ var BODY_TAG = intrinsic.assign(intrinsic.create(null), {
|
|
|
87
87
|
});
|
|
88
88
|
var CRMF_BODY = intrinsic.assign(intrinsic.create(null), { ir: 1, cr: 1, kur: 1, krr: 1, ccr: 1 });
|
|
89
89
|
var CERT_REP_ARM = intrinsic.assign(intrinsic.create(null), { ip: 1, cp: 1, kup: 1, ccp: 1 });
|
|
90
|
-
var KNOWN_OPTS_KEYS = { key: 1, cert: 1, mac: 1, extraCerts: 1, pem: 1, pss: 1, digestAlgorithm: 1 };
|
|
91
|
-
var KNOWN_OPTS_SIG_KEYS = { key: 1, cert: 1, extraCerts: 1, pem: 1, pss: 1, digestAlgorithm: 1 };
|
|
92
|
-
var KNOWN_OPTS_MAC_KEYS = { mac: 1, extraCerts: 1, pem: 1 };
|
|
93
|
-
var KNOWN_MESSAGE_KEYS = { header: 1, body: 1 };
|
|
94
|
-
var KNOWN_MAC_KEYS = { secret: 1, salt: 1, iterationCount: 1, prf: 1, keyLength: 1, algorithm: 1 };
|
|
90
|
+
var KNOWN_OPTS_KEYS = intrinsic.assign(intrinsic.create(null), { key: 1, cert: 1, mac: 1, extraCerts: 1, pem: 1, pss: 1, digestAlgorithm: 1 });
|
|
91
|
+
var KNOWN_OPTS_SIG_KEYS = intrinsic.assign(intrinsic.create(null), { key: 1, cert: 1, extraCerts: 1, pem: 1, pss: 1, digestAlgorithm: 1 });
|
|
92
|
+
var KNOWN_OPTS_MAC_KEYS = intrinsic.assign(intrinsic.create(null), { mac: 1, extraCerts: 1, pem: 1 });
|
|
93
|
+
var KNOWN_MESSAGE_KEYS = intrinsic.assign(intrinsic.create(null), { header: 1, body: 1 });
|
|
94
|
+
var KNOWN_MAC_KEYS = intrinsic.assign(intrinsic.create(null), { secret: 1, salt: 1, iterationCount: 1, prf: 1, keyLength: 1, algorithm: 1 });
|
|
95
95
|
|
|
96
96
|
var PBMAC1_DEFAULT_ITER = 100000;
|
|
97
97
|
var PBMAC1_DEFAULT_SALT_BYTES = 16;
|
|
@@ -102,7 +102,7 @@ var PBMAC1_MAX_KEYLEN = 1024;
|
|
|
102
102
|
var PBMAC1_MIN_ITER = 1000;
|
|
103
103
|
var PBMAC1_PRF = intrinsic.assign(intrinsic.create(null), { "SHA-256": "hmacWithSHA256", "SHA-384": "hmacWithSHA384", "SHA-512": "hmacWithSHA512" });
|
|
104
104
|
var PBMAC1_MAC_OID = intrinsic.assign(intrinsic.create(null), { "SHA-256": "hmacWithSHA256", "SHA-384": "hmacWithSHA384", "SHA-512": "hmacWithSHA512" });
|
|
105
|
-
var PBMAC1_PRF_HLEN = { "SHA-256": 32, "SHA-384": 48, "SHA-512": 64 };
|
|
105
|
+
var PBMAC1_PRF_HLEN = intrinsic.assign(intrinsic.create(null), { "SHA-256": 32, "SHA-384": 48, "SHA-512": 64 });
|
|
106
106
|
var FAIL_INFO_NAMES = ["badAlg", "badMessageCheck", "badRequest", "badTime", "badCertId", "badDataFormat",
|
|
107
107
|
"wrongAuthority", "incorrectData", "missingTimeStamp", "badPOP", "certRevoked", "certConfirmed",
|
|
108
108
|
"wrongIntegrity", "badRecipientNonce", "timeNotAvailable", "unacceptedPolicy", "unacceptedExtension",
|
|
@@ -256,8 +256,8 @@ function _encodeRevDetails(rd) {
|
|
|
256
256
|
return b.sequence(children);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
-
var KNOWN_REV_DETAILS_KEYS = { certDetails: 1, crlEntryDetails: 1 };
|
|
260
|
-
var KNOWN_CRL_ENTRY_DETAIL_KEYS = { reason: 1 };
|
|
259
|
+
var KNOWN_REV_DETAILS_KEYS = intrinsic.assign(intrinsic.create(null), { certDetails: 1, crlEntryDetails: 1 });
|
|
260
|
+
var KNOWN_CRL_ENTRY_DETAIL_KEYS = intrinsic.assign(intrinsic.create(null), { reason: 1 });
|
|
261
261
|
var CRL_REASON_BY_NAME = intrinsic.create(null);
|
|
262
262
|
_forEach(_keys(constants.NAMES.CRL_REASON), function (v) { CRL_REASON_BY_NAME[constants.NAMES.CRL_REASON[v]] = intrinsic.Number(v); });
|
|
263
263
|
function _encodeCrlEntryDetails(spec) {
|
|
@@ -272,8 +272,8 @@ function _encodeCrlEntryDetails(spec) {
|
|
|
272
272
|
return b.sequence([_b.ext(O("reasonCode"), false, b.enumerated(_bigInt(code)))]);
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
var KNOWN_CRL_STATUS_KEYS = { dpn: 1, issuer: 1, thisUpdate: 1 };
|
|
276
|
-
var KNOWN_DPN_KEYS = { fullName: 1 };
|
|
275
|
+
var KNOWN_CRL_STATUS_KEYS = intrinsic.assign(intrinsic.create(null), { dpn: 1, issuer: 1, thisUpdate: 1 });
|
|
276
|
+
var KNOWN_DPN_KEYS = intrinsic.assign(intrinsic.create(null), { fullName: 1 });
|
|
277
277
|
function buildCrlStatusList(spec) {
|
|
278
278
|
if (!spec || typeof spec !== "object" || _isBuffer(spec)) throw _err("cmp/bad-input", "a crlUpdate request must be an object { dpn | issuer, thisUpdate? }");
|
|
279
279
|
guard.identifier.assertKnownKeys(spec, KNOWN_CRL_STATUS_KEYS, _err, "cmp/bad-input", "unknown crlUpdate field ");
|
|
@@ -453,7 +453,7 @@ function _encodeKeyRecRepContent(spec, state) {
|
|
|
453
453
|
return b.sequence(children);
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
-
var CMP2021_POP_METHODS = { agreeMAC: 1, encryptedKey: 1 };
|
|
456
|
+
var CMP2021_POP_METHODS = intrinsic.assign(intrinsic.create(null), { agreeMAC: 1, encryptedKey: 1 });
|
|
457
457
|
function _popNeedsCmp2021(crmfDer) {
|
|
458
458
|
var messages;
|
|
459
459
|
try { messages = schemaCrmf.parse(crmfDer).messages; }
|
|
@@ -735,7 +735,7 @@ var DEFAULT_TRANSFER_TIMEOUT = constants.TIME.seconds(30);
|
|
|
735
735
|
var MAX_TRANSFER_TIMEOUT = constants.TIME.seconds(600);
|
|
736
736
|
var PKIXCMP = "application/pkixcmp";
|
|
737
737
|
var PKIXCMP_POLL = "application/pkixcmp-poll";
|
|
738
|
-
var KNOWN_TRANSFER_OPTS = { transport: 1, tls: 1, headers: 1, timeout: 1, maxResponseBytes: 1, proxy: 1 };
|
|
738
|
+
var KNOWN_TRANSFER_OPTS = intrinsic.assign(intrinsic.create(null), { transport: 1, tls: 1, headers: 1, timeout: 1, maxResponseBytes: 1, proxy: 1 });
|
|
739
739
|
|
|
740
740
|
function _cmpMessageDer(input) {
|
|
741
741
|
var der;
|
|
@@ -783,14 +783,24 @@ function transfer(url, message, opts) {
|
|
|
783
783
|
return guard.async.deferred(function () { return _transfer(url, message, opts); });
|
|
784
784
|
}
|
|
785
785
|
|
|
786
|
+
/** @internal Refused at the door and again where the value is used. The checked value is RETURNED
|
|
787
|
+
* and it is that one the caller uses: reading the option again would ask a second time, and an
|
|
788
|
+
* accessor can answer differently on each read. */
|
|
789
|
+
function _assertTransport(opts) {
|
|
790
|
+
return guard.identifier.assertCallableOption(opts, "transport", _err, "cmp/bad-input", "opts.transport",
|
|
791
|
+
"(request) => Promise<{ status, headers, body }>");
|
|
792
|
+
}
|
|
793
|
+
|
|
786
794
|
function _transfer(url, message, opts) {
|
|
787
795
|
opts = opts || {};
|
|
788
796
|
guard.identifier.assertKnownKeys(opts, KNOWN_TRANSFER_OPTS, _err, "cmp/bad-input", "unknown opts field ");
|
|
797
|
+
/** @internal Read once, at the door, and carried from here. Asking again would let an option that
|
|
798
|
+
* answers differently on each read hand back something other than the value that was checked. */
|
|
799
|
+
var transport = _assertTransport(opts);
|
|
789
800
|
var der = _cmpMessageDer(message);
|
|
790
801
|
var parsedUrl;
|
|
791
802
|
try { parsedUrl = new URL(String(url)); }
|
|
792
803
|
catch (e) { throw _err("cmp/bad-url", "the CMP URL did not parse: " + guard.text.showValue(url), e); }
|
|
793
|
-
var transport = opts.transport;
|
|
794
804
|
if (!transport) {
|
|
795
805
|
var t = opts.tls || {};
|
|
796
806
|
var hasAnchors = t.anchors !== undefined && t.anchors !== null && !(Array.isArray(t.anchors) && t.anchors.length === 0);
|
|
@@ -802,16 +812,16 @@ function _transfer(url, message, opts) {
|
|
|
802
812
|
var proxy;
|
|
803
813
|
try { proxy = httpTransport.snapshotProxy(opts.proxy); }
|
|
804
814
|
catch (e) { throw _err("cmp/bad-input", "the options object could not be read", e); }
|
|
805
|
-
var headers =
|
|
815
|
+
var headers = intrinsic.create(null);
|
|
806
816
|
Object.keys(opts.headers || {}).forEach(function (k) {
|
|
807
817
|
var lk = k.toLowerCase();
|
|
808
818
|
if (lk !== "content-length" && lk !== "transfer-encoding" && lk !== "content-type") headers[k] = opts.headers[k];
|
|
809
819
|
});
|
|
810
820
|
headers["content-type"] = PKIXCMP;
|
|
811
821
|
var tls = _tlsForTransfer(opts);
|
|
812
|
-
return guard.async.
|
|
822
|
+
return guard.async.invoked(transport, [{ method: "POST", url: parsedUrl.href, headers: headers, body: der, tls: tls, proxy: proxy, timeout: timeout, maxResponseBytes: maxResponseBytes }], _err, "cmp/bad-input", "opts.transport").then(function (res) {
|
|
813
823
|
res = res || {};
|
|
814
|
-
var h =
|
|
824
|
+
var h = intrinsic.create(null);
|
|
815
825
|
Object.keys(res.headers || {}).forEach(function (k) { h[k.toLowerCase()] = res.headers[k]; });
|
|
816
826
|
var body = guard.bytes.isByteSource(res.body)
|
|
817
827
|
? guard.bytes.source(res.body, CmpError, "cmp/bad-response", "the CMP response body")
|
|
@@ -835,7 +845,7 @@ function _wellKnownSeg(v, name) {
|
|
|
835
845
|
catch (e) { throw _err("cmp/bad-url", "the CMP " + name + " is not encodable (e.g. an unpaired surrogate): " + JSON.stringify(s), e); }
|
|
836
846
|
}
|
|
837
847
|
|
|
838
|
-
var KNOWN_WELLKNOWN_OPTS = { label: 1, operation: 1 };
|
|
848
|
+
var KNOWN_WELLKNOWN_OPTS = intrinsic.assign(intrinsic.create(null), { label: 1, operation: 1 });
|
|
839
849
|
|
|
840
850
|
function _isAsciiLetter(ch) { return (ch >= "A" && ch <= "Z") || (ch >= "a" && ch <= "z"); }
|
|
841
851
|
function _stripSchemeAuthority(s) {
|