@h-ai/crypto 0.1.0-alpha.67 → 0.1.0-alpha.69

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/dist/index.d.ts CHANGED
@@ -4,22 +4,144 @@ import { CacheFunctions } from '@h-ai/cache';
4
4
  import { ReldbFunctions } from '@h-ai/reldb';
5
5
 
6
6
  /**
7
- * @h-ai/crypto — 传输加密类型与协议常量
7
+ * @h-ai/crypto — 传输协议的字节预算与有界正文读取。
8
8
  *
9
- * 提供 SM2 + SM4(或等效非对称 + 对称)混合传输加密所需的接口与协议常量,
10
- * 由 kit / serv / api-client 共享,确保两端协议完全一致。
9
+ * serv/kit 共享相同预算,不依赖可省略或伪造的 Content-Length。
10
+ * @module crypto-transport-body
11
+ */
12
+ /**
13
+ * 传输预算;业务预算由明文容量推导,安全字段保持独立。
14
+ * @example
15
+ * ```ts
16
+ * import { resolveTransportBodyLimits, type TransportBodyLimits } from '@h-ai/crypto'
17
+ * const limits: TransportBodyLimits = resolveTransportBodyLimits(8 * 1024 * 1024)
18
+ * const proxyBytes = limits.encryptedPayloadBytes
19
+ * ```
20
+ */
21
+ interface TransportBodyLimits {
22
+ readonly keyExchangeBytes: number;
23
+ readonly envelopeHeaderBytes: number;
24
+ readonly publicKeyBytes: number;
25
+ readonly plaintextBytes: number;
26
+ readonly encryptedPayloadBytes: number;
27
+ }
28
+ /**
29
+ * 业务明文的有效 UTF-8 字节范围:1 KiB~64 MiB;不支持无限制。
30
+ * @example
31
+ * ```ts
32
+ * import { TRANSPORT_PLAINTEXT_RANGE } from '@h-ai/crypto'
33
+ * const maximumBytes = TRANSPORT_PLAINTEXT_RANGE.max
34
+ * ```
35
+ */
36
+ declare const TRANSPORT_PLAINTEXT_RANGE: Readonly<{
37
+ min: 1024;
38
+ max: number;
39
+ }>;
40
+ /**
41
+ * 默认UTF-8字节预算;按实际流读取,不依赖Content-Length,非字符串字符数限制。
11
42
  *
12
- * @module crypto-transport-types
43
+ * @example
44
+ * ```ts
45
+ * import { readTransportBody, TRANSPORT_BODY_LIMITS } from '@h-ai/crypto'
46
+ * const request = new Request('https://api.example.com/api/v1/orders', { method: 'POST', body: JSON.stringify({ message: 'hello' }) })
47
+ * const text = await readTransportBody(request.body, { maxBytes: TRANSPORT_BODY_LIMITS.plaintextBytes, signal: request.signal })
48
+ * ```
49
+ */
50
+ declare const TRANSPORT_BODY_LIMITS: TransportBodyLimits;
51
+ /**
52
+ * 校验单一业务明文容量并推导双向密文预算;返回不可变快照。
53
+ * SM4-CBC 使用十六进制编码,预算为明文的两倍加 32 KiB(填充及认证封装)。
54
+ * @param maxPlaintextBytes - UTF-8 字节数,默认 1 MiB,有效范围 1 KiB~64 MiB 的整数。
55
+ * @returns 明文、密文及独立安全预算。
56
+ * @throws RangeError - 配置无效;不接受字符串、null、无限制或静默回退。
57
+ * @example
58
+ * ```ts
59
+ * import { resolveTransportBodyLimits } from '@h-ai/crypto'
60
+ * const limits = resolveTransportBodyLimits(8 * 1024 * 1024)
61
+ * const nginxLimit = limits.encryptedPayloadBytes
62
+ * ```
13
63
  */
64
+ declare function resolveTransportBodyLimits(maxPlaintextBytes?: number): TransportBodyLimits;
65
+ /**
66
+ * 可识别的容量错误;只包含方向、阶段和字节数,不包含报文内容。
67
+ * @example
68
+ * ```ts
69
+ * import { TransportBodyTooLargeError } from '@h-ai/crypto'
70
+ * const error = new TransportBodyTooLargeError(1024, 1025, { direction: 'request', stage: 'plaintext' })
71
+ * const diagnostic = { code: error.code, limitBytes: error.limitBytes, actualBytes: error.actualBytes }
72
+ * ```
73
+ */
74
+ declare class TransportBodyTooLargeError extends RangeError {
75
+ readonly code: string | number;
76
+ readonly direction: 'request' | 'response';
77
+ readonly stage: 'plaintext' | 'encrypted' | 'header';
78
+ readonly limitBytes: number;
79
+ readonly actualBytes?: number;
80
+ constructor(limitBytes: number, actualBytes?: number, options?: {
81
+ direction?: 'request' | 'response';
82
+ stage?: 'plaintext' | 'encrypted' | 'header';
83
+ });
84
+ }
85
+ /**
86
+ * 有界原流读取选项;maxBytes是非负安全整数,signal取消等待和底层流。
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * import { readTransportBody, type ReadTransportBodyOptions } from '@h-ai/crypto'
91
+ * const request = new Request('https://api.example.com/api/v1/orders', { method: 'POST', body: 'hello' })
92
+ * const options: ReadTransportBodyOptions = { maxBytes: 1024, signal: request.signal }
93
+ * const text = await readTransportBody(request.body, options)
94
+ * ```
95
+ */
96
+ interface ReadTransportBodyOptions {
97
+ /** 允许读取的字节总数,必须为非负安全整数。 */
98
+ readonly maxBytes: number;
99
+ /** 请求取消时中止等待中的读取并取消底层流。 */
100
+ readonly signal?: AbortSignal;
101
+ /** 超限诊断方向;默认 request。 */
102
+ readonly direction?: 'request' | 'response';
103
+ /** 超限诊断阶段;默认 plaintext。 */
104
+ readonly stage?: 'plaintext' | 'encrypted' | 'header';
105
+ }
106
+ /**
107
+ * 逐块读取原始字节流并严格UTF-8解码;超限/取消后取消流并释放reader,清理失败不覆盖原异常。
108
+ * 不要传入clone/tee分支,否则另一分支仍可能保留数据。
109
+ * @param stream - 原始流;null返回空串但仍检查取消。
110
+ * @param options - 字节预算与取消信号。
111
+ * @returns 解码文本。
112
+ * @throws RangeError预算无效或超限;非法UTF-8、流异常和signal.reason继续抛出。
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * import { readTransportBody } from '@h-ai/crypto'
117
+ * const request = new Request('https://api.example.com/api/v1/orders', { method: 'POST', body: 'hello' })
118
+ * const text = await readTransportBody(request.body, { maxBytes: 1024, signal: request.signal })
119
+ * ```
120
+ */
121
+ declare function readTransportBody(stream: ReadableStream<Uint8Array> | null, options: ReadTransportBodyOptions): Promise<string>;
14
122
 
15
123
  /**
16
- * 传输加密协议常量。
124
+ * 认证传输v2的头名、窗口与默认协商子路径;各HTTP适配器共用,不手写漂移常量。
17
125
  *
18
- * 所有使用端必须复用这组常量,避免「header 名拼写漂移导致两端协议错配」。
126
+ * @example
127
+ * ```ts
128
+ * import { TRANSPORT_PROTOCOL } from '@h-ai/crypto'
129
+ * const headers = new Headers()
130
+ * headers.set(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER, TRANSPORT_PROTOCOL.ENCRYPTED_HEADER_VALUE)
131
+ * const keyExchangePath = TRANSPORT_PROTOCOL.DEFAULT_KEY_EXCHANGE_PATH
132
+ * ```
19
133
  */
