@blamejs/core 0.15.12 → 0.15.14
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 +4 -0
- package/index.js +2 -0
- package/lib/a2a-tasks.js +45 -29
- package/lib/acme.js +6 -5
- package/lib/agent-event-bus.js +18 -4
- package/lib/agent-idempotency.js +7 -6
- package/lib/agent-orchestrator.js +2 -5
- package/lib/agent-saga.js +3 -5
- package/lib/agent-snapshot.js +32 -2
- package/lib/agent-tenant.js +2 -5
- package/lib/ai-adverse-decision.js +2 -15
- package/lib/ai-aedt-bias-audit.js +2 -1
- package/lib/ai-capability.js +1 -6
- package/lib/ai-content-detect.js +1 -3
- package/lib/ai-dp.js +1 -5
- package/lib/ai-frontier-protocol.js +1 -1
- package/lib/ai-input.js +2 -2
- package/lib/ai-model-manifest.js +1 -1
- package/lib/ai-output.js +16 -7
- package/lib/ai-pref.js +3 -8
- package/lib/ai-quota.js +3 -14
- package/lib/api-key.js +37 -28
- package/lib/api-snapshot.js +4 -1
- package/lib/app-shutdown.js +7 -1
- package/lib/archive-adapters.js +2 -4
- package/lib/archive-entry-policy.js +32 -0
- package/lib/archive-gz.js +9 -0
- package/lib/archive-read.js +14 -24
- package/lib/archive-tar-read.js +56 -24
- package/lib/archive.js +6 -12
- package/lib/arg-parser.js +7 -6
- package/lib/asn1-der.js +70 -22
- package/lib/asyncapi-traits.js +2 -6
- package/lib/atomic-file.js +312 -33
- package/lib/audit-chain.js +183 -54
- package/lib/audit-daily-review.js +36 -16
- package/lib/audit-emit.js +82 -0
- package/lib/audit-sign.js +258 -0
- package/lib/audit-tools.js +108 -23
- package/lib/audit.js +91 -2
- package/lib/auth/access-lock.js +7 -29
- package/lib/auth/bot-challenge.js +1 -1
- package/lib/auth/ciba.js +43 -4
- package/lib/auth/dpop.js +29 -36
- package/lib/auth/fido-mds3.js +14 -16
- package/lib/auth/jwt-external.js +26 -8
- package/lib/auth/jwt.js +15 -17
- package/lib/auth/lockout.js +24 -27
- package/lib/auth/oauth.js +67 -45
- package/lib/auth/oid4vci.js +55 -32
- package/lib/auth/oid4vp.js +3 -2
- package/lib/auth/openid-federation.js +6 -6
- package/lib/auth/passkey.js +4 -4
- package/lib/auth/password.js +8 -2
- package/lib/auth/saml.js +70 -40
- package/lib/auth/sd-jwt-vc-holder.js +2 -14
- package/lib/auth/sd-jwt-vc-issuer.js +2 -14
- package/lib/auth/sd-jwt-vc.js +25 -5
- package/lib/auth/status-list.js +21 -9
- package/lib/auth/step-up.js +15 -13
- package/lib/auth-bot-challenge.js +27 -39
- package/lib/backup/bundle.js +18 -20
- package/lib/backup/crypto.js +23 -8
- package/lib/backup/index.js +55 -67
- package/lib/backup/manifest.js +7 -1
- package/lib/bounded-map.js +112 -1
- package/lib/breach-deadline.js +1 -11
- package/lib/break-glass.js +41 -22
- package/lib/cache.js +7 -18
- package/lib/cbor.js +36 -12
- package/lib/cdn-cache-control.js +15 -12
- package/lib/cert.js +8 -13
- package/lib/chain-writer.js +162 -47
- package/lib/cli.js +10 -2
- package/lib/client-hints.js +7 -9
- package/lib/cloud-events.js +43 -33
- package/lib/cluster-storage.js +9 -41
- package/lib/cms-codec.js +2 -1
- package/lib/codepoint-class.js +84 -1
- package/lib/compliance-ai-act-logging.js +1 -6
- package/lib/compliance-ai-act-transparency.js +2 -4
- package/lib/compliance-eaa.js +2 -12
- package/lib/compliance-sanctions-fetcher.js +21 -28
- package/lib/compliance-sanctions.js +11 -21
- package/lib/compliance.js +3 -10
- package/lib/config-drift.js +24 -20
- package/lib/content-credentials.js +11 -8
- package/lib/content-digest.js +21 -12
- package/lib/cookies.js +15 -13
- package/lib/cose.js +39 -11
- package/lib/cra-report.js +1 -11
- package/lib/crdt.js +2 -1
- package/lib/crypto-field.js +34 -33
- package/lib/crypto.js +138 -7
- package/lib/csp.js +239 -3
- package/lib/daemon.js +46 -42
- package/lib/data-act.js +46 -13
- package/lib/db-file-lifecycle.js +14 -6
- package/lib/db-query.js +75 -49
- package/lib/db.js +66 -27
- package/lib/dbsc.js +5 -6
- package/lib/ddl-change-control.js +18 -14
- package/lib/deprecate.js +4 -5
- package/lib/did.js +6 -2
- package/lib/dora.js +43 -13
- package/lib/dr-runbook.js +1 -1
- package/lib/dsa.js +2 -1
- package/lib/dsr.js +30 -20
- package/lib/early-hints.js +19 -0
- package/lib/eat.js +5 -1
- package/lib/external-db-migrate.js +21 -22
- package/lib/external-db.js +74 -30
- package/lib/fda-21cfr11.js +42 -13
- package/lib/fdx.js +22 -18
- package/lib/file-upload.js +80 -66
- package/lib/flag-evaluation-context.js +5 -8
- package/lib/flag-providers.js +6 -2
- package/lib/forms.js +1 -1
- package/lib/framework-error.js +12 -0
- package/lib/framework-schema.js +19 -0
- package/lib/fsm.js +7 -12
- package/lib/gate-contract.js +911 -39
- package/lib/gdpr-ropa.js +22 -22
- package/lib/graphql-federation.js +18 -5
- package/lib/guard-agent-registry.js +2 -1
- package/lib/guard-all.js +3 -2
- package/lib/guard-archive.js +9 -30
- package/lib/guard-auth.js +23 -80
- package/lib/guard-cidr.js +20 -96
- package/lib/guard-csv.js +135 -196
- package/lib/guard-domain.js +23 -106
- package/lib/guard-dsn.js +17 -14
- package/lib/guard-email.js +46 -53
- package/lib/guard-envelope.js +2 -2
- package/lib/guard-event-bus-topic.js +2 -1
- package/lib/guard-filename.js +12 -60
- package/lib/guard-graphql.js +28 -75
- package/lib/guard-html-wcag.js +15 -2
- package/lib/guard-html.js +74 -128
- package/lib/guard-idempotency-key.js +2 -1
- package/lib/guard-image.js +280 -77
- package/lib/guard-imap-command.js +9 -10
- package/lib/guard-jmap.js +1 -1
- package/lib/guard-json.js +101 -109
- package/lib/guard-jsonpath.js +20 -88
- package/lib/guard-jwt.js +32 -114
- package/lib/guard-list-id.js +2 -7
- package/lib/guard-list-unsubscribe.js +2 -7
- package/lib/guard-mail-compose.js +5 -6
- package/lib/guard-mail-move.js +3 -2
- package/lib/guard-mail-query.js +5 -3
- package/lib/guard-mail-sieve.js +6 -7
- package/lib/guard-managesieve-command.js +6 -5
- package/lib/guard-markdown.js +76 -110
- package/lib/guard-message-id.js +5 -6
- package/lib/guard-mime.js +20 -99
- package/lib/guard-oauth.js +19 -73
- package/lib/guard-pdf.js +65 -72
- package/lib/guard-pop3-command.js +13 -14
- package/lib/guard-posture-chain.js +2 -1
- package/lib/guard-regex.js +24 -99
- package/lib/guard-saga-config.js +2 -1
- package/lib/guard-shell.js +22 -87
- package/lib/guard-smtp-command.js +9 -12
- package/lib/guard-sql.js +15 -13
- package/lib/guard-stream-args.js +2 -1
- package/lib/guard-svg.js +103 -149
- package/lib/guard-template.js +23 -80
- package/lib/guard-tenant-id.js +2 -1
- package/lib/guard-text.js +592 -0
- package/lib/guard-time.js +27 -95
- package/lib/guard-uuid.js +21 -93
- package/lib/guard-xml.js +76 -106
- package/lib/guard-yaml.js +24 -60
- package/lib/html-balance.js +7 -3
- package/lib/http-client-cache.js +5 -12
- package/lib/http-client-cookie-jar.js +35 -16
- package/lib/http-client.js +233 -74
- package/lib/http-message-signature.js +3 -2
- package/lib/i18n-messageformat.js +5 -7
- package/lib/i18n.js +83 -26
- package/lib/iab-tcf.js +3 -2
- package/lib/importmap-integrity.js +41 -1
- package/lib/inbox.js +8 -8
- package/lib/incident-report.js +12 -27
- package/lib/ip-utils.js +49 -6
- package/lib/jobs.js +3 -2
- package/lib/json-patch.js +1 -1
- package/lib/json-path.js +24 -3
- package/lib/jtd.js +2 -2
- package/lib/keychain.js +6 -18
- package/lib/legal-hold.js +30 -23
- package/lib/log-stream-cloudwatch.js +44 -112
- package/lib/log-stream-otlp-grpc.js +17 -14
- package/lib/log-stream-otlp.js +16 -80
- package/lib/log-stream-webhook.js +20 -92
- package/lib/log.js +2 -2
- package/lib/mail-agent.js +2 -2
- package/lib/mail-arc-sign.js +8 -3
- package/lib/mail-arf.js +4 -3
- package/lib/mail-auth.js +43 -69
- package/lib/mail-bimi.js +35 -55
- package/lib/mail-bounce.js +3 -3
- package/lib/mail-crypto-pgp.js +3 -2
- package/lib/mail-crypto-smime.js +71 -6
- package/lib/mail-dav.js +8 -35
- package/lib/mail-deploy.js +15 -14
- package/lib/mail-dkim.js +19 -38
- package/lib/mail-greylist.js +17 -30
- package/lib/mail-helo.js +4 -7
- package/lib/mail-journal.js +13 -9
- package/lib/mail-mdn.js +12 -7
- package/lib/mail-rbl.js +7 -12
- package/lib/mail-scan.js +5 -7
- package/lib/mail-send-deliver.js +33 -20
- package/lib/mail-server-imap.js +32 -87
- package/lib/mail-server-jmap.js +39 -52
- package/lib/mail-server-managesieve.js +29 -83
- package/lib/mail-server-mx.js +33 -74
- package/lib/mail-server-net.js +177 -0
- package/lib/mail-server-pop3.js +30 -83
- package/lib/mail-server-rate-limit.js +30 -6
- package/lib/mail-server-registry.js +1 -1
- package/lib/mail-server-submission.js +34 -73
- package/lib/mail-server-tls.js +98 -2
- package/lib/mail-spam-score.js +9 -12
- package/lib/mail-store-fts.js +1 -1
- package/lib/mail-store.js +3 -2
- package/lib/mail.js +28 -13
- package/lib/markup-escape.js +31 -0
- package/lib/markup-tokenizer.js +78 -0
- package/lib/mcp-tool-registry.js +26 -23
- package/lib/mcp.js +7 -5
- package/lib/mdoc.js +36 -14
- package/lib/metrics.js +46 -33
- package/lib/middleware/age-gate.js +3 -23
- package/lib/middleware/api-encrypt.js +13 -24
- package/lib/middleware/assetlinks.js +2 -7
- package/lib/middleware/bearer-auth.js +2 -1
- package/lib/middleware/body-parser.js +41 -52
- package/lib/middleware/bot-disclose.js +7 -10
- package/lib/middleware/bot-guard.js +28 -28
- package/lib/middleware/clear-site-data.js +5 -1
- package/lib/middleware/compression.js +9 -0
- package/lib/middleware/cors.js +32 -23
- package/lib/middleware/csrf-protect.js +73 -23
- package/lib/middleware/daily-byte-quota.js +12 -30
- package/lib/middleware/deny-response.js +19 -1
- package/lib/middleware/fetch-metadata.js +35 -4
- package/lib/middleware/idempotency-key.js +4 -20
- package/lib/middleware/network-allowlist.js +61 -30
- package/lib/middleware/rate-limit.js +45 -44
- package/lib/middleware/scim-server.js +5 -3
- package/lib/middleware/security-headers.js +33 -7
- package/lib/middleware/security-txt.js +2 -6
- package/lib/middleware/speculation-rules.js +6 -3
- package/lib/middleware/tus-upload.js +14 -29
- package/lib/middleware/web-app-manifest.js +2 -7
- package/lib/migrations.js +4 -13
- package/lib/mime-parse.js +34 -17
- package/lib/module-loader.js +44 -0
- package/lib/money.js +105 -0
- package/lib/mtls-ca.js +125 -41
- package/lib/network-byte-quota.js +4 -18
- package/lib/network-dane.js +8 -6
- package/lib/network-dns-resolver.js +98 -7
- package/lib/network-dns.js +9 -2
- package/lib/network-dnssec.js +18 -17
- package/lib/network-heartbeat.js +3 -2
- package/lib/network-smtp-policy.js +52 -46
- package/lib/network-tls.js +67 -47
- package/lib/network-tsig.js +2 -2
- package/lib/nis2-report.js +2 -12
- package/lib/nist-crosswalk.js +1 -1
- package/lib/nonce-store.js +81 -3
- package/lib/ntp-check.js +28 -0
- package/lib/numeric-bounds.js +31 -8
- package/lib/object-store/azure-blob-bucket-ops.js +2 -6
- package/lib/object-store/azure-blob.js +6 -47
- package/lib/object-store/gcs-bucket-ops.js +4 -2
- package/lib/object-store/gcs.js +14 -75
- package/lib/object-store/http-put.js +2 -7
- package/lib/object-store/http-request.js +157 -0
- package/lib/object-store/local.js +37 -17
- package/lib/object-store/sigv4-bucket-ops.js +2 -1
- package/lib/object-store/sigv4.js +10 -79
- package/lib/observability-otlp-exporter.js +29 -29
- package/lib/observability.js +95 -0
- package/lib/openapi-paths-builder.js +7 -3
- package/lib/otel-export.js +7 -10
- package/lib/outbox.js +54 -41
- package/lib/pagination.js +11 -15
- package/lib/parsers/safe-env.js +5 -4
- package/lib/parsers/safe-ini.js +10 -4
- package/lib/parsers/safe-toml.js +11 -9
- package/lib/parsers/safe-xml.js +3 -3
- package/lib/parsers/safe-yaml.js +28 -9
- package/lib/pick.js +63 -5
- package/lib/pipl-cn.js +69 -59
- package/lib/privacy-pass.js +8 -6
- package/lib/problem-details.js +2 -5
- package/lib/pubsub.js +4 -8
- package/lib/queue-local.js +10 -3
- package/lib/redact.js +9 -4
- package/lib/render.js +4 -2
- package/lib/request-helpers.js +334 -29
- package/lib/resource-access-lock.js +3 -3
- package/lib/restore-bundle.js +46 -18
- package/lib/restore-rollback.js +10 -4
- package/lib/restore.js +24 -22
- package/lib/retention.js +23 -9
- package/lib/router.js +17 -4
- package/lib/safe-async.js +457 -0
- package/lib/safe-buffer.js +137 -6
- package/lib/safe-decompress.js +2 -1
- package/lib/safe-dns.js +2 -1
- package/lib/safe-ical.js +14 -28
- package/lib/safe-icap.js +1 -1
- package/lib/safe-json.js +51 -8
- package/lib/safe-jsonpath.js +6 -5
- package/lib/safe-mime.js +25 -29
- package/lib/safe-redirect.js +2 -5
- package/lib/safe-schema.js +7 -6
- package/lib/safe-sieve.js +1 -1
- package/lib/safe-sql.js +126 -0
- package/lib/safe-vcard.js +13 -27
- package/lib/sandbox-worker.js +15 -2
- package/lib/sandbox.js +4 -3
- package/lib/scheduler.js +22 -13
- package/lib/sec-cyber.js +82 -37
- package/lib/seeders.js +4 -11
- package/lib/self-update-standalone-verifier.js +16 -0
- package/lib/self-update.js +92 -69
- package/lib/session-device-binding.js +112 -66
- package/lib/session.js +219 -7
- package/lib/sql.js +228 -81
- package/lib/sse.js +6 -10
- package/lib/static.js +201 -111
- package/lib/storage.js +4 -2
- package/lib/structured-fields.js +275 -16
- package/lib/template.js +7 -5
- package/lib/tenant-quota.js +53 -38
- package/lib/tsa.js +16 -17
- package/lib/validate-opts.js +154 -8
- package/lib/vault/index.js +5 -0
- package/lib/vault/passphrase-ops.js +22 -26
- package/lib/vault/passphrase-source.js +8 -3
- package/lib/vault/rotate.js +13 -18
- package/lib/vault/seal-pem-file.js +34 -49
- package/lib/vault-aad.js +3 -2
- package/lib/vc.js +3 -8
- package/lib/vendor/MANIFEST.json +10 -10
- package/lib/vendor/public-suffix-list.dat +23 -10
- package/lib/vendor/public-suffix-list.data.js +5498 -5494
- package/lib/vex.js +35 -13
- package/lib/web-push-vapid.js +23 -20
- package/lib/webhook-dispatcher.js +706 -0
- package/lib/webhook.js +59 -19
- package/lib/websocket-channels.js +9 -7
- package/lib/websocket.js +8 -4
- package/lib/worm.js +3 -4
- package/lib/ws-client.js +65 -56
- package/lib/x509-chain.js +44 -0
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/cose.js
CHANGED
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
var nodeCrypto = require("node:crypto");
|
|
56
56
|
var cbor = require("./cbor");
|
|
57
57
|
var bCrypto = require("./crypto");
|
|
58
|
+
var safeBuffer = require("./safe-buffer");
|
|
58
59
|
var validateOpts = require("./validate-opts");
|
|
59
60
|
var { defineClass } = require("./framework-error");
|
|
60
61
|
|
|
@@ -109,11 +110,30 @@ function _algParamsFor(algId) {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
// RFC 9053 §2 binds each ECDSA alg to ONE curve. node:crypto will happily
|
|
114
|
+
// verify a sha512 (ES512-shape) signature against a P-256 key as
|
|
115
|
+
// self-consistent, so without this check a COSE_Sign1 declaring ES512 but
|
|
116
|
+
// carrying a P-256 key passes when ES512 is allowlisted — an alg/curve
|
|
117
|
+
// confusion (the COSE sibling of jwt-external._assertAlgKtyMatch). EdDSA /
|
|
118
|
+
// ML-DSA carry their parameters in the KeyObject and need no binding.
|
|
119
|
+
var _ES_ALG_CURVE = { ES256: "prime256v1", ES384: "secp384r1", ES512: "secp521r1" };
|
|
120
|
+
function _assertEcAlgCurve(algName, key) {
|
|
121
|
+
var want = _ES_ALG_CURVE[algName];
|
|
122
|
+
if (want === undefined) return; // not an ECDSA alg — nothing to bind
|
|
123
|
+
var got = (key && key.asymmetricKeyDetails && key.asymmetricKeyDetails.namedCurve) || null;
|
|
124
|
+
if (key.asymmetricKeyType !== "ec" || got !== want) {
|
|
125
|
+
throw new CoseError("cose/alg-curve-mismatch",
|
|
126
|
+
"cose: alg '" + algName + "' requires an EC key on " + want +
|
|
127
|
+
", got " + (key.asymmetricKeyType === "ec" ? got : key.asymmetricKeyType));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
112
131
|
function _bstr(x) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
return safeBuffer.toBuffer(x, {
|
|
133
|
+
errorFactory: function (code, msg) { return new CoseError(code, msg); },
|
|
134
|
+
typeCode: "cose/bad-bytes",
|
|
135
|
+
typeMessage: "cose: expected bytes (Buffer / Uint8Array / string)",
|
|
136
|
+
});
|
|
117
137
|
}
|
|
118
138
|
|
|
119
139
|
// Sig_structure (RFC 9052 §4.4) for COSE_Sign1:
|
|
@@ -167,6 +187,7 @@ async function sign(payload, opts) {
|
|
|
167
187
|
var algId = ALG_NAME_TO_ID[opts.alg];
|
|
168
188
|
var params = _algParamsFor(algId);
|
|
169
189
|
var key = _toKeyObject(opts.privateKey, "private");
|
|
190
|
+
_assertEcAlgCurve(opts.alg, key); // RFC 9053 alg↔curve binding — refuse e.g. ES512 over a P-256 key
|
|
170
191
|
|
|
171
192
|
var protMap = new Map();
|
|
172
193
|
protMap.set(HDR_ALG, algId);
|
|
@@ -350,6 +371,7 @@ async function verify(coseSign1, opts) {
|
|
|
350
371
|
var key = opts.publicKey
|
|
351
372
|
? _toKeyObject(opts.publicKey, "public")
|
|
352
373
|
: _toKeyObject(opts.keyResolver(protMap, unprotected), "public");
|
|
374
|
+
_assertEcAlgCurve(algName, key); // RFC 9053 alg↔curve binding
|
|
353
375
|
|
|
354
376
|
var externalAad = opts.externalAad == null ? Buffer.alloc(0) : _bstr(opts.externalAad);
|
|
355
377
|
var toBeSigned = _toBeSigned(protectedBstr, externalAad, payload);
|
|
@@ -753,11 +775,14 @@ var COSE_KEY_LABEL_KTY = 1;
|
|
|
753
775
|
var COSE_KEY_LABEL_KID = 2;
|
|
754
776
|
var COSE_KEY_LABEL_ALG = 3;
|
|
755
777
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
778
|
+
// COSE_Key components are byte strings, never text (allowString:false).
|
|
779
|
+
var _coseKeyBytes = safeBuffer.makeByteCoercer({
|
|
780
|
+
errorClass: CoseError,
|
|
781
|
+
typeCode: "cose/bad-cose-key",
|
|
782
|
+
messagePrefix: "cose.importKey: COSE_Key ",
|
|
783
|
+
messageSuffix: " must be a byte string",
|
|
784
|
+
allowString: false,
|
|
785
|
+
});
|
|
761
786
|
|
|
762
787
|
/**
|
|
763
788
|
* @primitive b.cose.importKey
|
|
@@ -806,8 +831,11 @@ function importKey(coseKey) {
|
|
|
806
831
|
} else {
|
|
807
832
|
throw new CoseError("cose/unsupported-key", "cose.importKey: kty must be OKP (1) or EC2 (2), got " + kty);
|
|
808
833
|
}
|
|
809
|
-
|
|
810
|
-
|
|
834
|
+
return bCrypto.importPublicJwk(jwk, {
|
|
835
|
+
errorClass: CoseError,
|
|
836
|
+
code: "cose/bad-cose-key",
|
|
837
|
+
messagePrefix: "cose.importKey: could not import COSE_Key: ",
|
|
838
|
+
});
|
|
811
839
|
}
|
|
812
840
|
|
|
813
841
|
/**
|
package/lib/cra-report.js
CHANGED
|
@@ -70,7 +70,6 @@ function create(opts) {
|
|
|
70
70
|
var enisaEndpoint = typeof opts.enisaEndpoint === "string" && opts.enisaEndpoint.length > 0
|
|
71
71
|
? opts.enisaEndpoint : null;
|
|
72
72
|
var httpClient = opts.httpClient || null;
|
|
73
|
-
var auditOn = opts.audit !== false;
|
|
74
73
|
|
|
75
74
|
// CRA Article 14 deadlines — operators don't override these without
|
|
76
75
|
// documented regulatory justification (the deadlines are statutory,
|
|
@@ -89,16 +88,7 @@ function create(opts) {
|
|
|
89
88
|
},
|
|
90
89
|
});
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
if (!auditOn) return;
|
|
94
|
-
try {
|
|
95
|
-
audit().safeEmit({
|
|
96
|
-
action: "cra.report." + action,
|
|
97
|
-
outcome: outcome,
|
|
98
|
-
metadata: metadata || {},
|
|
99
|
-
});
|
|
100
|
-
} catch (_e) { /* drop-silent */ }
|
|
101
|
-
}
|
|
91
|
+
var _emitAudit = audit().namespaced("cra.report", opts.audit);
|
|
102
92
|
|
|
103
93
|
async function _submitToEnisa(payload) {
|
|
104
94
|
if (!enisaEndpoint || !httpClient) {
|
package/lib/crdt.js
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
var bCrypto = require("./crypto");
|
|
43
43
|
var safeJson = require("./safe-json");
|
|
44
|
+
var numericBounds = require("./numeric-bounds");
|
|
44
45
|
var { defineClass } = require("./framework-error");
|
|
45
46
|
|
|
46
47
|
var CrdtError = defineClass("CrdtError", { alwaysPermanent: true });
|
|
@@ -52,7 +53,7 @@ function _replicaId(opts) {
|
|
|
52
53
|
return id;
|
|
53
54
|
}
|
|
54
55
|
function _posInt(n, label) {
|
|
55
|
-
if (
|
|
56
|
+
if (!numericBounds.isNonNegativeFiniteInt(n)) throw new CrdtError("crdt/bad-value", "crdt: " + label + " must be a non-negative integer");
|
|
56
57
|
return n;
|
|
57
58
|
}
|
|
58
59
|
function _maxMerge(a, b) {
|
package/lib/crypto-field.js
CHANGED
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
* Per-column field-level encryption with AAD-bound envelopes.
|
|
57
57
|
*/
|
|
58
58
|
var lazyRequire = require("./lazy-require");
|
|
59
|
+
var boundedMap = require("./bounded-map");
|
|
59
60
|
var vault = require("./vault");
|
|
60
61
|
var vaultAad = require("./vault-aad");
|
|
61
62
|
var validateOpts = require("./validate-opts");
|
|
62
63
|
var numericBounds = require("./numeric-bounds");
|
|
63
64
|
var safeJson = require("./safe-json");
|
|
64
|
-
var frameworkSchema = require("./framework-schema");
|
|
65
65
|
var sql = require("./sql");
|
|
66
66
|
var { defineClass } = require("./framework-error");
|
|
67
67
|
var { sha3Hash, kdf, generateBytes, encryptPacked, decryptPacked, generateToken } = require("./crypto");
|
|
@@ -225,14 +225,19 @@ var PER_ROW_KEYS_TABLE = "_blamejs_per_row_keys"; // allow:hand-rolled-sql
|
|
|
225
225
|
var PER_ROW_KEYS_COLUMN = "wrappedKey";
|
|
226
226
|
var PER_ROW_KEYS_SCHEMA_VERSION = "1";
|
|
227
227
|
|
|
228
|
-
// The per-row-key registry
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
//
|
|
228
|
+
// The per-row-key registry ALWAYS lives in the LOCAL sqlite — reconcile creates
|
|
229
|
+
// it under its RAW schema name, and per-row keys are never dispatched to an
|
|
230
|
+
// external backend (see _kRowOnce's db() fallback). It is read/written against
|
|
231
|
+
// the local db() / dbHandle directly, NOT through clusterStorage, so it must use
|
|
232
|
+
// the RAW table name. frameworkSchema.tableName() resolves to the cluster-mode
|
|
233
|
+
// EXTERNAL prefixed name (the prefix applies only to the external backend, via
|
|
234
|
+
// resolveTables — local DDL stays raw); under a custom tablePrefix that names a
|
|
235
|
+
// table that does not exist locally, which SILENTLY breaks crypto-shred:
|
|
236
|
+
// destroyPerRowKey deletes 0 rows and sealed cells stay decryptable after
|
|
237
|
+
// eraseHard. quoteName so b.sql emits the quoted identifier the local path expects.
|
|
233
238
|
var _PER_ROW_SQL_OPTS = { dialect: "sqlite", quoteName: true };
|
|
234
239
|
function _perRowKeysTableName() {
|
|
235
|
-
return
|
|
240
|
+
return PER_ROW_KEYS_TABLE;
|
|
236
241
|
}
|
|
237
242
|
|
|
238
243
|
// Build the canonical AAD parts for a row-secret wrap in
|
|
@@ -568,14 +573,9 @@ function computeNamespacedHash(ns, value, opts) {
|
|
|
568
573
|
"(default) or 'hmac-shake256', got " + JSON.stringify(mode));
|
|
569
574
|
}
|
|
570
575
|
var truncateBytes = opts.truncateBytes;
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
throw new CryptoFieldError("crypto-field/bad-truncate-bytes",
|
|
575
|
-
"computeNamespacedHash: opts.truncateBytes must be a " +
|
|
576
|
-
"positive integer (bytes), got " + JSON.stringify(truncateBytes));
|
|
577
|
-
}
|
|
578
|
-
}
|
|
576
|
+
numericBounds.requirePositiveFiniteIntIfPresent(truncateBytes,
|
|
577
|
+
"computeNamespacedHash: opts.truncateBytes", CryptoFieldError,
|
|
578
|
+
"crypto-field/bad-truncate-bytes");
|
|
579
579
|
var hex = _computeDerivedHash({ mode: mode }, mode, ns, String(value));
|
|
580
580
|
if (truncateBytes !== undefined) {
|
|
581
581
|
return hex.slice(0, truncateBytes * 2);
|
|
@@ -918,8 +918,7 @@ function _rateNoteFailure(actor, table, column) {
|
|
|
918
918
|
if (!_rateCap) return false;
|
|
919
919
|
var nowMs = _rateCap.now();
|
|
920
920
|
var key = _rateKey(actor, table, column);
|
|
921
|
-
var arr =
|
|
922
|
-
if (!arr) { arr = []; _rateFailWindows.set(key, arr); }
|
|
921
|
+
var arr = boundedMap.getOrInsert(_rateFailWindows, key, function () { return []; });
|
|
923
922
|
// Prune entries older than the window (sliding-window via timestamp
|
|
924
923
|
// array — same shape as b.mail.server.rateLimit._pruneWindow).
|
|
925
924
|
var cutoff = nowMs - _rateCap.windowMs;
|
|
@@ -1276,19 +1275,19 @@ function unsealRow(table, row, actor, dbHandle) {
|
|
|
1276
1275
|
unsealed = out[field];
|
|
1277
1276
|
}
|
|
1278
1277
|
} catch (e) {
|
|
1279
|
-
// A
|
|
1280
|
-
//
|
|
1281
|
-
//
|
|
1282
|
-
//
|
|
1283
|
-
//
|
|
1284
|
-
//
|
|
1285
|
-
//
|
|
1286
|
-
//
|
|
1287
|
-
|
|
1278
|
+
// A crypto-shredded (or never-materialized) per-row key is an EXPECTED
|
|
1279
|
+
// absence, not a decryption-oracle attack: the wrapped secret is gone,
|
|
1280
|
+
// so there is no oracle to brute-force. Reading such a row must read as
|
|
1281
|
+
// "no value" WITHOUT counting against the rate cap — otherwise a bulk
|
|
1282
|
+
// read over a table with many erased rows (GDPR eraseHard) trips the
|
|
1283
|
+
// cap and DoS's the live rows (self-DoS, CWE-307 mis-applied). It is
|
|
1284
|
+
// audited under a distinct, non-failure action so operators don't alert
|
|
1285
|
+
// on routine post-erasure reads as forged-ciphertext bursts.
|
|
1286
|
+
var _shredded = e && e.code === "crypto-field/row-key-unavailable";
|
|
1288
1287
|
try {
|
|
1289
1288
|
audit().safeEmit({
|
|
1290
|
-
action: "system.crypto.unseal_failed",
|
|
1291
|
-
outcome: "failure",
|
|
1289
|
+
action: _shredded ? "system.crypto.shredded_read" : "system.crypto.unseal_failed",
|
|
1290
|
+
outcome: _shredded ? "success" : "failure",
|
|
1292
1291
|
metadata: {
|
|
1293
1292
|
table: table,
|
|
1294
1293
|
field: field,
|
|
@@ -1298,11 +1297,13 @@ function unsealRow(table, row, actor, dbHandle) {
|
|
|
1298
1297
|
},
|
|
1299
1298
|
});
|
|
1300
1299
|
} catch (_e) { /* drop-silent */ }
|
|
1301
|
-
// Default-on rate cap: account
|
|
1302
|
-
//
|
|
1303
|
-
//
|
|
1304
|
-
//
|
|
1305
|
-
|
|
1300
|
+
// Default-on rate cap: account a genuine decryption / AEAD-verify /
|
|
1301
|
+
// AAD-downgrade failure (a possible forged-ciphertext attack) against
|
|
1302
|
+
// the (actor, table, column) tuple. A shredded-key read is exempt (see
|
|
1303
|
+
// above). When the cap trips the threshold, arm the cooldown + emit the
|
|
1304
|
+
// distinct rate-exceeded audit once on the transition. No-op when the
|
|
1305
|
+
// cap is disabled.
|
|
1306
|
+
if (!_shredded && _rateNoteFailure(capActor, table, field)) {
|
|
1306
1307
|
_emitRateAudit({
|
|
1307
1308
|
table: table, field: field, actor: capActor, shape: shape,
|
|
1308
1309
|
threshold: _rateCap.threshold, windowMs: _rateCap.windowMs, cooldownMs: _rateCap.cooldownMs,
|
package/lib/crypto.js
CHANGED
|
@@ -49,6 +49,7 @@ var nodeFs = require("node:fs");
|
|
|
49
49
|
var { pipeline } = require("node:stream/promises");
|
|
50
50
|
var { xchacha20poly1305 } = require("./vendor/noble-ciphers.cjs");
|
|
51
51
|
var C = require("./constants");
|
|
52
|
+
var numericBounds = require("./numeric-bounds");
|
|
52
53
|
// Circular: audit imports b.crypto for sha3Hash + envelope sign. Lazy-
|
|
53
54
|
// load the audit module so the legacy-envelope decrypt path can emit
|
|
54
55
|
// `system.crypto.decrypt.allow_legacy` events without an inline
|
|
@@ -337,8 +338,7 @@ function hashFilesParallel(filePaths, opts) {
|
|
|
337
338
|
// override per-call.
|
|
338
339
|
var maxBytesPerFile = opts.maxBytesPerFile !== undefined
|
|
339
340
|
? opts.maxBytesPerFile : C.BYTES.gib(1);
|
|
340
|
-
if (
|
|
341
|
-
maxBytesPerFile <= 0 || Math.floor(maxBytesPerFile) !== maxBytesPerFile) {
|
|
341
|
+
if (!numericBounds.isPositiveFiniteInt(maxBytesPerFile)) {
|
|
342
342
|
return Promise.reject(new TypeError(
|
|
343
343
|
"crypto.hashFilesParallel: opts.maxBytesPerFile must be a positive integer, got " + maxBytesPerFile
|
|
344
344
|
));
|
|
@@ -847,6 +847,74 @@ function fromBase64Url(s, opts) {
|
|
|
847
847
|
return Buffer.from(s, "base64url");
|
|
848
848
|
}
|
|
849
849
|
|
|
850
|
+
/**
|
|
851
|
+
* @primitive b.crypto.makeBase64UrlDecoder
|
|
852
|
+
* @signature b.crypto.makeBase64UrlDecoder(opts)
|
|
853
|
+
* @since 0.15.13
|
|
854
|
+
* @status stable
|
|
855
|
+
* @related b.crypto.fromBase64Url, b.crypto.toBase64Url
|
|
856
|
+
*
|
|
857
|
+
* Bind the strict `fromBase64Url` decoder to one module's error contract,
|
|
858
|
+
* returning a `decode(s)` that translates the decoder's `TypeError` (bad
|
|
859
|
+
* type or non-canonical input) into the caller's typed error. Every
|
|
860
|
+
* base64url-carrying surface — JWT segments, DPoP / OAuth tokens, status
|
|
861
|
+
* lists, pagination cursors — wrapped `fromBase64Url` in the same
|
|
862
|
+
* `if (typeof s !== "string") throw new XError(...); try { return
|
|
863
|
+
* fromBase64Url(s); } catch { throw new XError(...); }` shape, differing
|
|
864
|
+
* only in error class, code, and the two messages; this owns that binding.
|
|
865
|
+
*
|
|
866
|
+
* `opts.badMessage` is thrown on any decode failure (non-canonical /
|
|
867
|
+
* malformed input — the strict decoder rejects the CWE-347 signature-
|
|
868
|
+
* canonicalization footgun). `opts.typeMessage` is optional: when set, a
|
|
869
|
+
* non-string input throws it directly (the common case names the field —
|
|
870
|
+
* "cursor must be a string"); when omitted, a non-string falls through to
|
|
871
|
+
* `badMessage` like any other decode failure.
|
|
872
|
+
*
|
|
873
|
+
* @opts
|
|
874
|
+
* errorClass: Function, // required — (code, message) error constructor
|
|
875
|
+
* code: string, // required — error code for both throws
|
|
876
|
+
* badMessage: string, // required — message on a decode failure
|
|
877
|
+
* typeMessage: string, // optional — message on a non-string input
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* var b = require("blamejs");
|
|
881
|
+
*
|
|
882
|
+
* function JwtError(code, message) { this.code = code; this.message = message; }
|
|
883
|
+
* var decodeSeg = b.crypto.makeBase64UrlDecoder({
|
|
884
|
+
* errorClass: JwtError,
|
|
885
|
+
* code: "jwt/malformed",
|
|
886
|
+
* typeMessage: "expected base64url string",
|
|
887
|
+
* badMessage: "JWT segment is not valid base64url",
|
|
888
|
+
* });
|
|
889
|
+
* decodeSeg("aGVsbG8"); // → <Buffer 68 65 6c 6c 6f>
|
|
890
|
+
* // decodeSeg("!!!") throws JwtError("jwt/malformed", "JWT segment is not valid base64url")
|
|
891
|
+
*/
|
|
892
|
+
function makeBase64UrlDecoder(opts) {
|
|
893
|
+
if (!opts || typeof opts !== "object") {
|
|
894
|
+
throw new TypeError("crypto.makeBase64UrlDecoder: opts is required");
|
|
895
|
+
}
|
|
896
|
+
if (typeof opts.errorClass !== "function") {
|
|
897
|
+
throw new TypeError("crypto.makeBase64UrlDecoder: opts.errorClass must be a constructor");
|
|
898
|
+
}
|
|
899
|
+
if (typeof opts.badMessage !== "string") {
|
|
900
|
+
throw new TypeError("crypto.makeBase64UrlDecoder: opts.badMessage must be a string");
|
|
901
|
+
}
|
|
902
|
+
var ErrorClass = opts.errorClass;
|
|
903
|
+
var code = opts.code;
|
|
904
|
+
var typeMessage = opts.typeMessage;
|
|
905
|
+
var badMessage = opts.badMessage;
|
|
906
|
+
return function decode(s) {
|
|
907
|
+
if (typeMessage !== undefined && typeof s !== "string") {
|
|
908
|
+
throw new ErrorClass(code, typeMessage);
|
|
909
|
+
}
|
|
910
|
+
try {
|
|
911
|
+
return fromBase64Url(s);
|
|
912
|
+
} catch (_e) {
|
|
913
|
+
throw new ErrorClass(code, badMessage);
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
|
|
850
918
|
// ---- Subresource Integrity (W3C SRI 1.0) ----
|
|
851
919
|
//
|
|
852
920
|
// b.crypto.sri(content, { algorithm? }) — returns a `sha###-base64`
|
|
@@ -895,7 +963,7 @@ var SRI_ALGORITHMS = { "sha256": "sha256", "sha384": "sha384", "sha512": "sha512
|
|
|
895
963
|
function sri(content, opts) {
|
|
896
964
|
opts = opts || {};
|
|
897
965
|
var algorithm = (opts.algorithm || "sha384").toLowerCase();
|
|
898
|
-
if (!SRI_ALGORITHMS
|
|
966
|
+
if (!Object.prototype.hasOwnProperty.call(SRI_ALGORITHMS, algorithm)) {
|
|
899
967
|
throw new Error("crypto.sri: unsupported algorithm '" + algorithm +
|
|
900
968
|
"' (W3C SRI 1.0 §3.2 supports sha256/sha384/sha512)");
|
|
901
969
|
}
|
|
@@ -1024,6 +1092,53 @@ function verify(data, signature, publicKeyPem) {
|
|
|
1024
1092
|
return nodeCrypto.verify(null, Buffer.from(data), publicKeyPem, signature);
|
|
1025
1093
|
}
|
|
1026
1094
|
|
|
1095
|
+
/**
|
|
1096
|
+
* @primitive b.crypto.importPublicJwk
|
|
1097
|
+
* @signature b.crypto.importPublicJwk(jwk, opts?)
|
|
1098
|
+
* @since 0.15.13
|
|
1099
|
+
* @status stable
|
|
1100
|
+
* @related b.crypto.verify
|
|
1101
|
+
*
|
|
1102
|
+
* Import a JWK as a public `KeyObject` via
|
|
1103
|
+
* `crypto.createPublicKey({ key, format: "jwk" })`, translating the Node
|
|
1104
|
+
* import failure into a caller-supplied typed error. Untrusted JWKs reach
|
|
1105
|
+
* this from DID documents (`publicKeyJwk`), DNSKEY records, and COSE_Key
|
|
1106
|
+
* structures — each module validates the `kty` / `crv` it accepts BEFORE
|
|
1107
|
+
* calling, then hands the assembled JWK here for the final import + error
|
|
1108
|
+
* translation that was otherwise hand-rolled identically in every one.
|
|
1109
|
+
* Centralising it gives one place to harden untrusted-JWK import.
|
|
1110
|
+
*
|
|
1111
|
+
* On failure, when `opts.errorClass` is supplied the thrown error is
|
|
1112
|
+
* `new opts.errorClass(opts.code, opts.messagePrefix + nodeFailureDetail)`
|
|
1113
|
+
* so the operator sees the module's own code + a message naming the
|
|
1114
|
+
* source; without it the original Node error propagates unchanged.
|
|
1115
|
+
*
|
|
1116
|
+
* @opts
|
|
1117
|
+
* errorClass: Function, // (code, message) error constructor
|
|
1118
|
+
* code: string, // error code passed to errorClass
|
|
1119
|
+
* messagePrefix: string, // text before the Node failure detail. default: ""
|
|
1120
|
+
*
|
|
1121
|
+
* @example
|
|
1122
|
+
* var b = require("blamejs");
|
|
1123
|
+
*
|
|
1124
|
+
* function KeyError(code, message) { this.code = code; this.message = message; }
|
|
1125
|
+
* var key = b.crypto.importPublicJwk(
|
|
1126
|
+
* { kty: "OKP", crv: "Ed25519", x: "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo" },
|
|
1127
|
+
* { errorClass: KeyError, code: "bad-key", messagePrefix: "bad key: " });
|
|
1128
|
+
* // → <KeyObject> (or throws KeyError("bad-key", "bad key: <detail>"))
|
|
1129
|
+
*/
|
|
1130
|
+
function importPublicJwk(jwk, opts) {
|
|
1131
|
+
opts = opts || {};
|
|
1132
|
+
try {
|
|
1133
|
+
return nodeCrypto.createPublicKey({ key: jwk, format: "jwk" });
|
|
1134
|
+
} catch (e) {
|
|
1135
|
+
if (typeof opts.errorClass === "function") {
|
|
1136
|
+
throw new opts.errorClass(opts.code, (opts.messagePrefix || "") + ((e && e.message) || e));
|
|
1137
|
+
}
|
|
1138
|
+
throw e;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1027
1142
|
// Track whether the hybrid-disabled audit has been emitted at least
|
|
1028
1143
|
// once per process, so a high-volume KEM-only deployment doesn't peg
|
|
1029
1144
|
// the audit bus with one event per encrypt() call. Operators who want
|
|
@@ -1241,7 +1356,21 @@ function decrypt(ciphertext, privateKeys, opts) {
|
|
|
1241
1356
|
opts && opts.raw === true ? { raw: true } : undefined);
|
|
1242
1357
|
}
|
|
1243
1358
|
|
|
1359
|
+
// Bounds-checked 2-byte length read — a bare _envU16(packed, pos) on a
|
|
1360
|
+
// truncated envelope throws a raw Node RangeError that escapes the documented
|
|
1361
|
+
// "Invalid envelope: ..." error contract (untrusted ciphertext must fail with
|
|
1362
|
+
// the typed envelope error, not a stack-trace-leaking RangeError).
|
|
1363
|
+
function _envU16(buf, at) {
|
|
1364
|
+
if (at + 2 > buf.length) {
|
|
1365
|
+
throw new Error("Invalid envelope: truncated (expected a 2-byte length at offset " + at + ")");
|
|
1366
|
+
}
|
|
1367
|
+
return buf.readUInt16BE(at);
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1244
1370
|
function decryptEnvelope(packed, privateKeys, internalOpts) {
|
|
1371
|
+
if (!Buffer.isBuffer(packed) || packed.length < 4) {
|
|
1372
|
+
throw new Error("Invalid envelope: too short (need at least the 4-byte suite header)");
|
|
1373
|
+
}
|
|
1245
1374
|
var kemId = packed[1], cipherId = packed[2], kdfId = packed[3], pos = 4;
|
|
1246
1375
|
|
|
1247
1376
|
// The legacy 0xE1 envelope predates the FixedInfo / suite-binding
|
|
@@ -1257,7 +1386,7 @@ function decryptEnvelope(packed, privateKeys, internalOpts) {
|
|
|
1257
1386
|
throw new Error("Invalid envelope: unsupported KDF (only SHAKE256 supported)");
|
|
1258
1387
|
}
|
|
1259
1388
|
|
|
1260
|
-
var kemCtLen = packed
|
|
1389
|
+
var kemCtLen = _envU16(packed, pos); pos += 2;
|
|
1261
1390
|
var kemCt = packed.subarray(pos, pos + kemCtLen); pos += kemCtLen;
|
|
1262
1391
|
|
|
1263
1392
|
var mlkemPriv = nodeCrypto.createPrivateKey(
|
|
@@ -1268,7 +1397,7 @@ function decryptEnvelope(packed, privateKeys, internalOpts) {
|
|
|
1268
1397
|
var fixedInfo = omitFixedInfo ? Buffer.alloc(0) : _suiteFixedInfo(kemId, cipherId, kdfId);
|
|
1269
1398
|
|
|
1270
1399
|
if (kemId === C.KEM_IDS.ML_KEM_1024_P384) {
|
|
1271
|
-
var ecEphLen = packed
|
|
1400
|
+
var ecEphLen = _envU16(packed, pos); pos += 2;
|
|
1272
1401
|
var ecEphDer = packed.subarray(pos, pos + ecEphLen); pos += ecEphLen;
|
|
1273
1402
|
var ecPrivPem = typeof privateKeys === "string" ? null : privateKeys.ecPrivateKey;
|
|
1274
1403
|
if (!ecPrivPem) throw new Error("Hybrid KEM requires EC private key");
|
|
@@ -1285,7 +1414,7 @@ function decryptEnvelope(packed, privateKeys, internalOpts) {
|
|
|
1285
1414
|
// the correct keypair via privateKeys when the envelope was sealed
|
|
1286
1415
|
// with this algorithm. Same length-prefixed shape as the P-384
|
|
1287
1416
|
// hybrid: 2-byte ec-eph-len + DER X25519 pubkey + nonce + ct.
|
|
1288
|
-
var x25519EphLen = packed
|
|
1417
|
+
var x25519EphLen = _envU16(packed, pos); pos += 2;
|
|
1289
1418
|
var x25519EphDer = packed.subarray(pos, pos + x25519EphLen); pos += x25519EphLen;
|
|
1290
1419
|
var x25519PrivPem = typeof privateKeys === "string" ? null : privateKeys.x25519PrivateKey;
|
|
1291
1420
|
if (!x25519PrivPem) throw new Error("ML-KEM-768 + X25519 hybrid envelope requires x25519PrivateKey");
|
|
@@ -1768,7 +1897,7 @@ function _pemToDer(pemOrDer) {
|
|
|
1768
1897
|
// for mTLS bootstrap / webhook verification / peer-cert pinning.
|
|
1769
1898
|
// 64 KiB caps the largest plausible PEM (a P-384 cert + chain) at
|
|
1770
1899
|
// ~3× margin while refusing pathological inputs outright.
|
|
1771
|
-
if (pemOrDer
|
|
1900
|
+
if (safeBuffer.byteLengthOf(pemOrDer) > C.BYTES.kib(64)) {
|
|
1772
1901
|
throw new TypeError(
|
|
1773
1902
|
"crypto.hashCertFingerprint: PEM input exceeds 64 KiB (" +
|
|
1774
1903
|
pemOrDer.length + " bytes); refuse oversized input to avoid " +
|
|
@@ -2022,6 +2151,8 @@ module.exports = {
|
|
|
2022
2151
|
// Signatures
|
|
2023
2152
|
sign: sign,
|
|
2024
2153
|
verify: verify,
|
|
2154
|
+
importPublicJwk: importPublicJwk,
|
|
2155
|
+
makeBase64UrlDecoder: makeBase64UrlDecoder,
|
|
2025
2156
|
// Envelope encrypt/decrypt
|
|
2026
2157
|
encrypt: encrypt,
|
|
2027
2158
|
decrypt: decrypt,
|