@blamejs/pki 0.6.20 → 0.6.22
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 +16 -0
- package/README.md +1 -1
- package/lib/acme.js +81 -2
- package/lib/cmp-build.js +10 -10
- package/lib/lint.js +5 -5
- package/lib/pbes2.js +1 -1
- package/lib/pkcs12-build.js +9 -9
- package/lib/schema-c509.js +10 -10
- package/lib/sign-scheme.js +2 -2
- package/lib/tsp-sign.js +4 -4
- package/lib/webcrypto.js +12 -12
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ 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.22 — 2026-09-01
|
|
8
|
+
|
|
9
|
+
pki.acme.client gains scheduleRenewal, the RFC 9773 auto-sleeping certificate-renewal loop.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- pki.acme.client(...).scheduleRenewal(certDer, { random, shouldStop, renew, maxChecks, maxWait, longTermRetrySeconds, temporaryBaseSeconds }) is the RFC 9773 sec. 4.1 auto-sleeping renewal loop. It composes renewalWindow and the client's injectable sleep/clock: fetch the ARI decision, sleep until the sooner of the selected instant and the clamped Retry-After, refetch until renewNow, then resolve { reason: "renew-now", decision }. It resolves { reason: "expired" } once the certificate passes its notAfter (a client must not check RenewalInfo after expiry, RFC 9773 sec. 4.3), { reason: "stopped" } when shouldStop() signals the certificate is replaced, and { reason: "budget" } at the optional maxChecks or maxWait bound. An invalid suggested window or a transport error retries on the sec. 4.3.3 schedule, with a 5xx backing off exponentially from temporaryBaseSeconds and every other error waiting longTermRetrySeconds (default six hours). A supplied renew(decision) callback is awaited at renew-now instead of resolving, and returning a new certificate DER reschedules on it.
|
|
14
|
+
|
|
15
|
+
## v0.6.21 — 2026-09-01
|
|
16
|
+
|
|
17
|
+
WebCrypto and the signing and format builders refuse an algorithm, curve, digest, or profile name that collides with an inherited Object.prototype property name.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- pki.webcrypto (generateKey, sign, verify, encrypt, decrypt, deriveBits, deriveKey, wrapKey, unwrapKey, importKey, encapsulateBits, decapsulateBits) refuses an algorithm name or namedCurve that collides with an inherited Object.prototype property name, returning webcrypto/not-supported instead of a bare Node error. The digest, PBMAC1 PRF, CMP body, PKCS#12 MAC hash, PBES2 PRF, and lint-profile lookups behind pki.tsp.sign, pki.cmp.build, pki.pkcs12.build, pki.key.encrypt, pki.lint.certificate, and the RSA-PSS and C509 builders are hardened the same way, each returning the verb's typed error for such a name.
|
|
22
|
+
|
|
7
23
|
## v0.6.20 — 2026-09-01
|
|
8
24
|
|
|
9
25
|
A vulnerable build-time dependency is refreshed; it is not part of the published package.
|
package/README.md
CHANGED
|
@@ -225,7 +225,7 @@ comment blocks, is at [pkijs.com](https://pkijs.com).
|
|
|
225
225
|
| `pki.scep` | SCEP pkiMessage codec (RFC 8894), the client side of Simple Certificate Enrollment. `build(spec)` assembles a request: a `PKCSReq` or `RenewalReq` wraps a PKCS#10 certification request, whose own proof-of-possession it verifies first; a `CertPoll` wraps an IssuerAndSubject naming the issuing CA and the request subject; and a `GetCert` or `GetCRL` wraps an IssuerAndSerialNumber naming a certificate by its issuer and a positive serial of at most 20 octets. It encrypts the messageData to the CA as the inner EnvelopedData (`pkcsPKIEnvelope`, AES-128-CBC), and signs that under the transaction attributes RFC 8894 §3.2 defines, a messageType, a caller-unique transactionId, and a 16-byte senderNonce. The recipient CA certificate must assert `keyEncipherment`. `build` also issues the CA-side `CertRep` response (§3.3.2): a SUCCESS envelopes a certs-only SignedData of the issued certificate (or the CRL for a GetCRL) to the requester and signs it under the CA key, while a FAILURE (carrying a `failInfo`) or a PENDING omits the pkcsPKIEnvelope and is signed detached, each echoing the request's senderNonce as `recipientNonce`. `parse(bytes, opts?)` reads a `PKCSReq`, `RenewalReq`, `CertPoll`, `GetCert`, `GetCRL`, or `CertRep` back (a messageType outside the RFC 8894 registry is refused): it verifies the outer signature first and refuses a message whose signature does not check, so the transaction attributes it returns come only from a verified signer, never alongside a false verdict. Because a valid signature only proves self-consistency with the embedded certificate, pass `opts.signerCert` to authenticate a CA response against the CA certificate you hold (a public-key mismatch is refused, `signerAuthenticated` reports the result); a caller that omits it gets a crypto-only verdict and must authenticate the surfaced `signerCert` itself. It maps the messageType, pkiStatus, failInfo, and the nonces from their RFC 8894 enumerants and refuses an unknown one; given `recipientKey` it decrypts the `pkcsPKIEnvelope` to the messageData, and given `expectedSenderNonce` it refuses a response whose recipientNonce does not echo it. It reads a CA's CertRep in full. `getCACaps(baseUrl, opts?)`, `getCACert(baseUrl, opts?)`, `getNextCACert(baseUrl, opts)`, `enroll(baseUrl, opts)`, `renew(baseUrl, opts)`, `getCert(baseUrl, opts)`, and `getCrl(baseUrl, opts)` carry that codec to a live CA over HTTP (RFC 8894 §4) through an injectable transport (`pki.transport.https` by default): `getCACaps` reports the CA's advertised capabilities and never lowers the client's algorithm choice on the unauthenticated response, `getCACert` pins the CA certificate to an out-of-band `expectedFingerprint` a returned certificate must match, `getNextCACert` fetches the CA's next (rollover) certificate and verifies the SignedData response against the current CA certificate (`caCertificate`) before returning it, refusing a response signed by any other key, and `enroll` and `renew` POST a PKCSReq or RenewalReq, authenticate the CertRep against the CA certificate and its nonce echo, select the issued certificate by public-key match, throw on a FAILURE with the CA's failInfo, and poll a PENDING response with CertPoll requests until the CA answers or a bounded poll-count and total-wait budget is spent. `getCert` and `getCrl` retrieve an already-issued certificate or a CA CRL by issuer and serial number, authenticated the same way; RFC 8894 §2.6, §2.7, and §3.3.4 recommend these queries only where HTTP certificate-store access (RFC 4387), LDAP, or a CRL distribution point is unavailable, so prefer those where a CA offers them. GET-carried PKIOperation and HTTP proxy authentication are not yet built — `build`, `parse`, `parseCapabilities`, `getCACaps`, `getCACert`, `getNextCACert`, `enroll`, `renew`, `getCert`, `getCrl` |
|
|
226
226
|
| `pki.transport` | The shared, fail-closed `node:https` transport the enrollment clients drive. `pki.transport.https(defaults)` returns a `transport(request) → { status, headers, body, tls }`, where `tls` carries the negotiated `protocol`, `cipher`, and raw `peerCertificate`. This is the toolkit's only socket choke point: an explicit trust anchor (or an opt-in to the system store) is required, `rejectUnauthorized` is always on, TLS is floored at 1.2, the response body is capped while it streams, and a stalled socket times out. The EST, ACME, and CMP clients reuse it verbatim. If you inject your own transport, return `tls` too: `pki.est.serverkeygen` asserts the negotiated cipher can protect the delivered private key, and a transport that reports no cipher is trusted rather than refused, so omitting the field silently skips that check — `https` |
|
|
227
227
|
| `pki.jose` | Flattened JWS (RFC 7515) and JWK thumbprints (RFC 7638). `sign` and `verify` run a Flattened JWS against declarative profiles (ACME outer, EAB inner, keyChange inner) that carry the required and forbidden header rules as data. `base64url` is the strict RFC 4648 §5 codec, rejecting padding, non-alphabet characters, and non-canonical trailing bits. `parseJson` is a bounded reader that refuses duplicate members at any depth. `thumbprint` is the RFC 7638 / 8037 / 9964 canonical digest. The algorithm registry binds each `alg` to its key type (ES/RS/PS/EdDSA/ML-DSA), leaving no code path for `alg:none`, an RS256→HS256 key confusion, or an all-zero ECDSA signature; `assertPublicJwk` refuses a JWK carrying private material, so an exported private key is never published. `opts.key` names the key a message must be signed under and governs: where the profile also permits an embedded header `jwk`, the two must be the same key — compared as RFC 7638 thumbprints, so member order cannot make equal keys differ — and a disagreement is refused rather than resolved in the message's favor. `keySource` reports which key answered, since a signature checked against a key you named is a different claim from one checked against the key the message carried — `sign`, `verify`, `base64url`, `parseJson`, `thumbprint`, `assertPublicJwk` |
|
|
228
|
-
| `pki.acme` | ACME (RFC 8555 / 8737 / 8738 / 9773). `client(directoryUrl, opts)` is a stateful client driving a live CA directory over `pki.transport`: `newAccount`, `newOrder`, `newAuthz`, `getOrder`, `getAuthorization`, `getChallenge`, `respondToChallenge`, `finalize`, `pollOrder`, `pollAuthorization`, and `downloadCertificate` walk the issuance flow, with `newAuthz` pre-authorizing a single identifier (§7.4.1) and `downloadCertificate` binding the issued certificate to the order — its key, its identifiers, or both; at least one is required by default and the result reports `boundToKey` / `boundToIdentifiers` — before choosing among alternate chains (`Link rel="alternate"`, §7.4.2, via a `selectChain` predicate bounded by `maxAlternates`). `revokeCert` (account-key or certificate-key signed), `keyChange`, `updateAccount` (change the account contacts, §7.3.2), `listOrders` (the account's orders list, following the §7.1.2.1 `Link rel="next"` pagination bounded by a page cap and confined to the orders origin), `deactivateAccount`, `deactivateAuthorization`, `renewalInfo` (ARI),
|
|
228
|
+
| `pki.acme` | ACME (RFC 8555 / 8737 / 8738 / 9773). `client(directoryUrl, opts)` is a stateful client driving a live CA directory over `pki.transport`: `newAccount`, `newOrder`, `newAuthz`, `getOrder`, `getAuthorization`, `getChallenge`, `respondToChallenge`, `finalize`, `pollOrder`, `pollAuthorization`, and `downloadCertificate` walk the issuance flow, with `newAuthz` pre-authorizing a single identifier (§7.4.1) and `downloadCertificate` binding the issued certificate to the order — its key, its identifiers, or both; at least one is required by default and the result reports `boundToKey` / `boundToIdentifiers` — before choosing among alternate chains (`Link rel="alternate"`, §7.4.2, via a `selectChain` predicate bounded by `maxAlternates`). `revokeCert` (account-key or certificate-key signed), `keyChange`, `updateAccount` (change the account contacts, §7.3.2), `listOrders` (the account's orders list, following the §7.1.2.1 `Link rel="next"` pagination bounded by a page cap and confined to the orders origin), `deactivateAccount`, `deactivateAuthorization`, `renewalInfo` (ARI), `renewalWindow` (the RFC 9773 §4.2/4.3 renewal decision), and `scheduleRenewal` (the §4.1 auto-sleeping renewal loop that sleeps until the selected instant and refetches until it is time to renew, stopping at the certificate's notAfter) complete the lifecycle. Every URL is HTTPS only, an explicit trust anchor is required, each request carries a fresh single-use nonce with a bounded badNonce retry (and, when `opts.resignKeys` supplies caller-approved alternative account-key algorithms, a bounded RFC 8555 §6.2 badSignatureAlgorithm re-sign that the CA's advertised list can only filter, never widen, so it cannot force a weaker algorithm), reads are POST-as-GET, polling is bounded and sleeps on a Retry-After via an injectable sleeper capped by a poll count and a total-wait budget, and every response body is size-capped. The transport is injectable via `opts.transport`. Over the message layer it composes resource-object validators (closed status enums, conditional-required fields, unknown fields ignored), the three §7.1.6 state machines, the request builders (newAccount with External Account Binding, newOrder with `replaces`, finalize with a CSR identifier-set match and account-key-reuse rejection, challenge responses, deactivation, revokeCert in both key modes, the keyChange nested JWS, POST-as-GET), the http-01 / dns-01 / tls-alpn-01 challenge computations, the dns and ip identifier validators, and the ARI certID with serial sign-padding preserved — `client`, `validate`, `identify`, `assertTransition`, the builders, `keyAuthorization`, `http01`, `dns01`, `tlsAlpn01Extension`, `verifyTlsAlpn01`, `ariCertId` |
|
|
229
229
|
| `pki.schema.smime` | S/MIME ESS signed-attribute values (RFC 5035 / RFC 8551). `parseSigningCertificate` and `parseSigningCertificateV2` bind a signature to its signing certificate (cert hash, hash algorithm, issuer `GeneralNames` and serial); `parseSmimeCapabilities` decodes the ordered capability list; `decodeAttribute` dispatches a CMS attribute by OID, enforcing the single-value rule and deferring on unknown types. A companion decoder for CMS signed attributes rather than an auto-routed format — `parseSigningCertificate`, `parseSigningCertificateV2`, `parseSmimeCapabilities`, `decodeAttribute` |
|
|
230
230
|
| `pki.cmc` | Build and interpret CMC messages (RFC 5272). `build(spec, signer)` assembles a Full PKI Request across all three request arms (PKCS#10, CRMF, other) and signs it through `pki.cms.sign` under `id-cct-PKIData`. A PKCS#10 (`tcr`) request is verified against its own proof-of-possession before signing, so a request whose self-signature does not verify under its subject public key is refused rather than signed into a message a CA would reject. Body-part identifiers are unique across the whole message and never the reserved 0; a caller's clash is refused rather than renumbered, since a control may already reference it. An Identity Proof V2 witness is computed over the `reqSequence` bytes exactly as emitted (§6.2.1 step 1) rather than a re-serialization, a POP Link Witness is emitted only alongside the POP Link Random control §6.3.1.1 requires beside it, and a renewal carries neither Identification nor Identity Proof in either version. `verify(response, sent)` takes what the CA returned plus the state the client retained and reduces it to one terminal outcome: `issued`, `pending`, `confirm-required`, `pop-required`, or `rejected`. It binds the exchange first — Transaction Identifier, the Sender and Recipient Nonce echo compared in constant time and by full value so a truncation cannot match, and the Data Return echo — with each check applying only if the client sent that half, and, once sent, an absent or differing echo being a refusal, which is the replay defense. `bodyPartIDs` extends the same rule to what the response is about: a status reporting on a body part the request never sent is refused, which the transaction and nonce cannot catch, because a server can echo both correctly while answering about a different message. Several status controls are permitted and the worst governs, so a failure cannot hide behind an earlier success; the absence of any status control is success, per §6.1.2. The carrier's signature must verify (§3.2.1.3.4): a conforming SignedData carries its own signer certificate, so the ordinary build-then-verify flow needs nothing extra and the verdict reports `signatureVerified: true`. Where the signer is found nowhere the posture is fail-closed with a named opt-out — supply `certs` with the responder's certificate, or `allowUnverified: true`, in which case the verdict reports `signatureVerified: false`. Doing neither is refused, the opt-out never excuses a signature that is present and wrong, and a carrier with no signer at all is refused outright. The response's own `cmsSequence` and `otherMsgs` come back raw, since a request whose only arm was the other-message form has no certificate to return and §4.1 puts its answer there. Nothing is trusted: issued certificates are read from the CMS certificate bag (§4.2) and surfaced raw for `pki.path.validate`, and a Publish Trust Anchors control is surfaced with `trusted: false` rather than added to a store — `build`, `verify` |
|
|
231
231
|
| `pki.schema.cmc` | Decode CMC messages (RFC 5272 as updated by RFC 6402): a Full PKI Request (`PKIData`) or Full PKI Response (`PKIResponse`) riding inside a CMS SignedData, reached by the encapsulated content type (`id-cct-PKIData` / `id-cct-PKIResponse`). Controls are surfaced in wire order with their values raw, so an unrecognized one is data rather than a fault. Tagged requests decode across all three arms. The status verdicts (`CMCStatusInfo` v1 and `CMCStatusInfoV2`) are collected as an ordered list, and the RFC 6402 two-module `OtherStatusInfo` ambiguity — `pendInfo` and `extendedFailInfo` are both untagged SEQUENCEs in the 1988 module, told apart only by their first element — is resolved by inspection and refused when it cannot be told apart. Body-part identity is unique across the whole message rather than per sequence, 0 is reserved as the reference to the enclosing PKIData, and the `reqSequence` bytes are surfaced exactly as they appeared so an Identity Proof witness is computed over the wire bytes. A companion decoder for CMS content rather than an auto-routed format — `parse`, `parsePkiData`, `parsePkiResponse` |
|
package/lib/acme.js
CHANGED
|
@@ -51,6 +51,7 @@ var httpTransport = require("./http-transport");
|
|
|
51
51
|
var retryAfter = require("./http-retry-after");
|
|
52
52
|
var guard = require("./guard-all");
|
|
53
53
|
var intrinsic = require("./guard-intrinsic");
|
|
54
|
+
var _resolve = intrinsic.uncurry(intrinsic.promiseResolve);
|
|
54
55
|
var _hasOwn = intrinsic.hasOwn;
|
|
55
56
|
var _isBuffer = intrinsic.isBuffer;
|
|
56
57
|
var _isArrayI = intrinsic.isArray;
|
|
@@ -1757,7 +1758,7 @@ function _parseLinkNext(headers, base) { var m = _parseLinkRelation(headers, bas
|
|
|
1757
1758
|
* capped by a poll count and a total-wait budget. Returns a client
|
|
1758
1759
|
* object: `directory`, `newAccount`, `newOrder`, `newAuthz`, `getOrder` / `getAuthorization` / `getChallenge`,
|
|
1759
1760
|
* `respondToChallenge`, `finalize`, `pollOrder` / `pollAuthorization`, `downloadCertificate`,
|
|
1760
|
-
* `revokeCert`, `deactivateAccount` / `deactivateAuthorization`, `keyChange`, `renewalInfo`, `renewalWindow`.
|
|
1761
|
+
* `revokeCert`, `deactivateAccount` / `deactivateAuthorization`, `keyChange`, `renewalInfo`, `renewalWindow`, `scheduleRenewal`.
|
|
1761
1762
|
*
|
|
1762
1763
|
* @opts
|
|
1763
1764
|
* - `accountKey` / `accountJwk` / `alg` -- REQUIRED: the account private key, its public JWK, and the JWS alg.
|
|
@@ -1769,6 +1770,7 @@ function _parseLinkNext(headers, base) { var m = _parseLinkRelation(headers, bas
|
|
|
1769
1770
|
* - `newAuthz(identifier)` -- pre-authorize a single identifier (RFC 8555 sec. 7.4.1) -> { authorization, url }.
|
|
1770
1771
|
* - `downloadCertificate(url, { expectedSpki, identifiers, requireBinding, selectChain, maxAlternates })` -- bind the issued certificate to this order, then pick among RFC 8555 sec. 7.4.2 alternate chains. `expectedSpki` (the DER SubjectPublicKeyInfo this order's CSR asked to have certified) and `identifiers` (the order's own identifier array) are what the returned end-entity certificate is checked against: a different key is `acme/certificate-key-mismatch`, a different identifier set `acme/certificate-identifier-mismatch`. Only `dns` and `ip` identifiers map to a name a certificate carries, so an order identifier of another registered type, a certificate `subjectAltName` that is neither a dNSName nor an iPAddress, and a subject common name that is neither a dns name nor a canonical IP address, are each refused as `acme/unsupported-identifier-type` rather than dropped from the comparison. The certificate's alternative names are its identity; its common name is read only where it asserts none. At least one is required (`acme/binding-required`) unless `requireBinding: false`, which waives the requirement to supply material and never the check on material that is supplied. The result reports `boundToKey` / `boundToIdentifiers`. `selectChain({certificate, chain, certificates})` returns the first truthy candidate (primary first, then bounded `Link rel="alternate"` chains, confined to the download's own origin); the result adds `alternates` (the resolved alternate URLs).
|
|
1771
1772
|
* - `renewalWindow(certDer, { random, clock, replaced, previous })` -- the RFC 9773 ARI renewal decision: composes `renewalInfo`, selects a uniform-random instant in the suggested window -> { suggestedWindow, selectedTime, renewNow, retryAfterSeconds, explanationURL }. Pass a prior result back as `previous` to REUSE its selectedTime while the CA's window is unchanged (RFC 9773 sec. 4.2), so repeated refreshes keep one stable renewal instant.
|
|
1773
|
+
* - `scheduleRenewal(certDer, { random, shouldStop, renew, maxChecks, maxWait, longTermRetrySeconds, temporaryBaseSeconds })` -- the RFC 9773 sec. 4.1 auto-sleeping renewal loop over `renewalWindow`. It fetches the ARI decision, sleeps via the client `sleep` until the sooner of the selected instant and the Retry-After, and refetches until the window says renew now, resolving `{ reason: "renew-now", decision }`. It stops early with `{ reason: "expired" }` once the certificate passes its notAfter (a client MUST NOT check RenewalInfo after expiry, sec. 4.3), `{ reason: "stopped" }` when `shouldStop()` returns true (the caller's certificate-replaced signal, sec. 4.3), and `{ reason: "budget" }` when the optional `maxChecks` or `maxWait` (seconds) bound is reached. A transient server or transport error retries on the sec. 4.3.3 schedule: a 5xx backs off exponentially from `temporaryBaseSeconds`, and every other transient error waits `longTermRetrySeconds` (default six hours). A caller or certificate error, including a certificate that carries no authorityKeyIdentifier and so cannot produce an ARI certID, rejects. When `renew(decision)` is supplied it is awaited at renew now instead of resolving; returning a new certificate DER reschedules on it, returning nothing resolves `{ reason: "renewed", decision }`.
|
|
1772
1774
|
* @example
|
|
1773
1775
|
* var acme = pki.acme.client("https://acme.example/directory", { accountKey, accountJwk, alg: "ES256", transport });
|
|
1774
1776
|
* var acct = await acme.newAccount({ termsOfServiceAgreed: true });
|
|
@@ -1785,6 +1787,7 @@ var _METHOD_OPTS = {
|
|
|
1785
1787
|
revoke: { certAlg: 1, certJwk: 1, certKey: 1, certificate: 1, reason: 1 },
|
|
1786
1788
|
keyChange: { newAlg: 1, newJwk: 1, newKey: 1 },
|
|
1787
1789
|
renewalWindow: { random: 1, clock: 1, replaced: 1, previous: 1 },
|
|
1790
|
+
scheduleRenewal: { random: 1, shouldStop: 1, renew: 1, maxChecks: 1, maxWait: 1, longTermRetrySeconds: 1, temporaryBaseSeconds: 1 },
|
|
1788
1791
|
updateAccount: { contact: 1 },
|
|
1789
1792
|
listOrders: { maxPages: 1 },
|
|
1790
1793
|
};
|
|
@@ -2301,7 +2304,9 @@ function client(directoryUrl, opts) {
|
|
|
2301
2304
|
if (!isFinite(prevMs)) throw E("acme/bad-input", "renewalWindow opts.previous.selectedTime must be an RFC 3339 date-time");
|
|
2302
2305
|
selectedMs = Math.max(effStart, Math.min(effEnd, prevMs));
|
|
2303
2306
|
} else {
|
|
2304
|
-
var draw
|
|
2307
|
+
var draw;
|
|
2308
|
+
if (o.random) { try { draw = o.random(); } catch (e) { throw E("acme/bad-input", "the renewalWindow random callback threw", e); } }
|
|
2309
|
+
else { draw = _defaultRandom(); }
|
|
2305
2310
|
if (typeof draw !== "number" || !(draw >= 0 && draw <= 1)) throw E("acme/bad-input", "renewalWindow opts.random must return a number in [0, 1]");
|
|
2306
2311
|
selectedMs = Math.round(effStart + draw * (effEnd - effStart));
|
|
2307
2312
|
}
|
|
@@ -2318,6 +2323,79 @@ function client(directoryUrl, opts) {
|
|
|
2318
2323
|
});
|
|
2319
2324
|
}
|
|
2320
2325
|
|
|
2326
|
+
function _scheduleRenewal(certDer, o) {
|
|
2327
|
+
return _resolve(Promise).then(function () {
|
|
2328
|
+
o = _gateOpts(o, _METHOD_OPTS.scheduleRenewal, "scheduleRenewal");
|
|
2329
|
+
if (!guard.bytes.isByteSource(certDer)) throw E("acme/bad-input", "scheduleRenewal requires a DER certificate BufferSource");
|
|
2330
|
+
if (o.random !== undefined && typeof o.random !== "function") throw E("acme/bad-input", "scheduleRenewal opts.random must be a function returning a number in [0, 1]");
|
|
2331
|
+
if (o.shouldStop !== undefined && typeof o.shouldStop !== "function") throw E("acme/bad-input", "scheduleRenewal opts.shouldStop must be a function returning a boolean");
|
|
2332
|
+
if (o.renew !== undefined && typeof o.renew !== "function") throw E("acme/bad-input", "scheduleRenewal opts.renew must be an async function (decision) -> newCertDer | void");
|
|
2333
|
+
function optCount(v, name) {
|
|
2334
|
+
if (v === undefined) return null;
|
|
2335
|
+
if (typeof v !== "number" || !intrinsic.isFinite(v) || v < 1 || intrinsic.floor(v) !== v) throw E("acme/bad-input", "scheduleRenewal opts." + name + " must be a positive integer");
|
|
2336
|
+
return v;
|
|
2337
|
+
}
|
|
2338
|
+
var maxChecks = optCount(o.maxChecks, "maxChecks");
|
|
2339
|
+
var _mw = optCount(o.maxWait, "maxWait");
|
|
2340
|
+
var maxWaitMs = _mw == null ? null : constants.TIME.seconds(_mw);
|
|
2341
|
+
var longTermMs = constants.TIME.seconds(guard.limits.cap(o.longTermRetrySeconds, "longTermRetrySeconds", RENEWAL_RETRY_DEFAULT_SECONDS, { E: E, code: "acme/bad-input", min: RENEWAL_RETRY_MIN_SECONDS, max: RENEWAL_RETRY_MAX_SECONDS }));
|
|
2342
|
+
var tempBaseMs = constants.TIME.seconds(guard.limits.cap(o.temporaryBaseSeconds, "temporaryBaseSeconds", RENEWAL_RETRY_MIN_SECONDS, { E: E, code: "acme/bad-input", min: 1, max: RENEWAL_RETRY_MAX_SECONDS }));
|
|
2343
|
+
function _clk() { var t = clock(); if (typeof t !== "number" || !intrinsic.isFinite(t)) throw E("acme/bad-input", "the scheduleRenewal clock returned a non-finite value"); return t; }
|
|
2344
|
+
var startMs = _clk(), checks = 0, tempBackoffMs = tempBaseMs, previous = null;
|
|
2345
|
+
var cert = guard.bytes.snapshotSource(certDer, AcmeError, "acme/bad-input", "the scheduleRenewal certificate");
|
|
2346
|
+
function _boundedSleep(ms) { if (maxWaitMs != null) { ms = intrinsic.min(ms, intrinsic.max(0, maxWaitMs - (_clk() - startMs))); } return _resolve(Promise, sleep(ms)); }
|
|
2347
|
+
function _sleepThenLoop(ms) { return (maxChecks != null && checks >= maxChecks) ? { reason: "budget" } : _boundedSleep(ms).then(loop); }
|
|
2348
|
+
function _stop() {
|
|
2349
|
+
if (!o.shouldStop) return false;
|
|
2350
|
+
var s;
|
|
2351
|
+
try { s = o.shouldStop(); }
|
|
2352
|
+
catch (e) { throw E("acme/bad-input", "the scheduleRenewal shouldStop callback threw", e); }
|
|
2353
|
+
if (typeof s !== "boolean") throw E("acme/bad-input", "the scheduleRenewal shouldStop callback must return a boolean");
|
|
2354
|
+
return s;
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
function loop() {
|
|
2358
|
+
if (_stop()) return { reason: "stopped" };
|
|
2359
|
+
if (maxChecks != null && checks >= maxChecks) return { reason: "budget" };
|
|
2360
|
+
if (maxWaitMs != null && (_clk() - startMs) >= maxWaitMs) return { reason: "budget" };
|
|
2361
|
+
checks += 1;
|
|
2362
|
+
return _renewalWindow(cert, { random: o.random, clock: clock, previous: previous == null ? undefined : previous }).then(function (decision) {
|
|
2363
|
+
if (_stop()) return { reason: "stopped" };
|
|
2364
|
+
if (maxWaitMs != null && (_clk() - startMs) >= maxWaitMs) return { reason: "budget" };
|
|
2365
|
+
tempBackoffMs = tempBaseMs;
|
|
2366
|
+
if (decision.renewNow) {
|
|
2367
|
+
if (o.renew) {
|
|
2368
|
+
var _rc;
|
|
2369
|
+
try { _rc = o.renew(decision); }
|
|
2370
|
+
catch (e) { throw E("acme/bad-input", "the scheduleRenewal renew callback threw", e); }
|
|
2371
|
+
return _resolve(Promise, _rc).then(function (next) {
|
|
2372
|
+
if (next == null) return { reason: "renewed", decision: decision };
|
|
2373
|
+
if (!guard.bytes.isByteSource(next)) throw E("acme/bad-input", "scheduleRenewal opts.renew must return a DER certificate BufferSource or a nullish value");
|
|
2374
|
+
cert = guard.bytes.snapshotSource(next, AcmeError, "acme/bad-input", "the scheduleRenewal renewed certificate"); previous = null; return loop();
|
|
2375
|
+
}, function (e) { throw E("acme/bad-input", "the scheduleRenewal renew callback rejected", e); });
|
|
2376
|
+
}
|
|
2377
|
+
return { reason: "renew-now", decision: decision };
|
|
2378
|
+
}
|
|
2379
|
+
previous = decision;
|
|
2380
|
+
var untilSelected = guard.time.instantOf(rfc3339.parse(decision.selectedTime, E, "acme/bad-input", "the renewalWindow selected time")) - _clk();
|
|
2381
|
+
var retryMs = constants.TIME.seconds(decision.retryAfterSeconds);
|
|
2382
|
+
return _sleepThenLoop(intrinsic.max(0, intrinsic.min(untilSelected, retryMs)));
|
|
2383
|
+
}, function (err) {
|
|
2384
|
+
var code = err && err.code;
|
|
2385
|
+
if (code === "acme/certificate-expired") return { reason: "expired" };
|
|
2386
|
+
if (code === "acme/certificate-replaced") return { reason: "replaced" };
|
|
2387
|
+
if (code === "acme/bad-input" || code === "acme/bad-certid" || code === "acme/resource-unavailable" || (typeof code === "string" && intrinsic.stringIndexOf(code, "x509/") === 0)) throw err;
|
|
2388
|
+
var temporary = code === "acme/server-problem" && typeof err.httpStatus === "number" && err.httpStatus >= 500;
|
|
2389
|
+
var waitMs;
|
|
2390
|
+
if (temporary) { waitMs = intrinsic.min(tempBackoffMs, longTermMs); tempBackoffMs = tempBackoffMs * 2; }
|
|
2391
|
+
else { tempBackoffMs = tempBaseMs; waitMs = longTermMs; }
|
|
2392
|
+
return _sleepThenLoop(waitMs);
|
|
2393
|
+
});
|
|
2394
|
+
}
|
|
2395
|
+
return loop();
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2321
2399
|
return {
|
|
2322
2400
|
directory: _directory,
|
|
2323
2401
|
newAccount: _newAccount,
|
|
@@ -2339,6 +2417,7 @@ function client(directoryUrl, opts) {
|
|
|
2339
2417
|
keyChange: _keyChange,
|
|
2340
2418
|
renewalInfo: _renewalInfo,
|
|
2341
2419
|
renewalWindow: _renewalWindow,
|
|
2420
|
+
scheduleRenewal: _scheduleRenewal,
|
|
2342
2421
|
};
|
|
2343
2422
|
}
|
|
2344
2423
|
|
package/lib/cmp-build.js
CHANGED
|
@@ -75,18 +75,18 @@ var KNOWN_HEADER_KEYS = {
|
|
|
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
|
-
var KNOWN_BODY_KEYS = {
|
|
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,
|
|
81
81
|
nested: 1,
|
|
82
|
-
};
|
|
83
|
-
var BODY_TAG = {
|
|
82
|
+
});
|
|
83
|
+
var BODY_TAG = intrinsic.assign(intrinsic.create(null), {
|
|
84
84
|
ir: 0, cr: 2, p10cr: 4, kur: 7, krr: 9, ccr: 13, rr: 11, genm: 21, certConf: 24, pollReq: 25,
|
|
85
85
|
ip: 1, cp: 3, kup: 8, krp: 10, rp: 12, ccp: 14, pkiconf: 19, genp: 22, error: 23, pollRep: 26,
|
|
86
86
|
nested: 20,
|
|
87
|
-
};
|
|
88
|
-
var CRMF_BODY = { ir: 1, cr: 1, kur: 1, krr: 1, ccr: 1 };
|
|
89
|
-
var CERT_REP_ARM = { ip: 1, cp: 1, kup: 1, ccp: 1 };
|
|
87
|
+
});
|
|
88
|
+
var CRMF_BODY = intrinsic.assign(intrinsic.create(null), { ir: 1, cr: 1, kur: 1, krr: 1, ccr: 1 });
|
|
89
|
+
var CERT_REP_ARM = intrinsic.assign(intrinsic.create(null), { ip: 1, cp: 1, kup: 1, ccp: 1 });
|
|
90
90
|
var KNOWN_OPTS_KEYS = { key: 1, cert: 1, mac: 1, extraCerts: 1, pem: 1, pss: 1, digestAlgorithm: 1 };
|
|
91
91
|
var KNOWN_OPTS_SIG_KEYS = { key: 1, cert: 1, extraCerts: 1, pem: 1, pss: 1, digestAlgorithm: 1 };
|
|
92
92
|
var KNOWN_OPTS_MAC_KEYS = { mac: 1, extraCerts: 1, pem: 1 };
|
|
@@ -100,17 +100,17 @@ var PBMAC1_DEFAULT_KEYLEN = 32;
|
|
|
100
100
|
var PBMAC1_MIN_KEYLEN = 20;
|
|
101
101
|
var PBMAC1_MAX_KEYLEN = 1024;
|
|
102
102
|
var PBMAC1_MIN_ITER = 1000;
|
|
103
|
-
var PBMAC1_PRF = { "SHA-256": "hmacWithSHA256", "SHA-384": "hmacWithSHA384", "SHA-512": "hmacWithSHA512" };
|
|
104
|
-
var PBMAC1_MAC_OID = { "SHA-256": "hmacWithSHA256", "SHA-384": "hmacWithSHA384", "SHA-512": "hmacWithSHA512" };
|
|
103
|
+
var PBMAC1_PRF = intrinsic.assign(intrinsic.create(null), { "SHA-256": "hmacWithSHA256", "SHA-384": "hmacWithSHA384", "SHA-512": "hmacWithSHA512" });
|
|
104
|
+
var PBMAC1_MAC_OID = intrinsic.assign(intrinsic.create(null), { "SHA-256": "hmacWithSHA256", "SHA-384": "hmacWithSHA384", "SHA-512": "hmacWithSHA512" });
|
|
105
105
|
var PBMAC1_PRF_HLEN = { "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",
|
|
109
109
|
"addInfoNotAvailable", "badSenderNonce", "badCertTemplate", "signerNotTrusted", "transactionIdInUse",
|
|
110
110
|
"unsupportedVersion", "notAuthorized", "systemUnavail", "systemFailure", "duplicateCertReq"];
|
|
111
|
-
var FAIL_INFO_INDEX =
|
|
111
|
+
var FAIL_INFO_INDEX = intrinsic.create(null);
|
|
112
112
|
FAIL_INFO_NAMES.forEach(function (n, i) { FAIL_INFO_INDEX[n] = i; });
|
|
113
|
-
var CERT_CONF_HASH_ALGS = { sha1: 1, sha256: 1, sha384: 1, sha512: 1, "sha3-256": 1, "sha3-512": 1 };
|
|
113
|
+
var CERT_CONF_HASH_ALGS = intrinsic.assign(intrinsic.create(null), { sha1: 1, sha256: 1, sha384: 1, sha512: 1, "sha3-256": 1, "sha3-512": 1 });
|
|
114
114
|
|
|
115
115
|
|
|
116
116
|
function _reqOctets(v, what) {
|
package/lib/lint.js
CHANGED
|
@@ -44,7 +44,7 @@ var EXT_DECODERS = pkix.certExtensionDecoders(NS).byOid;
|
|
|
44
44
|
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
var SEVERITY = { fatal: 5, error: 4, warn: 3, notice: 2, pass: 1 };
|
|
47
|
+
var SEVERITY = Object.assign(Object.create(null), { fatal: 5, error: 4, warn: 3, notice: 2, pass: 1 });
|
|
48
48
|
var VALID_SEVERITY = Object.keys(SEVERITY);
|
|
49
49
|
|
|
50
50
|
function _worst(findings) {
|
|
@@ -191,7 +191,7 @@ function _rsaModulusBits(spki) {
|
|
|
191
191
|
return mod.toString(2).length;
|
|
192
192
|
} catch (_e) { return null; }
|
|
193
193
|
}
|
|
194
|
-
var RSA_KEY_ALGS = { rsaEncryption: 1, rsassaPss: 1, rsaesOaep: 1 };
|
|
194
|
+
var RSA_KEY_ALGS = Object.assign(Object.create(null), { rsaEncryption: 1, rsassaPss: 1, rsaesOaep: 1 });
|
|
195
195
|
var APPROVED_EC_CURVES = ["prime256v1", "secp384r1", "secp521r1"];
|
|
196
196
|
function _ecCurveName(spki) {
|
|
197
197
|
try {
|
|
@@ -476,7 +476,7 @@ var CABF_TLS_RULES = [
|
|
|
476
476
|
},
|
|
477
477
|
];
|
|
478
478
|
|
|
479
|
-
var ML_KEM_EK_LEN =
|
|
479
|
+
var ML_KEM_EK_LEN = Object.create(null);
|
|
480
480
|
["id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024"].forEach(function (n) { ML_KEM_EK_LEN[n] = oid.kemParams(n).ek; });
|
|
481
481
|
function _isMlKem(cert) {
|
|
482
482
|
var spki = cert.subjectPublicKeyInfo;
|
|
@@ -510,11 +510,11 @@ var RFC9935_RULES = [
|
|
|
510
510
|
},
|
|
511
511
|
];
|
|
512
512
|
|
|
513
|
-
var PROFILES = {
|
|
513
|
+
var PROFILES = Object.assign(Object.create(null), {
|
|
514
514
|
"rfc5280": RFC5280_RULES,
|
|
515
515
|
"rfc9935": RFC9935_RULES,
|
|
516
516
|
"cabf-tls": CABF_TLS_RULES,
|
|
517
|
-
};
|
|
517
|
+
});
|
|
518
518
|
var ALL_RULES = RFC5280_RULES.concat(RFC9935_RULES).concat(CABF_TLS_RULES);
|
|
519
519
|
|
|
520
520
|
function _selectRules(profile) {
|
package/lib/pbes2.js
CHANGED
|
@@ -13,7 +13,7 @@ var C = require("./constants");
|
|
|
13
13
|
var b = asn1.build;
|
|
14
14
|
function O(n) { return oid.byName(n); }
|
|
15
15
|
|
|
16
|
-
var PRF_NODE_BY_NAME = { hmacWithSHA1: "sha1", hmacWithSHA256: "sha256", hmacWithSHA384: "sha384", hmacWithSHA512: "sha512" };
|
|
16
|
+
var PRF_NODE_BY_NAME = Object.assign(Object.create(null), { hmacWithSHA1: "sha1", hmacWithSHA256: "sha256", hmacWithSHA384: "sha384", hmacWithSHA512: "sha512" });
|
|
17
17
|
var PRF_NODE_BY_OID = {}; Object.keys(PRF_NODE_BY_NAME).forEach(function (n) { PRF_NODE_BY_OID[O(n)] = PRF_NODE_BY_NAME[n]; });
|
|
18
18
|
|
|
19
19
|
var CONTENT_KEYBITS = {}, CONTENT_MODE = {};
|
package/lib/pkcs12-build.js
CHANGED
|
@@ -51,18 +51,18 @@ var MAX_PBMAC1_KEYLEN = 1024;
|
|
|
51
51
|
var CLASSIC_MAC_MAX_ITERATIONS = 1000000;
|
|
52
52
|
var KDF_MAX_ROUNDS = CLASSIC_MAC_MAX_ITERATIONS;
|
|
53
53
|
|
|
54
|
-
var P12_KDF_UV = {
|
|
54
|
+
var P12_KDF_UV = intrinsic.assign(intrinsic.create(null), {
|
|
55
55
|
sha1: { u: 20, v: 64 }, sha224: { u: 28, v: 64 }, sha256: { u: 32, v: 64 },
|
|
56
56
|
sha384: { u: 48, v: 128 }, sha512: { u: 64, v: 128 },
|
|
57
|
-
};
|
|
58
|
-
var PBMAC1_PRF = {
|
|
57
|
+
});
|
|
58
|
+
var PBMAC1_PRF = intrinsic.assign(intrinsic.create(null), {
|
|
59
59
|
sha256: { prfName: "hmacWithSHA256", wc: "SHA-256", keyLen: 32 },
|
|
60
60
|
sha384: { prfName: "hmacWithSHA384", wc: "SHA-384", keyLen: 48 },
|
|
61
61
|
sha512: { prfName: "hmacWithSHA512", wc: "SHA-512", keyLen: 64 },
|
|
62
|
-
};
|
|
63
|
-
var PRF_WC = { hmacWithSHA1: "SHA-1", hmacWithSHA256: "SHA-256", hmacWithSHA384: "SHA-384", hmacWithSHA512: "SHA-512" };
|
|
64
|
-
var CIPHER_NAME = { "aes-128-cbc": "aes128-CBC", "aes-192-cbc": "aes192-CBC", "aes-256-cbc": "aes256-CBC" };
|
|
65
|
-
var DIGEST_NAME = { sha1: "sha1", sha256: "sha256", sha384: "sha384", sha512: "sha512" };
|
|
62
|
+
});
|
|
63
|
+
var PRF_WC = intrinsic.assign(intrinsic.create(null), { hmacWithSHA1: "SHA-1", hmacWithSHA256: "SHA-256", hmacWithSHA384: "SHA-384", hmacWithSHA512: "SHA-512" });
|
|
64
|
+
var CIPHER_NAME = intrinsic.assign(intrinsic.create(null), { "aes-128-cbc": "aes128-CBC", "aes-192-cbc": "aes192-CBC", "aes-256-cbc": "aes256-CBC" });
|
|
65
|
+
var DIGEST_NAME = intrinsic.assign(intrinsic.create(null), { sha1: "sha1", sha256: "sha256", sha384: "sha384", sha512: "sha512" });
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
|
|
@@ -77,14 +77,14 @@ var _BUILD_OPTS_SHORTHAND = { integrity: 1, mac: 1, password: 1, pem: 1, recipie
|
|
|
77
77
|
var _SAFE_RECIPIENTS_KEYS = { bags: 1, recipients: 1, contentEncryptionAlgorithm: 1 };
|
|
78
78
|
var _SAFE_PASSWORD_KEYS = { bags: 1, encrypt: 1 };
|
|
79
79
|
var _SAFE_PLAINTEXT_KEYS = { bags: 1 };
|
|
80
|
-
var _BAG_KEYS_BY_TYPE = {
|
|
80
|
+
var _BAG_KEYS_BY_TYPE = intrinsic.assign(intrinsic.create(null), {
|
|
81
81
|
key: { type: 1, friendlyName: 1, localKeyId: 1, key: 1 },
|
|
82
82
|
shroudedKey: { type: 1, friendlyName: 1, localKeyId: 1, key: 1, encrypt: 1 },
|
|
83
83
|
cert: { type: 1, friendlyName: 1, localKeyId: 1, cert: 1 },
|
|
84
84
|
crl: { type: 1, friendlyName: 1, localKeyId: 1, crl: 1 },
|
|
85
85
|
secret: { type: 1, friendlyName: 1, localKeyId: 1, secretTypeId: 1, secretValue: 1 },
|
|
86
86
|
safeContents: { type: 1, friendlyName: 1, localKeyId: 1, nested: 1 },
|
|
87
|
-
};
|
|
87
|
+
});
|
|
88
88
|
var _ENCRYPT_KEYS = { password: 1, cipher: 1, salt: 1, iterations: 1, prf: 1 };
|
|
89
89
|
var _MAC_KEYS = { algorithm: 1, hash: 1, salt: 1, iterations: 1, keyLength: 1, password: 1 };
|
|
90
90
|
var _MAC_KEYS_HMAC = { algorithm: 1, hash: 1, salt: 1, iterations: 1, password: 1 };
|
package/lib/schema-c509.js
CHANGED
|
@@ -47,7 +47,7 @@ var PK_ALG_BY_INT = {
|
|
|
47
47
|
2: { alg: _name("ecPublicKey"), curve: _name("secp384r1") },
|
|
48
48
|
3: { alg: _name("ecPublicKey"), curve: _name("secp521r1") },
|
|
49
49
|
};
|
|
50
|
-
var EC_FIELD_BYTES = { "prime256v1": 32, "secp384r1": 48, "secp521r1": 66 };
|
|
50
|
+
var EC_FIELD_BYTES = Object.assign(Object.create(null), { "prime256v1": 32, "secp384r1": 48, "secp521r1": 66 });
|
|
51
51
|
|
|
52
52
|
var ATTR_BY_INT = {
|
|
53
53
|
0: _name("emailAddress"),
|
|
@@ -87,14 +87,14 @@ var EXT_BY_INT = {
|
|
|
87
87
|
36: _name("ocspNoCheck"),
|
|
88
88
|
38: _name("tlsFeature"),
|
|
89
89
|
};
|
|
90
|
-
var EXT_COMPACT = {
|
|
90
|
+
var EXT_COMPACT = Object.assign(Object.create(null), {
|
|
91
91
|
subjectKeyIdentifier: 1, keyUsage: 1, basicConstraints: 1, authorityKeyIdentifier: 1,
|
|
92
92
|
extKeyUsage: 1, inhibitAnyPolicy: 1, ocspNoCheck: 1, tlsFeature: 1,
|
|
93
93
|
subjectAltName: 1, issuerAltName: 1, nameConstraints: 1, cRLDistributionPoints: 1,
|
|
94
94
|
freshestCRL: 1, authorityInfoAccess: 1, subjectInfoAccess: 1, certificatePolicies: 1,
|
|
95
95
|
policyMappings: 1, policyConstraints: 1, subjectDirectoryAttributes: 1,
|
|
96
96
|
ipAddrBlocks: 1, autonomousSysIds: 1, ipAddrBlocksV2: 1, autonomousSysIdsV2: 1,
|
|
97
|
-
};
|
|
97
|
+
});
|
|
98
98
|
var EKU_BY_INT = {
|
|
99
99
|
0: _name("anyExtendedKeyUsage"), 1: _name("serverAuth"), 2: _name("clientAuth"),
|
|
100
100
|
3: _name("codeSigning"), 4: _name("emailProtection"), 8: _name("timeStamping"), 9: _name("ocspSigning"),
|
|
@@ -1561,11 +1561,11 @@ function matches(node) {
|
|
|
1561
1561
|
}
|
|
1562
1562
|
|
|
1563
1563
|
|
|
1564
|
-
var SIG_ALG_TO_INT = { ecdsaWithSHA256: 0, ecdsaWithSHA384: 1, ecdsaWithSHA512: 2 };
|
|
1565
|
-
var PK_ALG_TO_INT = { rsaEncryption: 0, "ecPublicKey|prime256v1": 1, "ecPublicKey|secp384r1": 2, "ecPublicKey|secp521r1": 3 };
|
|
1566
|
-
var ATTR_TO_INT =
|
|
1564
|
+
var SIG_ALG_TO_INT = Object.assign(Object.create(null), { ecdsaWithSHA256: 0, ecdsaWithSHA384: 1, ecdsaWithSHA512: 2 });
|
|
1565
|
+
var PK_ALG_TO_INT = Object.assign(Object.create(null), { rsaEncryption: 0, "ecPublicKey|prime256v1": 1, "ecPublicKey|secp384r1": 2, "ecPublicKey|secp521r1": 3 });
|
|
1566
|
+
var ATTR_TO_INT = Object.create(null);
|
|
1567
1567
|
Object.keys(ATTR_BY_INT).forEach(function (k) { ATTR_TO_INT[ATTR_BY_INT[k]] = Number(k); });
|
|
1568
|
-
var EXT_TO_INT =
|
|
1568
|
+
var EXT_TO_INT = Object.create(null);
|
|
1569
1569
|
Object.keys(EXT_BY_INT).forEach(function (k) { if (EXT_COMPACT[EXT_BY_INT[k]]) EXT_TO_INT[EXT_BY_INT[k]] = Number(k); });
|
|
1570
1570
|
|
|
1571
1571
|
function _minBytes(n) {
|
|
@@ -1754,9 +1754,9 @@ function _keyUsageBitsFromDer(extnValue) {
|
|
|
1754
1754
|
return _namedBitsFromContent(bs.bytes, bs.unusedBits);
|
|
1755
1755
|
}
|
|
1756
1756
|
var _NO_EXPIRY = Date.UTC(9999, 11, 31, 23, 59, 59);
|
|
1757
|
-
var NODE_TO_WEBCRYPTO = { "prime256v1": "P-256", "secp384r1": "P-384", "secp521r1": "P-521" };
|
|
1758
|
-
var WEBCRYPTO_FIELD_BYTES = { "P-256": 32, "P-384": 48, "P-521": 66 };
|
|
1759
|
-
var SIG_ALG_TO_CURVE = { "ecdsaWithSHA256": "P-256", "ecdsaWithSHA384": "P-384", "ecdsaWithSHA512": "P-521" };
|
|
1757
|
+
var NODE_TO_WEBCRYPTO = Object.assign(Object.create(null), { "prime256v1": "P-256", "secp384r1": "P-384", "secp521r1": "P-521" });
|
|
1758
|
+
var WEBCRYPTO_FIELD_BYTES = Object.assign(Object.create(null), { "P-256": 32, "P-384": 48, "P-521": 66 });
|
|
1759
|
+
var SIG_ALG_TO_CURVE = Object.assign(Object.create(null), { "ecdsaWithSHA256": "P-256", "ecdsaWithSHA384": "P-384", "ecdsaWithSHA512": "P-521" });
|
|
1760
1760
|
function _magBytes(intNode) {
|
|
1761
1761
|
var c = intNode.content, i = 0;
|
|
1762
1762
|
while (i < c.length - 1 && c[i] === 0x00) i++;
|
package/lib/sign-scheme.js
CHANGED
|
@@ -24,8 +24,8 @@ var _isBuffer = intrinsic.isBuffer;
|
|
|
24
24
|
var _bufferFrom = intrinsic.bufferFrom;
|
|
25
25
|
var _isU8 = intrinsic.types.isUint8Array;
|
|
26
26
|
|
|
27
|
-
var HASH = { sha256: "SHA-256", sha384: "SHA-384", sha512: "SHA-512" };
|
|
28
|
-
var NODE_DIGEST = { sha256: "sha256", sha384: "sha384", sha512: "sha512", shake128: "shake128", shake256: "shake256" };
|
|
27
|
+
var HASH = intrinsic.assign(intrinsic.create(null), { sha256: "SHA-256", sha384: "SHA-384", sha512: "SHA-512" });
|
|
28
|
+
var NODE_DIGEST = intrinsic.assign(intrinsic.create(null), { sha256: "sha256", sha384: "sha384", sha512: "sha512", shake128: "shake128", shake256: "shake256" });
|
|
29
29
|
var PSS_SALT = { "SHA-256": 32, "SHA-384": 48, "SHA-512": 64 };
|
|
30
30
|
var ECDSA_ALG = { sha256: "ecdsaWithSHA256", sha384: "ecdsaWithSHA384", sha512: "ecdsaWithSHA512" };
|
|
31
31
|
var RSA_PKCS1_SIG = { sha256: "sha256WithRSAEncryption", sha384: "sha384WithRSAEncryption", sha512: "sha512WithRSAEncryption" };
|
package/lib/tsp-sign.js
CHANGED
|
@@ -47,7 +47,7 @@ var _b = pkiBuild.makeBuilder({
|
|
|
47
47
|
NAME_SCHEMA: pkix.name(_NS), SPKI_SCHEMA: pkix.spki(_NS),
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
var NODE_DIGEST = { sha256: "sha256", sha384: "sha384", sha512: "sha512" };
|
|
50
|
+
var NODE_DIGEST = intrinsic.assign(intrinsic.create(null), { sha256: "sha256", sha384: "sha384", sha512: "sha512" });
|
|
51
51
|
var HASH_LEN = { sha256: 32, sha384: 48, sha512: 64 };
|
|
52
52
|
|
|
53
53
|
var _REVOCATION_RANK = { "false": 0, "undetermined": 1, "waived": 2, "determined": 3 };
|
|
@@ -397,9 +397,9 @@ function response(token, opts) {
|
|
|
397
397
|
function parseResponse(input) { return schemaTsp.parse(input); }
|
|
398
398
|
|
|
399
399
|
|
|
400
|
-
var _VERIFY_DIGEST = { sha256: "sha256", sha384: "sha384", sha512: "sha512", sha1: "sha1" };
|
|
401
|
-
var _VERIFY_DIGEST_LEN = { sha1: 20, sha256: 32, sha384: 48, sha512: 64 };
|
|
402
|
-
var _BIND_DIGEST = { sha256: "sha256", sha384: "sha384", sha512: "sha512" };
|
|
400
|
+
var _VERIFY_DIGEST = intrinsic.assign(intrinsic.create(null), { sha256: "sha256", sha384: "sha384", sha512: "sha512", sha1: "sha1" });
|
|
401
|
+
var _VERIFY_DIGEST_LEN = intrinsic.assign(intrinsic.create(null), { sha1: 20, sha256: 32, sha384: 48, sha512: 64 });
|
|
402
|
+
var _BIND_DIGEST = intrinsic.assign(intrinsic.create(null), { sha256: "sha256", sha384: "sha384", sha512: "sha512" });
|
|
403
403
|
|
|
404
404
|
function _imprintMatches(mi, data) {
|
|
405
405
|
var name = mi.hashAlgorithm && mi.hashAlgorithm.name;
|
package/lib/webcrypto.js
CHANGED
|
@@ -122,7 +122,7 @@ function _normalizeAlg(algorithm, who) {
|
|
|
122
122
|
return out;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
var _STD_ALG_NAME = { "RSASSA-PKCS1-V1_5": "RSASSA-PKCS1-v1_5", "ED25519": "Ed25519", "ED448": "Ed448" };
|
|
125
|
+
var _STD_ALG_NAME = intrinsic.assign(intrinsic.create(null), { "RSASSA-PKCS1-V1_5": "RSASSA-PKCS1-v1_5", "ED25519": "Ed25519", "ED448": "Ed448" });
|
|
126
126
|
function _stdName(name) { return _STD_ALG_NAME[name] || name; }
|
|
127
127
|
|
|
128
128
|
var HASH_NODE = {
|
|
@@ -164,24 +164,24 @@ function _hmacLengthBits(alg, who) {
|
|
|
164
164
|
return alg.length;
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
var CURVE_NODE = { "P-256": "prime256v1", "P-384": "secp384r1", "P-521": "secp521r1" };
|
|
168
|
-
var CURVE_FIELD_BYTES = { "P-256": 32, "P-384": 48, "P-521": 66 };
|
|
167
|
+
var CURVE_NODE = intrinsic.assign(intrinsic.create(null), { "P-256": "prime256v1", "P-384": "secp384r1", "P-521": "secp521r1" });
|
|
168
|
+
var CURVE_FIELD_BYTES = intrinsic.assign(intrinsic.create(null), { "P-256": 32, "P-384": 48, "P-521": 66 });
|
|
169
169
|
|
|
170
|
-
var ML_DSA_NODE = { "ML-DSA-44": "ml-dsa-44", "ML-DSA-65": "ml-dsa-65", "ML-DSA-87": "ml-dsa-87" };
|
|
171
|
-
var ML_KEM_NODE = { "ML-KEM-512": "ml-kem-512", "ML-KEM-768": "ml-kem-768", "ML-KEM-1024": "ml-kem-1024" };
|
|
170
|
+
var ML_DSA_NODE = intrinsic.assign(intrinsic.create(null), { "ML-DSA-44": "ml-dsa-44", "ML-DSA-65": "ml-dsa-65", "ML-DSA-87": "ml-dsa-87" });
|
|
171
|
+
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" });
|
|
172
172
|
|
|
173
|
-
var SLH_DSA_NODE =
|
|
173
|
+
var SLH_DSA_NODE = intrinsic.create(null);
|
|
174
174
|
["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
175
175
|
"shake-128s", "shake-128f", "shake-192s", "shake-192f", "shake-256s", "shake-256f"
|
|
176
176
|
].forEach(function (s) { SLH_DSA_NODE["SLH-DSA-" + _toUpperCase(s)] = "slh-dsa-" + s; });
|
|
177
177
|
|
|
178
|
-
var SIGN_VERIFY_NAMES =
|
|
178
|
+
var SIGN_VERIFY_NAMES = intrinsic.create(null);
|
|
179
179
|
["RSASSA-PKCS1-V1_5", "RSA-PSS", "ECDSA", "ED25519", "ED448", "HMAC"]
|
|
180
180
|
.concat(_keys(ML_DSA_NODE), _keys(SLH_DSA_NODE))
|
|
181
181
|
.forEach(function (n) { SIGN_VERIFY_NAMES[n] = true; });
|
|
182
|
-
var ENCRYPT_DECRYPT_NAMES = { "RSA-OAEP": true, "AES-GCM": true, "AES-CBC": true, "AES-CTR": true };
|
|
183
|
-
var DERIVE_NAMES = { "ECDH": true, "X25519": true, "X448": true, "HKDF": true, "PBKDF2": true, "X963KDF": true };
|
|
184
|
-
var SECRET_KEY_NAMES = { "AES-GCM": true, "AES-CBC": true, "AES-CTR": true, "AES-KW": true, "HMAC": true, "HKDF": true, "PBKDF2": true, "X963KDF": true };
|
|
182
|
+
var ENCRYPT_DECRYPT_NAMES = intrinsic.assign(intrinsic.create(null), { "RSA-OAEP": true, "AES-GCM": true, "AES-CBC": true, "AES-CTR": true });
|
|
183
|
+
var DERIVE_NAMES = intrinsic.assign(intrinsic.create(null), { "ECDH": true, "X25519": true, "X448": true, "HKDF": true, "PBKDF2": true, "X963KDF": true });
|
|
184
|
+
var SECRET_KEY_NAMES = intrinsic.assign(intrinsic.create(null), { "AES-GCM": true, "AES-CBC": true, "AES-CTR": true, "AES-KW": true, "HMAC": true, "HKDF": true, "PBKDF2": true, "X963KDF": true });
|
|
185
185
|
|
|
186
186
|
|
|
187
187
|
/**
|
|
@@ -974,12 +974,12 @@ function _importRawPublic(name, alg, raw, extractable, usages) {
|
|
|
974
974
|
throw new WebCryptoError("webcrypto/not-supported", "importKey raw: unsupported public-key algorithm " + _stringify(name));
|
|
975
975
|
}
|
|
976
976
|
|
|
977
|
-
var IMPORT_KEY_TYPE = {
|
|
977
|
+
var IMPORT_KEY_TYPE = intrinsic.assign(intrinsic.create(null), {
|
|
978
978
|
"RSASSA-PKCS1-V1_5": { rsa: 1 }, "RSA-PSS": { rsa: 1, "rsa-pss": 1 }, "RSA-OAEP": { rsa: 1 },
|
|
979
979
|
"ECDSA": { ec: 1 }, "ECDH": { ec: 1 },
|
|
980
980
|
"ED25519": { ed25519: 1 }, "ED448": { ed448: 1 },
|
|
981
981
|
"X25519": { x25519: 1 }, "X448": { x448: 1 },
|
|
982
|
-
};
|
|
982
|
+
});
|
|
983
983
|
[ML_DSA_NODE, ML_KEM_NODE, SLH_DSA_NODE].forEach(function (m) {
|
|
984
984
|
_forEach(_keys(m), function (webName) { var t = {}; t[m[webName]] = 1; IMPORT_KEY_TYPE[webName] = t; });
|
|
985
985
|
});
|
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:79647de9-cba8-48fb-9af1-d6ec9bebf2be",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-09-
|
|
8
|
+
"timestamp": "2026-09-02T01:10:34.456Z",
|
|
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.6.
|
|
22
|
+
"bom-ref": "@blamejs/pki@0.6.22",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "pki",
|
|
25
|
-
"version": "0.6.
|
|
25
|
+
"version": "0.6.22",
|
|
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.6.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/pki@0.6.22",
|
|
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.6.
|
|
57
|
+
"ref": "@blamejs/pki@0.6.22",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|