20
134
  declare const TRANSPORT_PROTOCOL: {
21
135
  /** 客户端 ID 请求头名。 */
22
136
  readonly CLIENT_ID_HEADER: "X-Client-Id";
137
+ /** GET/HEAD 等无正文请求的认证封装;禁止与正文封装同时出现。 */
138
+ readonly ENVELOPE_HEADER: "X-Hai-Transport";
139
+ /** 唯一支持的认证协议版本;旧未认证格式拒绝。 */
140
+ readonly VERSION: 2;
141
+ /** 请求允许的过去时间窗口(毫秒)。 */
142
+ readonly REQUEST_WINDOW_MS: 300000;
143
+ /** 节点时钟允许的最大未来偏差(毫秒)。 */
144
+ readonly CLOCK_SKEW_MS: 30000;
23
145
  /** 标识响应体已加密的响应头名。 */
24
146
  readonly ENCRYPTED_HEADER: "X-Encrypted";
25
147
  /** `X-Encrypted` 响应头的开启值。 */
@@ -28,45 +150,220 @@ declare const TRANSPORT_PROTOCOL: {
28
150
  readonly DEFAULT_KEY_EXCHANGE_PATH: "/_hai/key-exchange";
29
151
  };
30
152
  /**
31
- * 密钥协商请求体(客户端 → 服务端)。
153
+ * 密钥协商请求;只发送客户端公钥,私钥始终留在客户端,注册仍验证曲线点。
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * import { crypto, type KeyExchangeRequest } from '@h-ai/crypto'
158
+ * const initialized = await crypto.init()
159
+ * if (!initialized.success) throw new Error(initialized.error.message)
160
+ * try {
161
+ * const generated = crypto.asymmetric.generateKeyPair()
162
+ * if (!generated.success) throw new Error(generated.error.message)
163
+ * const pair = generated.data
164
+ * const body: KeyExchangeRequest = { clientPublicKey: pair.publicKey }
165
+ * const serialized = JSON.stringify(body)
166
+ * }
167
+ * finally { await crypto.close() }
168
+ * ```
32
169
  */
33
170
  interface KeyExchangeRequest {
34
171
  readonly clientPublicKey: string;
35
172
  }
36
173
  /**
37
- * 密钥协商响应体(服务端 → 客户端)。
174
+ * TLS协商响应,公开服务端版本、公钥和registry生成的clientId;不含服务端私钥。
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * import type { KeyExchangeRequest, KeyExchangeResponse, TransportEncryptionManager } from '@h-ai/crypto'
179
+ * async function exchange(manager: TransportEncryptionManager, body: KeyExchangeRequest): Promise<KeyExchangeResponse> {
180
+ * const clientId = await manager.registerClientKey(body.clientPublicKey)
181
+ * return { clientId, serverKeyId: manager.getServerKeyId(), serverPublicKey: manager.getServerPublicKey() }
182
+ * }
183
+ * ```
38
184
  */
39
185
  interface KeyExchangeResponse {
186
+ /** 服务端业务明文 UTF-8 字节上限;缺省表示旧服务端的 1 MiB 默认值。 */
187
+ readonly maxPlaintextBytes?: number;
188
+ /** 服务端当前加密密钥版本;业务请求必须带回该值。 */
189
+ readonly serverKeyId: string;
40
190
  readonly serverPublicKey: string;
41
191
  readonly clientId: string;
42
192
  }
43
- /** 非对称密钥对。 */
193
+ /**
194
+ * 传输使用的SM2公私钥对;服务端版本从私有Secret注入,客户端可本地生成独立会话密钥。
195
+ *
196
+ * @example
197
+ * ```ts
198
+ * import { crypto, type TransportKeyPair } from '@h-ai/crypto'
199
+ * const initialized = await crypto.init()
200
+ * if (!initialized.success) throw new Error(initialized.error.message)
201
+ * try {
202
+ * const generated = crypto.asymmetric.generateKeyPair()
203
+ * if (!generated.success) throw new Error(generated.error.message)
204
+ * const pair = generated.data
205
+ * const clientPair: TransportKeyPair = pair
206
+ * const publicKey = clientPair.publicKey
207
+ * }
208
+ * finally { await crypto.close() }
209
+ * ```
210
+ */
44
211
  interface TransportKeyPair {
45
212
  readonly publicKey: string;
46
213
  readonly privateKey: string;
47
214
  }
48
215
  /**
49
- * 端到端传输的加密载荷格式。
216
+ * 完整v2认证封装;encryptedKey含独立SM4/HMAC密钥,signature覆盖认证字段和MAC。
217
+ * HTTP适配器只用成功认证得到的上下文生成响应,不自行拼接示例密文。
50
218
  *
51
- * `encryptedKey` 用对端非对称公钥加密的对称会话密钥;`ciphertext` + `iv`
52
- * 为该会话密钥加密的明文。两端必须使用同一份字段命名。
219
+ * @example
220
+ * ```ts
221
+ * import { authenticateTransportRequest, type EncryptedPayload, type TransportEncryptionManager } from '@h-ai/crypto'
222
+ * async function sealResponse(manager: TransportEncryptionManager, request: Request): Promise<EncryptedPayload> {
223
+ * const verified = await authenticateTransportRequest(manager, request)
224
+ * if (!verified.success) throw new Error(verified.error.message)
225
+ * const encrypted = await manager.encryptResponse(verified.data.context, JSON.stringify({ accepted: true }), 200)
226
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
227
+ * return encrypted.data
228
+ * }
229
+ * ```
53
230
  */
54
231
  interface EncryptedPayload {
232
+ /** 认证的请求上下文;响应必须原样关联同一个请求。 */
233
+ readonly context: TransportMessageContext;
234
+ /** 认证方向,防止把合法响应反射到请求入口。 */
235
+ readonly direction: 'request' | 'response';
236
+ /** 请求固定为 0;响应认证实际 HTTP 状态码。 */
237
+ readonly status: number;
238
+ /** SM2 封装的 JSON [SM4 密钥 hex, 独立 HMAC 密钥 hex]。 */
55
239
  readonly encryptedKey: string;
240
+ /** SM4-CBC 密文 hex;认证输入包含原始编码值。 */
56
241
  readonly ciphertext: string;
242
+ /** 随机 16 字节 CBC IV 的 hex 编码。 */
57
243
  readonly iv: string;
244
+ /** 独立随机密钥计算的 HMAC-SM3;先验证后解密 CBC。 */
245
+ readonly tag: string;
246
+ /** 对完整封装和 tag 的发送方 SM2 签名,防止公钥持有者伪造发送方。 */
247
+ readonly signature: string;
248
+ }
249
+ /**
250
+ * 认证的单次HTTP上下文;128位nonce、版本、客户端、时间、方法和实际路径SM3摘要共同绑定。
251
+ * 服务端共享registry只允许消费一次nonce;响应必须关联成功认证后的同一上下文。
252
+ *
253
+ * @example
254
+ * ```ts
255
+ * import { authenticateTransportRequest, type TransportEncryptionManager, type TransportMessageContext } from '@h-ai/crypto'
256
+ * async function contextOf(manager: TransportEncryptionManager, request: Request): Promise<TransportMessageContext> {
257
+ * const verified = await authenticateTransportRequest(manager, request)
258
+ * if (!verified.success) throw new Error(verified.error.message)
259
+ * return verified.data.context
260
+ * }
261
+ * ```
262
+ */
263
+ interface TransportMessageContext {
264
+ /** 唯一受支持的协议版本。 */
265
+ readonly version: 2;
266
+ /** 协商选择的受管服务端密钥版本。 */
267
+ readonly serverKeyId: string;
268
+ /** registry 注册的客户端 ID;发送方必须证明持有对应私钥。 */
269
+ readonly clientId: string;
270
+ /** 128 位随机十六进制 nonce,同时用于响应关联。 */
271
+ readonly requestId: string;
272
+ /** 请求创建时间,Unix 毫秒;允许过去 5 分钟、未来 30 秒。 */
273
+ readonly issuedAt: number;
274
+ /** 大写 HTTP 方法,必须与实际 Request 完全一致。 */
275
+ readonly method: string;
276
+ /** 实际 pathname + 原始 search 的 SM3 摘要,64 位小写 hex,避免在认证头中重复长 URL。 */
277
+ readonly pathHash: string;
278
+ }
279
+ /**
280
+ * 从实际HTTP Request提取的可信绑定输入;不能直接复制密文的自报方法、路径或客户端。
281
+ *
282
+ * @example
283
+ * ```ts
284
+ * import type { TransportRequestContext } from '@h-ai/crypto'
285
+ * function expectedContext(request: Request): TransportRequestContext {
286
+ * const clientId = request.headers.get('X-Client-Id')
287
+ * if (!clientId) throw new Error('Missing client ID')
288
+ * const url = new URL(request.url)
289
+ * return { clientId, method: request.method, path: url.pathname + url.search }
290
+ * }
291
+ * ```
292
+ */
293
+ interface TransportRequestContext {
294
+ /** 实际 X-Client-Id 头,用于 registry 查询及发送方验签。 */
295
+ readonly clientId: string;
296
+ /** 实际 Request.method。 */
297
+ readonly method: string;
298
+ /** 实际 URL.pathname + URL.search,保留查询参数顺序及编码。 */
299
+ readonly path: string;
58
300
  }
59
301
  /**
60
- * 传输加密所需的非对称 + 对称能力子集。
302
+ * 客户端发出的完整请求封装,direction=request且status=0;结构类型不构成认证证明。
61
303
  *
62
- * 不直接依赖 `@h-ai/crypto` 的具体实现,便于测试时注入 mock;
63
- * 实际使用时 `crypto` 模块的实例本身即可结构兼容。
304
+ * @example
305
+ * ```ts
306
+ * import type { EncryptedRequestPayload, TransportEncryptionManager } from '@h-ai/crypto'
307
+ * async function decrypt(manager: TransportEncryptionManager, request: Request, payload: EncryptedRequestPayload): Promise<string> {
308
+ * const clientId = request.headers.get('X-Client-Id')
309
+ * if (!clientId) throw new Error('Missing client ID')
310
+ * const url = new URL(request.url)
311
+ * const result = await manager.decryptRequest(payload, { clientId, method: request.method, path: url.pathname + url.search })
312
+ * if (!result.success) throw new Error(result.error.message)
313
+ * return result.data
314
+ * }
315
+ * ```
316
+ */
317
+ interface EncryptedRequestPayload extends EncryptedPayload {
318
+ readonly direction: 'request';
319
+ readonly status: 0;
320
+ }
321
+ /**
322
+ * 服务端受管版本密钥环;所有节点同版本对应同密钥,新协商选activeKeyId,旧版本保留到撤销。
323
+ * 先分发新旧版本再切活动ID;删除旧版本即撤销,私钥不进入PUBLIC_/VITE_/日志。
324
+ *
325
+ * @example
326
+ * ```ts
327
+ * import { parseTransportServerKeyRing, type TransportServerKeyRing } from '@h-ai/crypto'
328
+ * const parsed = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
329
+ * if (!parsed.success) throw new Error(parsed.error.message)
330
+ * const ring: TransportServerKeyRing = parsed.data
331
+ * ```
332
+ */
333
+ interface TransportServerKeyRing {
334
+ /** 新协商使用的版本;1–64 个字母、数字、下划线或连字符。 */
335
+ readonly activeKeyId: string;
336
+ /** ID 与密钥对;仅供服务端保管,所有节点必须分发相同版本的相同密钥。 */
337
+ readonly keys: Readonly<Record<string, TransportKeyPair>>;
338
+ }
339
+ /**
340
+ * 传输协议实际需要的SM2/SM3/HMAC/SM4能力;可结构化注入真实crypto,不仿造另一套算法。
341
+ *
342
+ * @example
343
+ * ```ts
344
+ * import { crypto, type TransportCryptoServiceLike } from '@h-ai/crypto'
345
+ * const initialized = await crypto.init()
346
+ * if (!initialized.success) throw new Error(initialized.error.message)
347
+ * try {
348
+ * const service: TransportCryptoServiceLike = crypto
349
+ * const digest = service.hash.hash('/api/v1/orders')
350
+ * if (!digest.success) throw new Error(digest.error.message)
351
+ * }
352
+ * finally { await crypto.close() }
353
+ * ```
64
354
  */
65
355
  interface TransportCryptoServiceLike {
66
356
  asymmetric: {
67
357
  generateKeyPair: () => HaiResult<TransportKeyPair>;
68
358
  encrypt: (data: string, publicKey: string) => HaiResult<string>;
69
359
  decrypt: (ciphertext: string, privateKey: string) => HaiResult<string>;
360
+ sign: (data: string, privateKey: string) => HaiResult<string>;
361
+ verify: (data: string, signature: string, publicKey: string) => HaiResult<boolean>;
362
+ };
363
+ hash: {
364
+ /** SM3 摘要,用于实际请求路径绑定,不使用其它摘要算法替换。 */
365
+ hash: (data: string) => HaiResult<string>;
366
+ hmac: (data: string, key: string) => HaiResult<string>;
70
367
  };
71
368
  symmetric: {
72
369
  generateKey: () => string;
@@ -78,93 +375,471 @@ interface TransportCryptoServiceLike {
78
375
  };
79
376
  }
80
377
  /**
81
- * 客户端公钥存储抽象。
82
- *
83
- * 默认实现为进程内 Map({@link createInMemoryKeyStore}),多节点部署时建议
84
- * 接入 Redis / 数据库实现以保证跨节点一致性。
378
+ * 客户端公钥与nonce存储契约;生产显式共享Redis/数据库,真实共享与原子性由提供者保证。
379
+ * get的故障不能当未注册,claimRequest故障不能当成功;有效nonce不得在expiresAt前驱逐。
85
380
  *
86
- * 设计原则:方法均为异步签名,避免后续替换为分布式实现时大改接口;
87
- * 内存实现以 `Promise.resolve` 包裹即可。
381
+ * @example
382
+ * ```ts
383
+ * import { crypto, createRedisTransportKeyStore, parseTransportServerKeyRing } from '@h-ai/crypto'
384
+ * import { cache } from '@h-ai/cache'
385
+ * const initialized = await crypto.init()
386
+ * if (!initialized.success) throw new Error(initialized.error.message)
387
+ * try {
388
+ * const connected = await cache.init({ type: 'redis', host: 'cache', port: 6379, password: process.env.HAI_CACHE_PASSWORD })
389
+ * if (!connected.success) throw new Error(connected.error.message)
390
+ * try {
391
+ * const registry = createRedisTransportKeyStore({ cache, ttlSeconds: 3600 })
392
+ * const store: import('@h-ai/crypto').TransportKeyStore = registry
393
+ * const scope = store.stateScope
394
+ * // Redis部署须noeviction/可靠持久化,并同步各节点时钟。
395
+ * }
396
+ * finally { await cache.close() }
397
+ * }
398
+ * finally { await crypto.close() }
399
+ * ```
88
400
  */
89
401
  interface TransportKeyStore {
90
- /** 注册新客户端,返回服务端生成的 `clientId`。 */
402
+ /** 公钥与nonce状态的真实共享能力;生产只接受shared。 */
403
+ readonly stateScope: 'local' | 'shared';
404
+ /**
405
+ * 注册有效 SM2 公钥,返回服务端生成的 clientId;格式/曲线点无效或存储故障必须 reject。
406
+ * 容量策略见具体工厂契约:数据库满容量拒绝,开发/测试内存实现允许 FIFO 淘汰公钥。
407
+ * @param publicKey - 实际调用输入,按该方法约束验证。
408
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
409
+ *
410
+ * @example
411
+ * ```ts
412
+ * import { crypto } from '@h-ai/crypto'
413
+ * const initialized = await crypto.init()
414
+ * if (!initialized.success) throw new Error(initialized.error.message)
415
+ * try {
416
+ * const generated = crypto.asymmetric.generateKeyPair()
417
+ * if (!generated.success) throw new Error(generated.error.message)
418
+ * const pair = generated.data
419
+ * const { createInMemoryKeyStore } = await import('@h-ai/crypto')
420
+ * const registry = createInMemoryKeyStore(100)
421
+ * try { const clientId = await registry.register(pair.publicKey) }
422
+ * finally { await registry.close?.() }
423
+ * // 本例仅开发/测试;生产替换为共享Redis/数据库registry。
424
+ * }
425
+ * finally { await crypto.close() }
426
+ * ```
427
+ */
91
428
  register: (publicKey: string) => Promise<string>;
92
- /** 查询已注册客户端公钥。 */
429
+ /**
430
+ * 读取已注册有效公钥;缺失返回undefined,存储失败拒绝,不能伪装未注册。
431
+ * @param clientId - registry生成的客户端标识。
432
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
433
+ *
434
+ * @example
435
+ * ```ts
436
+ * import { crypto } from '@h-ai/crypto'
437
+ * const initialized = await crypto.init()
438
+ * if (!initialized.success) throw new Error(initialized.error.message)
439
+ * try {
440
+ * const generated = crypto.asymmetric.generateKeyPair()
441
+ * if (!generated.success) throw new Error(generated.error.message)
442
+ * const pair = generated.data
443
+ * const { createInMemoryKeyStore } = await import('@h-ai/crypto')
444
+ * const registry = createInMemoryKeyStore(100)
445
+ * try { const clientId = await registry.register(pair.publicKey); const publicKey = await registry.get(clientId) }
446
+ * finally { await registry.close?.() }
447
+ * }
448
+ * finally { await crypto.close() }
449
+ * ```
450
+ */
93
451
  get: (clientId: string) => Promise<string | undefined>;
94
- /** 主动删除(可选,便于客户端登出时清理)。 */
452
+ /**
453
+ * 原子消费客户端 requestId nonce;成功返回 true,重放返回 false。
454
+ * 必须跨节点共享且在 expiresAt(Unix 毫秒)前不驱逐;存储故障必须 reject,禁止当作成功。
455
+ * @param clientId - registry生成的客户端标识。
456
+ * @param requestId - 本次128位随机nonce。
457
+ * @param expiresAt - nonce至少保留到的Unix毫秒期限。
458
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
459
+ *
460
+ * @example
461
+ * ```ts
462
+ * import { crypto } from '@h-ai/crypto'
463
+ * const initialized = await crypto.init()
464
+ * if (!initialized.success) throw new Error(initialized.error.message)
465
+ * try {
466
+ * const generated = crypto.asymmetric.generateKeyPair()
467
+ * if (!generated.success) throw new Error(generated.error.message)
468
+ * const pair = generated.data
469
+ * const { createInMemoryKeyStore } = await import('@h-ai/crypto')
470
+ * const registry = createInMemoryKeyStore(100)
471
+ * try {
472
+ * const clientId = await registry.register(pair.publicKey)
473
+ * const requestId = globalThis.crypto.randomUUID().replaceAll('-', '')
474
+ * const expiresAt = Date.now() + 360000
475
+ * const first = await registry.claimRequest(clientId, requestId, expiresAt)
476
+ * const replay = await registry.claimRequest(clientId, requestId, expiresAt)
477
+ * // 单进程测试预期true/false;生产需要跨节点共享原子消费且有效期间不驱逐。
478
+ * }
479
+ * finally { await registry.close?.() }
480
+ * }
481
+ * finally { await crypto.close() }
482
+ * ```
483
+ */
484
+ claimRequest: (clientId: string, requestId: string, expiresAt: number) => Promise<boolean>;
485
+ /**
486
+ * 主动删除(可选,便于客户端登出时清理)。
487
+ * @param clientId - registry生成的客户端标识。
488
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
489
+ *
490
+ * @example
491
+ * ```ts
492
+ * import { crypto } from '@h-ai/crypto'
493
+ * const initialized = await crypto.init()
494
+ * if (!initialized.success) throw new Error(initialized.error.message)
495
+ * try {
496
+ * const generated = crypto.asymmetric.generateKeyPair()
497
+ * if (!generated.success) throw new Error(generated.error.message)
498
+ * const pair = generated.data
499
+ * const { createInMemoryKeyStore } = await import('@h-ai/crypto')
500
+ * const registry = createInMemoryKeyStore(100)
501
+ * try { const clientId = await registry.register(pair.publicKey); await registry.delete?.(clientId) }
502
+ * finally { await registry.close?.() }
503
+ * }
504
+ * finally { await crypto.close() }
505
+ * ```
506
+ */
95
507
  delete?: (clientId: string) => Promise<void>;
96
- /** 释放底层资源(关闭连接、清理定时器等)。 */
508
+ /**
509
+ * 可选释放registry自有资源;借用的cache/reldb不由registry关闭。
510
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
511
+ *
512
+ * @example
513
+ * ```ts
514
+ * import { createInMemoryKeyStore } from '@h-ai/crypto'
515
+ * const registry = createInMemoryKeyStore(100)
516
+ * await registry.close?.()
517
+ * // 共享registry借用的cache/reldb仍由应用反序关闭。
518
+ * ```
519
+ */
97
520
  close?: () => Promise<void>;
98
521
  }
99
522
  /**
100
- * 创建服务端传输加密管理器的配置。
523
+ * 服务端创建配置;受管密钥环和共享registry均必填,没有进程随机密钥回退。
101
524
  *
102
- * `keyStore` 未传时,默认使用 {@link createInMemoryKeyStore};此时可通过 `maxClients`
103
- * 控制进程内 FIFO 容量。若传入共享 `keyStore`,则 `maxClients` 不再生效。
525
+ * @example
526
+ * ```ts
527
+ * import { crypto, createRedisTransportKeyStore, parseTransportServerKeyRing } from '@h-ai/crypto'
528
+ * import { cache } from '@h-ai/cache'
529
+ * const initialized = await crypto.init()
530
+ * if (!initialized.success) throw new Error(initialized.error.message)
531
+ * try {
532
+ * const connected = await cache.init({ type: 'redis', host: 'cache', port: 6379, password: process.env.HAI_CACHE_PASSWORD })
533
+ * if (!connected.success) throw new Error(connected.error.message)
534
+ * try {
535
+ * const registry = createRedisTransportKeyStore({ cache, ttlSeconds: 3600 })
536
+ * const parsed = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
537
+ * if (!parsed.success) throw new Error(parsed.error.message)
538
+ * const options: import('@h-ai/crypto').TransportCreateServerOptions = { serverKeyRing: parsed.data, keyStore: registry }
539
+ * const created = crypto.transport.createServer(options)
540
+ * if (!created.success) throw new Error(created.error.message)
541
+ * await created.data.close()
542
+ * }
543
+ * finally { await cache.close() }
544
+ * }
545
+ * finally { await crypto.close() }
546
+ * ```
104
547
  */
105
548
  interface TransportCreateServerOptions {
106
- /** 客户端公钥存储;多节点部署时建议注入共享实现。 */
107
- readonly keyStore?: TransportKeyStore;
108
- /** 默认内存 keyStore 的最大容量(仅当 `keyStore` 未提供时生效)。 */
109
- readonly maxClients?: number;
549
+ /** 双向业务明文 UTF-8 字节上限;默认 1 MiB,整数范围 1 KiB~64 MiB。 */
550
+ readonly maxPlaintextBytes?: number;
551
+ /** 必填受管服务端密钥环;没有隐式随机生成或进程密钥回退。 */
552
+ readonly serverKeyRing: TransportServerKeyRing;
553
+ /** 客户端公钥存储;生产必须注入跨节点共享实现。 */
554
+ readonly keyStore: TransportKeyStore;
110
555
  }
111
556
  /**
112
- * 服务端传输加密管理器。
557
+ * 服务端认证传输管理器;注册公钥,按真实HTTP上下文验签/MAC/时效并消费nonce,随后才返回明文。
558
+ * 优先使用authenticateTransportRequest;响应只用已认证上下文。close释放registry自有资源,不关闭借用的cache/reldb。
113
559
  *
114
- * 由 {@link createTransportEncryption} 创建;负责服务端密钥对持有、客户端密钥
115
- * 注册与请求/响应的加解密。
116
- *
117
- * @remarks
118
- * 典型调用顺序:
119
- *
120
- * 1. `registerClientKey(clientPublicKey)`:在密钥协商端点中保存客户端公钥,并生成 `clientId`。
121
- * 2. `getServerPublicKey()`:把服务端公钥返回给客户端,供后续请求加密会话密钥。
122
- * 3. `decryptRequest(payload)`:普通业务请求进入业务逻辑前,先把密文请求体解成明文。
123
- * 4. `encryptResponse(clientId, data)`:业务处理完成后,按当前客户端公钥重新加密响应体。
124
- * 5. `close()`:服务关闭时释放底层 keyStore 资源。
560
+ * @example
561
+ * ```ts
562
+ * import { crypto, createRedisTransportKeyStore, parseTransportServerKeyRing } from '@h-ai/crypto'
563
+ * import { cache } from '@h-ai/cache'
564
+ * const initialized = await crypto.init()
565
+ * if (!initialized.success) throw new Error(initialized.error.message)
566
+ * try {
567
+ * const connected = await cache.init({ type: 'redis', host: 'cache', port: 6379, password: process.env.HAI_CACHE_PASSWORD })
568
+ * if (!connected.success) throw new Error(connected.error.message)
569
+ * try {
570
+ * const registry = createRedisTransportKeyStore({ cache, ttlSeconds: 3600 })
571
+ * const ring = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
572
+ * if (!ring.success) throw new Error(ring.error.message)
573
+ * const created = crypto.transport.createServer({ serverKeyRing: ring.data, keyStore: registry })
574
+ * if (!created.success) throw new Error(created.error.message)
575
+ * const manager = created.data
576
+ * try {
577
+ * const currentVersion = manager.getServerKeyId()
578
+ * const publicKey = manager.getServerPublicKey()
579
+ * }
580
+ * finally { await manager.close() }
581
+ * }
582
+ * finally { await cache.close() }
583
+ * }
584
+ * finally { await crypto.close() }
585
+ * ```
125
586
  */
126
587
  interface TransportEncryptionManager {
588
+ /** 本管理器不可变的双向预算;由 maxPlaintextBytes 推导,安全预算独立。 */
589
+ readonly bodyLimits: TransportBodyLimits;
590
+ /**
591
+ * 当前新协商使用的服务端密钥 ID。
592
+ * @returns 直接返回值,使用前先初始化模块。
593
+ *
594
+ * @example
595
+ * ```ts
596
+ * import type { TransportEncryptionManager } from '@h-ai/crypto'
597
+ * function activeVersion(manager: TransportEncryptionManager): string { return manager.getServerKeyId() }
598
+ * ```
599
+ */
600
+ getServerKeyId: () => string;
601
+ /**
602
+ * 返回当前活动版本的公开公钥,只用于可信TLS协商,不含私钥。
603
+ * @returns 直接返回值,使用前先初始化模块。
604
+ *
605
+ * @example
606
+ * ```ts
607
+ * import type { TransportEncryptionManager } from '@h-ai/crypto'
608
+ * function activePublicKey(manager: TransportEncryptionManager): string { return manager.getServerPublicKey() }
609
+ * ```
610
+ */
127
611
  getServerPublicKey: () => string;
612
+ /**
613
+ * 验证 SM2 公钥编码和曲线点后向显式 registry 注册。
614
+ * @throws 公钥无效或 registry 写入失败;HTTP 协商适配器负责转换成失败响应。
615
+ * @param clientPublicKey - 实际调用输入,按该方法约束验证。
616
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
617
+ *
618
+ * @example
619
+ * ```ts
620
+ * import type { TransportEncryptionManager } from '@h-ai/crypto'
621
+ * async function register(manager: TransportEncryptionManager, clientPublicKey: string): Promise<string> {
622
+ * // 方法校验编码/曲线点后写入共享registry;异常由HTTP协商适配器转成失败响应。
623
+ * return manager.registerClientKey(clientPublicKey)
624
+ * }
625
+ * ```
626
+ */
128
627
  registerClientKey: (clientPublicKey: string) => Promise<string>;
628
+ /**
629
+ * 查询客户端公钥;registry 读取故障会 reject,不作为未注册处理。
630
+ * @param clientId - registry生成的客户端标识。
631
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
632
+ *
633
+ * @example
634
+ * ```ts
635
+ * import type { TransportEncryptionManager } from '@h-ai/crypto'
636
+ * async function lookup(manager: TransportEncryptionManager, clientId: string): Promise<string | undefined> {
637
+ * return manager.getClientPublicKey(clientId)
638
+ * }
639
+ * ```
640
+ */
129
641
  getClientPublicKey: (clientId: string) => Promise<string | undefined>;
130
- encryptResponse: (clientId: string, data: string) => Promise<HaiResult<EncryptedPayload>>;
131
- decryptRequest: (payload: EncryptedPayload) => HaiResult<string>;
132
- /** 关闭:释放 keyStore 资源。 */
642
+ /**
643
+ * 按已认证请求上下文加密、MAC 并签名响应,绑定实际 HTTP 状态。
644
+ * registry 及加密故障均返回失败 HaiResult;上下文只能来自成功的请求认证。
645
+ * @param request - 实际调用输入,按该方法约束验证。
646
+ * @param data - 实际调用输入,按该方法约束验证。
647
+ * @param status - 实际调用输入,按该方法约束验证。
648
+ * @returns HaiResult,先检查success再读取data。
649
+ *
650
+ * @example
651
+ * ```ts
652
+ * import { authenticateTransportRequest, type EncryptedPayload, type TransportEncryptionManager } from '@h-ai/crypto'
653
+ * async function sealResponse(manager: TransportEncryptionManager, request: Request): Promise<EncryptedPayload> {
654
+ * const verified = await authenticateTransportRequest(manager, request)
655
+ * if (!verified.success) throw new Error(verified.error.message)
656
+ * const encrypted = await manager.encryptResponse(verified.data.context, JSON.stringify({ accepted: true }), 200)
657
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
658
+ * return encrypted.data
659
+ * }
660
+ * ```
661
+ */
662
+ encryptResponse: (request: TransportMessageContext, data: string, status: number) => Promise<HaiResult<EncryptedPayload>>;
663
+ /**
664
+ * 验证发送方、MAC、HTTP 绑定和时效,原子消费 nonce 后才返回明文;错误不含密文或 Secret。
665
+ * expected 须从实际 Request 提取,不从 payload 复制。HTTP 优先用 authenticateTransportRequest。
666
+ * @param payload - 实际调用输入,按该方法约束验证。
667
+ * @param expected - 实际调用输入,按该方法约束验证。
668
+ * @returns HaiResult,先检查success再读取data。
669
+ *
670
+ * @example
671
+ * ```ts
672
+ * import type { EncryptedRequestPayload, TransportEncryptionManager } from '@h-ai/crypto'
673
+ * async function decrypt(manager: TransportEncryptionManager, request: Request, payload: EncryptedRequestPayload): Promise<string> {
674
+ * const clientId = request.headers.get('X-Client-Id')
675
+ * if (!clientId) throw new Error('Missing client ID')
676
+ * const url = new URL(request.url)
677
+ * const result = await manager.decryptRequest(payload, { clientId, method: request.method, path: url.pathname + url.search })
678
+ * if (!result.success) throw new Error(result.error.message)
679
+ * return result.data
680
+ * }
681
+ * ```
682
+ */
683
+ decryptRequest: (payload: EncryptedRequestPayload, expected: TransportRequestContext) => Promise<HaiResult<string>>;
684
+ /**
685
+ * 释放registry自有资源;应用仍负责借用cache/reldb的关闭。
686
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
687
+ *
688
+ * @example
689
+ * ```ts
690
+ * import { crypto, createRedisTransportKeyStore, parseTransportServerKeyRing } from '@h-ai/crypto'
691
+ * import { cache } from '@h-ai/cache'
692
+ * const initialized = await crypto.init()
693
+ * if (!initialized.success) throw new Error(initialized.error.message)
694
+ * try {
695
+ * const connected = await cache.init({ type: 'redis', host: 'cache', port: 6379, password: process.env.HAI_CACHE_PASSWORD })
696
+ * if (!connected.success) throw new Error(connected.error.message)
697
+ * try {
698
+ * const registry = createRedisTransportKeyStore({ cache, ttlSeconds: 3600 })
699
+ * const ring = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
700
+ * if (!ring.success) throw new Error(ring.error.message)
701
+ * const created = crypto.transport.createServer({ serverKeyRing: ring.data, keyStore: registry })
702
+ * if (!created.success) throw new Error(created.error.message)
703
+ * const manager = created.data
704
+ * try {
705
+ * const currentVersion = manager.getServerKeyId()
706
+ * const publicKey = manager.getServerPublicKey()
707
+ * }
708
+ * finally { await manager.close() }
709
+ * }
710
+ * finally { await cache.close() }
711
+ * }
712
+ * finally { await crypto.close() }
713
+ * ```
714
+ */
133
715
  close: () => Promise<void>;
134
716
  }
135
717
  /**
136
- * 客户端传输加密会话。
718
+ * 客户端单会话;首次调用自动协商,后续请求生成随机nonce并认证响应关联/签名/MAC。
719
+ * init返回HaiResult;encryptedFetch按fetch契约reject;destroy清本地会话,不代表撤销服务端registry。
137
720
  *
138
- * 由 {@link createTransportClient} 创建;包装宿主 `fetch`,
139
- * 自动完成首次密钥协商并对后续请求自动加解密。
140
- *
141
- * @remarks
142
- * 典型调用顺序:
143
- *
144
- * 1. `init()`(可选):预先完成一次密钥协商。
145
- * 2. `encryptedFetch()`:业务请求统一走这里;若当前会话尚未 ready,会先自动执行 `init()`。
146
- * 3. `ready()`:查看当前会话是否已经拿到 `clientId` 与服务端公钥。
147
- * 4. `destroy()`:登出、切租户或切环境时清空会话;下一次请求会重新协商。
721
+ * @example
722
+ * ```ts
723
+ * import { crypto } from '@h-ai/crypto'
724
+ * const initialized = await crypto.init()
725
+ * if (!initialized.success) throw new Error(initialized.error.message)
726
+ * try {
727
+ * const client = crypto.transport.createClient({ keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange' })
728
+ * try {
729
+ * const ready = await client.init()
730
+ * if (!ready.success) throw new Error(ready.error.message)
731
+ * const response = await client.encryptedFetch('https://api.example.com/api/v1/orders')
732
+ * if (!response.ok) throw new Error('HTTP request failed')
733
+ * }
734
+ * finally { client.destroy() }
735
+ * }
736
+ * finally { await crypto.close() }
737
+ * ```
148
738
  */
149
739
  interface TransportClient {
150
740
  /**
151
741
  * 完成密钥协商;多次调用幂等(同一会话只协商一次)。
152
742
  *
153
743
  * 通常无需手动调用:`encryptedFetch` 在首次请求前会自动 `init()`。
744
+ * 协商在 30 秒内完成,握手 JSON 与单个公钥分别受 TRANSPORT_BODY_LIMITS 限制。
745
+ * @returns HaiResult,先检查success再读取data。
746
+ *
747
+ * @example
748
+ * ```ts
749
+ * import { crypto } from '@h-ai/crypto'
750
+ * const initialized = await crypto.init()
751
+ * if (!initialized.success) throw new Error(initialized.error.message)
752
+ * try {
753
+ * const client = crypto.transport.createClient({ keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange' })
754
+ * try {
755
+ * const ready = await client.init()
756
+ * if (!ready.success) throw new Error(ready.error.message)
757
+ * const response = await client.encryptedFetch('https://api.example.com/api/v1/orders')
758
+ * if (!response.ok) throw new Error('HTTP request failed')
759
+ * }
760
+ * finally { client.destroy() }
761
+ * }
762
+ * finally { await crypto.close() }
763
+ * ```
154
764
  */
155
765
  init: () => Promise<HaiResult<void>>;
156
766
  /**
157
767
  * 包装后的 fetch;签名与全局 `fetch` 一致,请求/响应自动加解密。
768
+ * 明文/密文按 TRANSPORT_BODY_LIMITS 有界读取原流;超限或取消释放 reader,保留调用方 signal。
769
+ * 仅接受关联同一请求上下文与 HTTP status 的认证响应;缺标记也拒绝,不回退明文或密文。
158
770
  *
159
771
  * @throws 与原生 fetch 一样,网络错误、密钥协商失败、加密失败或解密失败会 reject。
772
+ *
773
+ * @example
774
+ * ```ts
775
+ * import { crypto } from '@h-ai/crypto'
776
+ * const initialized = await crypto.init()
777
+ * if (!initialized.success) throw new Error(initialized.error.message)
778
+ * try {
779
+ * const client = crypto.transport.createClient({ keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange' })
780
+ * try {
781
+ * const ready = await client.init()
782
+ * if (!ready.success) throw new Error(ready.error.message)
783
+ * const response = await client.encryptedFetch('https://api.example.com/api/v1/orders')
784
+ * if (!response.ok) throw new Error('HTTP request failed')
785
+ * }
786
+ * finally { client.destroy() }
787
+ * }
788
+ * finally { await crypto.close() }
789
+ * ```
160
790
  */
161
791
  encryptedFetch: typeof fetch;
162
- /** 是否已完成密钥协商。 */
792
+ /**
793
+ * 是否已完成密钥协商。
794
+ * @returns 直接boolean,false表示不匹配/未就绪。
795
+ *
796
+ * @example
797
+ * ```ts
798
+ * import { crypto } from '@h-ai/crypto'
799
+ * const initialized = await crypto.init()
800
+ * if (!initialized.success) throw new Error(initialized.error.message)
801
+ * try {
802
+ * const client = crypto.transport.createClient({ keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange' })
803
+ * try { const ready = client.ready() }
804
+ * finally { client.destroy() }
805
+ * }
806
+ * finally { await crypto.close() }
807
+ * ```
808
+ */
163
809
  ready: () => boolean;
164
- /** 销毁会话(清空客户端密钥)。 */
810
+ /**
811
+ * 清空本地客户端密钥与协商状态;下次请求重新协商,不撤销服务端身份或业务效果。
812
+ * @returns 直接返回值,使用前先初始化模块。
813
+ *
814
+ * @example
815
+ * ```ts
816
+ * import { crypto } from '@h-ai/crypto'
817
+ * const initialized = await crypto.init()
818
+ * if (!initialized.success) throw new Error(initialized.error.message)
819
+ * try {
820
+ * const client = crypto.transport.createClient({ keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange' })
821
+ * client.destroy()
822
+ * // 只清本地会话;不撤销服务端registry或业务会话。
823
+ * }
824
+ * finally { await crypto.close() }
825
+ * ```
826
+ */
165
827
  destroy: () => void;
166
828
  }
167
829
 
830
+ /**
831
+ * 加密领域标准错误集合;先判断 HaiResult.success,错误上下文不得附带明文或私钥。
832
+ *
833
+ * @example
834
+ * ```ts
835
+ * import { crypto, HaiCryptoError } from '@h-ai/crypto'
836
+ * const result = crypto.hash.hash('hello')
837
+ * if (!result.success && result.error.code === HaiCryptoError.NOT_INITIALIZED.code) {
838
+ * // 尚未初始化时按生命周期处理,不忽略错误继续加密。
839
+ * const message = result.error.message
840
+ * }
841
+ * ```
842
+ */
168
843
  declare const HaiCryptoError: {
169
844
  readonly INVALID_INPUT: _h_ai_core.HaiErrorDef;
170
845
  readonly INVALID_KEY: _h_ai_core.HaiErrorDef;
@@ -178,40 +853,185 @@ declare const HaiCryptoError: {
178
853
  readonly HASH_FAILED: _h_ai_core.HaiErrorDef;
179
854
  readonly HMAC_FAILED: _h_ai_core.HaiErrorDef;
180
855
  readonly INVALID_IV: _h_ai_core.HaiErrorDef;
856
+ readonly TRANSPORT_PAYLOAD_TOO_LARGE: _h_ai_core.HaiErrorDef;
857
+ readonly TRANSPORT_TIME_INVALID: _h_ai_core.HaiErrorDef;
181
858
  };
182
- /** 密文模式:0=C1C2C3(旧版),1=C1C3C2(国标) */
859
+ /**
860
+ * SM2 密文排列:1为C1C3C2默认值,0为显式C1C2C3;解密必须匹配加密排列。
861
+ *
862
+ * @example
863
+ * ```ts
864
+ * import { crypto, type CipherMode } from '@h-ai/crypto'
865
+ * const initialized = await crypto.init()
866
+ * if (!initialized.success) throw new Error(initialized.error.message)
867
+ * try {
868
+ * const generated = crypto.asymmetric.generateKeyPair()
869
+ * if (!generated.success) throw new Error(generated.error.message)
870
+ * const pair = generated.data
871
+ * const mode: CipherMode = 1
872
+ * const encrypted = crypto.asymmetric.encrypt('hello', pair.publicKey, { cipherMode: mode })
873
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
874
+ * const decrypted = crypto.asymmetric.decrypt(encrypted.data, pair.privateKey, { cipherMode: mode })
875
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
876
+ * }
877
+ * finally { await crypto.close() }
878
+ * ```
879
+ */
183
880
  type CipherMode = 0 | 1;
184
- /** 非对称密钥对 */
881
+ /**
882
+ * SM2 公私钥对;私钥必须保密,不写日志、公开配置或响应。
883
+ *
884
+ * @example
885
+ * ```ts
886
+ * import { crypto, type KeyPair } from '@h-ai/crypto'
887
+ * const initialized = await crypto.init()
888
+ * if (!initialized.success) throw new Error(initialized.error.message)
889
+ * try {
890
+ * const generated = crypto.asymmetric.generateKeyPair()
891
+ * if (!generated.success) throw new Error(generated.error.message)
892
+ * const pair = generated.data
893
+ * const keyPair: KeyPair = pair
894
+ * const publicKey = keyPair.publicKey
895
+ * }
896
+ * finally { await crypto.close() }
897
+ * ```
898
+ */
185
899
  interface KeyPair {
186
900
  /** 公钥(十六进制字符串,包含 04 前缀为非压缩格式) */
187
901
  publicKey: string;
188
902
  /** 私钥(十六进制字符串,64 字符) */
189
903
  privateKey: string;
190
904
  }
191
- /** 非对称加密选项 */
905
+ /**
906
+ * SM2 密文排列和输出编码;加解密 cipherMode 必须一致,解密可识别受支持的 base64 输出。
907
+ *
908
+ * @example
909
+ * ```ts
910
+ * import { crypto, type AsymmetricEncryptOptions } from '@h-ai/crypto'
911
+ * const initialized = await crypto.init()
912
+ * if (!initialized.success) throw new Error(initialized.error.message)
913
+ * try {
914
+ * const generated = crypto.asymmetric.generateKeyPair()
915
+ * if (!generated.success) throw new Error(generated.error.message)
916
+ * const pair = generated.data
917
+ * const options: AsymmetricEncryptOptions = { cipherMode: 1, outputFormat: 'base64' }
918
+ * const encrypted = crypto.asymmetric.encrypt('hello', pair.publicKey, options)
919
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
920
+ * const decrypted = crypto.asymmetric.decrypt(encrypted.data, pair.privateKey, options)
921
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
922
+ * }
923
+ * finally { await crypto.close() }
924
+ * ```
925
+ */
192
926
  interface AsymmetricEncryptOptions {
193
927
  /** 密文模式:0=C1C2C3(旧版),1=C1C3C2(国标,默认) */
194
928
  cipherMode?: CipherMode;
195
929
  /** 输出格式 */
196
930
  outputFormat?: 'hex' | 'base64';
197
931
  }
198
- /** 签名选项 */
932
+ /**
933
+ * SM2 签名的哈希与用户标识参数;验签必须使用相同设置,默认启用哈希。
934
+ *
935
+ * @example
936
+ * ```ts
937
+ * import { crypto, type SignOptions } from '@h-ai/crypto'
938
+ * const initialized = await crypto.init()
939
+ * if (!initialized.success) throw new Error(initialized.error.message)
940
+ * try {
941
+ * const generated = crypto.asymmetric.generateKeyPair()
942
+ * if (!generated.success) throw new Error(generated.error.message)
943
+ * const pair = generated.data
944
+ * const options: SignOptions = { hash: true, userId: 'orders-service' }
945
+ * const signature = crypto.asymmetric.sign('hello', pair.privateKey, options)
946
+ * if (!signature.success) throw new Error(signature.error.message)
947
+ * const verified = crypto.asymmetric.verify('hello', signature.data, pair.publicKey, options)
948
+ * if (!verified.success) throw new Error(verified.error.message)
949
+ * const accepted = verified.data
950
+ * }
951
+ * finally { await crypto.close() }
952
+ * ```
953
+ */
199
954
  interface SignOptions {
200
955
  /** 是否对数据进行哈希(默认 true) */
201
956
  hash?: boolean;
202
957
  /** 用户 ID(默认 "1234567812345678") */
203
958
  userId?: string;
204
959
  }
205
- /** 哈希选项 */
960
+ /**
961
+ * 字符串输入编码;hex 表示解码后的字节,Uint8Array 直接作为字节输入。
962
+ *
963
+ * @example
964
+ * ```ts
965
+ * import { crypto, type HashOptions } from '@h-ai/crypto'
966
+ * const initialized = await crypto.init()
967
+ * if (!initialized.success) throw new Error(initialized.error.message)
968
+ * try {
969
+ * const options: HashOptions = { inputEncoding: 'hex' }
970
+ * const digest = crypto.hash.hash('6869', options)
971
+ * if (!digest.success) throw new Error(digest.error.message)
972
+ * }
973
+ * finally { await crypto.close() }
974
+ * ```
975
+ */
206
976
  interface HashOptions {
207
977
  /** 输入编码 */
208
978
  inputEncoding?: 'utf8' | 'hex';
209
979
  }
210
- /** 对称加密模式 */
980
+ /**
981
+ * SM4 的 CBC/ECB 模式;新数据使用默认 CBC,ECB 会暴露相同明文块结构,两者都不提供 MAC。
982
+ *
983
+ * @example
984
+ * ```ts
985
+ * import { crypto, type SymmetricMode } from '@h-ai/crypto'
986
+ * const initialized = await crypto.init()
987
+ * if (!initialized.success) throw new Error(initialized.error.message)
988
+ * try {
989
+ * const mode: SymmetricMode = 'cbc'
990
+ * const key = crypto.symmetric.generateKey()
991
+ * const encrypted = crypto.symmetric.encrypt('hello', key, { mode })
992
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
993
+ * }
994
+ * finally { await crypto.close() }
995
+ * ```
996
+ */
211
997
  type SymmetricMode = 'ecb' | 'cbc';
212
- /** 对称密文编码 */
998
+ /**
999
+ * 结构化 SM4 ciphertext 的 hex/base64 编码标识,解密必须保留。
1000
+ *
1001
+ * @example
1002
+ * ```ts
1003
+ * import { crypto, type SymmetricCiphertextEncoding } from '@h-ai/crypto'
1004
+ * const initialized = await crypto.init()
1005
+ * if (!initialized.success) throw new Error(initialized.error.message)
1006
+ * try {
1007
+ * const outputFormat: SymmetricCiphertextEncoding = 'base64'
1008
+ * const key = crypto.symmetric.generateKey()
1009
+ * const encrypted = crypto.symmetric.encrypt('hello', key, { outputFormat })
1010
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1011
+ * const decrypted = crypto.symmetric.decrypt(encrypted.data, key)
1012
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1013
+ * }
1014
+ * finally { await crypto.close() }
1015
+ * ```
1016
+ */
213
1017
  type SymmetricCiphertextEncoding = 'hex' | 'base64';
214
- /** 对称加密选项。默认 CBC,并自动生成随机 IV。 */
1018
+ /**
1019
+ * SM4 模式、IV 与编码;CBC 未提供 IV 时随机生成,手动 IV 必须每次独立随机。
1020
+ *
1021
+ * @example
1022
+ * ```ts
1023
+ * import { crypto, type SymmetricEncryptOptions } from '@h-ai/crypto'
1024
+ * const initialized = await crypto.init()
1025
+ * if (!initialized.success) throw new Error(initialized.error.message)
1026
+ * try {
1027
+ * const options: SymmetricEncryptOptions = { mode: 'cbc', outputFormat: 'base64' }
1028
+ * const key = crypto.symmetric.generateKey()
1029
+ * const encrypted = crypto.symmetric.encrypt('hello', key, options)
1030
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1031
+ * }
1032
+ * finally { await crypto.close() }
1033
+ * ```
1034
+ */
215
1035
  interface SymmetricEncryptOptions {
216
1036
  /** 加密模式;默认 cbc */
217
1037
  mode?: SymmetricMode;
@@ -220,7 +1040,25 @@ interface SymmetricEncryptOptions {
220
1040
  /** 密文输出编码;默认 hex */
221
1041
  outputFormat?: SymmetricCiphertextEncoding;
222
1042
  }
223
- /** 对称加密结构化结果。 */
1043
+ /**
1044
+ * SM4 密文及 mode/encoding/可选 IV;保留全部字段才能正确解密,不含消息认证能力。
1045
+ *
1046
+ * @example
1047
+ * ```ts
1048
+ * import { crypto, type SymmetricEncryptedPayload } from '@h-ai/crypto'
1049
+ * const initialized = await crypto.init()
1050
+ * if (!initialized.success) throw new Error(initialized.error.message)
1051
+ * try {
1052
+ * const key = crypto.symmetric.generateKey()
1053
+ * const encrypted = crypto.symmetric.encrypt('hello', key)
1054
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1055
+ * const payload: SymmetricEncryptedPayload = encrypted.data
1056
+ * const decrypted = crypto.symmetric.decrypt(payload, key)
1057
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1058
+ * }
1059
+ * finally { await crypto.close() }
1060
+ * ```
1061
+ */
224
1062
  interface SymmetricEncryptedPayload {
225
1063
  /** 加密模式 */
226
1064
  readonly mode: SymmetricMode;
@@ -231,16 +1069,87 @@ interface SymmetricEncryptedPayload {
231
1069
  /** ciphertext 字段的编码 */
232
1070
  readonly encoding: SymmetricCiphertextEncoding;
233
1071
  }
234
- /** CBC 模式结构化结果。 */
1072
+ /**
1073
+ * CBC 结构化密文,mode固定cbc且IV必填;仍需上层消息认证。
1074
+ *
1075
+ * @example
1076
+ * ```ts
1077
+ * import { crypto, type SymmetricCbcEncryptedPayload } from '@h-ai/crypto'
1078
+ * const initialized = await crypto.init()
1079
+ * if (!initialized.success) throw new Error(initialized.error.message)
1080
+ * try {
1081
+ * const key = crypto.symmetric.generateKey()
1082
+ * const encrypted = crypto.symmetric.encryptWithIV('hello', key)
1083
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1084
+ * const payload: SymmetricCbcEncryptedPayload = encrypted.data
1085
+ * const decrypted = crypto.symmetric.decrypt(payload, key)
1086
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1087
+ * }
1088
+ * finally { await crypto.close() }
1089
+ * ```
1090
+ */
235
1091
  interface SymmetricCbcEncryptedPayload extends SymmetricEncryptedPayload {
236
1092
  readonly mode: 'cbc';
237
1093
  readonly iv: string;
238
1094
  }
239
- /** 对称解密输入。 */
1095
+ /**
1096
+ * SM4 解密输入别名;传入加密返回的完整结构,不能用裸密文猜测IV或编码。
1097
+ *
1098
+ * @example
1099
+ * ```ts
1100
+ * import { crypto, type SymmetricDecryptInput } from '@h-ai/crypto'
1101
+ * const initialized = await crypto.init()
1102
+ * if (!initialized.success) throw new Error(initialized.error.message)
1103
+ * try {
1104
+ * const key = crypto.symmetric.generateKey()
1105
+ * const encrypted = crypto.symmetric.encrypt('hello', key)
1106
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1107
+ * const payload: SymmetricDecryptInput = encrypted.data
1108
+ * const decrypted = crypto.symmetric.decrypt(payload, key)
1109
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1110
+ * }
1111
+ * finally { await crypto.close() }
1112
+ * ```
1113
+ */
240
1114
  type SymmetricDecryptInput = SymmetricEncryptedPayload;
241
- /** 带 IV 加密结果。 */
1115
+ /**
1116
+ * encryptWithIV 的CBC结构化结果别名;含 mode、ciphertext、iv 与 encoding。
1117
+ *
1118
+ * @example
1119
+ * ```ts
1120
+ * import { crypto, type EncryptWithIVResult } from '@h-ai/crypto'
1121
+ * const initialized = await crypto.init()
1122
+ * if (!initialized.success) throw new Error(initialized.error.message)
1123
+ * try {
1124
+ * const key = crypto.symmetric.generateKey()
1125
+ * const encrypted = crypto.symmetric.encryptWithIV('hello', key)
1126
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1127
+ * const payload: EncryptWithIVResult = encrypted.data
1128
+ * const decrypted = crypto.symmetric.decrypt(payload, key)
1129
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1130
+ * }
1131
+ * finally { await crypto.close() }
1132
+ * ```
1133
+ */
242
1134
  type EncryptWithIVResult = SymmetricCbcEncryptedPayload;
243
- /** 密码哈希配置 */
1135
+ /**
1136
+ * 迭代SM3密码参数;默认盐长16、迭代10000,合法范围以实现校验为准,已有哈希自行携带参数。
1137
+ *
1138
+ * @example
1139
+ * ```ts
1140
+ * import { crypto, type PasswordConfig } from '@h-ai/crypto'
1141
+ * const initialized = await crypto.init()
1142
+ * if (!initialized.success) throw new Error(initialized.error.message)
1143
+ * try {
1144
+ * const config: PasswordConfig = { saltLength: 16, iterations: 10000 }
1145
+ * const hashed = crypto.password.hash('test-password', config)
1146
+ * if (!hashed.success) throw new Error(hashed.error.message)
1147
+ * const verified = crypto.password.verify('test-password', hashed.data)
1148
+ * if (!verified.success) throw new Error(verified.error.message)
1149
+ * }
1150
+ * finally { await crypto.close() }
1151
+ * ```
1152
+ */
244
1153
  interface PasswordConfig {
245
1154
  /** 盐值长度(默认 16) */
246
1155
  saltLength?: number;
@@ -248,15 +1157,47 @@ interface PasswordConfig {
248
1157
  iterations?: number;
249
1158
  }
250
1159
  /**
251
- * 非对称加密操作接口
1160
+ * SM2 操作域;先初始化,所有 HaiResult 先检查 success,boolean 校验器按直接返回值使用。
1161
+ * 公钥曲线点有效不等于对端身份可信;可信公钥分发仍由TLS/受管信任链保证。
252
1162
  *
253
- * 通过 `crypto.asymmetric` 访问,需先调用 `crypto.init()`。
1163
+ * @example
1164
+ * ```ts
1165
+ * import { crypto, type AsymmetricOperations } from '@h-ai/crypto'
1166
+ * const initialized = await crypto.init()
1167
+ * if (!initialized.success) throw new Error(initialized.error.message)
1168
+ * try {
1169
+ * const generated = crypto.asymmetric.generateKeyPair()
1170
+ * if (!generated.success) throw new Error(generated.error.message)
1171
+ * const pair = generated.data
1172
+ * const operations: AsymmetricOperations = crypto.asymmetric
1173
+ * const signature = operations.sign('hello', pair.privateKey)
1174
+ * if (!signature.success) throw new Error(signature.error.message)
1175
+ * const verified = operations.verify('hello', signature.data, pair.publicKey)
1176
+ * if (!verified.success) throw new Error(verified.error.message)
1177
+ * const matches = verified.data
1178
+ * }
1179
+ * finally { await crypto.close() }
1180
+ * ```
254
1181
  */
255
1182
  interface AsymmetricOperations {
256
1183
  /**
257
1184
  * 生成密钥对
258
1185
  *
259
1186
  * @returns 成功时包含公私钥对;失败时返回 KEY_GENERATION_FAILED
1187
+ *
1188
+ * @example
1189
+ * ```ts
1190
+ * import { crypto } from '@h-ai/crypto'
1191
+ * const initialized = await crypto.init()
1192
+ * if (!initialized.success) throw new Error(initialized.error.message)
1193
+ * try {
1194
+ * const generated = crypto.asymmetric.generateKeyPair()
1195
+ * if (!generated.success) throw new Error(generated.error.message)
1196
+ * const pair = generated.data
1197
+ * const publicKey = pair.publicKey
1198
+ * }
1199
+ * finally { await crypto.close() }
1200
+ * ```
260
1201
  */
261
1202
  generateKeyPair: () => HaiResult<KeyPair>;
262
1203
  /**
@@ -266,6 +1207,21 @@ interface AsymmetricOperations {
266
1207
  * @param publicKey - 公钥(十六进制,支持带/不带 04 前缀)
267
1208
  * @param options - 加密选项(密文模式、输出格式)
268
1209
  * @returns 成功时返回密文字符串;失败时返回 INVALID_KEY 或 ENCRYPTION_FAILED
1210
+ *
1211
+ * @example
1212
+ * ```ts
1213
+ * import { crypto } from '@h-ai/crypto'
1214
+ * const initialized = await crypto.init()
1215
+ * if (!initialized.success) throw new Error(initialized.error.message)
1216
+ * try {
1217
+ * const generated = crypto.asymmetric.generateKeyPair()
1218
+ * if (!generated.success) throw new Error(generated.error.message)
1219
+ * const pair = generated.data
1220
+ * const encrypted = crypto.asymmetric.encrypt('hello', pair.publicKey, { cipherMode: 1, outputFormat: 'hex' })
1221
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1222
+ * }
1223
+ * finally { await crypto.close() }
1224
+ * ```
269
1225
  */
270
1226
  encrypt: (data: string, publicKey: string, options?: AsymmetricEncryptOptions) => HaiResult<string>;
271
1227
  /**
@@ -277,6 +1233,23 @@ interface AsymmetricOperations {
277
1233
  * @param privateKey - 私钥(64 字符十六进制)
278
1234
  * @param options - 解密选项(密文模式需与加密时一致)
279
1235
  * @returns 成功时返回明文;失败时返回 INVALID_KEY 或 DECRYPTION_FAILED
1236
+ *
1237
+ * @example
1238
+ * ```ts
1239
+ * import { crypto } from '@h-ai/crypto'
1240
+ * const initialized = await crypto.init()
1241
+ * if (!initialized.success) throw new Error(initialized.error.message)
1242
+ * try {
1243
+ * const generated = crypto.asymmetric.generateKeyPair()
1244
+ * if (!generated.success) throw new Error(generated.error.message)
1245
+ * const pair = generated.data
1246
+ * const encrypted = crypto.asymmetric.encrypt('hello', pair.publicKey)
1247
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1248
+ * const decrypted = crypto.asymmetric.decrypt(encrypted.data, pair.privateKey)
1249
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1250
+ * }
1251
+ * finally { await crypto.close() }
1252
+ * ```
280
1253
  */
281
1254
  decrypt: (ciphertext: string, privateKey: string, options?: AsymmetricEncryptOptions) => HaiResult<string>;
282
1255
  /**
@@ -286,6 +1259,21 @@ interface AsymmetricOperations {
286
1259
  * @param privateKey - 私钥(64 字符十六进制)
287
1260
  * @param options - 签名选项(hash 开关、userId)
288
1261
  * @returns 成功时返回签名字符串;失败时返回 INVALID_KEY 或 SIGN_FAILED
1262
+ *
1263
+ * @example
1264
+ * ```ts
1265
+ * import { crypto } from '@h-ai/crypto'
1266
+ * const initialized = await crypto.init()
1267
+ * if (!initialized.success) throw new Error(initialized.error.message)
1268
+ * try {
1269
+ * const generated = crypto.asymmetric.generateKeyPair()
1270
+ * if (!generated.success) throw new Error(generated.error.message)
1271
+ * const pair = generated.data
1272
+ * const signature = crypto.asymmetric.sign('hello', pair.privateKey)
1273
+ * if (!signature.success) throw new Error(signature.error.message)
1274
+ * }
1275
+ * finally { await crypto.close() }
1276
+ * ```
289
1277
  */
290
1278
  sign: (data: string, privateKey: string, options?: SignOptions) => HaiResult<string>;
291
1279
  /**
@@ -296,25 +1284,84 @@ interface AsymmetricOperations {
296
1284
  * @param publicKey - 公钥(支持带/不带 04 前缀)
297
1285
  * @param options - 验签选项
298
1286
  * @returns 成功时返回 boolean;失败时返回 INVALID_KEY 或 VERIFY_FAILED
1287
+ *
1288
+ * @example
1289
+ * ```ts
1290
+ * import { crypto } from '@h-ai/crypto'
1291
+ * const initialized = await crypto.init()
1292
+ * if (!initialized.success) throw new Error(initialized.error.message)
1293
+ * try {
1294
+ * const generated = crypto.asymmetric.generateKeyPair()
1295
+ * if (!generated.success) throw new Error(generated.error.message)
1296
+ * const pair = generated.data
1297
+ * const signature = crypto.asymmetric.sign('hello', pair.privateKey)
1298
+ * if (!signature.success) throw new Error(signature.error.message)
1299
+ * const verified = crypto.asymmetric.verify('hello', signature.data, pair.publicKey)
1300
+ * if (!verified.success) throw new Error(verified.error.message)
1301
+ * const accepted = verified.data
1302
+ * }
1303
+ * finally { await crypto.close() }
1304
+ * ```
299
1305
  */
300
1306
  verify: (data: string, signature: string, publicKey: string, options?: SignOptions) => HaiResult<boolean>;
301
1307
  /**
302
- * 校验公钥格式是否合法
1308
+ * 校验128/130字符SM2非压缩公钥编码及曲线点;有效不代表对端持有私钥。
1309
+ * @param key - 本次操作的密钥,不记录到日志。
1310
+ * @returns 直接boolean,false表示不匹配/未就绪。
303
1311
  *
304
- * 合法格式:128 字符十六进制(无前缀)或 130 字符(含 04 前缀)。
1312
+ * @example
1313
+ * ```ts
1314
+ * import { crypto } from '@h-ai/crypto'
1315
+ * const initialized = await crypto.init()
1316
+ * if (!initialized.success) throw new Error(initialized.error.message)
1317
+ * try {
1318
+ * const generated = crypto.asymmetric.generateKeyPair()
1319
+ * if (!generated.success) throw new Error(generated.error.message)
1320
+ * const pair = generated.data
1321
+ * const valid = crypto.asymmetric.isValidPublicKey(pair.publicKey)
1322
+ * }
1323
+ * finally { await crypto.close() }
1324
+ * ```
305
1325
  */
306
1326
  isValidPublicKey: (key: string) => boolean;
307
1327
  /**
308
- * 校验私钥格式是否合法
1328
+ * 校验64字符十六进制私钥格式;这是格式检查,不是密钥配对证明。
1329
+ * @param key - 本次操作的密钥,不记录到日志。
1330
+ * @returns 直接boolean,false表示不匹配/未就绪。
309
1331
  *
310
- * 合法格式:64 字符十六进制。
1332
+ * @example
1333
+ * ```ts
1334
+ * import { crypto } from '@h-ai/crypto'
1335
+ * const initialized = await crypto.init()
1336
+ * if (!initialized.success) throw new Error(initialized.error.message)
1337
+ * try {
1338
+ * const generated = crypto.asymmetric.generateKeyPair()
1339
+ * if (!generated.success) throw new Error(generated.error.message)
1340
+ * const pair = generated.data
1341
+ * const valid = crypto.asymmetric.isValidPrivateKey(pair.privateKey)
1342
+ * }
1343
+ * finally { await crypto.close() }
1344
+ * ```
311
1345
  */
312
1346
  isValidPrivateKey: (key: string) => boolean;
313
1347
  }
314
1348
  /**
315
- * 哈希操作接口
1349
+ * SM3 摘要、HMAC-SM3 与常量时间摘要匹配操作;摘要不是加密,HMAC密钥不能公开。
316
1350
  *
317
- * 通过 `crypto.hash` 访问,需先调用 `crypto.init()`。
1351
+ * @example
1352
+ * ```ts
1353
+ * import { crypto, type HashOperations } from '@h-ai/crypto'
1354
+ * const initialized = await crypto.init()
1355
+ * if (!initialized.success) throw new Error(initialized.error.message)
1356
+ * try {
1357
+ * const operations: HashOperations = crypto.hash
1358
+ * const digest = operations.hash('hello')
1359
+ * if (!digest.success) throw new Error(digest.error.message)
1360
+ * const verified = operations.verify('hello', digest.data)
1361
+ * if (!verified.success) throw new Error(verified.error.message)
1362
+ * }
1363
+ * finally { await crypto.close() }
1364
+ * ```
318
1365
  */
319
1366
  interface HashOperations {
320
1367
  /**
@@ -323,6 +1370,18 @@ interface HashOperations {
323
1370
  * @param data - 待哈希数据(字符串或 Uint8Array)
324
1371
  * @param options - 输入编码选项
325
1372
  * @returns 成功时返回 64 字符十六进制哈希值;失败时返回 HASH_FAILED
1373
+ *
1374
+ * @example
1375
+ * ```ts
1376
+ * import { crypto } from '@h-ai/crypto'
1377
+ * const initialized = await crypto.init()
1378
+ * if (!initialized.success) throw new Error(initialized.error.message)
1379
+ * try {
1380
+ * const digest = crypto.hash.hash('6869', { inputEncoding: 'hex' })
1381
+ * if (!digest.success) throw new Error(digest.error.message)
1382
+ * }
1383
+ * finally { await crypto.close() }
1384
+ * ```
326
1385
  */
327
1386
  hash: (data: string | Uint8Array, options?: HashOptions) => HaiResult<string>;
328
1387
  /**
@@ -334,6 +1393,19 @@ interface HashOperations {
334
1393
  * @param data - 待计算数据
335
1394
  * @param key - HMAC 密钥
336
1395
  * @returns 成功时返回 64 字符十六进制 HMAC 值;失败时返回 HMAC_FAILED
1396
+ *
1397
+ * @example
1398
+ * ```ts
1399
+ * import { crypto } from '@h-ai/crypto'
1400
+ * const initialized = await crypto.init()
1401
+ * if (!initialized.success) throw new Error(initialized.error.message)
1402
+ * try {
1403
+ * const key = crypto.symmetric.generateKey()
1404
+ * const tag = crypto.hash.hmac('hello', key)
1405
+ * if (!tag.success) throw new Error(tag.error.message)
1406
+ * }
1407
+ * finally { await crypto.close() }
1408
+ * ```
337
1409
  */
338
1410
  hmac: (data: string, key: string) => HaiResult<string>;
339
1411
  /**
@@ -344,19 +1416,77 @@ interface HashOperations {
344
1416
  * @param data - 原始数据
345
1417
  * @param expectedHash - 期望的哈希值
346
1418
  * @returns 成功时返回 boolean;失败时返回 HASH_FAILED
1419
+ *
1420
+ * @example
1421
+ * ```ts
1422
+ * import { crypto } from '@h-ai/crypto'
1423
+ * const initialized = await crypto.init()
1424
+ * if (!initialized.success) throw new Error(initialized.error.message)
1425
+ * try {
1426
+ * const digest = crypto.hash.hash('hello')
1427
+ * if (!digest.success) throw new Error(digest.error.message)
1428
+ * const verified = crypto.hash.verify('hello', digest.data)
1429
+ * if (!verified.success) throw new Error(verified.error.message)
1430
+ * const matches = verified.data
1431
+ * }
1432
+ * finally { await crypto.close() }
1433
+ * ```
347
1434
  */
348
1435
  verify: (data: string, expectedHash: string) => HaiResult<boolean>;
349
1436
  }
350
1437
  /**
351
- * 对称加密操作接口
1438
+ * SM4 同步操作域;默认CBC与随机IV,返回完整结构化密文;CBC原语不提供完整性认证。
352
1439
  *
353
- * 通过 `crypto.symmetric` 访问,需先调用 `crypto.init()`。
354
- * 默认使用 CBC 并自动生成 IV;密文以结构化字段返回。
1440
+ * @example
1441
+ * ```ts
1442
+ * import { crypto, type SymmetricOperations } from '@h-ai/crypto'
1443
+ * const initialized = await crypto.init()
1444
+ * if (!initialized.success) throw new Error(initialized.error.message)
1445
+ * try {
1446
+ * const operations: SymmetricOperations = crypto.symmetric
1447
+ * const key = operations.generateKey()
1448
+ * const encrypted = operations.encrypt('hello', key)
1449
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1450
+ * const decrypted = operations.decrypt(encrypted.data, key)
1451
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1452
+ * }
1453
+ * finally { await crypto.close() }
1454
+ * ```
355
1455
  */
356
1456
  interface SymmetricOperations {
357
- /** 生成随机密钥(16 字节 = 32 个十六进制字符) */
1457
+ /**
1458
+ * 生成随机密钥(16 字节 = 32 个十六进制字符)
1459
+ * @returns 直接返回值,使用前先初始化模块。
1460
+ *
1461
+ * @example
1462
+ * ```ts
1463
+ * import { crypto } from '@h-ai/crypto'
1464
+ * const initialized = await crypto.init()
1465
+ * if (!initialized.success) throw new Error(initialized.error.message)
1466
+ * try {
1467
+ * const key = crypto.symmetric.generateKey()
1468
+ * const valid = crypto.symmetric.isValidKey(key)
1469
+ * }
1470
+ * finally { await crypto.close() }
1471
+ * ```
1472
+ */
358
1473
  generateKey: () => string;
359
- /** 生成随机 IV(16 字节 = 32 个十六进制字符) */
1474
+ /**
1475
+ * 生成随机 IV(16 字节 = 32 个十六进制字符)
1476
+ * @returns 直接返回值,使用前先初始化模块。
1477
+ *
1478
+ * @example
1479
+ * ```ts
1480
+ * import { crypto } from '@h-ai/crypto'
1481
+ * const initialized = await crypto.init()
1482
+ * if (!initialized.success) throw new Error(initialized.error.message)
1483
+ * try {
1484
+ * const iv = crypto.symmetric.generateIV()
1485
+ * const valid = crypto.symmetric.isValidIV(iv)
1486
+ * }
1487
+ * finally { await crypto.close() }
1488
+ * ```
1489
+ */
360
1490
  generateIV: () => string;
361
1491
  /**
362
1492
  * 对称加密
@@ -368,6 +1498,19 @@ interface SymmetricOperations {
368
1498
  * @param key - 密钥(32 字符十六进制)
369
1499
  * @param options - 加密模式/IV/输出格式
370
1500
  * @returns 成功时返回结构化密文;失败时返回 INVALID_KEY/INVALID_IV/ENCRYPTION_FAILED
1501
+ *
1502
+ * @example
1503
+ * ```ts
1504
+ * import { crypto } from '@h-ai/crypto'
1505
+ * const initialized = await crypto.init()
1506
+ * if (!initialized.success) throw new Error(initialized.error.message)
1507
+ * try {
1508
+ * const key = crypto.symmetric.generateKey()
1509
+ * const encrypted = crypto.symmetric.encrypt('hello', key)
1510
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1511
+ * }
1512
+ * finally { await crypto.close() }
1513
+ * ```
371
1514
  */
372
1515
  encrypt: (data: string, key: string, options?: SymmetricEncryptOptions) => HaiResult<SymmetricEncryptedPayload>;
373
1516
  /**
@@ -378,6 +1521,21 @@ interface SymmetricOperations {
378
1521
  * @param payload - 结构化密文(包含 mode/ciphertext/iv/encoding)
379
1522
  * @param key - 密钥(32 字符十六进制)
380
1523
  * @returns 成功时返回明文;失败时返回 INVALID_KEY/INVALID_IV/DECRYPTION_FAILED
1524
+ *
1525
+ * @example
1526
+ * ```ts
1527
+ * import { crypto } from '@h-ai/crypto'
1528
+ * const initialized = await crypto.init()
1529
+ * if (!initialized.success) throw new Error(initialized.error.message)
1530
+ * try {
1531
+ * const key = crypto.symmetric.generateKey()
1532
+ * const encrypted = crypto.symmetric.encrypt('hello', key)
1533
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1534
+ * const decrypted = crypto.symmetric.decrypt(encrypted.data, key)
1535
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1536
+ * }
1537
+ * finally { await crypto.close() }
1538
+ * ```
381
1539
  */
382
1540
  decrypt: (payload: SymmetricDecryptInput, key: string) => HaiResult<string>;
383
1541
  /**
@@ -385,43 +1543,103 @@ interface SymmetricOperations {
385
1543
  *
386
1544
  * @param data - 待加密明文
387
1545
  * @param key - 密钥(32 字符十六进制)
388
- * @returns 成功时返回 { ciphertext, iv };失败时同 encrypt
1546
+ * @returns 成功时返回完整 { mode, ciphertext, iv, encoding };失败时同 encrypt
1547
+ *
1548
+ * @example
1549
+ * ```ts
1550
+ * import { crypto } from '@h-ai/crypto'
1551
+ * const initialized = await crypto.init()
1552
+ * if (!initialized.success) throw new Error(initialized.error.message)
1553
+ * try {
1554
+ * const key = crypto.symmetric.generateKey()
1555
+ * const encrypted = crypto.symmetric.encryptWithIV('hello', key)
1556
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1557
+ * }
1558
+ * finally { await crypto.close() }
1559
+ * ```
389
1560
  */
390
1561
  encryptWithIV: (data: string, key: string) => HaiResult<EncryptWithIVResult>;
391
1562
  /**
392
1563
  * 带 IV 解密(CBC 模式)
393
1564
  *
1565
+ * 不提供完整性认证。传输场景必须用 transport 先验签和验证 MAC,禁止直接对 HTTP 密文调用此 primitive。
1566
+ *
394
1567
  * @param ciphertext - 密文
395
1568
  * @param key - 密钥
396
1569
  * @param iv - 加密时使用的 IV
397
1570
  * @returns 成功时返回明文;失败时同 decrypt
1571
+ *
1572
+ * @example
1573
+ * ```ts
1574
+ * import { crypto } from '@h-ai/crypto'
1575
+ * const initialized = await crypto.init()
1576
+ * if (!initialized.success) throw new Error(initialized.error.message)
1577
+ * try {
1578
+ * const key = crypto.symmetric.generateKey()
1579
+ * const encrypted = crypto.symmetric.encryptWithIV('hello', key)
1580
+ * if (!encrypted.success) throw new Error(encrypted.error.message)
1581
+ * const decrypted = crypto.symmetric.decryptWithIV(encrypted.data.ciphertext, key, encrypted.data.iv)
1582
+ * if (!decrypted.success) throw new Error(decrypted.error.message)
1583
+ * }
1584
+ * finally { await crypto.close() }
1585
+ * ```
398
1586
  */
399
1587
  decryptWithIV: (ciphertext: string, key: string, iv: string) => HaiResult<string>;
400
1588
  /**
401
- * 从密码和盐值派生密钥
402
- *
403
- * 内部仅执行单次哈希(password + salt) 取前 32 字符作为密钥。
404
- *
405
- * ⚠️ 安全警告:**此实现不是标准 KDF**,不具备密码爆破抗性。
406
- * - 禁止用于密码存储(请用 `crypto.password.hash`)。
407
- * - 禁止用于高价值密钥派生(请在应用层采用 PBKDF2 / scrypt / Argon2)。
1589
+ * 校验密钥格式是否合法(32 字符十六进制)
1590
+ * @param key - 本次操作的密钥,不记录到日志。
1591
+ * @returns 直接boolean,false表示不匹配/未就绪。
408
1592
  *
409
- * @deprecated 未来版本可能移除。详见模块 README 安全声明。
410
- * @param password - 密码
411
- * @param salt - 盐值
412
- * @returns 32 字符十六进制密钥
1593
+ * @example
1594
+ * ```ts
1595
+ * import { crypto } from '@h-ai/crypto'
1596
+ * const initialized = await crypto.init()
1597
+ * if (!initialized.success) throw new Error(initialized.error.message)
1598
+ * try {
1599
+ * const key = crypto.symmetric.generateKey()
1600
+ * const valid = crypto.symmetric.isValidKey(key)
1601
+ * }
1602
+ * finally { await crypto.close() }
1603
+ * ```
413
1604
  */
414
- deriveKey: (password: string, salt: string) => string;
415
- /** 校验密钥格式是否合法(32 字符十六进制) */
416
1605
  isValidKey: (key: string) => boolean;
417
- /** 校验 IV 格式是否合法(32 字符十六进制) */
1606
+ /**
1607
+ * 校验 IV 格式是否合法(32 字符十六进制)
1608
+ * @param iv - 实际调用输入,按该方法约束验证。
1609
+ * @returns 直接boolean,false表示不匹配/未就绪。
1610
+ *
1611
+ * @example
1612
+ * ```ts
1613
+ * import { crypto } from '@h-ai/crypto'
1614
+ * const initialized = await crypto.init()
1615
+ * if (!initialized.success) throw new Error(initialized.error.message)
1616
+ * try {
1617
+ * const iv = crypto.symmetric.generateIV()
1618
+ * const valid = crypto.symmetric.isValidIV(iv)
1619
+ * }
1620
+ * finally { await crypto.close() }
1621
+ * ```
1622
+ */
418
1623
  isValidIV: (iv: string) => boolean;
419
1624
  }
420
1625
  /**
421
- * 密码哈希操作接口
1626
+ * 迭代加盐SM3密码存储操作;验证从 $hai$ 格式读取参数,返回成功false表示密码不匹配。
422
1627
  *
423
- * 通过 `crypto.password` 访问,需先调用 `crypto.init()`。
424
- * 使用迭代加盐的方式生成密码哈希。
1628
+ * @example
1629
+ * ```ts
1630
+ * import { crypto, type PasswordOperations } from '@h-ai/crypto'
1631
+ * const initialized = await crypto.init()
1632
+ * if (!initialized.success) throw new Error(initialized.error.message)
1633
+ * try {
1634
+ * const operations: PasswordOperations = crypto.password
1635
+ * const hashed = operations.hash('test-password')
1636
+ * if (!hashed.success) throw new Error(hashed.error.message)
1637
+ * const verified = operations.verify('test-password', hashed.data)
1638
+ * if (!verified.success) throw new Error(verified.error.message)
1639
+ * const matches = verified.data
1640
+ * }
1641
+ * finally { await crypto.close() }
1642
+ * ```
425
1643
  */
426
1644
  interface PasswordOperations {
427
1645
  /**
@@ -432,6 +1650,18 @@ interface PasswordOperations {
432
1650
  * @param password - 明文密码(不能为空)
433
1651
  * @param config - 可选配置(盐值长度、迭代次数)
434
1652
  * @returns 成功时返回格式化的哈希字符串;失败时返回 INVALID_INPUT 或 HASH_FAILED
1653
+ *
1654
+ * @example
1655
+ * ```ts
1656
+ * import { crypto } from '@h-ai/crypto'
1657
+ * const initialized = await crypto.init()
1658
+ * if (!initialized.success) throw new Error(initialized.error.message)
1659
+ * try {
1660
+ * const hashed = crypto.password.hash('test-password', { iterations: 10000, saltLength: 16 })
1661
+ * if (!hashed.success) throw new Error(hashed.error.message)
1662
+ * }
1663
+ * finally { await crypto.close() }
1664
+ * ```
435
1665
  */
436
1666
  hash: (password: string, config?: PasswordConfig) => HaiResult<string>;
437
1667
  /**
@@ -442,61 +1672,86 @@ interface PasswordOperations {
442
1672
  * @param password - 待验证的明文密码
443
1673
  * @param hash - 存储的哈希值(格式: `$hai$<iterations>$<salt>$<hash>`)
444
1674
  * @returns 成功时返回 boolean;失败时返回 INVALID_INPUT 或 VERIFY_FAILED
1675
+ *
1676
+ * @example
1677
+ * ```ts
1678
+ * import { crypto } from '@h-ai/crypto'
1679
+ * const initialized = await crypto.init()
1680
+ * if (!initialized.success) throw new Error(initialized.error.message)
1681
+ * try {
1682
+ * const hashed = crypto.password.hash('test-password')
1683
+ * if (!hashed.success) throw new Error(hashed.error.message)
1684
+ * const verified = crypto.password.verify('test-password', hashed.data)
1685
+ * if (!verified.success) throw new Error(verified.error.message)
1686
+ * const matches = verified.data
1687
+ * }
1688
+ * finally { await crypto.close() }
1689
+ * ```
445
1690
  */
446
1691
  verify: (password: string, hash: string) => HaiResult<boolean>;
447
1692
  }
448
1693
  /**
449
- * 传输加密操作接口(端到端混合加密)。
1694
+ * 认证传输工厂;需先初始化crypto,服务端显式受管密钥环+共享registry,客户端通过TLS协商公钥。
1695
+ * 协议v2绑定方向、HTTP方法/路径/状态、密钥版本和nonce,验签/MAC成功后才解密;防重放不替代业务幂等。
450
1696
  *
451
- * 通过 `crypto.transport` 访问,需先调用 `crypto.init()`。
452
- *
453
- * @remarks
454
- * 使用流程(直接使用底层 transport 工厂时):
455
- *
456
- * 1. 先 `await crypto.init()`,确保 `crypto.asymmetric` / `crypto.symmetric` 已就绪。
457
- * 2. 服务端调用 `crypto.transport.createServer()` 创建 `TransportEncryptionManager`;该管理器负责持有服务端密钥对,并管理客户端公钥。多节点部署时可通过 `options.keyStore` 注入共享存储。
458
- * 3. 服务端暴露一个 POST 密钥协商端点:接收 `{ clientPublicKey }`,调用 `manager.registerClientKey()` 注册客户端公钥,再返回 `{ serverPublicKey: manager.getServerPublicKey(), clientId }`。
459
- * 4. 客户端调用 `crypto.transport.createClient({ keyExchangeUrl })` 创建会话;首次 `client.init()` 或 `client.encryptedFetch()` 会自动完成密钥协商。
460
- * 5. 协商完成后,客户端每次请求都会附带 `X-Client-Id`;若请求有 body,则 body 会被包装成 `{ encryptedKey, ciphertext, iv }`,并设置 `X-Encrypted: true`。
461
- * 6. 服务端在业务逻辑前调用 `manager.decryptRequest()` 解密请求体,在返回前调用 `manager.encryptResponse(clientId, data)` 为当前客户端重新加密响应。
462
- * 7. 客户端收到 `X-Encrypted: true` 的响应后会自动解密;调用 `client.destroy()` 可清空当前会话,下次请求会重新协商。
463
- *
464
- * 常规应用优先使用上层封装,而不是手写 HTTP 协商细节:
465
- * - `serv.createApp({ transport: { crypto } })`
466
- * - `kit.createHandle({ crypto: { crypto, transport: true } })`
467
- * - `apiClient.init({ transport: { crypto } })`
468
- *
469
- * @example 服务端
470
- * ```ts
471
- * const result = crypto.transport.createServer({
472
- * keyStore: createRedisTransportKeyStore({ cache, ttlSeconds: 3600 }),
473
- * })
474
- * if (!result.success) throw result.error
475
- * const manager = result.data
476
- * ```
477
- *
478
- * @example 客户端
1697
+ * @example
479
1698
  * ```ts
480
- * const client = crypto.transport.createClient({
481
- * keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange',
482
- * })
483
- * const resp = await client.encryptedFetch('https://api.example.com/api/v1/echo', {
484
- * method: 'POST', body: JSON.stringify({ hello: 'world' }),
485
- * })
1699
+ * import { crypto } from '@h-ai/crypto'
1700
+ * const initialized = await crypto.init()
1701
+ * if (!initialized.success) throw new Error(initialized.error.message)
1702
+ * try {
1703
+ * const client = crypto.transport.createClient({ keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange' })
1704
+ * try {
1705
+ * const ready = await client.init()
1706
+ * if (!ready.success) throw new Error(ready.error.message)
1707
+ * const response = await client.encryptedFetch('https://api.example.com/api/v1/orders')
1708
+ * if (!response.ok) throw new Error('HTTP request failed')
1709
+ * }
1710
+ * finally { client.destroy() }
1711
+ * }
1712
+ * finally { await crypto.close() }
486
1713
  * ```
487
1714
  */
488
1715
  interface TransportOperations {
489
1716
  /**
490
1717
  * 创建服务端传输加密管理器。
491
1718
  *
492
- * options.keyStore:注入共享客户端公钥存储。
493
- * options.maxClients:默认内存 keyStore 的最大客户端数(默认 10000,仅在未传 keyStore 时生效)。
494
- * 成功返回 manager;密钥生成失败返回 `HaiCommonError.INTERNAL_ERROR`。
1719
+ * serverKeyRing/keyStore 均必填;生产使用相同受管密钥环与共享 registry。
1720
+ * 成功返回 manager;缺失、格式错误或公私钥错配返回脱敏 HaiResult 错误。
495
1721
  *
496
1722
  * @remarks
497
1723
  * 通常在服务启动阶段创建一次,并交给 HTTP 中间件 / 路由处理器复用。
1724
+ * @param options - 实际调用输入,按该方法约束验证。
1725
+ * @returns HaiResult,先检查success再读取data。
1726
+ *
1727
+ * @example
1728
+ * ```ts
1729
+ * import { crypto, createRedisTransportKeyStore, parseTransportServerKeyRing } from '@h-ai/crypto'
1730
+ * import { cache } from '@h-ai/cache'
1731
+ * const initialized = await crypto.init()
1732
+ * if (!initialized.success) throw new Error(initialized.error.message)
1733
+ * try {
1734
+ * const connected = await cache.init({ type: 'redis', host: 'cache', port: 6379, password: process.env.HAI_CACHE_PASSWORD })
1735
+ * if (!connected.success) throw new Error(connected.error.message)
1736
+ * try {
1737
+ * const registry = createRedisTransportKeyStore({ cache, ttlSeconds: 3600 })
1738
+ * const ring = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
1739
+ * if (!ring.success) throw new Error(ring.error.message)
1740
+ * const created = crypto.transport.createServer({ serverKeyRing: ring.data, keyStore: registry })
1741
+ * if (!created.success) throw new Error(created.error.message)
1742
+ * const manager = created.data
1743
+ * try {
1744
+ * const currentVersion = manager.getServerKeyId()
1745
+ * const publicKey = manager.getServerPublicKey()
1746
+ * }
1747
+ * finally { await manager.close() }
1748
+ * }
1749
+ * finally { await cache.close() }
1750
+ * }
1751
+ * finally { await crypto.close() }
1752
+ * ```
498
1753
  */
499
- createServer: (options?: TransportCreateServerOptions) => HaiResult<TransportEncryptionManager>;
1754
+ createServer: (options: TransportCreateServerOptions) => HaiResult<TransportEncryptionManager>;
500
1755
  /**
501
1756
  * 创建客户端传输加密会话。
502
1757
  *
@@ -506,26 +1761,52 @@ interface TransportOperations {
506
1761
  * @remarks
507
1762
  * 返回的是“单会话”客户端:同一个实例会复用已协商得到的 `clientId` 与服务端公钥;
508
1763
  * 调用 `destroy()` 后会回到未协商状态。
1764
+ * @param options - 实际调用输入,按该方法约束验证。
1765
+ * @param options.keyExchangeUrl - 密钥协商端点完整 URL。
1766
+ * @param options.fetch - 实际发送 HTTP 请求的 fetch,默认 `globalThis.fetch`。
1767
+ * @param options.maxPlaintextBytes - 可选本地明文 UTF-8 字节上限,默认跟随服务端。
1768
+ * @returns 直接返回值,使用前先初始化模块。
1769
+ *
1770
+ * @example
1771
+ * ```ts
1772
+ * import { crypto } from '@h-ai/crypto'
1773
+ * const initialized = await crypto.init()
1774
+ * if (!initialized.success) throw new Error(initialized.error.message)
1775
+ * try {
1776
+ * const client = crypto.transport.createClient({ keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange' })
1777
+ * try {
1778
+ * const ready = await client.init()
1779
+ * if (!ready.success) throw new Error(ready.error.message)
1780
+ * const response = await client.encryptedFetch('https://api.example.com/api/v1/orders')
1781
+ * if (!response.ok) throw new Error('HTTP request failed')
1782
+ * }
1783
+ * finally { client.destroy() }
1784
+ * }
1785
+ * finally { await crypto.close() }
1786
+ * ```
509
1787
  */
510
1788
  createClient: (options: {
511
1789
  keyExchangeUrl: string;
512
1790
  fetch?: typeof fetch;
1791
+ maxPlaintextBytes?: number;
513
1792
  }) => TransportClient;
514
1793
  /** 协议常量(headers、密钥协商默认路径)。 */
515
1794
  readonly protocol: typeof TRANSPORT_PROTOCOL;
516
1795
  }
517
1796
  /**
518
- * 加密模块函数接口
519
- *
520
- * `crypto` 服务对象的类型定义。使用前必须调用 `init()` 初始化。
1797
+ * 加密模块服务接口;init检查HaiResult,close返回void,调用不能把原语当作已认证HTTP协议。
521
1798
  *
522
1799
  * @example
523
1800
  * ```ts
524
1801
  * import { crypto } from '@h-ai/crypto'
525
- *
526
- * await crypto.init()
527
- * const hash = crypto.hash.hash('hello')
528
- * await crypto.close()
1802
+ * const initialized = await crypto.init()
1803
+ * if (!initialized.success) throw new Error(initialized.error.message)
1804
+ * try {
1805
+ * const digest = crypto.hash.hash('hello')
1806
+ * if (!digest.success) throw new Error(digest.error.message)
1807
+ * const value = digest.data
1808
+ * }
1809
+ * finally { await crypto.close() }
529
1810
  * ```
530
1811
  */
531
1812
  interface CryptoFunctions {
@@ -536,12 +1817,30 @@ interface CryptoFunctions {
536
1817
  * 重复调用会先关闭再重新初始化。
537
1818
  *
538
1819
  * @returns 成功时返回 ok(undefined);失败时返回 INIT_FAILED
1820
+ *
1821
+ * @example
1822
+ * ```ts
1823
+ * import { crypto } from '@h-ai/crypto'
1824
+ * const initialized = await crypto.init()
1825
+ * if (!initialized.success) throw new Error(initialized.error.message)
1826
+ * await crypto.close()
1827
+ * ```
539
1828
  */
540
1829
  init: () => Promise<HaiResult<void>>;
541
1830
  /**
542
1831
  * 关闭加密模块,释放内部状态
543
1832
  *
544
1833
  * 关闭后再访问 asymmetric/hash/symmetric/password 会返回 NOT_INITIALIZED 错误。
1834
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
1835
+ *
1836
+ * @example
1837
+ * ```ts
1838
+ * import { crypto } from '@h-ai/crypto'
1839
+ * const initialized = await crypto.init()
1840
+ * if (!initialized.success) throw new Error(initialized.error.message)
1841
+ * await crypto.close()
1842
+ * const ready = crypto.isInitialized
1843
+ * ```
545
1844
  */
546
1845
  close: () => Promise<void>;
547
1846
  /** 是否已初始化 */
@@ -566,38 +1865,169 @@ interface CryptoFunctions {
566
1865
  */
567
1866
 
568
1867
  /**
569
- * 加密模块服务对象(统一入口)
570
- *
571
- * 使用前必须调用 `crypto.init()` 进行初始化。
572
- * 未初始化时访问 asymmetric/hash/symmetric/password 的任何方法均返回 NOT_INITIALIZED 错误。
1868
+ * 加密模块公开服务对象;先检查 init 的 HaiResult,再使用各操作域,最后 close。
1869
+ * SM2/SM3/SM4 原语不等于认证传输;HTTP 使用 transport 的签名、MAC、上下文和共享 nonce 校验。
573
1870
  *
574
1871
  * @example
575
1872
  * ```ts
576
1873
  * import { crypto } from '@h-ai/crypto'
577
- *
578
- * await crypto.init()
579
- * const hash = crypto.hash.hash('hello')
580
- * const keyPair = crypto.asymmetric.generateKeyPair()
581
- * await crypto.close()
1874
+ * const initialized = await crypto.init()
1875
+ * if (!initialized.success) throw new Error(initialized.error.message)
1876
+ * try {
1877
+ * const generated = crypto.asymmetric.generateKeyPair()
1878
+ * if (!generated.success) throw new Error(generated.error.message)
1879
+ * const pair = generated.data
1880
+ * const digest = crypto.hash.hash('hello')
1881
+ * if (!digest.success) throw new Error(digest.error.message)
1882
+ * const publicKeyValid = crypto.asymmetric.isValidPublicKey(pair.publicKey)
1883
+ * }
1884
+ * finally { await crypto.close() }
582
1885
  * ```
583
1886
  */
584
1887
  declare const crypto: CryptoFunctions;
585
1888
 
1889
+ /**
1890
+ * @h-ai/crypto — SM2 公钥输入校验。
1891
+ * @module crypto-public-key
1892
+ */
1893
+ /**
1894
+ * 纯函数校验 SM2 公钥的编码及曲线点,不初始化模块或访问 registry。
1895
+ * 仅接受128字符无前缀或130字符04前缀的十六进制非压缩点;拒绝曲线外点及其它编码。
1896
+ * @param publicKey - 不可信的输入。
1897
+ * @returns 有效字符串时为 true,并收窄类型;不证明密钥所有权,注册后仍须验签。
1898
+ *
1899
+ * @example
1900
+ * ```ts
1901
+ * import { crypto, isValidSM2PublicKey } from '@h-ai/crypto'
1902
+ * const initialized = await crypto.init()
1903
+ * if (!initialized.success) throw new Error(initialized.error.message)
1904
+ * try {
1905
+ * const generated = crypto.asymmetric.generateKeyPair()
1906
+ * if (!generated.success) throw new Error(generated.error.message)
1907
+ * const pair = generated.data
1908
+ * const valid = isValidSM2PublicKey(pair.publicKey)
1909
+ * const invalid = isValidSM2PublicKey('not-a-public-key')
1910
+ * }
1911
+ * finally { await crypto.close() }
1912
+ * ```
1913
+ */
1914
+ declare function isValidSM2PublicKey(publicKey: unknown): publicKey is string;
1915
+
1916
+ /** @h-ai/crypto — serv/kit 共用的安全传输错误响应。 */
1917
+
1918
+ /**
1919
+ * 已认证请求的时间窗口错误;只提供校时建议,不调整时钟或放宽防重放窗口。
1920
+ * @example
1921
+ * ```ts
1922
+ * import { TransportTimeError } from '@h-ai/crypto'
1923
+ * const error = new TransportTimeError()
1924
+ * // 展示 error.message;同步设备/服务器时间后由用户刷新重试。
1925
+ * ```
1926
+ */
1927
+ declare class TransportTimeError extends Error {
1928
+ readonly context?: TransportMessageContext | undefined;
1929
+ readonly code: string | number;
1930
+ constructor(context?: TransportMessageContext | undefined);
1931
+ }
1932
+ /**
1933
+ * 创建脱敏传输错误;已验证绑定、签名和 MAC 的时间/响应容量错误继续加密,请求读取超限返回 HTTP 413。
1934
+ * @param error - 容量或时间错误,不包含业务报文。
1935
+ * @param authenticated - 仅在请求绑定、签名和 MAC 已验证后提供管理器和上下文。
1936
+ * @param authenticated.manager - 使用原服务端预算的管理器。
1937
+ * @param authenticated.context - 已验证请求绑定、签名和 MAC 的上下文;时间拒绝不会放行业务。
1938
+ * @returns 可诊断的失败响应;加密失败仍只返回错误,不发送原业务响应。
1939
+ * @example
1940
+ * ```ts
1941
+ * import { createTransportErrorResponse, TransportBodyTooLargeError } from '@h-ai/crypto'
1942
+ * const response = await createTransportErrorResponse(new TransportBodyTooLargeError(1024, 1025))
1943
+ * const status = response.status // 413
1944
+ * ```
1945
+ */
1946
+ declare function createTransportErrorResponse(error: TransportBodyTooLargeError | TransportTimeError, authenticated?: {
1947
+ manager: TransportEncryptionManager;
1948
+ context: TransportMessageContext;
1949
+ }): Promise<Response>;
1950
+
1951
+ /**
1952
+ * @h-ai/crypto — 服务端受管传输密钥环的安全解析。
1953
+ * @module crypto-transport-keyring
1954
+ */
1955
+
1956
+ /**
1957
+ * 解析服务端私有JSON或受管对象,不读取环境或初始化模块;实际密钥配对由createServer验证。
1958
+ * @param serialized - Secret Manager提供的JSON字符串或对象。
1959
+ * @returns 结构有效的密钥环或脱敏INVALID_KEY,不回显私钥/原始输入。
1960
+ *
1961
+ * @example
1962
+ * ```ts
1963
+ * import { parseTransportServerKeyRing, type TransportServerKeyRing } from '@h-ai/crypto'
1964
+ * const parsed = parseTransportServerKeyRing(process.env.HAI_CRYPTO_TRANSPORT_SERVERKEYRING)
1965
+ * if (!parsed.success) throw new Error(parsed.error.message)
1966
+ * const ring: TransportServerKeyRing = parsed.data
1967
+ * // 仅服务端使用;createServer还会校验每个版本的公私钥配对。
1968
+ * ```
1969
+ */
1970
+ declare function parseTransportServerKeyRing(serialized: unknown): HaiResult<TransportServerKeyRing>;
1971
+
1972
+ /**
1973
+ * @h-ai/crypto — serv/kit 共用的实际 HTTP 请求认证入口。
1974
+ * @module crypto-transport-request
1975
+ */
1976
+
1977
+ /**
1978
+ * 从实际HTTP请求提取可信方法/路径/查询/客户端ID并有界认证;成功后才执行业务。
1979
+ * 拒绝缺少认证及头/正文重复承载,空请求也认证;不会由payload自证HTTP上下文。
1980
+ * @param manager - 使用共享原子nonce registry的已创建管理器。
1981
+ * @param request - 未消费正文的真实Request。
1982
+ * @returns 明文和响应关联上下文;认证失败无明文。
1983
+ * @throws RangeError超限;流读取/取消沿用原异常,HTTP适配器负责转响应。
1984
+ *
1985
+ * @example
1986
+ * ```ts
1987
+ * import { authenticateTransportRequest, TRANSPORT_PROTOCOL, type TransportEncryptionManager } from '@h-ai/crypto'
1988
+ * async function handle(manager: TransportEncryptionManager, request: Request): Promise<Response> {
1989
+ * const verified = await authenticateTransportRequest(manager, request)
1990
+ * if (!verified.success) return new Response(null, { status: 400 })
1991
+ * const encrypted = await manager.encryptResponse(verified.data.context, JSON.stringify({ accepted: true }), 200)
1992
+ * if (!encrypted.success) return new Response(null, { status: 500 })
1993
+ * return Response.json(encrypted.data, { headers: { [TRANSPORT_PROTOCOL.ENCRYPTED_HEADER]: TRANSPORT_PROTOCOL.ENCRYPTED_HEADER_VALUE } })
1994
+ * }
1995
+ * ```
1996
+ */
1997
+ declare function authenticateTransportRequest(manager: TransportEncryptionManager, request: Request): Promise<HaiResult<{
1998
+ plaintext: string;
1999
+ context: TransportMessageContext;
2000
+ }>>;
2001
+
586
2002
  /**
587
2003
  * @h-ai/crypto — 传输加密内存 key store
588
2004
  *
589
- * 提供默认的进程内客户端公钥存储实现。
2005
+ * 提供显式开发/测试使用的进程内客户端公钥存储,生产使用共享 registry。
590
2006
  * @module crypto-transport-store-memory
591
2007
  */
592
2008
 
593
2009
  /**
594
- * 创建进程内 FIFO 客户端密钥存储。
595
- *
596
- * ⚠️ 进程内实现:多节点部署时需让客户端首次请求后保持「会话粘性」(sticky session),
597
- * 否则后续请求路由到其他节点会因找不到客户端公钥而失败。需要跨节点请改用
598
- * Redis / 数据库实现 {@link TransportKeyStore}。
2010
+ * 显式创建开发/测试用进程内FIFO公钥registry;不跨进程、不持久化,生产共享状态守卫拒绝它。
2011
+ * 有效nonce不会因公钥FIFO容量而提前逐出;过期nonce惰性清理。
2012
+ * @param maxClients - 公钥容量,默认10000,超限淘汰最早公钥。
2013
+ * @returns 本地registry;无效SM2公钥拒绝Promise。
599
2014
  *
600
- * @param maxClients - 最大客户端数(默认 10000),超过后按注册顺序淘汰最早条目。
2015
+ * @example
2016
+ * ```ts
2017
+ * import { crypto, createInMemoryKeyStore } from '@h-ai/crypto'
2018
+ * const initialized = await crypto.init()
2019
+ * if (!initialized.success) throw new Error(initialized.error.message)
2020
+ * try {
2021
+ * const generated = crypto.asymmetric.generateKeyPair()
2022
+ * if (!generated.success) throw new Error(generated.error.message)
2023
+ * const pair = generated.data
2024
+ * const registry = createInMemoryKeyStore(100)
2025
+ * const clientId = await registry.register(pair.publicKey)
2026
+ * const saved = await registry.get(clientId)
2027
+ * await registry.delete?.(clientId)
2028
+ * }
2029
+ * finally { await crypto.close() }
2030
+ * ```
601
2031
  */
602
2032
  declare function createInMemoryKeyStore(maxClients?: number): TransportKeyStore;
603
2033
 
@@ -608,18 +2038,59 @@ declare function createInMemoryKeyStore(maxClients?: number): TransportKeyStore;
608
2038
  * @module crypto-transport-store-redis
609
2039
  */
610
2040
 
611
- /** 创建 Redis 版传输 key store 的配置。 */
2041
+ /**
2042
+ * 借用已初始化cache的registry配置;只有Redis provider报告shared,内存cache不能满足生产。
2043
+ * TTL是客户端公钥寿命,nonce另按认证窗口持有;连接由应用关闭。
2044
+ *
2045
+ * @example
2046
+ * ```ts
2047
+ * import { crypto, createRedisTransportKeyStore, parseTransportServerKeyRing } from '@h-ai/crypto'
2048
+ * import { cache } from '@h-ai/cache'
2049
+ * const initialized = await crypto.init()
2050
+ * if (!initialized.success) throw new Error(initialized.error.message)
2051
+ * try {
2052
+ * const connected = await cache.init({ type: 'redis', host: 'cache', port: 6379, password: process.env.HAI_CACHE_PASSWORD })
2053
+ * if (!connected.success) throw new Error(connected.error.message)
2054
+ * try {
2055
+ * const registry = createRedisTransportKeyStore({ cache, ttlSeconds: 3600 })
2056
+ * const options: import('@h-ai/crypto').CreateRedisTransportKeyStoreOptions = { cache, ttlSeconds: 3600 }
2057
+ * const secondView = createRedisTransportKeyStore(options)
2058
+ * const scope = secondView.stateScope
2059
+ * }
2060
+ * finally { await cache.close() }
2061
+ * }
2062
+ * finally { await crypto.close() }
2063
+ * ```
2064
+ */
612
2065
  interface CreateRedisTransportKeyStoreOptions {
613
2066
  /** 已初始化的 `@h-ai/cache` 实例;生产环境通常应使用 Redis provider。 */
614
2067
  readonly cache: CacheFunctions;
615
- /** 客户端公钥的 TTL(秒);未传则保持不过期。 */
2068
+ /** 客户端公钥的 TTL(正整数秒,最大 2147483647);未传则保持不过期。 */
616
2069
  readonly ttlSeconds?: number;
617
2070
  }
618
2071
  /**
619
- * 创建基于 `@h-ai/cache` 的传输 key store。
2072
+ * 创建借用cache的公钥/nonce registry;生产必须Redis共享provider,nonce用单key原子CAS。
2073
+ * 公钥TTL省略则不过期,nonce有效期间禁止驱逐;容量由Redis部署预算管理,不提供DB maxClients。
2074
+ * @param options - 已初始化cache与可选正整数TTL秒,最大2147483647。
2075
+ * @returns registry;非法TTL同步TypeError,读写/公钥错误拒绝Promise,不关闭cache。
620
2076
  *
621
- * 说明:本实现依赖 cache 模块的 KV 语义;若要获得跨节点共享能力,应传入
622
- * 已连接 Redis 的 `cache` 实例,而不是内存 provider。
2077
+ * @example
2078
+ * ```ts
2079
+ * import { crypto, createRedisTransportKeyStore, parseTransportServerKeyRing } from '@h-ai/crypto'
2080
+ * import { cache } from '@h-ai/cache'
2081
+ * const initialized = await crypto.init()
2082
+ * if (!initialized.success) throw new Error(initialized.error.message)
2083
+ * try {
2084
+ * const connected = await cache.init({ type: 'redis', host: 'cache', port: 6379, password: process.env.HAI_CACHE_PASSWORD })
2085
+ * if (!connected.success) throw new Error(connected.error.message)
2086
+ * try {
2087
+ * const registry = createRedisTransportKeyStore({ cache, ttlSeconds: 3600 })
2088
+ * const scope = registry.stateScope
2089
+ * }
2090
+ * finally { await cache.close() }
2091
+ * }
2092
+ * finally { await crypto.close() }
2093
+ * ```
623
2094
  */
624
2095
  declare function createRedisTransportKeyStore(options: CreateRedisTransportKeyStoreOptions): TransportKeyStore;
625
2096
 
@@ -630,18 +2101,90 @@ declare function createRedisTransportKeyStore(options: CreateRedisTransportKeySt
630
2101
  * @module crypto-transport-store-reldb
631
2102
  */
632
2103
 
633
- /** 创建关系数据库版传输 key store 的配置。 */
2104
+ /**
2105
+ * 借用已初始化数据库的registry配置;TTL与共享maxClients各节点必须一致。
2106
+ * 生产使用PostgreSQL/MySQL,DB时钟维护期限;连接由应用关闭。
2107
+ *
2108
+ * @example
2109
+ * ```ts
2110
+ * import { createReldbTransportKeyStore } from '@h-ai/crypto'
2111
+ * import { reldb } from '@h-ai/reldb'
2112
+ * const connected = await reldb.init({ type: 'postgresql', host: 'db', port: 5432, database: 'hai', user: 'postgres', password: process.env.HAI_DB_PASSWORD })
2113
+ * if (!connected.success) throw new Error(connected.error.message)
2114
+ * try {
2115
+ * const registry = createReldbTransportKeyStore({ reldb, ttlSeconds: 3600, maxClients: 10000 })
2116
+ * const options: import('@h-ai/crypto').CreateReldbTransportKeyStoreOptions = { reldb, ttlSeconds: 3600, maxClients: 10000 }
2117
+ * const secondView = createReldbTransportKeyStore(options)
2118
+ * const removed = await secondView.pruneExpired()
2119
+ * }
2120
+ * finally { await reldb.close() }
2121
+ * ```
2122
+ */
634
2123
  interface CreateReldbTransportKeyStoreOptions {
635
2124
  /** 已初始化的 `@h-ai/reldb` 实例。 */
636
2125
  readonly reldb: ReldbFunctions;
637
- /** 客户端公钥的 TTL(秒);未传则保持不过期。 */
2126
+ /** 公钥 TTL,正整数秒且最大 2147483647;省略则不过期。 */
638
2127
  readonly ttlSeconds?: number;
2128
+ /** 所有节点共享的有效公钥容量,正安全整数,默认 10000;各节点必须一致。 */
2129
+ readonly maxClients?: number;
639
2130
  }
640
2131
  /**
641
- * 创建基于 `@h-ai/reldb` 的传输 key store。
2132
+ * 数据库registry及有界过期维护;注册自动维护,无流量时应用应定期调度pruneExpired。
2133
+ * 不淘汰有效公钥/nonce,不创建后台计时器;维护失败拒绝并可重试。
642
2134
  *
643
- * 首次读写时会自动创建 `hai_crypto_transport_client_keys` 表。
2135
+ * @example
2136
+ * ```ts
2137
+ * import { createReldbTransportKeyStore } from '@h-ai/crypto'
2138
+ * import { reldb } from '@h-ai/reldb'
2139
+ * const connected = await reldb.init({ type: 'postgresql', host: 'db', port: 5432, database: 'hai', user: 'postgres', password: process.env.HAI_DB_PASSWORD })
2140
+ * if (!connected.success) throw new Error(connected.error.message)
2141
+ * try {
2142
+ * const registry = createReldbTransportKeyStore({ reldb, ttlSeconds: 3600, maxClients: 10000 })
2143
+ * const removed = await registry.pruneExpired()
2144
+ * }
2145
+ * finally { await reldb.close() }
2146
+ * ```
2147
+ */
2148
+ interface ReldbTransportKeyStore extends TransportKeyStore {
2149
+ /**
2150
+ * 按数据库时钟最多删除 100 条过期公钥和 100 条过期 nonce,返回实际删除总数。
2151
+ * 不驱逐有效记录;建表或维护故障会 reject,之后允许重新调用。应用可以定期调度本方法。
2152
+ * @returns 异步操作结果;存储或网络故障按方法契约拒绝。
2153
+ *
2154
+ * @example
2155
+ * ```ts
2156
+ * import { createReldbTransportKeyStore } from '@h-ai/crypto'
2157
+ * import { reldb } from '@h-ai/reldb'
2158
+ * const connected = await reldb.init({ type: 'postgresql', host: 'db', port: 5432, database: 'hai', user: 'postgres', password: process.env.HAI_DB_PASSWORD })
2159
+ * if (!connected.success) throw new Error(connected.error.message)
2160
+ * try {
2161
+ * const registry = createReldbTransportKeyStore({ reldb, ttlSeconds: 3600, maxClients: 10000 })
2162
+ * const removed = await registry.pruneExpired()
2163
+ * }
2164
+ * finally { await reldb.close() }
2165
+ * ```
2166
+ */
2167
+ pruneExpired: () => Promise<number>;
2168
+ }
2169
+ /**
2170
+ * 创建共享数据库registry;首次操作惰性建表,失败可重试,事务锁住持久容量行后注册。
2171
+ * 每次注册有界维护;公钥TTL与过期维护使用数据库epoch毫秒,传输窗口仍要求节点时钟同步,不能提前删除有效nonce。
2172
+ * @param options - 已初始化数据库、公钥TTL和各节点一致的正安全整数maxClients,默认10000。
2173
+ * @returns registry;非法配置同步TypeError,操作故障拒绝Promise;不关闭借用数据库。
2174
+ *
2175
+ * @example
2176
+ * ```ts
2177
+ * import { createReldbTransportKeyStore } from '@h-ai/crypto'
2178
+ * import { reldb } from '@h-ai/reldb'
2179
+ * const connected = await reldb.init({ type: 'postgresql', host: 'db', port: 5432, database: 'hai', user: 'postgres', password: process.env.HAI_DB_PASSWORD })
2180
+ * if (!connected.success) throw new Error(connected.error.message)
2181
+ * try {
2182
+ * const registry = createReldbTransportKeyStore({ reldb, ttlSeconds: 3600, maxClients: 10000 })
2183
+ * const removed = await registry.pruneExpired()
2184
+ * }
2185
+ * finally { await reldb.close() }
2186
+ * ```
644
2187
  */
645
- declare function createReldbTransportKeyStore(options: CreateReldbTransportKeyStoreOptions): TransportKeyStore;
2188
+ declare function createReldbTransportKeyStore(options: CreateReldbTransportKeyStoreOptions): ReldbTransportKeyStore;
646
2189
 
647
- export { type AsymmetricEncryptOptions, type AsymmetricOperations, type CipherMode, type CreateRedisTransportKeyStoreOptions, type CreateReldbTransportKeyStoreOptions, type CryptoFunctions, type EncryptWithIVResult, type EncryptedPayload, HaiCryptoError, type HashOperations, type HashOptions, type KeyExchangeRequest, type KeyExchangeResponse, type KeyPair, type PasswordConfig, type PasswordOperations, type SignOptions, type SymmetricCbcEncryptedPayload, type SymmetricCiphertextEncoding, type SymmetricDecryptInput, type SymmetricEncryptOptions, type SymmetricEncryptedPayload, type SymmetricMode, type SymmetricOperations, TRANSPORT_PROTOCOL, type TransportClient, type TransportCreateServerOptions, type TransportCryptoServiceLike, type TransportEncryptionManager, type TransportKeyPair, type TransportKeyStore, type TransportOperations, createInMemoryKeyStore, createRedisTransportKeyStore, createReldbTransportKeyStore, crypto };
2190
+ 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 };