@h-ai/crypto 0.1.0-alpha.74 → 0.1.0-alpha.76
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -0
- package/README.ja.md +2 -0
- package/README.md +2 -0
- package/dist/index.d.ts +27 -7
- package/dist/index.js +51 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.en.md
CHANGED
|
@@ -254,6 +254,8 @@ Empty POSTs still send an authenticated envelope for empty plaintext. GET/HEAD c
|
|
|
254
254
|
|
|
255
255
|
Set `transport.maxPlaintextBytes` for both request and response JSON plaintext, measured in UTF-8 bytes: default 1 MiB, integer range 1 KiB–64 MiB. Clients learn the server limit during key exchange. `resolveTransportBodyLimits()` derives encrypted/proxy bytes as twice the plaintext limit plus 32 KiB. Handshake, public-key, header and replay constraints remain independent. Oversized streams are cancelled and readers released: requests return 413; oversized responses return an encrypted 500 capacity error, recognized as `TransportBodyTooLargeError` / `hai:crypto:070`. [容量配置、文件换算与升级](TRANSPORT-CAPACITY.md)。
|
|
256
256
|
|
|
257
|
+
Ordinary routes retain `transport.maxPlaintextBytes` (auto/omitted: 1 MiB). Declare Feedback report intake, evidence, attachments and ZIP download capacity separately using `routePlaintextBytes` and `feedback.budget.maxTransportBytes`; `*` matches one complete path segment and explicit host route values take precedence. Handshakes, adapter-node and proxies use the maximum route capacity. HTTP adapters admit at most 2 explicitly declared material requests above 1 MiB and a separate 16 ordinary business requests, releasing admission after the entire response or failure. Busy admission returns 503 / `hai:crypto:072`; business writes are not automatically replayed.
|
|
258
|
+
|
|
257
259
|
serv/kit return an encrypted HTTP 400 time error for an out-of-window message only after request binding, signature and MAC verification. The client throws `TransportTimeError` (`hai:crypto:071`) with advice to synchronize device/server clocks and refresh. `api-client` maps it to `VALIDATION_FAILED` and preserves `cause.transportCode`. Requests are not replayed automatically and replay windows remain unchanged; tampered or unauthenticated messages retain the generic authentication failure.
|
|
258
260
|
|
|
259
261
|
Custom HTTP adapters check `error instanceof TransportTimeError && error.context`, then encrypt the rejection with `createTransportErrorResponse(error, { manager, context: error.context })`. Never classify an unverified message by its timestamp.
|
package/README.ja.md
CHANGED
|
@@ -254,6 +254,8 @@ const server = crypto.transport.createServer({ serverKeyRing, keyStore })
|
|
|
254
254
|
|
|
255
255
|
`transport.maxPlaintextBytes` でリクエストとレスポンスの JSON 平文容量を共通設定します。単位は UTF-8 バイト、既定値は 1 MiB、有効範囲は 1 KiB~64 MiB の整数です。クライアントは鍵交換で上限を取得し、`resolveTransportBodyLimits()` が暗号文とプロキシ容量(平文の 2 倍 + 32 KiB)を算出します。鍵交換、公開鍵、認証ヘッダー、防リプレイ制約は独立です。超過時は元ストリームを停止して reader を解放します。要求は 413、応答は暗号化された 500 容量エラーとなり、`TransportBodyTooLargeError` / `hai:crypto:070` で識別できます。 [容量配置、文件换算与升级](TRANSPORT-CAPACITY.md)。
|
|
256
256
|
|
|
257
|
+
通常業務は `transport.maxPlaintextBytes`(auto/省略は 1 MiB)を維持します。Feedback の受理・証拠・添付・ZIP ダウンロードは `routePlaintextBytes` と `feedback.budget.maxTransportBytes` で別途宣言します。`*` は完全な1パス区間のみ一致し、ホストの明示値が優先です。ハンドシェイク、adapter-node、プロキシは経路の最大値を使用します。HTTP アダプターは個別宣言された 1 MiB 超の資料経路を最大2件、通常業務を別枠で16件まで許可し、応答完了・失敗時に解放します。混雑は503 / `hai:crypto:072` を返し、業務書込は自動再送しません。
|
|
258
|
+
|
|
257
259
|
serv/kit は要求の結合、署名、MAC を検証した後、時間窓を超えた報文に暗号化した HTTP 400 時刻エラーを返します。クライアントは `TransportTimeError`(`hai:crypto:071`)で端末とサーバーの時刻同期・再読み込みを案内します。`api-client` は `VALIDATION_FAILED` に変換し `cause.transportCode` に原因を保持します。自動再送やリプレイ時間窓の緩和は行わず、改ざん・未認証の要求は従来の認証エラーです。
|
|
258
260
|
|
|
259
261
|
独自 HTTP アダプターでは `error instanceof TransportTimeError && error.context` を確認し、`createTransportErrorResponse(error, { manager, context: error.context })` で拒否応答を暗号化します。未認証の報文のタイムスタンプだけで時刻異常を診断しないでください。
|
package/README.md
CHANGED
|
@@ -254,6 +254,8 @@ const server = crypto.transport.createServer({ serverKeyRing, keyStore })
|
|
|
254
254
|
|
|
255
255
|
业务容量通过 `transport.maxPlaintextBytes` 统一配置:默认 1 MiB,整数范围 1 KiB~64 MiB,请求和响应共用 UTF-8 明文字节预算。客户端从握手自动获取上限,密文与部署代理预算由 `resolveTransportBodyLimits()` 推导(两倍明文 + 32 KiB)。握手、公钥、认证头和防重放约束独立;超限取消原流并释放 reader,请求 413、响应为加密的 500 容量错误,客户端识别 `TransportBodyTooLargeError` / `hai:crypto:070`。 [容量配置、文件换算与升级](TRANSPORT-CAPACITY.md)。
|
|
256
256
|
|
|
257
|
+
普通业务仍使用 `transport.maxPlaintextBytes`(auto/省略为 1 MiB);Feedback 的报告受理、证据、附件及 ZIP 下载路由通过 `routePlaintextBytes` 单独声明 `feedback.budget.maxTransportBytes`。路径中的 `*` 仅匹配一个完整路径段;宿主显式路由值优先。握手、adapter-node 与代理使用各路由最大容量,普通业务不会随材料预算扩大。HTTP 适配器为单独声明且大于 1 MiB 的材料路由保留最多 2 个槽,普通业务另有 16 个槽,完整响应/失败后释放;忙碌返回 503 / `hai:crypto:072`,不自动重放业务写入。
|
|
258
|
+
|
|
257
259
|
serv/kit 对通过请求绑定、签名和 MAC 校验但超出时间窗口的报文返回加密的 HTTP 400 时间错误;客户端抛 `TransportTimeError`(`hai:crypto:071`),提示同步设备和服务器时间后刷新重试。`api-client` 映射为 `VALIDATION_FAILED`,在 `cause.transportCode` 保留该原因。不会自动重放请求或放宽防重放窗口;篡改或未认证报文仍返回通用认证失败。
|
|
258
260
|
|
|
259
261
|
自定义 HTTP 适配器检查失败原因 `error instanceof TransportTimeError && error.context` 后,使用 `createTransportErrorResponse(error, { manager, context: error.context })` 加密拒绝响应;不能根据未认证报文的时间戳给出可信时间诊断。
|
package/dist/index.d.ts
CHANGED
|
@@ -123,6 +123,29 @@ interface ReadTransportBodyOptions {
|
|
|
123
123
|
* ```
|
|
124
124
|
*/
|
|
125
125
|
declare function readTransportBody(stream: ReadableStream<Uint8Array> | null, options: ReadTransportBodyOptions): Promise<string>;
|
|
126
|
+
/**
|
|
127
|
+
* 为真实 HTTP 适配器分离业务与大附件容量;* 只匹配一个完整路径段。
|
|
128
|
+
* 单独声明且超过 1 MiB 的材料路由最多两个,普通业务最多十六个,租约须在响应完成或失败时释放。
|
|
129
|
+
* @param maxPlaintextBytes - 普通业务容量;省略使用 1 MiB。
|
|
130
|
+
* @param routes - 受信任的绝对路径到 UTF-8 容量映射,最多 100 条。
|
|
131
|
+
* @returns 协商最大容量及每请求的限额和可释放并发准入。
|
|
132
|
+
* @throws RangeError 配置路径、数量或容量无效。
|
|
133
|
+
* @example
|
|
134
|
+
* ```ts
|
|
135
|
+
* import { createTransportBodyPolicy } from '@h-ai/crypto'
|
|
136
|
+
* const policy = createTransportBodyPolicy(undefined, { '/api/files/*': 8 * 1024 * 1024 })
|
|
137
|
+
* const lease = policy.acquire('/api/files/attachment')
|
|
138
|
+
* try { if (lease) lease.limits.plaintextBytes }
|
|
139
|
+
* finally { lease?.release() }
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
declare function createTransportBodyPolicy(maxPlaintextBytes?: number, routes?: Readonly<Record<string, number>>): {
|
|
143
|
+
maximum: TransportBodyLimits;
|
|
144
|
+
acquire(pathname: string): {
|
|
145
|
+
limits: TransportBodyLimits;
|
|
146
|
+
release(): void;
|
|
147
|
+
} | null;
|
|
148
|
+
};
|
|
126
149
|
|
|
127
150
|
/**
|
|
128
151
|
* 认证传输v2的头名、窗口与默认协商子路径;各HTTP适配器共用,不手写漂移常量。
|
|
@@ -859,6 +882,7 @@ declare const HaiCryptoError: {
|
|
|
859
882
|
readonly INVALID_IV: _h_ai_core.HaiErrorDef;
|
|
860
883
|
readonly TRANSPORT_PAYLOAD_TOO_LARGE: _h_ai_core.HaiErrorDef;
|
|
861
884
|
readonly TRANSPORT_TIME_INVALID: _h_ai_core.HaiErrorDef;
|
|
885
|
+
readonly TRANSPORT_BUSY: _h_ai_core.HaiErrorDef;
|
|
862
886
|
};
|
|
863
887
|
/**
|
|
864
888
|
* SM2 密文排列:1为C1C3C2默认值,0为显式C1C2C3;解密必须匹配加密排列。
|
|
@@ -1973,16 +1997,12 @@ declare function createTransportErrorResponse(error: TransportBodyTooLargeError
|
|
|
1973
1997
|
*/
|
|
1974
1998
|
declare function parseTransportServerKeyRing(serialized: unknown): HaiResult<TransportServerKeyRing>;
|
|
1975
1999
|
|
|
1976
|
-
/**
|
|
1977
|
-
* @h-ai/crypto — serv/kit 共用的实际 HTTP 请求认证入口。
|
|
1978
|
-
* @module crypto-transport-request
|
|
1979
|
-
*/
|
|
1980
|
-
|
|
1981
2000
|
/**
|
|
1982
2001
|
* 从实际HTTP请求提取可信方法/路径/查询/客户端ID并有界认证;成功后才执行业务。
|
|
1983
2002
|
* 拒绝缺少认证及头/正文重复承载,空请求也认证;不会由payload自证HTTP上下文。
|
|
1984
2003
|
* @param manager - 使用共享原子nonce registry的已创建管理器。
|
|
1985
2004
|
* @param request - 未消费正文的真实Request。
|
|
2005
|
+
* @param limits - HTTP 路由容量;默认管理器协商容量。
|
|
1986
2006
|
* @returns 明文和响应关联上下文;认证失败无明文。
|
|
1987
2007
|
* @throws RangeError超限;流读取/取消沿用原异常,HTTP适配器负责转响应。
|
|
1988
2008
|
*
|
|
@@ -1998,7 +2018,7 @@ declare function parseTransportServerKeyRing(serialized: unknown): HaiResult<Tra
|
|
|
1998
2018
|
* }
|
|
1999
2019
|
* ```
|
|
2000
2020
|
*/
|
|
2001
|
-
declare function authenticateTransportRequest(manager: TransportEncryptionManager, request: Request): Promise<HaiResult<{
|
|
2021
|
+
declare function authenticateTransportRequest(manager: TransportEncryptionManager, request: Request, limits?: TransportBodyLimits): Promise<HaiResult<{
|
|
2002
2022
|
plaintext: string;
|
|
2003
2023
|
context: TransportMessageContext;
|
|
2004
2024
|
}>>;
|
|
@@ -2191,4 +2211,4 @@ interface ReldbTransportKeyStore extends TransportKeyStore {
|
|
|
2191
2211
|
*/
|
|
2192
2212
|
declare function createReldbTransportKeyStore(options: CreateReldbTransportKeyStoreOptions): ReldbTransportKeyStore;
|
|
2193
2213
|
|
|
2194
|
-
export { type AsymmetricEncryptOptions, type AsymmetricOperations, type CipherMode, type CreateRedisTransportKeyStoreOptions, type CreateReldbTransportKeyStoreOptions, type CryptoFunctions, type EncryptWithIVResult, type EncryptedPayload, type EncryptedRequestPayload, HaiCryptoError, type HashOperations, type HashOptions, type KeyExchangeRequest, type KeyExchangeResponse, type KeyPair, type PasswordConfig, type PasswordOperations, type ReadTransportBodyOptions, type ReldbTransportKeyStore, type SignOptions, type SymmetricCbcEncryptedPayload, type SymmetricCiphertextEncoding, type SymmetricDecryptInput, type SymmetricEncryptOptions, type SymmetricEncryptedPayload, type SymmetricMode, type SymmetricOperations, TRANSPORT_BODY_LIMITS, TRANSPORT_PLAINTEXT_RANGE, TRANSPORT_PROTOCOL, type TransportBodyLimits, TransportBodyTooLargeError, type TransportClient, type TransportCreateServerOptions, type TransportCryptoServiceLike, type TransportEncryptionManager, type TransportKeyPair, type TransportKeyStore, type TransportMessageContext, type TransportOperations, type TransportRequestContext, type TransportServerKeyRing, TransportTimeError, authenticateTransportRequest, createInMemoryKeyStore, createRedisTransportKeyStore, createReldbTransportKeyStore, createTransportErrorResponse, crypto, isValidSM2PublicKey, parseTransportServerKeyRing, readTransportBody, resolveTransportBodyLimits };
|
|
2214
|
+
export { type AsymmetricEncryptOptions, type AsymmetricOperations, type CipherMode, type CreateRedisTransportKeyStoreOptions, type CreateReldbTransportKeyStoreOptions, type CryptoFunctions, type EncryptWithIVResult, type EncryptedPayload, type EncryptedRequestPayload, HaiCryptoError, type HashOperations, type HashOptions, type KeyExchangeRequest, type KeyExchangeResponse, type KeyPair, type PasswordConfig, type PasswordOperations, type ReadTransportBodyOptions, type ReldbTransportKeyStore, type SignOptions, type SymmetricCbcEncryptedPayload, type SymmetricCiphertextEncoding, type SymmetricDecryptInput, type SymmetricEncryptOptions, type SymmetricEncryptedPayload, type SymmetricMode, type SymmetricOperations, TRANSPORT_BODY_LIMITS, TRANSPORT_PLAINTEXT_RANGE, TRANSPORT_PROTOCOL, type TransportBodyLimits, TransportBodyTooLargeError, type TransportClient, type TransportCreateServerOptions, type TransportCryptoServiceLike, type TransportEncryptionManager, type TransportKeyPair, type TransportKeyStore, type TransportMessageContext, type TransportOperations, type TransportRequestContext, type TransportServerKeyRing, TransportTimeError, authenticateTransportRequest, createInMemoryKeyStore, createRedisTransportKeyStore, createReldbTransportKeyStore, createTransportBodyPolicy, createTransportErrorResponse, crypto, isValidSM2PublicKey, parseTransportServerKeyRing, readTransportBody, resolveTransportBodyLimits };
|
package/dist/index.js
CHANGED
|
@@ -59,7 +59,8 @@ var en_US_default = {
|
|
|
59
59
|
crypto_transportBodyLimitInvalid: "Transport plaintext limit must be an integer between 1024 and 67108864 bytes",
|
|
60
60
|
crypto_transportBodyTooLarge: "Encrypted transport payload exceeds the configured byte limit",
|
|
61
61
|
crypto_transportTimeInvalid: "Your device and server clocks may be out of sync, or the request has expired. Enable automatic time synchronization and refresh to retry. If this continues, ask an administrator to check the server clock.",
|
|
62
|
-
crypto_transportBodyLimitConflict: "Explicit transport limit {limit} bytes is below the enabled module requirement of {required} bytes; adjust the module budget or explicit limit"
|
|
62
|
+
crypto_transportBodyLimitConflict: "Explicit transport limit {limit} bytes is below the enabled module requirement of {required} bytes; adjust the module budget or explicit limit",
|
|
63
|
+
crypto_transportBusy: "Material processing is busy. Please retry shortly."
|
|
63
64
|
};
|
|
64
65
|
|
|
65
66
|
// messages/ja-JP.json
|
|
@@ -118,7 +119,8 @@ var ja_JP_default = {
|
|
|
118
119
|
crypto_transportBodyLimitInvalid: "\u901A\u4FE1\u5E73\u6587\u306E\u4E0A\u9650\u306F 1024 \u304B\u3089 67108864 \u30D0\u30A4\u30C8\u306E\u6574\u6570\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
119
120
|
crypto_transportBodyTooLarge: "\u6697\u53F7\u5316\u901A\u4FE1\u306E\u30C7\u30FC\u30BF\u304C\u8A2D\u5B9A\u3055\u308C\u305F\u30D0\u30A4\u30C8\u4E0A\u9650\u3092\u8D85\u3048\u3066\u3044\u307E\u3059",
|
|
120
121
|
crypto_transportTimeInvalid: "\u7AEF\u672B\u3068\u30B5\u30FC\u30D0\u30FC\u306E\u6642\u523B\u304C\u540C\u671F\u3057\u3066\u3044\u306A\u3044\u304B\u3001\u8981\u6C42\u306E\u6709\u52B9\u671F\u9650\u304C\u5207\u308C\u3066\u3044\u307E\u3059\u3002\u81EA\u52D5\u6642\u523B\u540C\u671F\u3092\u6709\u52B9\u306B\u3057\u3066\u30DA\u30FC\u30B8\u3092\u518D\u8AAD\u307F\u8FBC\u307F\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u89E3\u6D88\u3057\u306A\u3044\u5834\u5408\u306F\u7BA1\u7406\u8005\u306B\u30B5\u30FC\u30D0\u30FC\u306E\u6642\u523B\u78BA\u8A8D\u3092\u4F9D\u983C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
|
|
121
|
-
crypto_transportBodyLimitConflict: "\u660E\u793A\u3055\u308C\u305F\u8EE2\u9001\u4E0A\u9650 {limit} \u30D0\u30A4\u30C8\u306F\u6709\u52B9\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u5FC5\u8981\u91CF {required} \u30D0\u30A4\u30C8\u672A\u6E80\u3067\u3059\u3002\u4E88\u7B97\u307E\u305F\u306F\u4E0A\u9650\u3092\u5909\u66F4\u3057\u3066\u304F\u3060\u3055\u3044"
|
|
122
|
+
crypto_transportBodyLimitConflict: "\u660E\u793A\u3055\u308C\u305F\u8EE2\u9001\u4E0A\u9650 {limit} \u30D0\u30A4\u30C8\u306F\u6709\u52B9\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u5FC5\u8981\u91CF {required} \u30D0\u30A4\u30C8\u672A\u6E80\u3067\u3059\u3002\u4E88\u7B97\u307E\u305F\u306F\u4E0A\u9650\u3092\u5909\u66F4\u3057\u3066\u304F\u3060\u3055\u3044",
|
|
123
|
+
crypto_transportBusy: "\u8CC7\u6599\u306E\u51E6\u7406\u304C\u6DF7\u307F\u5408\u3063\u3066\u3044\u307E\u3059\u3002\u3057\u3070\u3089\u304F\u3057\u3066\u304B\u3089\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
// messages/zh-CN.json
|
|
@@ -177,7 +179,8 @@ var zh_CN_default = {
|
|
|
177
179
|
crypto_transportBodyLimitInvalid: "\u4F20\u8F93\u660E\u6587\u5BB9\u91CF\u5FC5\u987B\u662F 1024 \u5230 67108864 \u5B57\u8282\u4E4B\u95F4\u7684\u6574\u6570",
|
|
178
180
|
crypto_transportBodyTooLarge: "\u52A0\u5BC6\u4F20\u8F93\u62A5\u6587\u8D85\u8FC7\u914D\u7F6E\u7684\u5B57\u8282\u4E0A\u9650",
|
|
179
181
|
crypto_transportTimeInvalid: "\u8BBE\u5907\u4E0E\u670D\u52A1\u5668\u65F6\u95F4\u53EF\u80FD\u4E0D\u540C\u6B65\uFF0C\u6216\u8BF7\u6C42\u5DF2\u8FC7\u671F\u3002\u8BF7\u5F00\u542F\u81EA\u52A8\u6821\u65F6\u5E76\u5237\u65B0\u91CD\u8BD5\uFF1B\u82E5\u4ECD\u5931\u8D25\uFF0C\u8BF7\u8054\u7CFB\u7BA1\u7406\u5458\u68C0\u67E5\u670D\u52A1\u5668\u65F6\u95F4\u3002",
|
|
180
|
-
crypto_transportBodyLimitConflict: "\u663E\u5F0F\u4F20\u8F93\u4E0A\u9650 {limit} \u5B57\u8282\u5C0F\u4E8E\u5DF2\u542F\u7528\u6A21\u5757\u6240\u9700\u7684 {required} \u5B57\u8282\uFF1B\u8BF7\u8C03\u6574\u6A21\u5757\u9884\u7B97\u6216\u663E\u5F0F\u4E0A\u9650"
|
|
182
|
+
crypto_transportBodyLimitConflict: "\u663E\u5F0F\u4F20\u8F93\u4E0A\u9650 {limit} \u5B57\u8282\u5C0F\u4E8E\u5DF2\u542F\u7528\u6A21\u5757\u6240\u9700\u7684 {required} \u5B57\u8282\uFF1B\u8BF7\u8C03\u6574\u6A21\u5757\u9884\u7B97\u6216\u663E\u5F0F\u4E0A\u9650",
|
|
183
|
+
crypto_transportBusy: "\u6750\u6599\u5904\u7406\u7E41\u5FD9\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"
|
|
181
184
|
};
|
|
182
185
|
|
|
183
186
|
// src/crypto-i18n.ts
|
|
@@ -200,7 +203,8 @@ var CryptoErrorInfo = {
|
|
|
200
203
|
HMAC_FAILED: "041:500",
|
|
201
204
|
INVALID_IV: "060:400",
|
|
202
205
|
TRANSPORT_PAYLOAD_TOO_LARGE: "070:413",
|
|
203
|
-
TRANSPORT_TIME_INVALID: "071:400"
|
|
206
|
+
TRANSPORT_TIME_INVALID: "071:400",
|
|
207
|
+
TRANSPORT_BUSY: "072:503"
|
|
204
208
|
};
|
|
205
209
|
var HaiCryptoError = core.error.buildHaiErrorsDef("crypto", CryptoErrorInfo);
|
|
206
210
|
|
|
@@ -931,6 +935,41 @@ async function readTransportBody(stream, options) {
|
|
|
931
935
|
reader.releaseLock();
|
|
932
936
|
}
|
|
933
937
|
}
|
|
938
|
+
function createTransportBodyPolicy(maxPlaintextBytes, routes = {}) {
|
|
939
|
+
const ordinary = resolveTransportBodyLimits(maxPlaintextBytes);
|
|
940
|
+
const entries = Object.entries(routes);
|
|
941
|
+
if (entries.length > 100 || entries.some(([path]) => !path.startsWith("/") || path.includes("?") || path.includes("#") || path.split("/").some((part) => part.includes("*") && part !== "*")))
|
|
942
|
+
throw new RangeError(cryptoM("crypto_transportBodyLimitInvalid"));
|
|
943
|
+
const configured = entries.map(([path, bytes]) => ({ parts: path.split("/"), limits: resolveTransportBodyLimits(bytes) }));
|
|
944
|
+
const maximum = resolveTransportBodyLimits(Math.max(ordinary.plaintextBytes, ...configured.map((route) => route.limits.plaintextBytes)));
|
|
945
|
+
let small = 0;
|
|
946
|
+
let large = 0;
|
|
947
|
+
return {
|
|
948
|
+
maximum,
|
|
949
|
+
acquire(pathname) {
|
|
950
|
+
const parts = pathname.split("/");
|
|
951
|
+
const matching = configured.filter((route) => route.parts.length === parts.length && route.parts.every((part, index) => part === "*" || part === parts[index]));
|
|
952
|
+
const limits = matching.length ? matching.reduce((left, right) => left.limits.plaintextBytes < right.limits.plaintextBytes ? left : right).limits : ordinary;
|
|
953
|
+
const heavy = matching.length > 0 && limits.plaintextBytes > TRANSPORT_BODY_LIMITS.plaintextBytes;
|
|
954
|
+
if (heavy ? large >= 2 : small >= 16)
|
|
955
|
+
return null;
|
|
956
|
+
if (heavy)
|
|
957
|
+
large++;
|
|
958
|
+
else
|
|
959
|
+
small++;
|
|
960
|
+
let released = false;
|
|
961
|
+
return { limits, release() {
|
|
962
|
+
if (released)
|
|
963
|
+
return;
|
|
964
|
+
released = true;
|
|
965
|
+
if (heavy)
|
|
966
|
+
large--;
|
|
967
|
+
else
|
|
968
|
+
small--;
|
|
969
|
+
} };
|
|
970
|
+
}
|
|
971
|
+
};
|
|
972
|
+
}
|
|
934
973
|
|
|
935
974
|
// src/transport/crypto-transport-types.ts
|
|
936
975
|
var TRANSPORT_PROTOCOL = {
|
|
@@ -1252,6 +1291,8 @@ function createTransportClient(options) {
|
|
|
1252
1291
|
if (response.headers.get(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER) !== TRANSPORT_PROTOCOL.ENCRYPTED_HEADER_VALUE) {
|
|
1253
1292
|
void response.body?.cancel().catch(() => {
|
|
1254
1293
|
});
|
|
1294
|
+
if (response.status === 503)
|
|
1295
|
+
throw Object.assign(new Error(cryptoM("crypto_transportBusy")), { code: HaiCryptoError.TRANSPORT_BUSY.code, httpStatus: 503 });
|
|
1255
1296
|
if (response.status === 413)
|
|
1256
1297
|
throw new TransportBodyTooLargeError(bodyLimits.encryptedPayloadBytes, void 0, { stage: "encrypted" });
|
|
1257
1298
|
throw new Error(cryptoM("crypto_transportResponseDecryptFailed"));
|
|
@@ -1585,7 +1626,7 @@ var crypto2 = {
|
|
|
1585
1626
|
logger.info("Crypto module closed");
|
|
1586
1627
|
}
|
|
1587
1628
|
};
|
|
1588
|
-
async function authenticateTransportRequest(manager, request) {
|
|
1629
|
+
async function authenticateTransportRequest(manager, request, limits = manager.bodyLimits) {
|
|
1589
1630
|
const reject = () => {
|
|
1590
1631
|
void request.body?.cancel().catch(() => {
|
|
1591
1632
|
});
|
|
@@ -1603,7 +1644,7 @@ async function authenticateTransportRequest(manager, request) {
|
|
|
1603
1644
|
if (envelope && new TextEncoder().encode(envelope).byteLength > TRANSPORT_BODY_LIMITS.envelopeHeaderBytes)
|
|
1604
1645
|
throw new TransportBodyTooLargeError(TRANSPORT_BODY_LIMITS.envelopeHeaderBytes, new TextEncoder().encode(envelope).byteLength, { stage: "header" });
|
|
1605
1646
|
const text = envelope ?? await readTransportBody(request.body, {
|
|
1606
|
-
maxBytes:
|
|
1647
|
+
maxBytes: limits.encryptedPayloadBytes,
|
|
1607
1648
|
stage: "encrypted",
|
|
1608
1649
|
signal: request.signal
|
|
1609
1650
|
});
|
|
@@ -1613,7 +1654,7 @@ async function authenticateTransportRequest(manager, request) {
|
|
|
1613
1654
|
} catch {
|
|
1614
1655
|
return transportAuthenticationFailure();
|
|
1615
1656
|
}
|
|
1616
|
-
if (!isValidEncryptedPayload(payload,
|
|
1657
|
+
if (!isValidEncryptedPayload(payload, limits) || payload.direction !== "request" || payload.status !== 0)
|
|
1617
1658
|
return transportAuthenticationFailure();
|
|
1618
1659
|
const url = new URL(request.url);
|
|
1619
1660
|
const decrypted = await manager.decryptRequest(payload, {
|
|
@@ -1626,8 +1667,8 @@ async function authenticateTransportRequest(manager, request) {
|
|
|
1626
1667
|
throw decrypted.error.cause;
|
|
1627
1668
|
return decrypted;
|
|
1628
1669
|
}
|
|
1629
|
-
if (new TextEncoder().encode(decrypted.data).byteLength >
|
|
1630
|
-
throw new TransportBodyTooLargeError(
|
|
1670
|
+
if (new TextEncoder().encode(decrypted.data).byteLength > limits.plaintextBytes)
|
|
1671
|
+
throw new TransportBodyTooLargeError(limits.plaintextBytes, new TextEncoder().encode(decrypted.data).byteLength);
|
|
1631
1672
|
if (bodyless && decrypted.data !== "")
|
|
1632
1673
|
return transportAuthenticationFailure();
|
|
1633
1674
|
return ok({ plaintext: decrypted.data, context: payload.context });
|
|
@@ -1932,6 +1973,6 @@ function createReldbTransportKeyStore(options) {
|
|
|
1932
1973
|
};
|
|
1933
1974
|
}
|
|
1934
1975
|
|
|
1935
|
-
export { HaiCryptoError, TRANSPORT_BODY_LIMITS, TRANSPORT_PLAINTEXT_RANGE, TRANSPORT_PROTOCOL, TransportBodyTooLargeError, TransportTimeError, authenticateTransportRequest, createInMemoryKeyStore, createRedisTransportKeyStore, createReldbTransportKeyStore, createTransportErrorResponse, crypto2 as crypto, isValidSM2PublicKey, parseTransportServerKeyRing, readTransportBody, resolveTransportBodyLimits };
|
|
1976
|
+
export { HaiCryptoError, TRANSPORT_BODY_LIMITS, TRANSPORT_PLAINTEXT_RANGE, TRANSPORT_PROTOCOL, TransportBodyTooLargeError, TransportTimeError, authenticateTransportRequest, createInMemoryKeyStore, createRedisTransportKeyStore, createReldbTransportKeyStore, createTransportBodyPolicy, createTransportErrorResponse, crypto2 as crypto, isValidSM2PublicKey, parseTransportServerKeyRing, readTransportBody, resolveTransportBodyLimits };
|
|
1936
1977
|
//# sourceMappingURL=index.js.map
|
|
1937
1978
|
//# sourceMappingURL=index.js.map
|