@h-ai/crypto 0.1.0-alpha.16 → 0.1.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -14
- package/dist/index.d.ts +126 -31
- package/dist/index.js +250 -61
- package/dist/index.js.map +1 -1
- package/package.json +11 -7
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../messages/en-US.json","../messages/zh-CN.json","../src/crypto-i18n.ts","../src/crypto-types.ts","../src/crypto-password.ts","../src/crypto-utils.ts","../src/crypto-sm2.ts","../src/crypto-sm3.ts","../src/crypto-sm4.ts","../src/transport/crypto-transport-types.ts","../src/transport/crypto-transport-client.ts","../src/transport/crypto-transport-server.ts","../src/crypto-main.ts"],"names":["core","ok","err","smCrypto","sm3","HaiCommonError","crypto"],"mappings":"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","file":"index.js","sourcesContent":["{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n \"crypto_notInitialized\": \"Crypto module not initialized, call crypto.init() first\",\n \"crypto_initFailed\": \"Crypto module initialization failed: {error}\",\n \"crypto_sm2PublicKeyInvalid\": \"Invalid SM2 public key format\",\n \"crypto_sm2PrivateKeyInvalid\": \"Invalid SM2 private key format\",\n \"crypto_sm2EncryptEmpty\": \"SM2 encryption returned empty result\",\n \"crypto_sm2DecryptFailed\": \"SM2 decryption failed or returned invalid result\",\n \"crypto_sm2SignEmpty\": \"SM2 signature returned empty result\",\n \"crypto_sm2KeyPairGenerateFailed\": \"SM2 key pair generation failed: {error}\",\n \"crypto_sm2EncryptFailed\": \"SM2 encryption failed: {error}\",\n \"crypto_sm2DecryptFailedWithError\": \"SM2 decryption failed: {error}\",\n \"crypto_sm2SignFailed\": \"SM2 signing failed: {error}\",\n \"crypto_sm2VerifyFailed\": \"SM2 verification failed: {error}\",\n \"crypto_sm3HashEmpty\": \"SM3 hash returned empty result\",\n \"crypto_sm3HashFailed\": \"SM3 hash calculation failed: {error}\",\n \"crypto_sm3HmacFailed\": \"HMAC-SM3 calculation failed: {error}\",\n \"crypto_sm3VerifyFailed\": \"SM3 hash verification failed: {error}\",\n \"crypto_sm4KeyInvalid\": \"SM4 key must be 16 bytes (32 hex characters)\",\n \"crypto_sm4CbcNeedIv\": \"CBC mode requires IV\",\n \"crypto_sm4IvInvalid\": \"SM4 IV must be 16 bytes (32 hex characters)\",\n \"crypto_sm4EncryptEmpty\": \"SM4 encryption returned empty result\",\n \"crypto_sm4DecryptFailed\": \"SM4 decryption failed\",\n \"crypto_sm4EncryptFailed\": \"SM4 encryption failed: {error}\",\n \"crypto_sm4DecryptFailedWithError\": \"SM4 decryption failed: {error}\",\n \"crypto_passwordEmpty\": \"Password cannot be empty\",\n \"crypto_passwordHashEmpty\": \"Password and hash cannot be empty\",\n \"crypto_passwordHashFailed\": \"Password hashing failed\",\n \"crypto_hashFormatInvalid\": \"Invalid hash format\",\n \"crypto_passwordVerifyFailed\": \"Password verification failed\"\n}\n","{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n \"crypto_notInitialized\": \"加密模块尚未初始化,请先调用 crypto.init()\",\n \"crypto_initFailed\": \"加密模块初始化失败:{error}\",\n \"crypto_sm2PublicKeyInvalid\": \"无效的 SM2 公钥格式\",\n \"crypto_sm2PrivateKeyInvalid\": \"无效的 SM2 私钥格式\",\n \"crypto_sm2EncryptEmpty\": \"SM2 加密返回空结果\",\n \"crypto_sm2DecryptFailed\": \"SM2 解密失败或返回无效结果\",\n \"crypto_sm2SignEmpty\": \"SM2 签名返回空结果\",\n \"crypto_sm2KeyPairGenerateFailed\": \"SM2 密钥对生成失败: {error}\",\n \"crypto_sm2EncryptFailed\": \"SM2 加密失败: {error}\",\n \"crypto_sm2DecryptFailedWithError\": \"SM2 解密失败: {error}\",\n \"crypto_sm2SignFailed\": \"SM2 签名失败: {error}\",\n \"crypto_sm2VerifyFailed\": \"SM2 验签失败: {error}\",\n \"crypto_sm3HashEmpty\": \"SM3 哈希返回空结果\",\n \"crypto_sm3HashFailed\": \"SM3 哈希计算失败: {error}\",\n \"crypto_sm3HmacFailed\": \"HMAC-SM3 计算失败: {error}\",\n \"crypto_sm3VerifyFailed\": \"SM3 哈希验证失败: {error}\",\n \"crypto_sm4KeyInvalid\": \"SM4 密钥必须为 16 字节(32 个十六进制字符)\",\n \"crypto_sm4CbcNeedIv\": \"CBC 模式必须提供 IV\",\n \"crypto_sm4IvInvalid\": \"SM4 IV 必须为 16 字节(32 个十六进制字符)\",\n \"crypto_sm4EncryptEmpty\": \"SM4 加密返回空结果\",\n \"crypto_sm4DecryptFailed\": \"SM4 解密失败\",\n \"crypto_sm4EncryptFailed\": \"SM4 加密失败: {error}\",\n \"crypto_sm4DecryptFailedWithError\": \"SM4 解密失败: {error}\",\n \"crypto_passwordEmpty\": \"密码不能为空\",\n \"crypto_passwordHashEmpty\": \"密码和哈希值不能为空\",\n \"crypto_passwordHashFailed\": \"密码哈希失败\",\n \"crypto_hashFormatInvalid\": \"无效的哈希格式\",\n \"crypto_passwordVerifyFailed\": \"密码验证失败\"\n}\n","/**\n * @h-ai/crypto — i18n\n *\n * 本文件提供加密模块的 i18n 文案访问入口。\n * @module crypto-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\n/** 加密模块 i18n 消息键类型(自动从 zh-CN 消息文件推断) */\ntype CryptoMessageKey = keyof typeof messagesZhCN\n\n/**\n * 加密模块 i18n 消息获取器\n *\n * 根据当前全局 locale 返回对应语言的消息文本,支持参数插值。\n *\n * @example\n * ```ts\n * cryptoM('crypto_sm2PublicKeyInvalid')\n * cryptoM('crypto_initFailed', { params: { error: 'bad config' } })\n * ```\n */\nexport const cryptoM = core.i18n.createMessageGetter<CryptoMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n})\n","/**\n * @h-ai/crypto — 公共类型\n *\n * 定义加密模块的对外接口类型。\n * @module crypto-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type {\n TRANSPORT_PROTOCOL as TRANSPORT_PROTOCOL_T,\n TransportClient,\n TransportEncryptionManager,\n} from './transport/crypto-transport-types.js'\nimport { core } from '@h-ai/core'\n\nconst CryptoErrorInfo = {\n INVALID_INPUT: '002:400',\n INVALID_KEY: '003:400',\n NOT_INITIALIZED: '010:500',\n INIT_FAILED: '011:500',\n KEY_GENERATION_FAILED: '020:500',\n ENCRYPTION_FAILED: '021:500',\n DECRYPTION_FAILED: '022:500',\n SIGN_FAILED: '023:500',\n VERIFY_FAILED: '024:500',\n HASH_FAILED: '040:500',\n HMAC_FAILED: '041:500',\n INVALID_IV: '060:400',\n} as const satisfies ErrorInfo\n\nexport const HaiCryptoError = core.error.buildHaiErrorsDef('crypto', CryptoErrorInfo)\n\n// ─── 非对称加密类型 ───\n\n/** 密文模式:0=C1C2C3(旧版),1=C1C3C2(国标) */\nexport type CipherMode = 0 | 1\n\n/** 非对称密钥对 */\nexport interface KeyPair {\n /** 公钥(十六进制字符串,包含 04 前缀为非压缩格式) */\n publicKey: string\n /** 私钥(十六进制字符串,64 字符) */\n privateKey: string\n}\n\n/** 非对称加密选项 */\nexport interface AsymmetricEncryptOptions {\n /** 密文模式:0=C1C2C3(旧版),1=C1C3C2(国标,默认) */\n cipherMode?: CipherMode\n /** 输出格式 */\n outputFormat?: 'hex' | 'base64'\n}\n\n/** 签名选项 */\nexport interface SignOptions {\n /** 是否对数据进行哈希(默认 true) */\n hash?: boolean\n /** 用户 ID(默认 \"1234567812345678\") */\n userId?: string\n}\n\n// ─── 哈希类型 ───\n\n/** 哈希选项 */\nexport interface HashOptions {\n /** 输入编码 */\n inputEncoding?: 'utf8' | 'hex'\n}\n\n// ─── 对称加密类型 ───\n\n/** 对称加密模式 */\nexport type SymmetricMode = 'ecb' | 'cbc'\n\n/** 对称加密选项 */\nexport interface SymmetricOptions {\n /** 加密模式 */\n mode?: SymmetricMode\n /** IV 向量(CBC 模式必需,32 个十六进制字符) */\n iv?: string\n /** 输入编码 */\n inputEncoding?: 'utf8' | 'hex'\n /** 输出格式 */\n outputFormat?: 'hex' | 'base64'\n}\n\n/** 带 IV 加密结果 */\nexport interface EncryptWithIVResult {\n /** 密文 */\n ciphertext: string\n /** IV 向量 */\n iv: string\n}\n\n// ─── 密码类型 ───\n\n/** 密码哈希配置 */\nexport interface PasswordConfig {\n /** 盐值长度(默认 16) */\n saltLength?: number\n /** 迭代次数(默认 10000) */\n iterations?: number\n}\n\n// ─── 操作接口 ───\n\n/**\n * 非对称加密操作接口\n *\n * 通过 `crypto.asymmetric` 访问,需先调用 `crypto.init()`。\n */\nexport interface AsymmetricOperations {\n /**\n * 生成密钥对\n *\n * @returns 成功时包含公私钥对;失败时返回 KEY_GENERATION_FAILED\n */\n generateKeyPair: () => HaiResult<KeyPair>\n /**\n * 非对称加密\n *\n * @param data - 待加密明文\n * @param publicKey - 公钥(十六进制,支持带/不带 04 前缀)\n * @param options - 加密选项(密文模式、输出格式)\n * @returns 成功时返回密文字符串;失败时返回 INVALID_KEY 或 ENCRYPTION_FAILED\n */\n encrypt: (data: string, publicKey: string, options?: AsymmetricEncryptOptions) => HaiResult<string>\n /**\n * 非对称解密\n *\n * 自动检测 base64 格式输入并转换为 hex。\n *\n * @param ciphertext - 密文(hex 或 base64)\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 解密选项(密文模式需与加密时一致)\n * @returns 成功时返回明文;失败时返回 INVALID_KEY 或 DECRYPTION_FAILED\n */\n decrypt: (ciphertext: string, privateKey: string, options?: AsymmetricEncryptOptions) => HaiResult<string>\n /**\n * 签名\n *\n * @param data - 待签名数据\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 签名选项(hash 开关、userId)\n * @returns 成功时返回签名字符串;失败时返回 INVALID_KEY 或 SIGN_FAILED\n */\n sign: (data: string, privateKey: string, options?: SignOptions) => HaiResult<string>\n /**\n * 验签\n *\n * @param data - 原始数据\n * @param signature - 签名(需与签名时使用相同的 hash/userId 选项)\n * @param publicKey - 公钥(支持带/不带 04 前缀)\n * @param options - 验签选项\n * @returns 成功时返回 boolean;失败时返回 INVALID_KEY 或 VERIFY_FAILED\n */\n verify: (data: string, signature: string, publicKey: string, options?: SignOptions) => HaiResult<boolean>\n /**\n * 校验公钥格式是否合法\n *\n * 合法格式:128 字符十六进制(无前缀)或 130 字符(含 04 前缀)。\n */\n isValidPublicKey: (key: string) => boolean\n /**\n * 校验私钥格式是否合法\n *\n * 合法格式:64 字符十六进制。\n */\n isValidPrivateKey: (key: string) => boolean\n}\n\n/**\n * 哈希操作接口\n *\n * 通过 `crypto.hash` 访问,需先调用 `crypto.init()`。\n */\nexport interface HashOperations {\n /**\n * 计算哈希\n *\n * @param data - 待哈希数据(字符串或 Uint8Array)\n * @param options - 输入编码选项\n * @returns 成功时返回 64 字符十六进制哈希值;失败时返回 HASH_FAILED\n */\n hash: (data: string | Uint8Array, options?: HashOptions) => HaiResult<string>\n /**\n * 计算 HMAC\n *\n * 使用 HMAC 算法(RFC 2104)计算消息认证码。\n * 当密钥长度超过块大小(64 字节)时,会先对密钥进行哈希。\n *\n * @param data - 待计算数据\n * @param key - HMAC 密钥\n * @returns 成功时返回 64 字符十六进制 HMAC 值;失败时返回 HMAC_FAILED\n */\n hmac: (data: string, key: string) => HaiResult<string>\n /**\n * 验证数据的哈希是否匹配\n *\n * 比较时忽略大小写。\n *\n * @param data - 原始数据\n * @param expectedHash - 期望的哈希值\n * @returns 成功时返回 boolean;失败时返回 HASH_FAILED\n */\n verify: (data: string, expectedHash: string) => HaiResult<boolean>\n}\n\n/**\n * 对称加密操作接口\n *\n * 通过 `crypto.symmetric` 访问,需先调用 `crypto.init()`。\n * 支持 ECB/CBC 两种模式,CBC 模式需要提供 IV。\n */\nexport interface SymmetricOperations {\n /** 生成随机密钥(16 字节 = 32 个十六进制字符) */\n generateKey: () => string\n /** 生成随机 IV(16 字节 = 32 个十六进制字符) */\n generateIV: () => string\n /**\n * 对称加密\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @param options - 加密模式/IV/输出格式\n * @returns 成功时返回密文;失败时返回 INVALID_KEY/INVALID_IV/ENCRYPTION_FAILED\n */\n encrypt: (data: string, key: string, options?: SymmetricOptions) => HaiResult<string>\n /**\n * 对称解密\n *\n * 自动检测 base64 格式输入并转换为 hex。\n *\n * @param ciphertext - 密文(hex 或 base64)\n * @param key - 密钥(32 字符十六进制)\n * @param options - 解密模式/IV(需与加密时一致)\n * @returns 成功时返回明文;失败时返回 INVALID_KEY/INVALID_IV/DECRYPTION_FAILED\n */\n decrypt: (ciphertext: string, key: string, options?: SymmetricOptions) => HaiResult<string>\n /**\n * 带 IV 加密(CBC 模式,自动生成随机 IV)\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @returns 成功时返回 { ciphertext, iv };失败时同 encrypt\n */\n encryptWithIV: (data: string, key: string) => HaiResult<EncryptWithIVResult>\n /**\n * 带 IV 解密(CBC 模式)\n *\n * @param ciphertext - 密文\n * @param key - 密钥\n * @param iv - 加密时使用的 IV\n * @returns 成功时返回明文;失败时同 decrypt\n */\n decryptWithIV: (ciphertext: string, key: string, iv: string) => HaiResult<string>\n /**\n * 从密码和盐值派生密钥\n *\n * 内部仅执行单次哈希(password + salt) 取前 32 字符作为密钥。\n *\n * ⚠️ 安全警告:**此实现不是标准 KDF**,不具备密码爆破抗性。\n * - 禁止用于密码存储(请用 `crypto.password.hash`)。\n * - 禁止用于高价值密钥派生(请在应用层采用 PBKDF2 / scrypt / Argon2)。\n *\n * @deprecated 未来版本可能移除。详见模块 README 安全声明。\n * @param password - 密码\n * @param salt - 盐值\n * @returns 32 字符十六进制密钥\n */\n deriveKey: (password: string, salt: string) => string\n /** 校验密钥格式是否合法(32 字符十六进制) */\n isValidKey: (key: string) => boolean\n /** 校验 IV 格式是否合法(32 字符十六进制) */\n isValidIV: (iv: string) => boolean\n}\n\n/**\n * 密码哈希操作接口\n *\n * 通过 `crypto.password` 访问,需先调用 `crypto.init()`。\n * 使用迭代加盐的方式生成密码哈希。\n */\nexport interface PasswordOperations {\n /**\n * 对密码进行哈希\n *\n * 输出格式: `$hai$<iterations>$<salt>$<hash>`\n *\n * @param password - 明文密码(不能为空)\n * @param config - 可选配置(盐值长度、迭代次数)\n * @returns 成功时返回格式化的哈希字符串;失败时返回 INVALID_INPUT 或 HASH_FAILED\n */\n hash: (password: string, config?: PasswordConfig) => HaiResult<string>\n /**\n * 验证密码是否匹配\n *\n * 自动从哈希字符串中解析迭代次数和盐值进行重新计算。\n *\n * @param password - 待验证的明文密码\n * @param hash - 存储的哈希值(格式: `$hai$<iterations>$<salt>$<hash>`)\n * @returns 成功时返回 boolean;失败时返回 INVALID_INPUT 或 VERIFY_FAILED\n */\n verify: (password: string, hash: string) => HaiResult<boolean>\n}\n\n// ─── 传输加密 ───\n\n/**\n * 传输加密操作接口(端到端混合加密)。\n *\n * 通过 `crypto.transport` 访问,需先调用 `crypto.init()`。\n *\n * @remarks\n * 使用流程(直接使用底层 transport 工厂时):\n *\n * 1. 先 `await crypto.init()`,确保 `crypto.asymmetric` / `crypto.symmetric` 已就绪。\n * 2. 服务端调用 `crypto.transport.createServer()` 创建 `TransportEncryptionManager`;该管理器负责持有服务端密钥对,并管理客户端公钥。\n * 3. 服务端暴露一个 POST 密钥协商端点:接收 `{ clientPublicKey }`,调用 `manager.registerClientKey()` 注册客户端公钥,再返回 `{ serverPublicKey: manager.getServerPublicKey(), clientId }`。\n * 4. 客户端调用 `crypto.transport.createClient({ keyExchangeUrl })` 创建会话;首次 `client.init()` 或 `client.encryptedFetch()` 会自动完成密钥协商。\n * 5. 协商完成后,客户端每次请求都会附带 `X-Client-Id`;若请求有 body,则 body 会被包装成 `{ encryptedKey, ciphertext, iv }`,并设置 `X-Encrypted: true`。\n * 6. 服务端在业务逻辑前调用 `manager.decryptRequest()` 解密请求体,在返回前调用 `manager.encryptResponse(clientId, data)` 为当前客户端重新加密响应。\n * 7. 客户端收到 `X-Encrypted: true` 的响应后会自动解密;调用 `client.destroy()` 可清空当前会话,下次请求会重新协商。\n *\n * 常规应用优先使用上层封装,而不是手写 HTTP 协商细节:\n * - `serv.createApp({ transport: { crypto } })`\n * - `kit.createHandle({ crypto: { crypto, transport: true } })`\n * - `apiClient.init({ transport: { crypto } })`\n *\n * @example 服务端\n * ```ts\n * const result = crypto.transport.createServer()\n * if (!result.success) throw result.error\n * const manager = result.data\n * ```\n *\n * @example 客户端\n * ```ts\n * const client = crypto.transport.createClient({\n * keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange',\n * })\n * const resp = await client.encryptedFetch('https://api.example.com/api/v1/echo', {\n * method: 'POST', body: JSON.stringify({ hello: 'world' }),\n * })\n * ```\n */\nexport interface TransportOperations {\n /**\n * 创建服务端传输加密管理器。\n *\n * options.maxClients:默认内存 keyStore 的最大客户端数(默认 10000)。\n * 成功返回 manager;密钥生成失败返回 `HaiCommonError.INTERNAL_ERROR`。\n *\n * @remarks\n * 通常在服务启动阶段创建一次,并交给 HTTP 中间件 / 路由处理器复用。\n */\n createServer: (options?: { maxClients?: number }) => HaiResult<TransportEncryptionManager>\n /**\n * 创建客户端传输加密会话。\n *\n * options.keyExchangeUrl:密钥协商端点完整 URL。\n * options.fetch:实际发送 HTTP 请求的 fetch(默认 `globalThis.fetch`)。\n *\n * @remarks\n * 返回的是“单会话”客户端:同一个实例会复用已协商得到的 `clientId` 与服务端公钥;\n * 调用 `destroy()` 后会回到未协商状态。\n */\n createClient: (options: { keyExchangeUrl: string, fetch?: typeof fetch }) => TransportClient\n /** 协议常量(headers、密钥协商默认路径)。 */\n readonly protocol: typeof TRANSPORT_PROTOCOL_T\n}\n\n// ─── 函数接口 ───\n\n/**\n * 加密模块函数接口\n *\n * `crypto` 服务对象的类型定义。使用前必须调用 `init()` 初始化。\n *\n * @example\n * ```ts\n * import { crypto } from '@h-ai/crypto'\n *\n * await crypto.init()\n * const hash = crypto.hash.hash('hello')\n * await crypto.close()\n * ```\n */\nexport interface CryptoFunctions {\n /**\n * 初始化加密模块\n *\n * 创建非对称/哈希/对称/密码哈希操作实例。\n * 重复调用会先关闭再重新初始化。\n *\n * @returns 成功时返回 ok(undefined);失败时返回 INIT_FAILED\n */\n init: () => Promise<HaiResult<void>>\n /**\n * 关闭加密模块,释放内部状态\n *\n * 关闭后再访问 asymmetric/hash/symmetric/password 会返回 NOT_INITIALIZED 错误。\n */\n close: () => Promise<void>\n /** 是否已初始化 */\n readonly isInitialized: boolean\n /** 非对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly asymmetric: AsymmetricOperations\n /** 哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly hash: HashOperations\n /** 对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly symmetric: SymmetricOperations\n /** 密码哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly password: PasswordOperations\n /** 传输加密操作(端到端混合加密;createServer 在未初始化时返回 NOT_INITIALIZED) */\n readonly transport: TransportOperations\n}\n","/**\n * @h-ai/crypto — 密码操作\n *\n * 提供迭代加盐(SM3)密码哈希与校验功能。\n * @module crypto-password\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\nimport type { HashOperations, PasswordConfig, PasswordOperations } from './crypto-types.js'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport { HaiCryptoError } from './crypto-types.js'\n\n// ─── 常量 ───\n\n/** 迭代次数最小值(防止退化为 0 迭代导致明文等价泄漏) */\nconst MIN_ITERATIONS = 1\n/** 迭代次数最大值(防止伪造哈希触发 CPU 饱和) */\nconst MAX_ITERATIONS = 1_000_000\n/** 盐值长度范围,限制异常输入 */\nconst MIN_SALT_LENGTH = 8\nconst MAX_SALT_LENGTH = 128\n\n// ─── 依赖接口 ───\n\n/** createPasswordFunctions 所需的外部依赖 */\ninterface PasswordDeps {\n /** 哈希操作实例,用于迭代哈希计算 */\n hash: HashOperations\n}\n\n// ─── 工具函数 ───\n\n/**\n * 生成加密安全的随机盐值\n *\n * 使用 Web Crypto API(crypto.getRandomValues)从大小写字母和数字中随机选取字符。\n *\n * @param length - 盐值长度(字符数)\n * @returns 随机盐值字符串\n */\nfunction generateSalt(length: number): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n const randomBytes = new Uint8Array(length)\n globalThis.crypto.getRandomValues(randomBytes)\n let salt = ''\n for (let i = 0; i < length; i++) {\n salt += chars.charAt(randomBytes[i] % chars.length)\n }\n return salt\n}\n\n/**\n * 对数据进行多次迭代哈希(密钥拉伸)\n *\n * 首次输入为 salt + data,后续每次用前一轮的哈希结果作为输入。\n * 任一轮哈希计算失败则立即返回错误。\n *\n * @param hash - 哈希操作实例\n * @param data - 原始数据(通常为密码)\n * @param salt - 盐值\n * @param iterations - 迭代次数\n * @returns 成功时返回最终哈希值(64 字符十六进制)\n */\nfunction iterateHash(\n hash: HashOperations,\n data: string,\n salt: string,\n iterations: number,\n): HaiResult<string> {\n let current = salt + data\n for (let i = 0; i < iterations; i++) {\n const result = hash.hash(current)\n if (!result.success) {\n return result\n }\n current = result.data\n }\n return ok(current)\n}\n\n// ─── 密码操作工厂 ───\n\n/**\n * 创建密码哈希操作实例\n *\n * 内部使用迭代加盐的方式生成密码哈希,格式为 `$hai$<iterations>$<salt>$<hash>`。\n *\n * @param deps - 依赖(需要注入哈希操作实例)\n * @returns PasswordOperations 接口实现\n */\nexport function createPasswordFunctions(deps: PasswordDeps): PasswordOperations {\n const { hash: hashOps } = deps\n\n return {\n /**\n * 对密码进行迭代加盐哈希\n *\n * 输出格式: `$hai$<iterations>$<salt>$<hash>`\n *\n * @param password - 明文密码(不能为空)\n * @param config - 可选配置(盐值长度、迭代次数)\n * @returns 成功时返回格式化的哈希字符串;失败时返回 INVALID_INPUT 或 HASH_FAILED\n */\n hash(password: string, config: PasswordConfig = {}): HaiResult<string> {\n const { saltLength = 16, iterations = 10000 } = config\n\n try {\n if (!password) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_passwordEmpty'),\n )\n }\n\n if (!Number.isInteger(iterations) || iterations < MIN_ITERATIONS || iterations > MAX_ITERATIONS) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n if (!Number.isInteger(saltLength) || saltLength < MIN_SALT_LENGTH || saltLength > MAX_SALT_LENGTH) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n\n const salt = generateSalt(saltLength)\n const hashResult = iterateHash(hashOps, password, salt, iterations)\n if (!hashResult.success) {\n return hashResult\n }\n\n const formatted = `$hai$${iterations}$${salt}$${hashResult.data}`\n return ok(formatted)\n }\n catch (error) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_passwordHashFailed'),\n error,\n )\n }\n },\n\n /**\n * 验证密码是否匹配已存储的哈希\n *\n * 从哈希字符串中解析迭代次数和盐值,重新计算后比较。\n * 格式要求: `$hai$<iterations>$<salt>$<hash>`\n *\n * @param password - 待验证的明文密码\n * @param hash - 存储的哈希值\n * @returns 成功时返回 boolean;失败时返回 INVALID_INPUT 或 VERIFY_FAILED\n */\n verify(password: string, hash: string): HaiResult<boolean> {\n try {\n if (!password || !hash) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_passwordHashEmpty'),\n )\n }\n\n const parts = hash.split('$')\n if (parts.length !== 5 || parts[1] !== 'hai') {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n\n const storedIterations = Number.parseInt(parts[2], 10)\n const salt = parts[3]\n const storedHash = parts[4]\n\n if (\n Number.isNaN(storedIterations)\n || storedIterations < MIN_ITERATIONS\n || storedIterations > MAX_ITERATIONS\n || !salt\n || !storedHash\n ) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n\n const hashResult = iterateHash(hashOps, password, salt, storedIterations)\n if (!hashResult.success) {\n return hashResult\n }\n\n return ok(core.string.constantTimeEqual(hashResult.data, storedHash))\n }\n catch (error) {\n return err(\n HaiCryptoError.VERIFY_FAILED,\n cryptoM('crypto_passwordVerifyFailed'),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/crypto — 内部工具函数\n *\n * 提供 SM2/SM4 共用的编码转换辅助函数。 仅供模块内部使用,不对外导出。\n * @module crypto-utils\n */\n\n/**\n * 判断字符串是否为 Base64 格式\n *\n * 使用简单启发式:包含 +、/ 或以 = 结尾视为 base64。\n *\n * @param str - 待检测字符串\n */\nexport function isBase64(str: string): boolean {\n return str.includes('+') || str.includes('/') || str.endsWith('=')\n}\n\n/**\n * Hex 字符串转 Base64 编码\n *\n * 使用 Web 标准 API btoa,前后端通用(Node 16+ / 所有现代浏览器)。\n *\n * @param hex - 十六进制字符串(长度必须为偶数)\n * @returns Base64 编码字符串\n */\nexport function hexToBase64(hex: string): string {\n const bytes = new Uint8Array(hex.length / 2)\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16)\n }\n return btoa(String.fromCharCode(...bytes))\n}\n\n/**\n * Base64 编码转 Hex 字符串\n *\n * 使用 Web 标准 API atob,前后端通用(Node 16+ / 所有现代浏览器)。\n *\n * @param base64 - Base64 编码字符串\n * @returns 小写十六进制字符串\n */\nexport function base64ToHex(base64: string): string {\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n","/**\n * @h-ai/crypto — SM2 非对称加密\n *\n * 提供 SM2 密钥对生成、加解密、签名与验签操作。\n * @module crypto-sm2\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { AsymmetricEncryptOptions, AsymmetricOperations, KeyPair, SignOptions } from './crypto-types.js'\n\nimport { err, ok } from '@h-ai/core'\n// @ts-expect-error sm-crypto 无类型定义\nimport smCrypto from 'sm-crypto'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport {\n\n HaiCryptoError,\n\n} from './crypto-types.js'\nimport { base64ToHex, hexToBase64, isBase64 } from './crypto-utils.js'\n\nconst { sm2 } = smCrypto\nconst SM2_PUBLIC_KEY_REGEX = /^[0-9a-f]{128}$/i\nconst SM2_PRIVATE_KEY_REGEX = /^[0-9a-f]{64}$/i\n\n// ─── SM2 算法实现 ───\n\n/**\n * 创建 SM2 算法操作实例\n *\n * 基于 sm-crypto 库实现 SM2 非对称加密、签名与验签。\n * 公钥支持带/不带 04 前缀两种格式(内部统一补齐)。\n * 密文支持 hex/base64 两种格式(解密时自动检测)。\n *\n * @returns AsymmetricOperations 接口实现\n */\nexport function createSM2(): AsymmetricOperations {\n return {\n /**\n * 生成 SM2 密钥对\n *\n * @returns 成功时返回包含公钥(130 字符含 04 前缀)和私钥(64 字符)的密钥对\n */\n generateKeyPair(): HaiResult<KeyPair> {\n try {\n const keyPair = sm2.generateKeyPairHex()\n return ok({\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n })\n }\n catch (error) {\n return err(\n HaiCryptoError.KEY_GENERATION_FAILED,\n cryptoM('crypto_sm2KeyPairGenerateFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 非对称加密\n *\n * 公钥自动补齐 04 前缀;支持 hex/base64 输出。\n *\n * @param data - 待加密明文\n * @param publicKey - 公钥(支持带/不带 04 前缀)\n * @param options - 加密选项(密文模式、输出格式)\n * @returns 成功时返回密文;失败时返回 INVALID_KEY 或 ENCRYPTION_FAILED\n */\n encrypt(\n data: string,\n publicKey: string,\n options: AsymmetricEncryptOptions = {},\n ): HaiResult<string> {\n const { cipherMode = 1, outputFormat = 'hex' } = options\n\n if (!this.isValidPublicKey(publicKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PublicKeyInvalid'),\n )\n }\n\n try {\n // 确保公钥带 04 前缀\n const key = publicKey.startsWith('04') ? publicKey : `04${publicKey}`\n const encrypted = sm2.doEncrypt(data, key, cipherMode)\n\n if (!encrypted) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm2EncryptEmpty'),\n )\n }\n\n if (outputFormat === 'base64') {\n return ok(hexToBase64(encrypted))\n }\n\n return ok(encrypted)\n }\n catch (error) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm2EncryptFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 非对称解密\n *\n * 自动检测 base64 格式输入并转换为 hex 后解密。\n *\n * @param ciphertext - 密文(hex 或 base64)\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 解密选项(密文模式需与加密时一致)\n * @returns 成功时返回明文;失败时返回 INVALID_KEY 或 DECRYPTION_FAILED\n */\n decrypt(\n ciphertext: string,\n privateKey: string,\n options: AsymmetricEncryptOptions = {},\n ): HaiResult<string> {\n const { cipherMode = 1 } = options\n\n if (!this.isValidPrivateKey(privateKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PrivateKeyInvalid'),\n )\n }\n\n try {\n // 自动检测并转换 base64 格式\n let input = ciphertext\n if (isBase64(ciphertext)) {\n input = base64ToHex(ciphertext)\n }\n\n const decrypted = sm2.doDecrypt(input, privateKey, cipherMode)\n\n if (decrypted === false || decrypted === null || decrypted === undefined) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm2DecryptFailed'),\n )\n }\n\n return ok(decrypted)\n }\n catch (error) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm2DecryptFailedWithError', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 数字签名\n *\n * 默认对数据先做哈希(hash=true),使用 userId 作为签名附加参数。\n *\n * @param data - 待签名数据\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 签名选项(hash 开关、userId)\n * @returns 成功时返回签名字符串;失败时返回 INVALID_KEY 或 SIGN_FAILED\n */\n sign(\n data: string,\n privateKey: string,\n options: SignOptions = {},\n ): HaiResult<string> {\n const { hash = true, userId = '1234567812345678' } = options\n\n if (!this.isValidPrivateKey(privateKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PrivateKeyInvalid'),\n )\n }\n\n try {\n const signature = sm2.doSignature(data, privateKey, { hash, userId })\n\n if (!signature) {\n return err(\n HaiCryptoError.SIGN_FAILED,\n cryptoM('crypto_sm2SignEmpty'),\n )\n }\n\n return ok(signature)\n }\n catch (error) {\n return err(\n HaiCryptoError.SIGN_FAILED,\n cryptoM('crypto_sm2SignFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 签名验证\n *\n * 公钥自动补齐 04 前缀;hash/userId 需与签名时一致。\n *\n * @param data - 原始数据\n * @param signature - 签名值\n * @param publicKey - 公钥(支持带/不带 04 前缀)\n * @param options - 验签选项(hash 开关、userId)\n * @returns 成功时返回 boolean;失败时返回 INVALID_KEY 或 VERIFY_FAILED\n */\n verify(\n data: string,\n signature: string,\n publicKey: string,\n options: SignOptions = {},\n ): HaiResult<boolean> {\n const { hash = true, userId = '1234567812345678' } = options\n\n if (!this.isValidPublicKey(publicKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PublicKeyInvalid'),\n )\n }\n\n try {\n // 确保公钥带 04 前缀\n const key = publicKey.startsWith('04') ? publicKey : `04${publicKey}`\n const isValid = sm2.doVerifySignature(data, signature, key, { hash, userId })\n return ok(!!isValid)\n }\n catch (error) {\n return err(\n HaiCryptoError.VERIFY_FAILED,\n cryptoM('crypto_sm2VerifyFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 校验公钥格式是否合法\n *\n * 合法格式:128 字符十六进制(无前缀)或 130 字符(含 04 前缀)。\n *\n * @param key - 待校验公钥\n * @returns 格式合法返回 true\n */\n isValidPublicKey(key: string): boolean {\n if (!key || typeof key !== 'string')\n return false\n // 公钥长度:无前缀 128 字符,带 04 前缀 130 字符\n const cleanKey = key.startsWith('04') ? key.slice(2) : key\n return SM2_PUBLIC_KEY_REGEX.test(cleanKey)\n },\n\n /**\n * 校验私钥格式是否合法\n *\n * 合法格式:64 字符十六进制。\n *\n * @param key - 待校验私钥\n * @returns 格式合法返回 true\n */\n isValidPrivateKey(key: string): boolean {\n if (!key || typeof key !== 'string')\n return false\n // 私钥长度:64 字符\n return SM2_PRIVATE_KEY_REGEX.test(key)\n },\n }\n}\n","/**\n * @h-ai/crypto — SM3 哈希\n *\n * 提供 SM3 消息摘要与 HMAC 操作。\n * @module crypto-sm3\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\nimport type { HashOperations, HashOptions } from './crypto-types.js'\nimport { core, err, ok } from '@h-ai/core'\n// @ts-expect-error sm-crypto 无类型定义\nimport smCrypto from 'sm-crypto'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport {\n HaiCryptoError,\n\n} from './crypto-types.js'\n\nconst { sm3 } = smCrypto\n\n// ─── SM3 算法实现 ───\n\n/**\n * 创建 SM3 算法操作实例\n *\n * 基于 sm-crypto 库实现 SM3 哈希、HMAC 与哈希验证。\n * 支持字符串(UTF-8/Hex)和 Uint8Array 输入。\n * HMAC 实现遵循 RFC 2104 标准。\n *\n * @returns HashOperations 接口实现\n */\nexport function createSM3(): HashOperations {\n return {\n /**\n * 计算 SM3 哈希\n *\n * 支持字符串(UTF-8/Hex)和 Uint8Array 输入。\n *\n * @param data - 待哈希数据\n * @param options - 输入编码与输出格式\n * @returns 成功时返回 64 字符十六进制哈希值;失败时返回 HASH_FAILED\n */\n hash(\n data: string | Uint8Array,\n options: HashOptions = {},\n ): HaiResult<string> {\n const { inputEncoding = 'utf8' } = options\n\n try {\n let input: string | number[]\n\n if (data instanceof Uint8Array) {\n // Uint8Array 转为数字数组(sm-crypto 支持的格式)\n input = Array.from(data)\n }\n else if (inputEncoding === 'hex') {\n // 十六进制字符串转为数字数组\n input = hexToBytes(data)\n }\n else {\n // UTF-8 字符串直接传入\n input = data\n }\n\n const result = sm3(input)\n\n if (!result) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_sm3HashEmpty'),\n )\n }\n\n return ok(result)\n }\n catch (error) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_sm3HashFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 计算 HMAC-SM3 消息认证码\n *\n * 实现遵循 RFC 2104;密钥超过块大小(64 字节)时先对密钥做哈希。\n *\n * @param data - 待计算数据\n * @param key - HMAC 密钥\n * @returns 成功时返回 64 字符十六进制 HMAC 值;失败时返回 HMAC_FAILED\n */\n hmac(data: string, key: string): HaiResult<string> {\n try {\n const blockSize = 64\n const opad = 0x5C\n const ipad = 0x36\n\n // 处理密钥\n let keyBytes: number[]\n if (key.length > blockSize) {\n const hashedKey = sm3(key)\n keyBytes = hexToBytes(hashedKey)\n }\n else {\n keyBytes = stringToBytes(key)\n }\n\n // 填充密钥到块大小\n while (keyBytes.length < blockSize) {\n keyBytes.push(0)\n }\n\n // 计算 iKeyPad 和 oKeyPad\n const iKeyPad = keyBytes.map(b => b ^ ipad)\n const oKeyPad = keyBytes.map(b => b ^ opad)\n\n // 计算内层哈希:H(iKeyPad || data)\n const innerInput = iKeyPad.concat(stringToBytes(data))\n const innerHash = sm3(innerInput)\n\n // 计算外层哈希:H(oKeyPad || innerHash)\n const outerInput = oKeyPad.concat(hexToBytes(innerHash))\n const result = sm3(outerInput)\n\n return ok(result)\n }\n catch (error) {\n return err(\n HaiCryptoError.HMAC_FAILED,\n cryptoM('crypto_sm3HmacFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 验证数据的哈希是否匹配\n *\n * 对数据做 SM3 哈希后与期望值比较(忽略大小写)。\n *\n * @param data - 原始数据\n * @param expectedHash - 期望的哈希值\n * @returns 成功时返回 boolean;失败时返回 HASH_FAILED\n */\n verify(data: string, expectedHash: string): HaiResult<boolean> {\n try {\n const hashResult = sm3(data)\n return ok(core.string.constantTimeEqual(hashResult.toLowerCase(), expectedHash.toLowerCase()))\n }\n catch (error) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_sm3VerifyFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n }\n}\n\n// ─── 辅助函数 ───\n\n/**\n * 十六进制字符串转字节数组\n *\n * @param hex - 十六进制字符串(长度必须为偶数)\n * @returns 字节数组\n */\nfunction hexToBytes(hex: string): number[] {\n const bytes: number[] = []\n for (let i = 0; i < hex.length; i += 2) {\n bytes.push(Number.parseInt(hex.slice(i, i + 2), 16))\n }\n return bytes\n}\n\n/**\n * UTF-8 字符串转字节数组\n *\n * 使用 TextEncoder 进行编码转换。\n *\n * @param str - UTF-8 字符串\n * @returns 字节数组\n */\nfunction stringToBytes(str: string): number[] {\n const encoder = new TextEncoder()\n return Array.from(encoder.encode(str))\n}\n","/**\n * @h-ai/crypto — SM4 对称加密\n *\n * 提供 SM4 对称加解密操作(CBC/ECB 模式)。\n * @module crypto-sm4\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { EncryptWithIVResult, SymmetricOperations, SymmetricOptions } from './crypto-types.js'\n\nimport { err, ok } from '@h-ai/core'\n// @ts-expect-error sm-crypto 无类型定义\nimport smCrypto from 'sm-crypto'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport {\n\n HaiCryptoError,\n\n} from './crypto-types.js'\nimport { base64ToHex, hexToBase64, isBase64 } from './crypto-utils.js'\n\nconst { sm3, sm4 } = smCrypto\nconst SM4_HEX_32_REGEX = /^[0-9a-f]{32}$/i\n\n// ─── SM4 算法实现 ───\n\n/**\n * 创建 SM4 算法操作实例\n *\n * 基于 sm-crypto 库实现 SM4 对称加密/解密。\n * 支持 ECB(默认)和 CBC 两种模式,使用 PKCS#7 填充。\n * 密文支持 hex/base64 两种格式(解密时自动检测)。\n *\n * @returns SymmetricOperations 接口实现\n */\nexport function createSM4(): SymmetricOperations {\n return {\n /** 生成随机密钥(16 字节 = 32 个十六进制字符) */\n generateKey(): string {\n return generateRandomHex(16)\n },\n\n /** 生成随机 IV(16 字节 = 32 个十六进制字符) */\n generateIV(): string {\n return generateRandomHex(16)\n },\n\n /**\n * SM4 对称加密\n *\n * 支持 ECB(默认)和 CBC 两种模式,使用 PKCS#7 填充。\n * CBC 模式需提供合法 IV。\n *\n * ⚠️ 安全警告:**ECB 默认模式不安全**—相同明文块产生相同密文块,泄漏结构信息。\n * 生产场景请优先使用 `encryptWithIV()`(自动随机 IV 的 CBC)或显式传入\n * `{ mode: 'cbc', iv }`。ECB 模式仅保留兼容性,未来版本可能移除默认值。\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @param options - 加密模式/IV/输出格式\n * @returns 成功时返回密文;失败时返回 INVALID_KEY/INVALID_IV/ENCRYPTION_FAILED\n */\n encrypt(\n data: string,\n key: string,\n options: SymmetricOptions = {},\n ): HaiResult<string> {\n const {\n mode = 'ecb',\n iv,\n outputFormat = 'hex',\n } = options\n\n if (!this.isValidKey(key)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm4KeyInvalid'),\n )\n }\n\n if (mode === 'cbc' && !iv) {\n return err(\n HaiCryptoError.INVALID_IV,\n cryptoM('crypto_sm4CbcNeedIv'),\n )\n }\n\n if (mode === 'cbc' && iv && !this.isValidIV(iv)) {\n return err(\n HaiCryptoError.INVALID_IV,\n cryptoM('crypto_sm4IvInvalid'),\n )\n }\n\n try {\n const sm4Options: Record<string, unknown> = {\n mode,\n padding: 'pkcs#7',\n }\n\n if (mode === 'cbc' && iv) {\n sm4Options.iv = iv\n }\n\n const encrypted = sm4.encrypt(data, key, sm4Options)\n\n if (!encrypted) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm4EncryptEmpty'),\n )\n }\n\n if (outputFormat === 'base64') {\n return ok(hexToBase64(encrypted))\n }\n\n return ok(encrypted)\n }\n catch (error) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm4EncryptFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM4 对称解密\n *\n * 自动检测 base64 格式输入并转换为 hex。\n * 解密模式和 IV 需与加密时一致。\n *\n * @param ciphertext - 密文(hex 或 base64)\n * @param key - 密钥(32 字符十六进制)\n * @param options - 解密模式/IV\n * @returns 成功时返回明文;失败时返回 INVALID_KEY/INVALID_IV/DECRYPTION_FAILED\n */\n decrypt(\n ciphertext: string,\n key: string,\n options: SymmetricOptions = {},\n ): HaiResult<string> {\n const { mode = 'ecb', iv } = options\n\n if (!this.isValidKey(key)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm4KeyInvalid'),\n )\n }\n\n if (mode === 'cbc' && !iv) {\n return err(\n HaiCryptoError.INVALID_IV,\n cryptoM('crypto_sm4CbcNeedIv'),\n )\n }\n\n try {\n // 自动检测并转换 base64 格式\n let input = ciphertext\n if (isBase64(ciphertext)) {\n input = base64ToHex(ciphertext)\n }\n\n const sm4Options: Record<string, unknown> = {\n mode,\n padding: 'pkcs#7',\n }\n\n if (mode === 'cbc' && iv) {\n sm4Options.iv = iv\n }\n\n const decrypted = sm4.decrypt(input, key, sm4Options)\n\n if (decrypted === false || decrypted === null || decrypted === undefined) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm4DecryptFailed'),\n )\n }\n\n return ok(decrypted)\n }\n catch (error) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm4DecryptFailedWithError', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 带 IV 加密(CBC 模式,自动生成随机 IV)\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @returns 成功时返回 { ciphertext, iv };失败时同 encrypt\n */\n encryptWithIV(\n data: string,\n key: string,\n ): HaiResult<EncryptWithIVResult> {\n const iv = this.generateIV()\n const result = this.encrypt(data, key, { mode: 'cbc', iv })\n\n if (!result.success) {\n return result\n }\n\n return ok({ ciphertext: result.data, iv })\n },\n\n /**\n * 带 IV 解密(CBC 模式)\n *\n * @param ciphertext - 密文\n * @param key - 密钥\n * @param iv - 加密时使用的 IV\n * @returns 成功时返回明文;失败时同 decrypt\n */\n decryptWithIV(\n ciphertext: string,\n key: string,\n iv: string,\n ): HaiResult<string> {\n return this.decrypt(ciphertext, key, { mode: 'cbc', iv })\n },\n\n /**\n * 从密码和盐值派生密钥\n *\n * 内部仅执行单次 SM3 哈希(password + salt),取前 32 字符作为密钥。\n *\n * ⚠️ 安全警告:**此实现不是标准 KDF**,不具备密码爆破抗性(无迭代、无内存硬化)。\n * - **禁止用于密码存储**:密码散列请用 `crypto.password.hash()`。\n * - **禁止用于高价值密钥派生**:如需从密码派生加密密钥,请在应用层自行实现 PBKDF2 / scrypt / Argon2。\n * - 仅适用于测试、迭代兼容或不敏感的场景。\n *\n * @deprecated 未来版本可能移除。密码散列请用 `crypto.password.hash`;密钥派生请使用标准 KDF。\n * @param password - 密码\n * @param salt - 盐值\n * @returns 32 字符十六进制密钥\n */\n deriveKey(password: string, salt: string): string {\n const combined = password + salt\n const hash = sm3(combined)\n // 取前 32 个十六进制字符(16 字节)\n return hash.slice(0, 32)\n },\n\n /** 校验密钥格式是否合法(32 字符十六进制) */\n isValidKey(key: string): boolean {\n return SM4_HEX_32_REGEX.test(key)\n },\n\n /** 校验 IV 格式是否合法(32 字符十六进制) */\n isValidIV(iv: string): boolean {\n return SM4_HEX_32_REGEX.test(iv)\n },\n }\n}\n\n// ─── 辅助函数 ───\n\n/**\n * 生成加密安全的随机十六进制字符串\n *\n * 使用 Web Crypto API(crypto.getRandomValues),前后端通用。\n *\n * @param byteLength - 字节数(输出字符数为 byteLength × 2)\n * @returns 小写十六进制字符串\n */\nfunction generateRandomHex(byteLength: number): string {\n const bytes = new Uint8Array(byteLength)\n // Web Crypto API,前后端通用\n crypto.getRandomValues(bytes)\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n","/**\n * @h-ai/crypto — 传输加密类型与协议常量\n *\n * 提供 SM2 + SM4(或等效非对称 + 对称)混合传输加密所需的接口与协议常量,\n * 由 kit / serv / api-client 共享,确保两端协议完全一致。\n *\n * @module crypto-transport-types\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\n// ─── 协议常量(kit / serv / api-client 必须严格一致) ───\n\n/**\n * 传输加密协议常量。\n *\n * 所有使用端必须复用这组常量,避免「header 名拼写漂移导致两端协议错配」。\n */\nexport const TRANSPORT_PROTOCOL = {\n /** 客户端 ID 请求头名。 */\n CLIENT_ID_HEADER: 'X-Client-Id',\n /** 标识响应体已加密的响应头名。 */\n ENCRYPTED_HEADER: 'X-Encrypted',\n /** `X-Encrypted` 响应头的开启值。 */\n ENCRYPTED_HEADER_VALUE: 'true',\n /** 密钥协商端点的默认子路径(相对于挂载前缀)。 */\n DEFAULT_KEY_EXCHANGE_PATH: '/_hai/key-exchange',\n} as const\n\n/**\n * 密钥协商请求体(客户端 → 服务端)。\n */\nexport interface KeyExchangeRequest {\n readonly clientPublicKey: string\n}\n\n/**\n * 密钥协商响应体(服务端 → 客户端)。\n */\nexport interface KeyExchangeResponse {\n readonly serverPublicKey: string\n readonly clientId: string\n}\n\n// ─── 加解密载荷 ───\n\n/** 非对称密钥对。 */\nexport interface TransportKeyPair {\n publicKey: string\n privateKey: string\n}\n\n/**\n * 端到端传输的加密载荷格式。\n *\n * `encryptedKey` 用对端非对称公钥加密的对称会话密钥;`ciphertext` + `iv`\n * 为该会话密钥加密的明文。两端必须使用同一份字段命名。\n */\nexport interface EncryptedPayload {\n readonly encryptedKey: string\n readonly ciphertext: string\n readonly iv: string\n}\n\n// ─── 注入式服务接口 ───\n\n/**\n * 传输加密所需的非对称 + 对称能力子集。\n *\n * 不直接依赖 `@h-ai/crypto` 的具体实现,便于测试时注入 mock;\n * 实际使用时 `crypto` 模块的实例本身即可结构兼容。\n */\nexport interface TransportCryptoServiceLike {\n asymmetric: {\n generateKeyPair: () => HaiResult<TransportKeyPair>\n encrypt: (data: string, publicKey: string) => HaiResult<string>\n decrypt: (ciphertext: string, privateKey: string) => HaiResult<string>\n }\n symmetric: {\n generateKey: () => string\n encryptWithIV: (data: string, key: string) => HaiResult<{ ciphertext: string, iv: string }>\n decryptWithIV: (ciphertext: string, key: string, iv: string) => HaiResult<string>\n }\n}\n\n// ─── 客户端密钥存储(可插拔,支持分布式) ───\n\n/**\n * 客户端公钥存储抽象。\n *\n * 默认实现为进程内 Map({@link createInMemoryKeyStore}),多节点部署时建议\n * 接入 Redis / 数据库实现以保证跨节点一致性。\n *\n * 设计原则:方法均为异步签名,避免后续替换为分布式实现时大改接口;\n * 内存实现以 `Promise.resolve` 包裹即可。\n */\nexport interface TransportKeyStore {\n /** 注册新客户端,返回服务端生成的 `clientId`。 */\n register: (publicKey: string) => Promise<string>\n /** 查询已注册客户端公钥。 */\n get: (clientId: string) => Promise<string | undefined>\n /** 主动删除(可选,便于客户端登出时清理)。 */\n delete?: (clientId: string) => Promise<void>\n /** 释放底层资源(关闭连接、清理定时器等)。 */\n close?: () => Promise<void>\n}\n\n// ─── 管理器与客户端公开接口 ───\n\n/**\n * 服务端传输加密管理器。\n *\n * 由 {@link createTransportEncryption} 创建;负责服务端密钥对持有、客户端密钥\n * 注册与请求/响应的加解密。\n *\n * @remarks\n * 典型调用顺序:\n *\n * 1. `registerClientKey(clientPublicKey)`:在密钥协商端点中保存客户端公钥,并生成 `clientId`。\n * 2. `getServerPublicKey()`:把服务端公钥返回给客户端,供后续请求加密会话密钥。\n * 3. `decryptRequest(payload)`:普通业务请求进入业务逻辑前,先把密文请求体解成明文。\n * 4. `encryptResponse(clientId, data)`:业务处理完成后,按当前客户端公钥重新加密响应体。\n * 5. `close()`:服务关闭时释放底层 keyStore 资源。\n */\nexport interface TransportEncryptionManager {\n getServerPublicKey: () => string\n registerClientKey: (clientPublicKey: string) => Promise<string>\n getClientPublicKey: (clientId: string) => Promise<string | undefined>\n encryptResponse: (clientId: string, data: string) => Promise<HaiResult<EncryptedPayload>>\n decryptRequest: (payload: EncryptedPayload) => HaiResult<string>\n /** 关闭:释放 keyStore 资源。 */\n close: () => Promise<void>\n}\n\n/**\n * 客户端传输加密会话。\n *\n * 由 {@link createTransportClient} 创建;包装宿主 `fetch`,\n * 自动完成首次密钥协商并对后续请求自动加解密。\n *\n * @remarks\n * 典型调用顺序:\n *\n * 1. `init()`(可选):预先完成一次密钥协商。\n * 2. `encryptedFetch()`:业务请求统一走这里;若当前会话尚未 ready,会先自动执行 `init()`。\n * 3. `ready()`:查看当前会话是否已经拿到 `clientId` 与服务端公钥。\n * 4. `destroy()`:登出、切租户或切环境时清空会话;下一次请求会重新协商。\n */\nexport interface TransportClient {\n /**\n * 完成密钥协商;多次调用幂等(同一会话只协商一次)。\n *\n * 通常无需手动调用:`encryptedFetch` 在首次请求前会自动 `init()`。\n */\n init: () => Promise<HaiResult<void>>\n /** 包装后的 fetch;签名与全局 `fetch` 一致,请求/响应自动加解密。 */\n encryptedFetch: typeof fetch\n /** 是否已完成密钥协商。 */\n ready: () => boolean\n /** 销毁会话(清空客户端密钥)。 */\n destroy: () => void\n}\n","/**\n * @h-ai/crypto — 传输加密客户端实现\n *\n * 提供浏览器 / Node 环境下使用的 `encryptedFetch` 包装:\n * - 首次调用前自动与服务端做一次密钥协商;\n * - 之后所有出站请求自动以混合加密包裹;\n * - 标记为 `X-Encrypted: true` 的响应自动解密。\n *\n * 与服务端协议常量统一来自 {@link TRANSPORT_PROTOCOL},确保不漂移。\n *\n * @module crypto-transport-client\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n EncryptedPayload,\n KeyExchangeResponse,\n TransportClient,\n TransportCryptoServiceLike,\n TransportKeyPair,\n} from './crypto-transport-types.js'\nimport { err, HaiCommonError, ok } from '@h-ai/core'\nimport { TRANSPORT_PROTOCOL } from './crypto-transport-types.js'\n\n/** {@link createTransportClient} 的配置项。 */\nexport interface CreateTransportClientOptions {\n /** 加密能力实现(通常直接传 `crypto` 实例)。 */\n crypto: TransportCryptoServiceLike\n /** 密钥协商完整 URL,例如 `https://api.example.com/_hai/key-exchange`。 */\n keyExchangeUrl: string\n /**\n * 实际发送 HTTP 请求的 fetch 实现;默认使用全局 `fetch`。\n *\n * 在测试中可注入 mock;在 Node < 18 环境中需注入 polyfill。\n */\n fetch?: typeof fetch\n}\n\n/**\n * 创建传输加密客户端。\n *\n * 返回的 `encryptedFetch` 与全局 `fetch` 同签名,可直接替换业务代码中的 `fetch`。\n * 内部首次请求前会自动完成密钥协商(线程安全;并发请求只触发一次协商)。\n *\n * @remarks\n * 内部流程:\n *\n * 1. `createTransportClient()` 只创建本地会话状态,不会立刻发起网络请求。\n * 2. 首次 `init()` / `encryptedFetch()` 会进入 `ensureReady()`;同一时刻只允许一个协商 Promise,避免并发重复协商。\n * 3. `doInit()` 会生成客户端非对称密钥对,并向 `keyExchangeUrl` POST `{ clientPublicKey }`。\n * 4. 服务端返回 `{ serverPublicKey, clientId }` 后,会话进入 ready 状态;后续请求复用这组协商结果。\n * 5. `encryptedFetch()` 对普通业务请求附加 `X-Client-Id`;只有请求存在 body 时,才会把 body 加密成 `{ encryptedKey, ciphertext, iv }`。\n * 6. 响应带 `X-Encrypted: true` 时自动解密;不带该标记时直接透传,便于与未启用 transport 的接口共存。\n */\nexport function createTransportClient(options: CreateTransportClientOptions): TransportClient {\n const baseFetch = options.fetch ?? fetch\n let keyPair: TransportKeyPair | null = null\n let serverPublicKey: string | null = null\n let clientId: string | null = null\n /** 进行中的协商 Promise;用于并发去重。 */\n let initPromise: Promise<HaiResult<void>> | null = null\n\n async function doInit(): Promise<HaiResult<void>> {\n const kpResult = options.crypto.asymmetric.generateKeyPair()\n if (!kpResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to generate client key pair', kpResult.error)\n const localKeyPair = kpResult.data\n\n let response: Response\n try {\n response = await baseFetch(options.keyExchangeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientPublicKey: localKeyPair.publicKey }),\n })\n }\n catch (cause) {\n return err(HaiCommonError.INTERNAL_ERROR, 'Key exchange request failed', cause)\n }\n\n if (!response.ok)\n return err(HaiCommonError.INTERNAL_ERROR, `Key exchange returned HTTP ${response.status}`)\n\n let body: KeyExchangeResponse\n try {\n body = await response.json() as KeyExchangeResponse\n }\n catch (cause) {\n return err(HaiCommonError.INTERNAL_ERROR, 'Key exchange response is not valid JSON', cause)\n }\n if (!body.serverPublicKey || !body.clientId)\n return err(HaiCommonError.INTERNAL_ERROR, 'Key exchange response missing fields')\n\n keyPair = localKeyPair\n serverPublicKey = body.serverPublicKey\n clientId = body.clientId\n return ok(undefined)\n }\n\n async function ensureReady(): Promise<HaiResult<void>> {\n if (clientId && serverPublicKey)\n return ok(undefined)\n if (!initPromise) {\n initPromise = doInit().then((result) => {\n // 失败时清空 promise,允许下次重试;成功时保留即可。\n if (!result.success)\n initPromise = null\n return result\n })\n }\n return initPromise\n }\n\n function encryptBody(plaintext: string): HaiResult<EncryptedPayload> {\n if (!serverPublicKey)\n return err(HaiCommonError.INTERNAL_ERROR, 'Transport client not initialized')\n const symKey = options.crypto.symmetric.generateKey()\n const encResult = options.crypto.symmetric.encryptWithIV(plaintext, symKey)\n if (!encResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to encrypt request body', encResult.error)\n const keyEncResult = options.crypto.asymmetric.encrypt(symKey, serverPublicKey)\n if (!keyEncResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to encrypt session key', keyEncResult.error)\n return ok({\n encryptedKey: keyEncResult.data,\n ciphertext: encResult.data.ciphertext,\n iv: encResult.data.iv,\n })\n }\n\n function decryptPayload(payload: EncryptedPayload): HaiResult<string> {\n if (!keyPair)\n return err(HaiCommonError.INTERNAL_ERROR, 'Transport client not initialized')\n const keyDec = options.crypto.asymmetric.decrypt(payload.encryptedKey, keyPair.privateKey)\n if (!keyDec.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to decrypt session key', keyDec.error)\n const dec = options.crypto.symmetric.decryptWithIV(payload.ciphertext, keyDec.data, payload.iv)\n if (!dec.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to decrypt response body', dec.error)\n return ok(dec.data)\n }\n\n const encryptedFetch: typeof fetch = async (input, init) => {\n const requestInput = isRequestLike(input) ? input : undefined\n // 密钥协商请求本身不加密,避免无限递归。\n const targetUrl = typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.toString()\n : requestInput?.url ?? String(input)\n if (targetUrl === options.keyExchangeUrl)\n return baseFetch(input, init)\n\n const ready = await ensureReady()\n if (!ready.success)\n throw new Error(ready.error.message)\n\n // 复制并改造 init:附加 X-Client-Id;若有 body,则加密。\n const headers = new Headers(init?.headers ?? requestInput?.headers)\n headers.set(TRANSPORT_PROTOCOL.CLIENT_ID_HEADER, clientId!)\n\n // 兼容 oRPC 等场景:body 可能在 Request 上而非 init.body。\n let rawBody: BodyInit | null | undefined = init?.body\n if (rawBody == null && requestInput) {\n const method = (init?.method ?? requestInput.method).toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') {\n const text = await requestInput.clone().text()\n if (text)\n rawBody = text\n }\n }\n\n let nextBody: BodyInit | null | undefined = rawBody\n if (rawBody != null) {\n const plaintext = await bodyToText(rawBody)\n const encResult = encryptBody(plaintext)\n if (!encResult.success)\n throw new Error(encResult.error.message)\n nextBody = JSON.stringify(encResult.data)\n headers.set('Content-Type', 'application/json')\n headers.set(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER, TRANSPORT_PROTOCOL.ENCRYPTED_HEADER_VALUE)\n }\n\n // 当 input 是已带 body 的 Request 时,必须改用 URL 字符串作为 input,\n // 否则底层 fetch 会优先读取原始 Request 上的明文 body,覆盖我们的密文。\n const finalInput: RequestInfo | URL = requestInput ? requestInput.url : input\n const finalInit: RequestInit = {\n ...init,\n method: init?.method ?? requestInput?.method,\n headers,\n body: nextBody,\n cache: init?.cache ?? requestInput?.cache,\n credentials: init?.credentials ?? requestInput?.credentials,\n integrity: init?.integrity ?? requestInput?.integrity,\n keepalive: init?.keepalive ?? requestInput?.keepalive,\n mode: init?.mode ?? requestInput?.mode,\n redirect: init?.redirect ?? requestInput?.redirect,\n referrer: init?.referrer ?? requestInput?.referrer,\n referrerPolicy: init?.referrerPolicy ?? requestInput?.referrerPolicy,\n signal: init?.signal ?? requestInput?.signal,\n }\n const response = await baseFetch(finalInput, finalInit)\n\n // 响应未加密:直接返回。\n if (response.headers.get(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER) !== TRANSPORT_PROTOCOL.ENCRYPTED_HEADER_VALUE)\n return response\n\n const cloned = response.clone()\n let payload: unknown\n try {\n payload = await cloned.json()\n }\n catch {\n return response\n }\n if (!isEncryptedPayload(payload))\n return response\n\n const decResult = decryptPayload(payload)\n if (!decResult.success)\n throw new Error(decResult.error.message)\n\n // 透传原响应头但去掉加密标记;Content-Type 还原为下游可能期望的 JSON。\n const respHeaders = new Headers(response.headers)\n respHeaders.delete(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER)\n respHeaders.delete('Content-Length')\n return new Response(decResult.data, {\n status: response.status,\n statusText: response.statusText,\n headers: respHeaders,\n })\n }\n\n return {\n init: ensureReady,\n encryptedFetch,\n ready: () => clientId !== null && serverPublicKey !== null,\n destroy() {\n keyPair = null\n serverPublicKey = null\n clientId = null\n initPromise = null\n },\n }\n}\n\n/** 把任意 `BodyInit` 转为字符串明文,便于统一加密。 */\nasync function bodyToText(body: BodyInit): Promise<string> {\n if (typeof body === 'string')\n return body\n if (body instanceof URLSearchParams)\n return body.toString()\n if (body instanceof Blob)\n return body.text()\n if (body instanceof ArrayBuffer)\n return new TextDecoder().decode(body)\n if (ArrayBuffer.isView(body))\n return new TextDecoder().decode(body.buffer as ArrayBuffer)\n // FormData / ReadableStream:转为 Response 再读 text,由运行时序列化。\n return new Response(body as BodyInit).text()\n}\n\nfunction isRequestLike(input: RequestInfo | URL): input is Request {\n if (typeof input !== 'object' || input === null)\n return false\n\n const candidate = input as Partial<Request>\n const headers = candidate.headers as { get?: unknown } | undefined\n return typeof candidate.url === 'string'\n && typeof headers?.get === 'function'\n && typeof candidate.method === 'string'\n && typeof candidate.clone === 'function'\n}\n\nfunction isEncryptedPayload(payload: unknown): payload is EncryptedPayload {\n if (!payload || typeof payload !== 'object')\n return false\n const p = payload as Record<string, unknown>\n return typeof p.encryptedKey === 'string' && typeof p.ciphertext === 'string' && typeof p.iv === 'string'\n}\n","/**\n * @h-ai/crypto — 传输加密服务端实现\n *\n * 提供:\n * - {@link createInMemoryKeyStore}:默认内存版 {@link TransportKeyStore}(含 LRU 淘汰)。\n * - {@link createTransportEncryption}:服务端管理器工厂。\n *\n * @module crypto-transport-server\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n EncryptedPayload,\n TransportCryptoServiceLike,\n TransportEncryptionManager,\n TransportKeyPair,\n TransportKeyStore,\n} from './crypto-transport-types.js'\nimport { err, HaiCommonError, ok } from '@h-ai/core'\n\n/**\n * 创建进程内 LRU 客户端密钥存储。\n *\n * ⚠️ 进程内实现:多节点部署时需让客户端首次请求后保持「会话粘性」(sticky session),\n * 否则后续请求路由到其他节点会因找不到客户端公钥而失败。需要跨节点请改用\n * Redis / 数据库实现 {@link TransportKeyStore}。\n *\n * @param maxClients - 最大客户端数(默认 10000),超过后按注册顺序淘汰最早条目。\n */\nexport function createInMemoryKeyStore(maxClients = 10000): TransportKeyStore {\n const clientKeys = new Map<string, string>()\n let counter = 0\n return {\n async register(publicKey) {\n counter++\n const clientId = `c_${counter}_${Date.now()}`\n if (clientKeys.size >= maxClients) {\n const oldest = clientKeys.keys().next().value\n if (oldest !== undefined)\n clientKeys.delete(oldest)\n }\n clientKeys.set(clientId, publicKey)\n return clientId\n },\n async get(clientId) {\n return clientKeys.get(clientId)\n },\n async delete(clientId) {\n clientKeys.delete(clientId)\n },\n async close() {\n clientKeys.clear()\n },\n }\n}\n\n/** {@link createTransportEncryption} 的配置项。 */\nexport interface CreateTransportEncryptionOptions {\n /**\n * 客户端公钥存储;默认使用 {@link createInMemoryKeyStore}。\n *\n * 多节点部署时通过此项注入 Redis 等共享存储以保证跨节点一致。\n */\n keyStore?: TransportKeyStore\n /** 默认内存 keyStore 的最大容量(仅当 `keyStore` 未提供时生效)。 */\n maxClients?: number\n}\n\n/**\n * 创建传输加密管理器。\n *\n * 启动时生成服务端非对称密钥对,所有客户端公钥由 `keyStore` 管理。\n *\n * @param cryptoService - 注入的非对称 + 对称加密实现(通常直接传入 `crypto` 实例)。\n * @param options - 可选配置。\n * @returns 成功返回管理器;密钥对生成失败返回 `HaiCommonError.INTERNAL_ERROR`。\n *\n * @remarks\n * 内部流程:\n *\n * 1. 创建时先生成一对服务端非对称密钥,并准备 `keyStore`。\n * 2. 上层在密钥协商端点中调用 `registerClientKey()` 保存客户端公钥,再把 `getServerPublicKey()` 返回给客户端。\n * 3. 普通业务请求到达时,上层先根据 `clientId` 确认客户端已注册,再调用 `decryptRequest()` 拿到明文请求体。\n * 4. 业务逻辑完成后,上层调用 `encryptResponse(clientId, data)` 为该客户端生成密文响应。\n * 5. `close()` 负责清理 `keyStore` 等底层资源。\n *\n * 若使用 `@h-ai/serv` / `@h-ai/kit`,上述 HTTP 协商与请求包装流程通常已由上层封装完成。\n */\nexport function createTransportEncryption(\n cryptoService: TransportCryptoServiceLike,\n options: CreateTransportEncryptionOptions = {},\n): HaiResult<TransportEncryptionManager> {\n const keyPairResult = cryptoService.asymmetric.generateKeyPair()\n if (!keyPairResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to generate transport key pair', keyPairResult.error)\n const serverKeyPair: TransportKeyPair = keyPairResult.data\n const keyStore = options.keyStore ?? createInMemoryKeyStore(options.maxClients)\n\n const manager: TransportEncryptionManager = {\n getServerPublicKey() {\n return serverKeyPair.publicKey\n },\n\n async registerClientKey(clientPublicKey) {\n return keyStore.register(clientPublicKey)\n },\n\n async getClientPublicKey(clientId) {\n return keyStore.get(clientId)\n },\n\n async encryptResponse(clientId, data) {\n const clientPublicKey = await keyStore.get(clientId)\n if (!clientPublicKey)\n return err(HaiCommonError.NOT_FOUND, `Unknown transport client: ${clientId}`)\n\n // 1. 生成随机会话密钥;2. 用会话密钥加密内容;3. 用客户端公钥加密会话密钥。\n const symmetricKey = cryptoService.symmetric.generateKey()\n const encResult = cryptoService.symmetric.encryptWithIV(data, symmetricKey)\n if (!encResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to encrypt response payload', encResult.error)\n const keyEncResult = cryptoService.asymmetric.encrypt(symmetricKey, clientPublicKey)\n if (!keyEncResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to encrypt session key', keyEncResult.error)\n\n const payload: EncryptedPayload = {\n encryptedKey: keyEncResult.data,\n ciphertext: encResult.data.ciphertext,\n iv: encResult.data.iv,\n }\n return ok(payload)\n },\n\n decryptRequest(payload) {\n // 1. 用服务端私钥解出会话密钥;2. 用会话密钥解出明文。\n const keyDecResult = cryptoService.asymmetric.decrypt(payload.encryptedKey, serverKeyPair.privateKey)\n if (!keyDecResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to decrypt session key', keyDecResult.error)\n const decResult = cryptoService.symmetric.decryptWithIV(payload.ciphertext, keyDecResult.data, payload.iv)\n if (!decResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, 'Failed to decrypt request payload', decResult.error)\n return ok(decResult.data)\n },\n\n async close() {\n await keyStore.close?.()\n },\n }\n\n return ok(manager)\n}\n\n/**\n * 判断对象是否为合法 {@link EncryptedPayload}。\n *\n * 字段必须为非空字符串。用于服务端在调用 `decryptRequest` 前做形状校验,\n * 把畸形请求拦截在加密层之外。\n */\nexport function isValidEncryptedPayload(payload: unknown): payload is EncryptedPayload {\n if (!payload || typeof payload !== 'object')\n return false\n const p = payload as Record<string, unknown>\n return (\n typeof p.encryptedKey === 'string' && p.encryptedKey.length > 0\n && typeof p.ciphertext === 'string' && p.ciphertext.length > 0\n && typeof p.iv === 'string' && p.iv.length > 0\n )\n}\n","/**\n * @h-ai/crypto — 加密服务主入口\n *\n * 提供统一的 `crypto` 对象,聚合所有结构化加密操作。\n * @module crypto-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { AsymmetricOperations, CryptoFunctions, HashOperations, PasswordOperations, SymmetricOperations, TransportOperations } from './crypto-types.js'\n\nimport { core, err, ok } from '@h-ai/core'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport { createPasswordFunctions } from './crypto-password.js'\nimport { createSM2 } from './crypto-sm2.js'\nimport { createSM3 } from './crypto-sm3.js'\nimport { createSM4 } from './crypto-sm4.js'\nimport {\n\n HaiCryptoError,\n\n} from './crypto-types.js'\nimport { createTransportClient } from './transport/crypto-transport-client.js'\nimport { createTransportEncryption } from './transport/crypto-transport-server.js'\nimport { TRANSPORT_PROTOCOL } from './transport/crypto-transport-types.js'\n\nconst logger = core.logger.child({ module: 'crypto', scope: 'main' })\n\n// ─── 内部状态 ───\n\n/** 是否已初始化 */\nlet initialized = false\n/** 并发初始化防护标志 */\nlet initInProgress = false\n/** 当前非对称加密操作实例 */\nlet currentAsymmetric: AsymmetricOperations | null = null\n/** 当前哈希操作实例 */\nlet currentHash: HashOperations | null = null\n/** 当前对称加密操作实例 */\nlet currentSymmetric: SymmetricOperations | null = null\n/** 当前密码哈希操作实例 */\nlet currentPassword: PasswordOperations | null = null\n\n// ─── 未初始化占位 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiCryptoError.NOT_INITIALIZED,\n () => cryptoM('crypto_notInitialized'),\n)\n\nconst notInitializedAsymmetric = notInitialized.proxy<AsymmetricOperations>('sync')\nconst notInitializedHash = notInitialized.proxy<HashOperations>('sync')\nconst notInitializedSymmetric = notInitialized.proxy<SymmetricOperations>('sync')\nconst notInitializedPassword = notInitialized.proxy<PasswordOperations>('sync')\n\n// ─── 传输加密 ───\n// 直接复用顶层 `crypto`:未初始化时 asymmetric/symmetric 会自动返回\n// NOT_INITIALIZED 错误,无需额外 proxy。\n\n// 通过函数声明(hoisted)延迟引用 `crypto`,避免 use-before-define 报错;\n// 实际调用发生在 init 之后,闭包持有的引用是安全的。\nfunction getCrypto(): CryptoFunctions {\n // eslint-disable-next-line ts/no-use-before-define\n return crypto\n}\nconst transportOperations: TransportOperations = {\n createServer: options => createTransportEncryption(getCrypto(), options),\n createClient: options => createTransportClient({ crypto: getCrypto(), ...options }),\n protocol: TRANSPORT_PROTOCOL,\n}\n\n// ─── 服务对象 ───\n\n/**\n * 加密模块服务对象(统一入口)\n *\n * 使用前必须调用 `crypto.init()` 进行初始化。\n * 未初始化时访问 asymmetric/hash/symmetric/password 的任何方法均返回 NOT_INITIALIZED 错误。\n *\n * @example\n * ```ts\n * import { crypto } from '@h-ai/crypto'\n *\n * await crypto.init()\n * const hash = crypto.hash.hash('hello')\n * const keyPair = crypto.asymmetric.generateKeyPair()\n * await crypto.close()\n * ```\n */\nexport const crypto: CryptoFunctions = {\n /**\n * 初始化加密模块\n *\n * 创建非对称/哈希/对称/密码哈希操作实例。\n * 重复调用会先关闭再重新初始化。\n *\n * @returns 成功时返回 ok(undefined);失败时返回 INIT_FAILED\n */\n async init(): Promise<HaiResult<void>> {\n // 并发初始化防护:避免多次 init 同时执行导致资源泄漏\n if (initInProgress) {\n logger.warn('Crypto init already in progress, skipping concurrent call')\n return err(\n HaiCryptoError.INIT_FAILED,\n cryptoM('crypto_initFailed', { params: { error: 'Concurrent initialization detected' } }),\n )\n }\n initInProgress = true\n\n try {\n if (initialized) {\n logger.warn('Crypto module is already initialized, reinitializing')\n await crypto.close()\n }\n\n logger.info('Initializing crypto module')\n\n currentAsymmetric = createSM2()\n currentHash = createSM3()\n currentSymmetric = createSM4()\n currentPassword = createPasswordFunctions({ hash: currentHash })\n initialized = true\n logger.info('Crypto module initialized')\n return ok(undefined)\n }\n catch (error) {\n // 清理部分赋值的状态\n currentAsymmetric = null\n currentHash = null\n currentSymmetric = null\n currentPassword = null\n initialized = false\n logger.error('Crypto module initialization failed', { error })\n return err(\n HaiCryptoError.INIT_FAILED,\n cryptoM('crypto_initFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n finally {\n initInProgress = false\n }\n },\n\n /** 非对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get asymmetric(): AsymmetricOperations { return currentAsymmetric ?? notInitializedAsymmetric },\n /** 哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get hash(): HashOperations { return currentHash ?? notInitializedHash },\n /** 对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get symmetric(): SymmetricOperations { return currentSymmetric ?? notInitializedSymmetric },\n /** 密码哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get password(): PasswordOperations { return currentPassword ?? notInitializedPassword },\n /**\n * 传输加密操作(端到端混合加密)\n *\n * createServer 内部直接复用 asymmetric/symmetric,因此未初始化时\n * 自动通过 asymmetric proxy 返回 NOT_INITIALIZED 错误。\n */\n transport: transportOperations,\n /** 是否已初始化 */\n get isInitialized() { return initialized },\n\n /**\n * 关闭加密模块,释放内部状态\n *\n * 关闭后访问 asymmetric/hash/symmetric/password 会返回 NOT_INITIALIZED 错误。\n */\n async close() {\n if (!initialized) {\n logger.info('Crypto module already closed, skipping')\n return\n }\n\n logger.info('Closing crypto module')\n\n currentAsymmetric = null\n currentHash = null\n currentSymmetric = null\n currentPassword = null\n initialized = false\n\n logger.info('Crypto module closed')\n },\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../messages/en-US.json","../messages/zh-CN.json","../src/crypto-i18n.ts","../src/crypto-types.ts","../src/crypto-password.ts","../src/crypto-utils.ts","../src/crypto-sm2.ts","../src/crypto-sm3.ts","../src/crypto-sm4.ts","../src/transport/crypto-transport-types.ts","../src/transport/crypto-transport-client.ts","../src/transport/store-provider/crypto-transport-store-memory.ts","../src/transport/crypto-transport-server.ts","../src/crypto-main.ts","../src/transport/store-provider/crypto-transport-store-redis.ts","../src/transport/store-provider/crypto-transport-store-reldb.ts"],"names":["core","ok","err","smCrypto","sm3","HaiCommonError","crypto","createClientId","normalizeTtlSeconds","toOperationError","unwrapResult"],"mappings":"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","file":"index.js","sourcesContent":["{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n \"crypto_notInitialized\": \"Crypto module not initialized, call crypto.init() first\",\n \"crypto_initFailed\": \"Crypto module initialization failed: {error}\",\n \"crypto_sm2PublicKeyInvalid\": \"Invalid SM2 public key format\",\n \"crypto_sm2PrivateKeyInvalid\": \"Invalid SM2 private key format\",\n \"crypto_sm2EncryptEmpty\": \"SM2 encryption returned empty result\",\n \"crypto_sm2DecryptFailed\": \"SM2 decryption failed or returned invalid result\",\n \"crypto_sm2SignEmpty\": \"SM2 signature returned empty result\",\n \"crypto_sm2KeyPairGenerateFailed\": \"SM2 key pair generation failed: {error}\",\n \"crypto_sm2EncryptFailed\": \"SM2 encryption failed: {error}\",\n \"crypto_sm2DecryptFailedWithError\": \"SM2 decryption failed: {error}\",\n \"crypto_sm2SignFailed\": \"SM2 signing failed: {error}\",\n \"crypto_sm2VerifyFailed\": \"SM2 verification failed: {error}\",\n \"crypto_sm3HashEmpty\": \"SM3 hash returned empty result\",\n \"crypto_sm3HashFailed\": \"SM3 hash calculation failed: {error}\",\n \"crypto_sm3HmacFailed\": \"HMAC-SM3 calculation failed: {error}\",\n \"crypto_sm3VerifyFailed\": \"SM3 hash verification failed: {error}\",\n \"crypto_sm4KeyInvalid\": \"SM4 key must be 16 bytes (32 hex characters)\",\n \"crypto_sm4CbcNeedIv\": \"CBC mode requires IV\",\n \"crypto_sm4IvInvalid\": \"SM4 IV must be 16 bytes (32 hex characters)\",\n \"crypto_sm4EncryptEmpty\": \"SM4 encryption returned empty result\",\n \"crypto_sm4DecryptFailed\": \"SM4 decryption failed\",\n \"crypto_sm4EncryptFailed\": \"SM4 encryption failed: {error}\",\n \"crypto_sm4DecryptFailedWithError\": \"SM4 decryption failed: {error}\",\n \"crypto_passwordEmpty\": \"Password cannot be empty\",\n \"crypto_passwordHashEmpty\": \"Password and hash cannot be empty\",\n \"crypto_passwordHashFailed\": \"Password hashing failed\",\n \"crypto_hashFormatInvalid\": \"Invalid hash format\",\n \"crypto_passwordVerifyFailed\": \"Password verification failed\",\n \"crypto_transportClientKeyGenerateFailed\": \"Failed to generate transport client key pair\",\n \"crypto_transportServerKeyGenerateFailed\": \"Failed to generate transport server key pair\",\n \"crypto_transportKeyExchangeRequestFailed\": \"Transport key exchange request failed\",\n \"crypto_transportKeyExchangeHttpFailed\": \"Transport key exchange returned HTTP {status}\",\n \"crypto_transportKeyExchangeInvalidJson\": \"Transport key exchange response is not valid JSON\",\n \"crypto_transportKeyExchangeMissingFields\": \"Transport key exchange response is missing required fields\",\n \"crypto_transportClientNotInitialized\": \"Transport client has not completed key exchange\",\n \"crypto_transportClientNotRegistered\": \"Transport client is not registered or has expired\",\n \"crypto_transportRequestEncryptFailed\": \"Failed to encrypt transport request body\",\n \"crypto_transportRequestDecryptFailed\": \"Failed to decrypt transport request body\",\n \"crypto_transportResponseEncryptFailed\": \"Failed to encrypt transport response body\",\n \"crypto_transportResponseDecryptFailed\": \"Failed to decrypt transport response body\",\n \"crypto_transportSessionKeyEncryptFailed\": \"Failed to encrypt transport session key\",\n \"crypto_transportSessionKeyDecryptFailed\": \"Failed to decrypt transport session key\"\n}\n","{\n \"$schema\": \"https://inlang.com/schema/inlang-message-format\",\n \"crypto_notInitialized\": \"加密模块尚未初始化,请先调用 crypto.init()\",\n \"crypto_initFailed\": \"加密模块初始化失败:{error}\",\n \"crypto_sm2PublicKeyInvalid\": \"无效的 SM2 公钥格式\",\n \"crypto_sm2PrivateKeyInvalid\": \"无效的 SM2 私钥格式\",\n \"crypto_sm2EncryptEmpty\": \"SM2 加密返回空结果\",\n \"crypto_sm2DecryptFailed\": \"SM2 解密失败或返回无效结果\",\n \"crypto_sm2SignEmpty\": \"SM2 签名返回空结果\",\n \"crypto_sm2KeyPairGenerateFailed\": \"SM2 密钥对生成失败: {error}\",\n \"crypto_sm2EncryptFailed\": \"SM2 加密失败: {error}\",\n \"crypto_sm2DecryptFailedWithError\": \"SM2 解密失败: {error}\",\n \"crypto_sm2SignFailed\": \"SM2 签名失败: {error}\",\n \"crypto_sm2VerifyFailed\": \"SM2 验签失败: {error}\",\n \"crypto_sm3HashEmpty\": \"SM3 哈希返回空结果\",\n \"crypto_sm3HashFailed\": \"SM3 哈希计算失败: {error}\",\n \"crypto_sm3HmacFailed\": \"HMAC-SM3 计算失败: {error}\",\n \"crypto_sm3VerifyFailed\": \"SM3 哈希验证失败: {error}\",\n \"crypto_sm4KeyInvalid\": \"SM4 密钥必须为 16 字节(32 个十六进制字符)\",\n \"crypto_sm4CbcNeedIv\": \"CBC 模式必须提供 IV\",\n \"crypto_sm4IvInvalid\": \"SM4 IV 必须为 16 字节(32 个十六进制字符)\",\n \"crypto_sm4EncryptEmpty\": \"SM4 加密返回空结果\",\n \"crypto_sm4DecryptFailed\": \"SM4 解密失败\",\n \"crypto_sm4EncryptFailed\": \"SM4 加密失败: {error}\",\n \"crypto_sm4DecryptFailedWithError\": \"SM4 解密失败: {error}\",\n \"crypto_passwordEmpty\": \"密码不能为空\",\n \"crypto_passwordHashEmpty\": \"密码和哈希值不能为空\",\n \"crypto_passwordHashFailed\": \"密码哈希失败\",\n \"crypto_hashFormatInvalid\": \"无效的哈希格式\",\n \"crypto_passwordVerifyFailed\": \"密码验证失败\",\n \"crypto_transportClientKeyGenerateFailed\": \"传输加密客户端密钥生成失败\",\n \"crypto_transportServerKeyGenerateFailed\": \"传输加密服务端密钥生成失败\",\n \"crypto_transportKeyExchangeRequestFailed\": \"传输加密密钥协商请求失败\",\n \"crypto_transportKeyExchangeHttpFailed\": \"传输加密密钥协商返回 HTTP {status}\",\n \"crypto_transportKeyExchangeInvalidJson\": \"传输加密密钥协商响应不是有效 JSON\",\n \"crypto_transportKeyExchangeMissingFields\": \"传输加密密钥协商响应缺少必要字段\",\n \"crypto_transportClientNotInitialized\": \"传输加密客户端尚未完成密钥协商\",\n \"crypto_transportClientNotRegistered\": \"传输加密客户端未注册或已过期\",\n \"crypto_transportRequestEncryptFailed\": \"传输加密请求体加密失败\",\n \"crypto_transportRequestDecryptFailed\": \"传输加密请求体解密失败\",\n \"crypto_transportResponseEncryptFailed\": \"传输加密响应体加密失败\",\n \"crypto_transportResponseDecryptFailed\": \"传输加密响应体解密失败\",\n \"crypto_transportSessionKeyEncryptFailed\": \"传输加密会话密钥加密失败\",\n \"crypto_transportSessionKeyDecryptFailed\": \"传输加密会话密钥解密失败\"\n}\n","/**\n * @h-ai/crypto — i18n\n *\n * 本文件提供加密模块的 i18n 文案访问入口。\n * @module crypto-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\n/** 加密模块 i18n 消息键类型(自动从 zh-CN 消息文件推断) */\ntype CryptoMessageKey = keyof typeof messagesZhCN\n\n/**\n * 加密模块 i18n 消息获取器\n *\n * 根据当前全局 locale 返回对应语言的消息文本,支持参数插值。\n *\n * @example\n * ```ts\n * cryptoM('crypto_sm2PublicKeyInvalid')\n * cryptoM('crypto_initFailed', { params: { error: 'bad config' } })\n * ```\n */\nexport const cryptoM = core.i18n.createMessageGetter<CryptoMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n})\n","/**\n * @h-ai/crypto — 公共类型\n *\n * 定义加密模块的对外接口类型。\n * @module crypto-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type {\n TRANSPORT_PROTOCOL as TRANSPORT_PROTOCOL_T,\n TransportClient,\n TransportCreateServerOptions,\n TransportEncryptionManager,\n} from './transport/crypto-transport-types.js'\nimport { core } from '@h-ai/core'\n\nconst CryptoErrorInfo = {\n INVALID_INPUT: '002:400',\n INVALID_KEY: '003:400',\n NOT_INITIALIZED: '010:500',\n INIT_FAILED: '011:500',\n KEY_GENERATION_FAILED: '020:500',\n ENCRYPTION_FAILED: '021:500',\n DECRYPTION_FAILED: '022:500',\n SIGN_FAILED: '023:500',\n VERIFY_FAILED: '024:500',\n HASH_FAILED: '040:500',\n HMAC_FAILED: '041:500',\n INVALID_IV: '060:400',\n} as const satisfies ErrorInfo\n\nexport const HaiCryptoError = core.error.buildHaiErrorsDef('crypto', CryptoErrorInfo)\n\n// ─── 非对称加密类型 ───\n\n/** 密文模式:0=C1C2C3(旧版),1=C1C3C2(国标) */\nexport type CipherMode = 0 | 1\n\n/** 非对称密钥对 */\nexport interface KeyPair {\n /** 公钥(十六进制字符串,包含 04 前缀为非压缩格式) */\n publicKey: string\n /** 私钥(十六进制字符串,64 字符) */\n privateKey: string\n}\n\n/** 非对称加密选项 */\nexport interface AsymmetricEncryptOptions {\n /** 密文模式:0=C1C2C3(旧版),1=C1C3C2(国标,默认) */\n cipherMode?: CipherMode\n /** 输出格式 */\n outputFormat?: 'hex' | 'base64'\n}\n\n/** 签名选项 */\nexport interface SignOptions {\n /** 是否对数据进行哈希(默认 true) */\n hash?: boolean\n /** 用户 ID(默认 \"1234567812345678\") */\n userId?: string\n}\n\n// ─── 哈希类型 ───\n\n/** 哈希选项 */\nexport interface HashOptions {\n /** 输入编码 */\n inputEncoding?: 'utf8' | 'hex'\n}\n\n// ─── 对称加密类型 ───\n\n/** 对称加密模式 */\nexport type SymmetricMode = 'ecb' | 'cbc'\n\n/** 对称密文编码 */\nexport type SymmetricCiphertextEncoding = 'hex' | 'base64'\n\n/** 对称加密选项。默认 CBC,并自动生成随机 IV。 */\nexport interface SymmetricEncryptOptions {\n /** 加密模式;默认 cbc */\n mode?: SymmetricMode\n /** IV 向量(CBC 模式可选;未传时自动生成,32 个十六进制字符) */\n iv?: string\n /** 密文输出编码;默认 hex */\n outputFormat?: SymmetricCiphertextEncoding\n}\n\n/** 对称加密结构化结果。 */\nexport interface SymmetricEncryptedPayload {\n /** 加密模式 */\n readonly mode: SymmetricMode\n /** 密文内容,编码由 encoding 字段说明 */\n readonly ciphertext: string\n /** CBC 模式的 IV 向量;ECB 模式无该字段 */\n readonly iv?: string\n /** ciphertext 字段的编码 */\n readonly encoding: SymmetricCiphertextEncoding\n}\n\n/** CBC 模式结构化结果。 */\nexport interface SymmetricCbcEncryptedPayload extends SymmetricEncryptedPayload {\n readonly mode: 'cbc'\n readonly iv: string\n}\n\n/** 对称解密输入。 */\nexport type SymmetricDecryptInput = SymmetricEncryptedPayload\n\n/** 带 IV 加密结果。 */\nexport type EncryptWithIVResult = SymmetricCbcEncryptedPayload\n\n// ─── 密码类型 ───\n\n/** 密码哈希配置 */\nexport interface PasswordConfig {\n /** 盐值长度(默认 16) */\n saltLength?: number\n /** 迭代次数(默认 10000) */\n iterations?: number\n}\n\n// ─── 操作接口 ───\n\n/**\n * 非对称加密操作接口\n *\n * 通过 `crypto.asymmetric` 访问,需先调用 `crypto.init()`。\n */\nexport interface AsymmetricOperations {\n /**\n * 生成密钥对\n *\n * @returns 成功时包含公私钥对;失败时返回 KEY_GENERATION_FAILED\n */\n generateKeyPair: () => HaiResult<KeyPair>\n /**\n * 非对称加密\n *\n * @param data - 待加密明文\n * @param publicKey - 公钥(十六进制,支持带/不带 04 前缀)\n * @param options - 加密选项(密文模式、输出格式)\n * @returns 成功时返回密文字符串;失败时返回 INVALID_KEY 或 ENCRYPTION_FAILED\n */\n encrypt: (data: string, publicKey: string, options?: AsymmetricEncryptOptions) => HaiResult<string>\n /**\n * 非对称解密\n *\n * 自动检测 base64 格式输入并转换为 hex。\n *\n * @param ciphertext - 密文(hex 或 base64)\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 解密选项(密文模式需与加密时一致)\n * @returns 成功时返回明文;失败时返回 INVALID_KEY 或 DECRYPTION_FAILED\n */\n decrypt: (ciphertext: string, privateKey: string, options?: AsymmetricEncryptOptions) => HaiResult<string>\n /**\n * 签名\n *\n * @param data - 待签名数据\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 签名选项(hash 开关、userId)\n * @returns 成功时返回签名字符串;失败时返回 INVALID_KEY 或 SIGN_FAILED\n */\n sign: (data: string, privateKey: string, options?: SignOptions) => HaiResult<string>\n /**\n * 验签\n *\n * @param data - 原始数据\n * @param signature - 签名(需与签名时使用相同的 hash/userId 选项)\n * @param publicKey - 公钥(支持带/不带 04 前缀)\n * @param options - 验签选项\n * @returns 成功时返回 boolean;失败时返回 INVALID_KEY 或 VERIFY_FAILED\n */\n verify: (data: string, signature: string, publicKey: string, options?: SignOptions) => HaiResult<boolean>\n /**\n * 校验公钥格式是否合法\n *\n * 合法格式:128 字符十六进制(无前缀)或 130 字符(含 04 前缀)。\n */\n isValidPublicKey: (key: string) => boolean\n /**\n * 校验私钥格式是否合法\n *\n * 合法格式:64 字符十六进制。\n */\n isValidPrivateKey: (key: string) => boolean\n}\n\n/**\n * 哈希操作接口\n *\n * 通过 `crypto.hash` 访问,需先调用 `crypto.init()`。\n */\nexport interface HashOperations {\n /**\n * 计算哈希\n *\n * @param data - 待哈希数据(字符串或 Uint8Array)\n * @param options - 输入编码选项\n * @returns 成功时返回 64 字符十六进制哈希值;失败时返回 HASH_FAILED\n */\n hash: (data: string | Uint8Array, options?: HashOptions) => HaiResult<string>\n /**\n * 计算 HMAC\n *\n * 使用 HMAC 算法(RFC 2104)计算消息认证码。\n * 当密钥长度超过块大小(64 字节)时,会先对密钥进行哈希。\n *\n * @param data - 待计算数据\n * @param key - HMAC 密钥\n * @returns 成功时返回 64 字符十六进制 HMAC 值;失败时返回 HMAC_FAILED\n */\n hmac: (data: string, key: string) => HaiResult<string>\n /**\n * 验证数据的哈希是否匹配\n *\n * 比较时忽略大小写。\n *\n * @param data - 原始数据\n * @param expectedHash - 期望的哈希值\n * @returns 成功时返回 boolean;失败时返回 HASH_FAILED\n */\n verify: (data: string, expectedHash: string) => HaiResult<boolean>\n}\n\n/**\n * 对称加密操作接口\n *\n * 通过 `crypto.symmetric` 访问,需先调用 `crypto.init()`。\n * 默认使用 CBC 并自动生成 IV;密文以结构化字段返回。\n */\nexport interface SymmetricOperations {\n /** 生成随机密钥(16 字节 = 32 个十六进制字符) */\n generateKey: () => string\n /** 生成随机 IV(16 字节 = 32 个十六进制字符) */\n generateIV: () => string\n /**\n * 对称加密\n *\n * 默认 CBC + 自动随机 IV,返回 `{ mode, ciphertext, iv, encoding }`。\n * 显式 `{ mode: 'ecb' }` 可使用 ECB,但不推荐用于新数据。\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @param options - 加密模式/IV/输出格式\n * @returns 成功时返回结构化密文;失败时返回 INVALID_KEY/INVALID_IV/ENCRYPTION_FAILED\n */\n encrypt: (data: string, key: string, options?: SymmetricEncryptOptions) => HaiResult<SymmetricEncryptedPayload>\n /**\n * 对称解密\n *\n * 解密 `encrypt()` 返回的结构化密文;不猜测字符串格式。\n *\n * @param payload - 结构化密文(包含 mode/ciphertext/iv/encoding)\n * @param key - 密钥(32 字符十六进制)\n * @returns 成功时返回明文;失败时返回 INVALID_KEY/INVALID_IV/DECRYPTION_FAILED\n */\n decrypt: (payload: SymmetricDecryptInput, key: string) => HaiResult<string>\n /**\n * 带 IV 加密(CBC 模式,自动生成随机 IV)\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @returns 成功时返回 { ciphertext, iv };失败时同 encrypt\n */\n encryptWithIV: (data: string, key: string) => HaiResult<EncryptWithIVResult>\n /**\n * 带 IV 解密(CBC 模式)\n *\n * @param ciphertext - 密文\n * @param key - 密钥\n * @param iv - 加密时使用的 IV\n * @returns 成功时返回明文;失败时同 decrypt\n */\n decryptWithIV: (ciphertext: string, key: string, iv: string) => HaiResult<string>\n /**\n * 从密码和盐值派生密钥\n *\n * 内部仅执行单次哈希(password + salt) 取前 32 字符作为密钥。\n *\n * ⚠️ 安全警告:**此实现不是标准 KDF**,不具备密码爆破抗性。\n * - 禁止用于密码存储(请用 `crypto.password.hash`)。\n * - 禁止用于高价值密钥派生(请在应用层采用 PBKDF2 / scrypt / Argon2)。\n *\n * @deprecated 未来版本可能移除。详见模块 README 安全声明。\n * @param password - 密码\n * @param salt - 盐值\n * @returns 32 字符十六进制密钥\n */\n deriveKey: (password: string, salt: string) => string\n /** 校验密钥格式是否合法(32 字符十六进制) */\n isValidKey: (key: string) => boolean\n /** 校验 IV 格式是否合法(32 字符十六进制) */\n isValidIV: (iv: string) => boolean\n}\n\n/**\n * 密码哈希操作接口\n *\n * 通过 `crypto.password` 访问,需先调用 `crypto.init()`。\n * 使用迭代加盐的方式生成密码哈希。\n */\nexport interface PasswordOperations {\n /**\n * 对密码进行哈希\n *\n * 输出格式: `$hai$<iterations>$<salt>$<hash>`\n *\n * @param password - 明文密码(不能为空)\n * @param config - 可选配置(盐值长度、迭代次数)\n * @returns 成功时返回格式化的哈希字符串;失败时返回 INVALID_INPUT 或 HASH_FAILED\n */\n hash: (password: string, config?: PasswordConfig) => HaiResult<string>\n /**\n * 验证密码是否匹配\n *\n * 自动从哈希字符串中解析迭代次数和盐值进行重新计算。\n *\n * @param password - 待验证的明文密码\n * @param hash - 存储的哈希值(格式: `$hai$<iterations>$<salt>$<hash>`)\n * @returns 成功时返回 boolean;失败时返回 INVALID_INPUT 或 VERIFY_FAILED\n */\n verify: (password: string, hash: string) => HaiResult<boolean>\n}\n\n// ─── 传输加密 ───\n\n/**\n * 传输加密操作接口(端到端混合加密)。\n *\n * 通过 `crypto.transport` 访问,需先调用 `crypto.init()`。\n *\n * @remarks\n * 使用流程(直接使用底层 transport 工厂时):\n *\n * 1. 先 `await crypto.init()`,确保 `crypto.asymmetric` / `crypto.symmetric` 已就绪。\n * 2. 服务端调用 `crypto.transport.createServer()` 创建 `TransportEncryptionManager`;该管理器负责持有服务端密钥对,并管理客户端公钥。多节点部署时可通过 `options.keyStore` 注入共享存储。\n * 3. 服务端暴露一个 POST 密钥协商端点:接收 `{ clientPublicKey }`,调用 `manager.registerClientKey()` 注册客户端公钥,再返回 `{ serverPublicKey: manager.getServerPublicKey(), clientId }`。\n * 4. 客户端调用 `crypto.transport.createClient({ keyExchangeUrl })` 创建会话;首次 `client.init()` 或 `client.encryptedFetch()` 会自动完成密钥协商。\n * 5. 协商完成后,客户端每次请求都会附带 `X-Client-Id`;若请求有 body,则 body 会被包装成 `{ encryptedKey, ciphertext, iv }`,并设置 `X-Encrypted: true`。\n * 6. 服务端在业务逻辑前调用 `manager.decryptRequest()` 解密请求体,在返回前调用 `manager.encryptResponse(clientId, data)` 为当前客户端重新加密响应。\n * 7. 客户端收到 `X-Encrypted: true` 的响应后会自动解密;调用 `client.destroy()` 可清空当前会话,下次请求会重新协商。\n *\n * 常规应用优先使用上层封装,而不是手写 HTTP 协商细节:\n * - `serv.createApp({ transport: { crypto } })`\n * - `kit.createHandle({ crypto: { crypto, transport: true } })`\n * - `apiClient.init({ transport: { crypto } })`\n *\n * @example 服务端\n * ```ts\n * const result = crypto.transport.createServer({\n * keyStore: createRedisTransportKeyStore({ cache, ttlSeconds: 3600 }),\n * })\n * if (!result.success) throw result.error\n * const manager = result.data\n * ```\n *\n * @example 客户端\n * ```ts\n * const client = crypto.transport.createClient({\n * keyExchangeUrl: 'https://api.example.com/api/v1/_hai/key-exchange',\n * })\n * const resp = await client.encryptedFetch('https://api.example.com/api/v1/echo', {\n * method: 'POST', body: JSON.stringify({ hello: 'world' }),\n * })\n * ```\n */\nexport interface TransportOperations {\n /**\n * 创建服务端传输加密管理器。\n *\n * options.keyStore:注入共享客户端公钥存储。\n * options.maxClients:默认内存 keyStore 的最大客户端数(默认 10000,仅在未传 keyStore 时生效)。\n * 成功返回 manager;密钥生成失败返回 `HaiCommonError.INTERNAL_ERROR`。\n *\n * @remarks\n * 通常在服务启动阶段创建一次,并交给 HTTP 中间件 / 路由处理器复用。\n */\n createServer: (options?: TransportCreateServerOptions) => HaiResult<TransportEncryptionManager>\n /**\n * 创建客户端传输加密会话。\n *\n * options.keyExchangeUrl:密钥协商端点完整 URL。\n * options.fetch:实际发送 HTTP 请求的 fetch(默认 `globalThis.fetch`)。\n *\n * @remarks\n * 返回的是“单会话”客户端:同一个实例会复用已协商得到的 `clientId` 与服务端公钥;\n * 调用 `destroy()` 后会回到未协商状态。\n */\n createClient: (options: { keyExchangeUrl: string, fetch?: typeof fetch }) => TransportClient\n /** 协议常量(headers、密钥协商默认路径)。 */\n readonly protocol: typeof TRANSPORT_PROTOCOL_T\n}\n\n// ─── 函数接口 ───\n\n/**\n * 加密模块函数接口\n *\n * `crypto` 服务对象的类型定义。使用前必须调用 `init()` 初始化。\n *\n * @example\n * ```ts\n * import { crypto } from '@h-ai/crypto'\n *\n * await crypto.init()\n * const hash = crypto.hash.hash('hello')\n * await crypto.close()\n * ```\n */\nexport interface CryptoFunctions {\n /**\n * 初始化加密模块\n *\n * 创建非对称/哈希/对称/密码哈希操作实例。\n * 重复调用会先关闭再重新初始化。\n *\n * @returns 成功时返回 ok(undefined);失败时返回 INIT_FAILED\n */\n init: () => Promise<HaiResult<void>>\n /**\n * 关闭加密模块,释放内部状态\n *\n * 关闭后再访问 asymmetric/hash/symmetric/password 会返回 NOT_INITIALIZED 错误。\n */\n close: () => Promise<void>\n /** 是否已初始化 */\n readonly isInitialized: boolean\n /** 非对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly asymmetric: AsymmetricOperations\n /** 哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly hash: HashOperations\n /** 对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly symmetric: SymmetricOperations\n /** 密码哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n readonly password: PasswordOperations\n /** 传输加密操作(端到端混合加密;createServer 在未初始化时返回 NOT_INITIALIZED) */\n readonly transport: TransportOperations\n}\n","/**\n * @h-ai/crypto — 密码操作\n *\n * 提供迭代加盐(SM3)密码哈希与校验功能。\n * @module crypto-password\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\nimport type { HashOperations, PasswordConfig, PasswordOperations } from './crypto-types.js'\nimport { core, err, ok } from '@h-ai/core'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport { HaiCryptoError } from './crypto-types.js'\n\n// ─── 常量 ───\n\n/** 迭代次数最小值(防止退化为 0 迭代导致明文等价泄漏) */\nconst MIN_ITERATIONS = 1\n/** 迭代次数最大值(防止伪造哈希触发 CPU 饱和) */\nconst MAX_ITERATIONS = 1_000_000\n/** 盐值长度范围,限制异常输入 */\nconst MIN_SALT_LENGTH = 8\nconst MAX_SALT_LENGTH = 128\n\n// ─── 依赖接口 ───\n\n/** createPasswordFunctions 所需的外部依赖 */\ninterface PasswordDeps {\n /** 哈希操作实例,用于迭代哈希计算 */\n hash: HashOperations\n}\n\n// ─── 工具函数 ───\n\n/**\n * 生成加密安全的随机盐值\n *\n * 使用 Web Crypto API(crypto.getRandomValues)从大小写字母和数字中随机选取字符。\n *\n * @param length - 盐值长度(字符数)\n * @returns 随机盐值字符串\n */\nfunction generateSalt(length: number): string {\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'\n const randomBytes = new Uint8Array(length)\n globalThis.crypto.getRandomValues(randomBytes)\n let salt = ''\n for (let i = 0; i < length; i++) {\n salt += chars.charAt(randomBytes[i] % chars.length)\n }\n return salt\n}\n\n/**\n * 对数据进行多次迭代哈希(密钥拉伸)\n *\n * 首次输入为 salt + data,后续每次用前一轮的哈希结果作为输入。\n * 任一轮哈希计算失败则立即返回错误。\n *\n * @param hash - 哈希操作实例\n * @param data - 原始数据(通常为密码)\n * @param salt - 盐值\n * @param iterations - 迭代次数\n * @returns 成功时返回最终哈希值(64 字符十六进制)\n */\nfunction iterateHash(\n hash: HashOperations,\n data: string,\n salt: string,\n iterations: number,\n): HaiResult<string> {\n let current = salt + data\n for (let i = 0; i < iterations; i++) {\n const result = hash.hash(current)\n if (!result.success) {\n return result\n }\n current = result.data\n }\n return ok(current)\n}\n\n// ─── 密码操作工厂 ───\n\n/**\n * 创建密码哈希操作实例\n *\n * 内部使用迭代加盐的方式生成密码哈希,格式为 `$hai$<iterations>$<salt>$<hash>`。\n *\n * @param deps - 依赖(需要注入哈希操作实例)\n * @returns PasswordOperations 接口实现\n */\nexport function createPasswordFunctions(deps: PasswordDeps): PasswordOperations {\n const { hash: hashOps } = deps\n\n return {\n /**\n * 对密码进行迭代加盐哈希\n *\n * 输出格式: `$hai$<iterations>$<salt>$<hash>`\n *\n * @param password - 明文密码(不能为空)\n * @param config - 可选配置(盐值长度、迭代次数)\n * @returns 成功时返回格式化的哈希字符串;失败时返回 INVALID_INPUT 或 HASH_FAILED\n */\n hash(password: string, config: PasswordConfig = {}): HaiResult<string> {\n const { saltLength = 16, iterations = 10000 } = config\n\n try {\n if (!password) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_passwordEmpty'),\n )\n }\n\n if (!Number.isInteger(iterations) || iterations < MIN_ITERATIONS || iterations > MAX_ITERATIONS) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n if (!Number.isInteger(saltLength) || saltLength < MIN_SALT_LENGTH || saltLength > MAX_SALT_LENGTH) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n\n const salt = generateSalt(saltLength)\n const hashResult = iterateHash(hashOps, password, salt, iterations)\n if (!hashResult.success) {\n return hashResult\n }\n\n const formatted = `$hai$${iterations}$${salt}$${hashResult.data}`\n return ok(formatted)\n }\n catch (error) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_passwordHashFailed'),\n error,\n )\n }\n },\n\n /**\n * 验证密码是否匹配已存储的哈希\n *\n * 从哈希字符串中解析迭代次数和盐值,重新计算后比较。\n * 格式要求: `$hai$<iterations>$<salt>$<hash>`\n *\n * @param password - 待验证的明文密码\n * @param hash - 存储的哈希值\n * @returns 成功时返回 boolean;失败时返回 INVALID_INPUT 或 VERIFY_FAILED\n */\n verify(password: string, hash: string): HaiResult<boolean> {\n try {\n if (!password || !hash) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_passwordHashEmpty'),\n )\n }\n\n const parts = hash.split('$')\n if (parts.length !== 5 || parts[1] !== 'hai') {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n\n const storedIterations = Number.parseInt(parts[2], 10)\n const salt = parts[3]\n const storedHash = parts[4]\n\n if (\n Number.isNaN(storedIterations)\n || storedIterations < MIN_ITERATIONS\n || storedIterations > MAX_ITERATIONS\n || !salt\n || !storedHash\n ) {\n return err(\n HaiCryptoError.INVALID_INPUT,\n cryptoM('crypto_hashFormatInvalid'),\n )\n }\n\n const hashResult = iterateHash(hashOps, password, salt, storedIterations)\n if (!hashResult.success) {\n return hashResult\n }\n\n return ok(core.string.constantTimeEqual(hashResult.data, storedHash))\n }\n catch (error) {\n return err(\n HaiCryptoError.VERIFY_FAILED,\n cryptoM('crypto_passwordVerifyFailed'),\n error,\n )\n }\n },\n }\n}\n","/**\n * @h-ai/crypto — 内部工具函数\n *\n * 提供 SM2/SM4 共用的编码转换辅助函数。 仅供模块内部使用,不对外导出。\n * @module crypto-utils\n */\n\n/**\n * 判断字符串是否为 Base64 格式\n *\n * 使用简单启发式:包含 +、/ 或以 = 结尾视为 base64。\n *\n * @param str - 待检测字符串\n */\nexport function isBase64(str: string): boolean {\n return str.includes('+') || str.includes('/') || str.endsWith('=')\n}\n\n/**\n * Hex 字符串转 Base64 编码\n *\n * 使用 Web 标准 API btoa,前后端通用(Node 16+ / 所有现代浏览器)。\n *\n * @param hex - 十六进制字符串(长度必须为偶数)\n * @returns Base64 编码字符串\n */\nexport function hexToBase64(hex: string): string {\n const bytes = new Uint8Array(hex.length / 2)\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16)\n }\n return btoa(String.fromCharCode(...bytes))\n}\n\n/**\n * Base64 编码转 Hex 字符串\n *\n * 使用 Web 标准 API atob,前后端通用(Node 16+ / 所有现代浏览器)。\n *\n * @param base64 - Base64 编码字符串\n * @returns 小写十六进制字符串\n */\nexport function base64ToHex(base64: string): string {\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n","/**\n * @h-ai/crypto — SM2 非对称加密\n *\n * 提供 SM2 密钥对生成、加解密、签名与验签操作。\n * @module crypto-sm2\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { AsymmetricEncryptOptions, AsymmetricOperations, KeyPair, SignOptions } from './crypto-types.js'\n\nimport { err, ok } from '@h-ai/core'\n// @ts-expect-error sm-crypto 无类型定义\nimport smCrypto from 'sm-crypto'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport {\n\n HaiCryptoError,\n\n} from './crypto-types.js'\nimport { base64ToHex, hexToBase64, isBase64 } from './crypto-utils.js'\n\nconst { sm2 } = smCrypto\nconst SM2_PUBLIC_KEY_REGEX = /^[0-9a-f]{128}$/i\nconst SM2_PRIVATE_KEY_REGEX = /^[0-9a-f]{64}$/i\n\n// ─── SM2 算法实现 ───\n\n/**\n * 创建 SM2 算法操作实例\n *\n * 基于 sm-crypto 库实现 SM2 非对称加密、签名与验签。\n * 公钥支持带/不带 04 前缀两种格式(内部统一补齐)。\n * 密文支持 hex/base64 两种格式(解密时自动检测)。\n *\n * @returns AsymmetricOperations 接口实现\n */\nexport function createSM2(): AsymmetricOperations {\n return {\n /**\n * 生成 SM2 密钥对\n *\n * @returns 成功时返回包含公钥(130 字符含 04 前缀)和私钥(64 字符)的密钥对\n */\n generateKeyPair(): HaiResult<KeyPair> {\n try {\n const keyPair = sm2.generateKeyPairHex()\n return ok({\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n })\n }\n catch (error) {\n return err(\n HaiCryptoError.KEY_GENERATION_FAILED,\n cryptoM('crypto_sm2KeyPairGenerateFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 非对称加密\n *\n * 公钥自动补齐 04 前缀;支持 hex/base64 输出。\n *\n * @param data - 待加密明文\n * @param publicKey - 公钥(支持带/不带 04 前缀)\n * @param options - 加密选项(密文模式、输出格式)\n * @returns 成功时返回密文;失败时返回 INVALID_KEY 或 ENCRYPTION_FAILED\n */\n encrypt(\n data: string,\n publicKey: string,\n options: AsymmetricEncryptOptions = {},\n ): HaiResult<string> {\n const { cipherMode = 1, outputFormat = 'hex' } = options\n\n if (!this.isValidPublicKey(publicKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PublicKeyInvalid'),\n )\n }\n\n try {\n // 确保公钥带 04 前缀\n const key = publicKey.startsWith('04') ? publicKey : `04${publicKey}`\n const encrypted = sm2.doEncrypt(data, key, cipherMode)\n\n if (!encrypted) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm2EncryptEmpty'),\n )\n }\n\n if (outputFormat === 'base64') {\n return ok(hexToBase64(encrypted))\n }\n\n return ok(encrypted)\n }\n catch (error) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm2EncryptFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 非对称解密\n *\n * 自动检测 base64 格式输入并转换为 hex 后解密。\n *\n * @param ciphertext - 密文(hex 或 base64)\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 解密选项(密文模式需与加密时一致)\n * @returns 成功时返回明文;失败时返回 INVALID_KEY 或 DECRYPTION_FAILED\n */\n decrypt(\n ciphertext: string,\n privateKey: string,\n options: AsymmetricEncryptOptions = {},\n ): HaiResult<string> {\n const { cipherMode = 1 } = options\n\n if (!this.isValidPrivateKey(privateKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PrivateKeyInvalid'),\n )\n }\n\n try {\n // 自动检测并转换 base64 格式\n let input = ciphertext\n if (isBase64(ciphertext)) {\n input = base64ToHex(ciphertext)\n }\n\n const decrypted = sm2.doDecrypt(input, privateKey, cipherMode)\n\n if (decrypted === false || decrypted === null || decrypted === undefined) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm2DecryptFailed'),\n )\n }\n\n return ok(decrypted)\n }\n catch (error) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm2DecryptFailedWithError', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 数字签名\n *\n * 默认对数据先做哈希(hash=true),使用 userId 作为签名附加参数。\n *\n * @param data - 待签名数据\n * @param privateKey - 私钥(64 字符十六进制)\n * @param options - 签名选项(hash 开关、userId)\n * @returns 成功时返回签名字符串;失败时返回 INVALID_KEY 或 SIGN_FAILED\n */\n sign(\n data: string,\n privateKey: string,\n options: SignOptions = {},\n ): HaiResult<string> {\n const { hash = true, userId = '1234567812345678' } = options\n\n if (!this.isValidPrivateKey(privateKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PrivateKeyInvalid'),\n )\n }\n\n try {\n const signature = sm2.doSignature(data, privateKey, { hash, userId })\n\n if (!signature) {\n return err(\n HaiCryptoError.SIGN_FAILED,\n cryptoM('crypto_sm2SignEmpty'),\n )\n }\n\n return ok(signature)\n }\n catch (error) {\n return err(\n HaiCryptoError.SIGN_FAILED,\n cryptoM('crypto_sm2SignFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM2 签名验证\n *\n * 公钥自动补齐 04 前缀;hash/userId 需与签名时一致。\n *\n * @param data - 原始数据\n * @param signature - 签名值\n * @param publicKey - 公钥(支持带/不带 04 前缀)\n * @param options - 验签选项(hash 开关、userId)\n * @returns 成功时返回 boolean;失败时返回 INVALID_KEY 或 VERIFY_FAILED\n */\n verify(\n data: string,\n signature: string,\n publicKey: string,\n options: SignOptions = {},\n ): HaiResult<boolean> {\n const { hash = true, userId = '1234567812345678' } = options\n\n if (!this.isValidPublicKey(publicKey)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm2PublicKeyInvalid'),\n )\n }\n\n try {\n // 确保公钥带 04 前缀\n const key = publicKey.startsWith('04') ? publicKey : `04${publicKey}`\n const isValid = sm2.doVerifySignature(data, signature, key, { hash, userId })\n return ok(!!isValid)\n }\n catch (error) {\n return err(\n HaiCryptoError.VERIFY_FAILED,\n cryptoM('crypto_sm2VerifyFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 校验公钥格式是否合法\n *\n * 合法格式:128 字符十六进制(无前缀)或 130 字符(含 04 前缀)。\n *\n * @param key - 待校验公钥\n * @returns 格式合法返回 true\n */\n isValidPublicKey(key: string): boolean {\n if (!key || typeof key !== 'string')\n return false\n // 公钥长度:无前缀 128 字符,带 04 前缀 130 字符\n const cleanKey = key.startsWith('04') ? key.slice(2) : key\n return SM2_PUBLIC_KEY_REGEX.test(cleanKey)\n },\n\n /**\n * 校验私钥格式是否合法\n *\n * 合法格式:64 字符十六进制。\n *\n * @param key - 待校验私钥\n * @returns 格式合法返回 true\n */\n isValidPrivateKey(key: string): boolean {\n if (!key || typeof key !== 'string')\n return false\n // 私钥长度:64 字符\n return SM2_PRIVATE_KEY_REGEX.test(key)\n },\n }\n}\n","/**\n * @h-ai/crypto — SM3 哈希\n *\n * 提供 SM3 消息摘要与 HMAC 操作。\n * @module crypto-sm3\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\nimport type { HashOperations, HashOptions } from './crypto-types.js'\nimport { core, err, ok } from '@h-ai/core'\n// @ts-expect-error sm-crypto 无类型定义\nimport smCrypto from 'sm-crypto'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport {\n HaiCryptoError,\n\n} from './crypto-types.js'\n\nconst { sm3 } = smCrypto\n\n// ─── SM3 算法实现 ───\n\n/**\n * 创建 SM3 算法操作实例\n *\n * 基于 sm-crypto 库实现 SM3 哈希、HMAC 与哈希验证。\n * 支持字符串(UTF-8/Hex)和 Uint8Array 输入。\n * HMAC 实现遵循 RFC 2104 标准。\n *\n * @returns HashOperations 接口实现\n */\nexport function createSM3(): HashOperations {\n return {\n /**\n * 计算 SM3 哈希\n *\n * 支持字符串(UTF-8/Hex)和 Uint8Array 输入。\n *\n * @param data - 待哈希数据\n * @param options - 输入编码与输出格式\n * @returns 成功时返回 64 字符十六进制哈希值;失败时返回 HASH_FAILED\n */\n hash(\n data: string | Uint8Array,\n options: HashOptions = {},\n ): HaiResult<string> {\n const { inputEncoding = 'utf8' } = options\n\n try {\n let input: string | number[]\n\n if (data instanceof Uint8Array) {\n // Uint8Array 转为数字数组(sm-crypto 支持的格式)\n input = Array.from(data)\n }\n else if (inputEncoding === 'hex') {\n // 十六进制字符串转为数字数组\n input = hexToBytes(data)\n }\n else {\n // UTF-8 字符串直接传入\n input = data\n }\n\n const result = sm3(input)\n\n if (!result) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_sm3HashEmpty'),\n )\n }\n\n return ok(result)\n }\n catch (error) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_sm3HashFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 计算 HMAC-SM3 消息认证码\n *\n * 实现遵循 RFC 2104;密钥超过块大小(64 字节)时先对密钥做哈希。\n *\n * @param data - 待计算数据\n * @param key - HMAC 密钥\n * @returns 成功时返回 64 字符十六进制 HMAC 值;失败时返回 HMAC_FAILED\n */\n hmac(data: string, key: string): HaiResult<string> {\n try {\n const blockSize = 64\n const opad = 0x5C\n const ipad = 0x36\n\n // 处理密钥\n let keyBytes: number[]\n if (key.length > blockSize) {\n const hashedKey = sm3(key)\n keyBytes = hexToBytes(hashedKey)\n }\n else {\n keyBytes = stringToBytes(key)\n }\n\n // 填充密钥到块大小\n while (keyBytes.length < blockSize) {\n keyBytes.push(0)\n }\n\n // 计算 iKeyPad 和 oKeyPad\n const iKeyPad = keyBytes.map(b => b ^ ipad)\n const oKeyPad = keyBytes.map(b => b ^ opad)\n\n // 计算内层哈希:H(iKeyPad || data)\n const innerInput = iKeyPad.concat(stringToBytes(data))\n const innerHash = sm3(innerInput)\n\n // 计算外层哈希:H(oKeyPad || innerHash)\n const outerInput = oKeyPad.concat(hexToBytes(innerHash))\n const result = sm3(outerInput)\n\n return ok(result)\n }\n catch (error) {\n return err(\n HaiCryptoError.HMAC_FAILED,\n cryptoM('crypto_sm3HmacFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 验证数据的哈希是否匹配\n *\n * 对数据做 SM3 哈希后与期望值比较(忽略大小写)。\n *\n * @param data - 原始数据\n * @param expectedHash - 期望的哈希值\n * @returns 成功时返回 boolean;失败时返回 HASH_FAILED\n */\n verify(data: string, expectedHash: string): HaiResult<boolean> {\n try {\n const hashResult = sm3(data)\n return ok(core.string.constantTimeEqual(hashResult.toLowerCase(), expectedHash.toLowerCase()))\n }\n catch (error) {\n return err(\n HaiCryptoError.HASH_FAILED,\n cryptoM('crypto_sm3VerifyFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n }\n}\n\n// ─── 辅助函数 ───\n\n/**\n * 十六进制字符串转字节数组\n *\n * @param hex - 十六进制字符串(长度必须为偶数)\n * @returns 字节数组\n */\nfunction hexToBytes(hex: string): number[] {\n const bytes: number[] = []\n for (let i = 0; i < hex.length; i += 2) {\n bytes.push(Number.parseInt(hex.slice(i, i + 2), 16))\n }\n return bytes\n}\n\n/**\n * UTF-8 字符串转字节数组\n *\n * 使用 TextEncoder 进行编码转换。\n *\n * @param str - UTF-8 字符串\n * @returns 字节数组\n */\nfunction stringToBytes(str: string): number[] {\n const encoder = new TextEncoder()\n return Array.from(encoder.encode(str))\n}\n","/**\n * @h-ai/crypto — SM4 对称加密\n *\n * 提供 SM4 对称加解密操作(CBC/ECB 模式)。\n * @module crypto-sm4\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n EncryptWithIVResult,\n SymmetricCiphertextEncoding,\n SymmetricDecryptInput,\n SymmetricEncryptedPayload,\n SymmetricEncryptOptions,\n SymmetricOperations,\n} from './crypto-types.js'\n\nimport { err, ok } from '@h-ai/core'\n// @ts-expect-error sm-crypto 无类型定义\nimport smCrypto from 'sm-crypto'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport {\n\n HaiCryptoError,\n\n} from './crypto-types.js'\nimport { base64ToHex, hexToBase64 } from './crypto-utils.js'\n\nconst { sm3, sm4 } = smCrypto\nconst SM4_HEX_32_REGEX = /^[0-9a-f]{32}$/i\n\n// ─── SM4 算法实现 ───\n\n/**\n * 创建 SM4 算法操作实例\n *\n * 基于 sm-crypto 库实现 SM4 对称加密/解密。\n * 支持 CBC(默认)和 ECB 两种模式,使用 PKCS#7 填充。\n * 密文以结构化字段返回,解密时不猜测字符串格式。\n *\n * @returns SymmetricOperations 接口实现\n */\nexport function createSM4(): SymmetricOperations {\n return {\n /** 生成随机密钥(16 字节 = 32 个十六进制字符) */\n generateKey(): string {\n return generateRandomHex(16)\n },\n\n /** 生成随机 IV(16 字节 = 32 个十六进制字符) */\n generateIV(): string {\n return generateRandomHex(16)\n },\n\n /**\n * SM4 对称加密\n *\n * 默认使用 CBC 并自动生成随机 IV,返回结构化字段。\n *\n * ⚠️ 安全警告:ECB 模式会让相同明文块产生相同密文块,泄漏结构信息。\n * 生产场景请使用默认 CBC,或显式传入 `{ mode: 'cbc', iv }`。\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @param options - 加密模式/IV/输出格式\n * @returns 成功时返回结构化密文;失败时返回 INVALID_KEY/INVALID_IV/ENCRYPTION_FAILED\n */\n encrypt(\n data: string,\n key: string,\n options: SymmetricEncryptOptions = {},\n ): HaiResult<SymmetricEncryptedPayload> {\n const {\n mode = 'cbc',\n iv,\n outputFormat = 'hex',\n } = options\n const actualIv = mode === 'cbc' ? iv ?? this.generateIV() : undefined\n\n if (!this.isValidKey(key)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm4KeyInvalid'),\n )\n }\n\n if (mode === 'cbc') {\n if (!actualIv || !this.isValidIV(actualIv)) {\n return err(\n HaiCryptoError.INVALID_IV,\n cryptoM('crypto_sm4IvInvalid'),\n )\n }\n }\n\n try {\n const sm4Options: Record<string, unknown> = {\n mode,\n padding: 'pkcs#7',\n }\n\n if (mode === 'cbc' && actualIv) {\n sm4Options.iv = actualIv\n }\n\n const encrypted = sm4.encrypt(data, key, sm4Options)\n\n if (!encrypted) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm4EncryptEmpty'),\n )\n }\n\n return ok({\n mode,\n ciphertext: encodeCiphertext(encrypted, outputFormat),\n ...(actualIv ? { iv: actualIv } : {}),\n encoding: outputFormat,\n })\n }\n catch (error) {\n return err(\n HaiCryptoError.ENCRYPTION_FAILED,\n cryptoM('crypto_sm4EncryptFailed', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * SM4 对称解密\n *\n * 使用结构化字段解密;解密模式、IV 与密文编码均来自 payload。\n *\n * @param payload - 结构化密文\n * @param key - 密钥(32 字符十六进制)\n * @returns 成功时返回明文;失败时返回 INVALID_KEY/INVALID_IV/DECRYPTION_FAILED\n */\n decrypt(\n payload: SymmetricDecryptInput,\n key: string,\n ): HaiResult<string> {\n const { mode, iv } = payload\n\n if (!this.isValidKey(key)) {\n return err(\n HaiCryptoError.INVALID_KEY,\n cryptoM('crypto_sm4KeyInvalid'),\n )\n }\n\n if (mode === 'cbc' && (!iv || !this.isValidIV(iv))) {\n return err(\n HaiCryptoError.INVALID_IV,\n cryptoM('crypto_sm4IvInvalid'),\n )\n }\n\n try {\n const input = decodeCiphertext(payload)\n\n const sm4Options: Record<string, unknown> = {\n mode,\n padding: 'pkcs#7',\n }\n\n if (mode === 'cbc' && iv) {\n sm4Options.iv = iv\n }\n\n const decrypted = sm4.decrypt(input, key, sm4Options)\n\n if (decrypted === false || decrypted === null || decrypted === undefined) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm4DecryptFailed'),\n )\n }\n\n return ok(decrypted)\n }\n catch (error) {\n return err(\n HaiCryptoError.DECRYPTION_FAILED,\n cryptoM('crypto_sm4DecryptFailedWithError', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n },\n\n /**\n * 带 IV 加密(CBC 模式,自动生成随机 IV)\n *\n * @param data - 待加密明文\n * @param key - 密钥(32 字符十六进制)\n * @returns 成功时返回 { ciphertext, iv };失败时同 encrypt\n */\n encryptWithIV(\n data: string,\n key: string,\n ): HaiResult<EncryptWithIVResult> {\n const iv = this.generateIV()\n const result = this.encrypt(data, key, { mode: 'cbc', iv })\n\n if (!result.success) {\n return result\n }\n\n return ok({\n mode: 'cbc',\n ciphertext: result.data.ciphertext,\n iv,\n encoding: result.data.encoding,\n })\n },\n\n /**\n * 带 IV 解密(CBC 模式)\n *\n * @param ciphertext - 密文\n * @param key - 密钥\n * @param iv - 加密时使用的 IV\n * @returns 成功时返回明文;失败时同 decrypt\n */\n decryptWithIV(\n ciphertext: string,\n key: string,\n iv: string,\n ): HaiResult<string> {\n return this.decrypt({ mode: 'cbc', ciphertext, iv, encoding: 'hex' }, key)\n },\n\n /**\n * 从密码和盐值派生密钥\n *\n * 内部仅执行单次 SM3 哈希(password + salt),取前 32 字符作为密钥。\n *\n * ⚠️ 安全警告:**此实现不是标准 KDF**,不具备密码爆破抗性(无迭代、无内存硬化)。\n * - **禁止用于密码存储**:密码散列请用 `crypto.password.hash()`。\n * - **禁止用于高价值密钥派生**:如需从密码派生加密密钥,请在应用层自行实现 PBKDF2 / scrypt / Argon2。\n * - 仅适用于测试、迭代兼容或不敏感的场景。\n *\n * @deprecated 未来版本可能移除。密码散列请用 `crypto.password.hash`;密钥派生请使用标准 KDF。\n * @param password - 密码\n * @param salt - 盐值\n * @returns 32 字符十六进制密钥\n */\n deriveKey(password: string, salt: string): string {\n const combined = password + salt\n const hash = sm3(combined)\n // 取前 32 个十六进制字符(16 字节)\n return hash.slice(0, 32)\n },\n\n /** 校验密钥格式是否合法(32 字符十六进制) */\n isValidKey(key: string): boolean {\n return SM4_HEX_32_REGEX.test(key)\n },\n\n /** 校验 IV 格式是否合法(32 字符十六进制) */\n isValidIV(iv: string): boolean {\n return SM4_HEX_32_REGEX.test(iv)\n },\n }\n}\n\n// ─── 辅助函数 ───\n\n/**\n * 生成加密安全的随机十六进制字符串\n *\n * 使用 Web Crypto API(crypto.getRandomValues),前后端通用。\n *\n * @param byteLength - 字节数(输出字符数为 byteLength × 2)\n * @returns 小写十六进制字符串\n */\nfunction generateRandomHex(byteLength: number): string {\n const bytes = new Uint8Array(byteLength)\n // Web Crypto API,前后端通用\n crypto.getRandomValues(bytes)\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('')\n}\n\n/** 按输出编码转换 SM4 hex 密文。 */\nfunction encodeCiphertext(ciphertext: string, encoding: SymmetricCiphertextEncoding): string {\n return encoding === 'base64' ? hexToBase64(ciphertext) : ciphertext\n}\n\n/** 将结构化密文转换为 sm-crypto 需要的 hex 输入。 */\nfunction decodeCiphertext(payload: SymmetricDecryptInput): string {\n return payload.encoding === 'base64' ? base64ToHex(payload.ciphertext) : payload.ciphertext\n}\n","/**\n * @h-ai/crypto — 传输加密类型与协议常量\n *\n * 提供 SM2 + SM4(或等效非对称 + 对称)混合传输加密所需的接口与协议常量,\n * 由 kit / serv / api-client 共享,确保两端协议完全一致。\n *\n * @module crypto-transport-types\n */\n\nimport type { HaiResult } from '@h-ai/core'\n\n// ─── 协议常量(kit / serv / api-client 必须严格一致) ───\n\n/**\n * 传输加密协议常量。\n *\n * 所有使用端必须复用这组常量,避免「header 名拼写漂移导致两端协议错配」。\n */\nexport const TRANSPORT_PROTOCOL = {\n /** 客户端 ID 请求头名。 */\n CLIENT_ID_HEADER: 'X-Client-Id',\n /** 标识响应体已加密的响应头名。 */\n ENCRYPTED_HEADER: 'X-Encrypted',\n /** `X-Encrypted` 响应头的开启值。 */\n ENCRYPTED_HEADER_VALUE: 'true',\n /** 密钥协商端点的默认子路径(相对于挂载前缀)。 */\n DEFAULT_KEY_EXCHANGE_PATH: '/_hai/key-exchange',\n} as const\n\n/**\n * 密钥协商请求体(客户端 → 服务端)。\n */\nexport interface KeyExchangeRequest {\n readonly clientPublicKey: string\n}\n\n/**\n * 密钥协商响应体(服务端 → 客户端)。\n */\nexport interface KeyExchangeResponse {\n readonly serverPublicKey: string\n readonly clientId: string\n}\n\n// ─── 加解密载荷 ───\n\n/** 非对称密钥对。 */\nexport interface TransportKeyPair {\n readonly publicKey: string\n readonly privateKey: string\n}\n\n/**\n * 端到端传输的加密载荷格式。\n *\n * `encryptedKey` 用对端非对称公钥加密的对称会话密钥;`ciphertext` + `iv`\n * 为该会话密钥加密的明文。两端必须使用同一份字段命名。\n */\nexport interface EncryptedPayload {\n readonly encryptedKey: string\n readonly ciphertext: string\n readonly iv: string\n}\n\n// ─── 注入式服务接口 ───\n\n/**\n * 传输加密所需的非对称 + 对称能力子集。\n *\n * 不直接依赖 `@h-ai/crypto` 的具体实现,便于测试时注入 mock;\n * 实际使用时 `crypto` 模块的实例本身即可结构兼容。\n */\nexport interface TransportCryptoServiceLike {\n asymmetric: {\n generateKeyPair: () => HaiResult<TransportKeyPair>\n encrypt: (data: string, publicKey: string) => HaiResult<string>\n decrypt: (ciphertext: string, privateKey: string) => HaiResult<string>\n }\n symmetric: {\n generateKey: () => string\n encryptWithIV: (data: string, key: string) => HaiResult<{ ciphertext: string, iv: string }>\n decryptWithIV: (ciphertext: string, key: string, iv: string) => HaiResult<string>\n }\n}\n\n// ─── 客户端密钥存储(可插拔,支持分布式) ───\n\n/**\n * 客户端公钥存储抽象。\n *\n * 默认实现为进程内 Map({@link createInMemoryKeyStore}),多节点部署时建议\n * 接入 Redis / 数据库实现以保证跨节点一致性。\n *\n * 设计原则:方法均为异步签名,避免后续替换为分布式实现时大改接口;\n * 内存实现以 `Promise.resolve` 包裹即可。\n */\nexport interface TransportKeyStore {\n /** 注册新客户端,返回服务端生成的 `clientId`。 */\n register: (publicKey: string) => Promise<string>\n /** 查询已注册客户端公钥。 */\n get: (clientId: string) => Promise<string | undefined>\n /** 主动删除(可选,便于客户端登出时清理)。 */\n delete?: (clientId: string) => Promise<void>\n /** 释放底层资源(关闭连接、清理定时器等)。 */\n close?: () => Promise<void>\n}\n\n/**\n * 创建服务端传输加密管理器的配置。\n *\n * `keyStore` 未传时,默认使用 {@link createInMemoryKeyStore};此时可通过 `maxClients`\n * 控制进程内 FIFO 容量。若传入共享 `keyStore`,则 `maxClients` 不再生效。\n */\nexport interface TransportCreateServerOptions {\n /** 客户端公钥存储;多节点部署时建议注入共享实现。 */\n readonly keyStore?: TransportKeyStore\n /** 默认内存 keyStore 的最大容量(仅当 `keyStore` 未提供时生效)。 */\n readonly maxClients?: number\n}\n\n// ─── 管理器与客户端公开接口 ───\n\n/**\n * 服务端传输加密管理器。\n *\n * 由 {@link createTransportEncryption} 创建;负责服务端密钥对持有、客户端密钥\n * 注册与请求/响应的加解密。\n *\n * @remarks\n * 典型调用顺序:\n *\n * 1. `registerClientKey(clientPublicKey)`:在密钥协商端点中保存客户端公钥,并生成 `clientId`。\n * 2. `getServerPublicKey()`:把服务端公钥返回给客户端,供后续请求加密会话密钥。\n * 3. `decryptRequest(payload)`:普通业务请求进入业务逻辑前,先把密文请求体解成明文。\n * 4. `encryptResponse(clientId, data)`:业务处理完成后,按当前客户端公钥重新加密响应体。\n * 5. `close()`:服务关闭时释放底层 keyStore 资源。\n */\nexport interface TransportEncryptionManager {\n getServerPublicKey: () => string\n registerClientKey: (clientPublicKey: string) => Promise<string>\n getClientPublicKey: (clientId: string) => Promise<string | undefined>\n encryptResponse: (clientId: string, data: string) => Promise<HaiResult<EncryptedPayload>>\n decryptRequest: (payload: EncryptedPayload) => HaiResult<string>\n /** 关闭:释放 keyStore 资源。 */\n close: () => Promise<void>\n}\n\n/**\n * 客户端传输加密会话。\n *\n * 由 {@link createTransportClient} 创建;包装宿主 `fetch`,\n * 自动完成首次密钥协商并对后续请求自动加解密。\n *\n * @remarks\n * 典型调用顺序:\n *\n * 1. `init()`(可选):预先完成一次密钥协商。\n * 2. `encryptedFetch()`:业务请求统一走这里;若当前会话尚未 ready,会先自动执行 `init()`。\n * 3. `ready()`:查看当前会话是否已经拿到 `clientId` 与服务端公钥。\n * 4. `destroy()`:登出、切租户或切环境时清空会话;下一次请求会重新协商。\n */\nexport interface TransportClient {\n /**\n * 完成密钥协商;多次调用幂等(同一会话只协商一次)。\n *\n * 通常无需手动调用:`encryptedFetch` 在首次请求前会自动 `init()`。\n */\n init: () => Promise<HaiResult<void>>\n /**\n * 包装后的 fetch;签名与全局 `fetch` 一致,请求/响应自动加解密。\n *\n * @throws 与原生 fetch 一样,网络错误、密钥协商失败、加密失败或解密失败会 reject。\n */\n encryptedFetch: typeof fetch\n /** 是否已完成密钥协商。 */\n ready: () => boolean\n /** 销毁会话(清空客户端密钥)。 */\n destroy: () => void\n}\n","/**\n * @h-ai/crypto — 传输加密客户端实现\n *\n * 提供浏览器 / Node 环境下使用的 `encryptedFetch` 包装:\n * - 首次调用前自动与服务端做一次密钥协商;\n * - 之后所有出站请求自动以混合加密包裹;\n * - 标记为 `X-Encrypted: true` 的响应自动解密。\n *\n * 与服务端协议常量统一来自 {@link TRANSPORT_PROTOCOL},确保不漂移。\n *\n * @module crypto-transport-client\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n EncryptedPayload,\n KeyExchangeResponse,\n TransportClient,\n TransportCryptoServiceLike,\n TransportKeyPair,\n} from './crypto-transport-types.js'\nimport { err, HaiCommonError, ok } from '@h-ai/core'\nimport { cryptoM } from '../crypto-i18n.js'\nimport { TRANSPORT_PROTOCOL } from './crypto-transport-types.js'\n\n/** {@link createTransportClient} 的配置项。 */\nexport interface CreateTransportClientOptions {\n /** 加密能力实现(通常直接传 `crypto` 实例)。 */\n crypto: TransportCryptoServiceLike\n /** 密钥协商完整 URL,例如 `https://api.example.com/_hai/key-exchange`。 */\n keyExchangeUrl: string\n /**\n * 实际发送 HTTP 请求的 fetch 实现;默认使用全局 `fetch`。\n *\n * 在测试中可注入 mock;在 Node < 18 环境中需注入 polyfill。\n */\n fetch?: typeof fetch\n}\n\n/**\n * 创建传输加密客户端。\n *\n * 返回的 `encryptedFetch` 与全局 `fetch` 同签名,可直接替换业务代码中的 `fetch`。\n * 内部首次请求前会自动完成密钥协商(线程安全;并发请求只触发一次协商)。\n *\n * @remarks\n * 内部流程:\n *\n * 1. `createTransportClient()` 只创建本地会话状态,不会立刻发起网络请求。\n * 2. 首次 `init()` / `encryptedFetch()` 会进入 `ensureReady()`;同一时刻只允许一个协商 Promise,避免并发重复协商。\n * 3. `doInit()` 会生成客户端非对称密钥对,并向 `keyExchangeUrl` POST `{ clientPublicKey }`。\n * 4. 服务端返回 `{ serverPublicKey, clientId }` 后,会话进入 ready 状态;后续请求复用这组协商结果。\n * 5. `encryptedFetch()` 对普通业务请求附加 `X-Client-Id`;只有请求存在 body 时,才会把 body 加密成 `{ encryptedKey, ciphertext, iv }`。\n * 6. 响应带 `X-Encrypted: true` 时自动解密;不带该标记时直接透传,便于与未启用 transport 的接口共存。\n */\nexport function createTransportClient(options: CreateTransportClientOptions): TransportClient {\n const baseFetch = options.fetch ?? fetch\n let keyPair: TransportKeyPair | null = null\n let serverPublicKey: string | null = null\n let clientId: string | null = null\n /** 进行中的协商 Promise;用于并发去重。 */\n let initPromise: Promise<HaiResult<void>> | null = null\n\n async function doInit(): Promise<HaiResult<void>> {\n const kpResult = options.crypto.asymmetric.generateKeyPair()\n if (!kpResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportClientKeyGenerateFailed'), kpResult.error)\n const localKeyPair = kpResult.data\n\n let response: Response\n try {\n response = await baseFetch(options.keyExchangeUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientPublicKey: localKeyPair.publicKey }),\n })\n }\n catch (cause) {\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportKeyExchangeRequestFailed'), cause)\n }\n\n if (!response.ok)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportKeyExchangeHttpFailed', { params: { status: response.status } }))\n\n let body: KeyExchangeResponse\n try {\n body = await response.json() as KeyExchangeResponse\n }\n catch (cause) {\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportKeyExchangeInvalidJson'), cause)\n }\n if (!body.serverPublicKey || !body.clientId)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportKeyExchangeMissingFields'))\n\n keyPair = localKeyPair\n serverPublicKey = body.serverPublicKey\n clientId = body.clientId\n return ok(undefined)\n }\n\n async function ensureReady(): Promise<HaiResult<void>> {\n if (clientId && serverPublicKey)\n return ok(undefined)\n if (!initPromise) {\n initPromise = doInit().then((result) => {\n // 失败时清空 promise,允许下次重试;成功时保留即可。\n if (!result.success)\n initPromise = null\n return result\n })\n }\n return initPromise\n }\n\n function encryptBody(plaintext: string): HaiResult<EncryptedPayload> {\n if (!serverPublicKey)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportClientNotInitialized'))\n const symKey = options.crypto.symmetric.generateKey()\n const encResult = options.crypto.symmetric.encryptWithIV(plaintext, symKey)\n if (!encResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportRequestEncryptFailed'), encResult.error)\n const keyEncResult = options.crypto.asymmetric.encrypt(symKey, serverPublicKey)\n if (!keyEncResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportSessionKeyEncryptFailed'), keyEncResult.error)\n return ok({\n encryptedKey: keyEncResult.data,\n ciphertext: encResult.data.ciphertext,\n iv: encResult.data.iv,\n })\n }\n\n function decryptPayload(payload: EncryptedPayload): HaiResult<string> {\n if (!keyPair)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportClientNotInitialized'))\n const keyDec = options.crypto.asymmetric.decrypt(payload.encryptedKey, keyPair.privateKey)\n if (!keyDec.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportSessionKeyDecryptFailed'), keyDec.error)\n const dec = options.crypto.symmetric.decryptWithIV(payload.ciphertext, keyDec.data, payload.iv)\n if (!dec.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportResponseDecryptFailed'), dec.error)\n return ok(dec.data)\n }\n\n const encryptedFetch: typeof fetch = async (input, init) => {\n const requestInput = isRequestLike(input) ? input : undefined\n // 密钥协商请求本身不加密,避免无限递归。\n const targetUrl = typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.toString()\n : requestInput?.url ?? String(input)\n if (targetUrl === options.keyExchangeUrl)\n return baseFetch(input, init)\n\n const ready = await ensureReady()\n if (!ready.success)\n throw new Error(ready.error.message)\n\n // 复制并改造 init:附加 X-Client-Id;若有 body,则加密。\n const headers = new Headers(init?.headers ?? requestInput?.headers)\n headers.set(TRANSPORT_PROTOCOL.CLIENT_ID_HEADER, clientId!)\n\n // 兼容 oRPC 等场景:body 可能在 Request 上而非 init.body。\n let rawBody: BodyInit | null | undefined = init?.body\n if (rawBody == null && requestInput) {\n const method = (init?.method ?? requestInput.method).toUpperCase()\n if (method !== 'GET' && method !== 'HEAD') {\n const text = await requestInput.clone().text()\n if (text)\n rawBody = text\n }\n }\n\n let nextBody: BodyInit | null | undefined = rawBody\n if (rawBody != null) {\n const plaintext = await bodyToText(rawBody)\n const encResult = encryptBody(plaintext)\n if (!encResult.success)\n throw new Error(encResult.error.message)\n nextBody = JSON.stringify(encResult.data)\n headers.set('Content-Type', 'application/json')\n headers.set(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER, TRANSPORT_PROTOCOL.ENCRYPTED_HEADER_VALUE)\n }\n\n // 当 input 是已带 body 的 Request 时,必须改用 URL 字符串作为 input,\n // 否则底层 fetch 会优先读取原始 Request 上的明文 body,覆盖我们的密文。\n const finalInput: RequestInfo | URL = requestInput ? requestInput.url : input\n const finalInit: RequestInit = {\n ...init,\n method: init?.method ?? requestInput?.method,\n headers,\n body: nextBody,\n cache: init?.cache ?? requestInput?.cache,\n credentials: init?.credentials ?? requestInput?.credentials,\n integrity: init?.integrity ?? requestInput?.integrity,\n keepalive: init?.keepalive ?? requestInput?.keepalive,\n mode: init?.mode ?? requestInput?.mode,\n redirect: init?.redirect ?? requestInput?.redirect,\n referrer: init?.referrer ?? requestInput?.referrer,\n referrerPolicy: init?.referrerPolicy ?? requestInput?.referrerPolicy,\n signal: init?.signal ?? requestInput?.signal,\n }\n const response = await baseFetch(finalInput, finalInit)\n\n // 响应未加密:直接返回。\n if (response.headers.get(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER) !== TRANSPORT_PROTOCOL.ENCRYPTED_HEADER_VALUE)\n return response\n\n const cloned = response.clone()\n let payload: unknown\n try {\n payload = await cloned.json()\n }\n catch {\n return response\n }\n if (!isEncryptedPayload(payload))\n return response\n\n const decResult = decryptPayload(payload)\n if (!decResult.success)\n throw new Error(decResult.error.message)\n\n // 透传原响应头但去掉加密标记;Content-Type 还原为下游可能期望的 JSON。\n const respHeaders = new Headers(response.headers)\n respHeaders.delete(TRANSPORT_PROTOCOL.ENCRYPTED_HEADER)\n respHeaders.delete('Content-Length')\n return new Response(decResult.data, {\n status: response.status,\n statusText: response.statusText,\n headers: respHeaders,\n })\n }\n\n return {\n init: ensureReady,\n encryptedFetch,\n ready: () => clientId !== null && serverPublicKey !== null,\n destroy() {\n keyPair = null\n serverPublicKey = null\n clientId = null\n initPromise = null\n },\n }\n}\n\n/** 把任意 `BodyInit` 转为字符串明文,便于统一加密。 */\nasync function bodyToText(body: BodyInit): Promise<string> {\n if (typeof body === 'string')\n return body\n if (body instanceof URLSearchParams)\n return body.toString()\n if (body instanceof Blob)\n return body.text()\n if (body instanceof ArrayBuffer)\n return new TextDecoder().decode(body)\n if (ArrayBuffer.isView(body))\n return new TextDecoder().decode(body.buffer as ArrayBuffer)\n // FormData / ReadableStream:转为 Response 再读 text,由运行时序列化。\n return new Response(body as BodyInit).text()\n}\n\nfunction isRequestLike(input: RequestInfo | URL): input is Request {\n if (typeof input !== 'object' || input === null)\n return false\n\n const candidate = input as Partial<Request>\n const headers = candidate.headers as { get?: unknown } | undefined\n return typeof candidate.url === 'string'\n && typeof headers?.get === 'function'\n && typeof candidate.method === 'string'\n && typeof candidate.clone === 'function'\n}\n\nfunction isEncryptedPayload(payload: unknown): payload is EncryptedPayload {\n if (!payload || typeof payload !== 'object')\n return false\n const p = payload as Record<string, unknown>\n return typeof p.encryptedKey === 'string' && typeof p.ciphertext === 'string' && typeof p.iv === 'string'\n}\n","/**\n * @h-ai/crypto — 传输加密内存 key store\n *\n * 提供默认的进程内客户端公钥存储实现。\n * @module crypto-transport-store-memory\n */\n\nimport type { TransportKeyStore } from '../crypto-transport-types.js'\n\nconst DEFAULT_MAX_CLIENTS = 10000\n\nfunction normalizeMaxClients(maxClients: number): number {\n if (!Number.isFinite(maxClients))\n return DEFAULT_MAX_CLIENTS\n return Math.max(1, Math.floor(maxClients))\n}\n\nfunction createClientId(counter: number): string {\n const entropy = typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function'\n ? crypto.randomUUID().replace(/-/g, '')\n : Math.random().toString(36).slice(2, 12)\n\n return `c_${counter}_${Date.now()}_${entropy}`\n}\n\n/**\n * 创建进程内 FIFO 客户端密钥存储。\n *\n * ⚠️ 进程内实现:多节点部署时需让客户端首次请求后保持「会话粘性」(sticky session),\n * 否则后续请求路由到其他节点会因找不到客户端公钥而失败。需要跨节点请改用\n * Redis / 数据库实现 {@link TransportKeyStore}。\n *\n * @param maxClients - 最大客户端数(默认 10000),超过后按注册顺序淘汰最早条目。\n */\nexport function createInMemoryKeyStore(maxClients = DEFAULT_MAX_CLIENTS): TransportKeyStore {\n const clientKeys = new Map<string, string>()\n const capacity = normalizeMaxClients(maxClients)\n let counter = 0\n\n return {\n async register(publicKey) {\n counter++\n const clientId = createClientId(counter)\n\n if (clientKeys.size >= capacity) {\n const oldest = clientKeys.keys().next().value\n if (oldest !== undefined)\n clientKeys.delete(oldest)\n }\n\n clientKeys.set(clientId, publicKey)\n return clientId\n },\n\n async get(clientId) {\n return clientKeys.get(clientId)\n },\n\n async delete(clientId) {\n clientKeys.delete(clientId)\n },\n\n async close() {\n clientKeys.clear()\n },\n }\n}\n","/**\n * @h-ai/crypto — 传输加密服务端实现\n *\n * 提供服务端传输加密管理器工厂。\n *\n * @module crypto-transport-server\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type {\n EncryptedPayload,\n TransportCreateServerOptions,\n TransportCryptoServiceLike,\n TransportEncryptionManager,\n TransportKeyPair,\n} from './crypto-transport-types.js'\nimport { err, HaiCommonError, ok } from '@h-ai/core'\nimport { cryptoM } from '../crypto-i18n.js'\nimport { createInMemoryKeyStore } from './store-provider/crypto-transport-store-memory.js'\n\n/**\n * 创建传输加密管理器。\n *\n * 启动时生成服务端非对称密钥对,所有客户端公钥由 `keyStore` 管理。\n *\n * @param cryptoService - 注入的非对称 + 对称加密实现(通常直接传入 `crypto` 实例)。\n * @param options - 可选配置。\n * @returns 成功返回管理器;密钥对生成失败返回 `HaiCommonError.INTERNAL_ERROR`。\n *\n * @remarks\n * 内部流程:\n *\n * 1. 创建时先生成一对服务端非对称密钥,并准备 `keyStore`。\n * 2. 上层在密钥协商端点中调用 `registerClientKey()` 保存客户端公钥,再把 `getServerPublicKey()` 返回给客户端。\n * 3. 普通业务请求到达时,上层先根据 `clientId` 确认客户端已注册,再调用 `decryptRequest()` 拿到明文请求体。\n * 4. 业务逻辑完成后,上层调用 `encryptResponse(clientId, data)` 为该客户端生成密文响应。\n * 5. `close()` 负责清理 `keyStore` 等底层资源。\n *\n * 若使用 `@h-ai/serv` / `@h-ai/kit`,上述 HTTP 协商与请求包装流程通常已由上层封装完成。\n */\nexport function createTransportEncryption(\n cryptoService: TransportCryptoServiceLike,\n options: TransportCreateServerOptions = {},\n): HaiResult<TransportEncryptionManager> {\n const keyPairResult = cryptoService.asymmetric.generateKeyPair()\n if (!keyPairResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportServerKeyGenerateFailed'), keyPairResult.error)\n const serverKeyPair: TransportKeyPair = keyPairResult.data\n const keyStore = options.keyStore ?? createInMemoryKeyStore(options.maxClients)\n\n const manager: TransportEncryptionManager = {\n getServerPublicKey() {\n return serverKeyPair.publicKey\n },\n\n async registerClientKey(clientPublicKey) {\n return keyStore.register(clientPublicKey)\n },\n\n async getClientPublicKey(clientId) {\n return keyStore.get(clientId)\n },\n\n async encryptResponse(clientId, data) {\n const clientPublicKey = await keyStore.get(clientId)\n if (!clientPublicKey)\n return err(HaiCommonError.NOT_FOUND, cryptoM('crypto_transportClientNotRegistered'))\n\n // 1. 生成随机会话密钥;2. 用会话密钥加密内容;3. 用客户端公钥加密会话密钥。\n const symmetricKey = cryptoService.symmetric.generateKey()\n const encResult = cryptoService.symmetric.encryptWithIV(data, symmetricKey)\n if (!encResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportResponseEncryptFailed'), encResult.error)\n const keyEncResult = cryptoService.asymmetric.encrypt(symmetricKey, clientPublicKey)\n if (!keyEncResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportSessionKeyEncryptFailed'), keyEncResult.error)\n\n const payload: EncryptedPayload = {\n encryptedKey: keyEncResult.data,\n ciphertext: encResult.data.ciphertext,\n iv: encResult.data.iv,\n }\n return ok(payload)\n },\n\n decryptRequest(payload) {\n // 1. 用服务端私钥解出会话密钥;2. 用会话密钥解出明文。\n const keyDecResult = cryptoService.asymmetric.decrypt(payload.encryptedKey, serverKeyPair.privateKey)\n if (!keyDecResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportSessionKeyDecryptFailed'), keyDecResult.error)\n const decResult = cryptoService.symmetric.decryptWithIV(payload.ciphertext, keyDecResult.data, payload.iv)\n if (!decResult.success)\n return err(HaiCommonError.INTERNAL_ERROR, cryptoM('crypto_transportRequestDecryptFailed'), decResult.error)\n return ok(decResult.data)\n },\n\n async close() {\n await keyStore.close?.()\n },\n }\n\n return ok(manager)\n}\n\n/**\n * 判断对象是否为合法 {@link EncryptedPayload}。\n *\n * 字段必须为非空字符串。用于服务端在调用 `decryptRequest` 前做形状校验,\n * 把畸形请求拦截在加密层之外。\n */\nexport function isValidEncryptedPayload(payload: unknown): payload is EncryptedPayload {\n if (!payload || typeof payload !== 'object')\n return false\n const p = payload as Record<string, unknown>\n return (\n typeof p.encryptedKey === 'string' && p.encryptedKey.length > 0\n && typeof p.ciphertext === 'string' && p.ciphertext.length > 0\n && typeof p.iv === 'string' && p.iv.length > 0\n )\n}\n","/**\n * @h-ai/crypto — 加密服务主入口\n *\n * 提供统一的 `crypto` 对象,聚合所有结构化加密操作。\n * @module crypto-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { AsymmetricOperations, CryptoFunctions, HashOperations, PasswordOperations, SymmetricOperations, TransportOperations } from './crypto-types.js'\n\nimport { core, err, ok } from '@h-ai/core'\n\nimport { cryptoM } from './crypto-i18n.js'\nimport { createPasswordFunctions } from './crypto-password.js'\nimport { createSM2 } from './crypto-sm2.js'\nimport { createSM3 } from './crypto-sm3.js'\nimport { createSM4 } from './crypto-sm4.js'\nimport {\n\n HaiCryptoError,\n\n} from './crypto-types.js'\nimport { createTransportClient } from './transport/crypto-transport-client.js'\nimport { createTransportEncryption } from './transport/crypto-transport-server.js'\nimport { TRANSPORT_PROTOCOL } from './transport/crypto-transport-types.js'\n\nconst logger = core.logger.child({ module: 'crypto', scope: 'main' })\n\n// ─── 内部状态 ───\n\n/** 是否已初始化 */\nlet initialized = false\n/** 并发初始化防护标志 */\nlet initInProgress = false\n/** 当前非对称加密操作实例 */\nlet currentAsymmetric: AsymmetricOperations | null = null\n/** 当前哈希操作实例 */\nlet currentHash: HashOperations | null = null\n/** 当前对称加密操作实例 */\nlet currentSymmetric: SymmetricOperations | null = null\n/** 当前密码哈希操作实例 */\nlet currentPassword: PasswordOperations | null = null\n\n// ─── 未初始化占位 ───\n\nconst notInitialized = core.module.createNotInitializedKit(\n HaiCryptoError.NOT_INITIALIZED,\n () => cryptoM('crypto_notInitialized'),\n)\n\nconst notInitializedAsymmetric = notInitialized.proxy<AsymmetricOperations>('sync')\nconst notInitializedHash = notInitialized.proxy<HashOperations>('sync')\nconst notInitializedSymmetric = notInitialized.proxy<SymmetricOperations>('sync')\nconst notInitializedPassword = notInitialized.proxy<PasswordOperations>('sync')\n\n// ─── 传输加密 ───\n// 直接复用顶层 `crypto`:未初始化时 asymmetric/symmetric 会自动返回\n// NOT_INITIALIZED 错误,无需额外 proxy。\n\n// 通过函数声明(hoisted)延迟引用 `crypto`,避免 use-before-define 报错;\n// 实际调用发生在 init 之后,闭包持有的引用是安全的。\nfunction getCrypto(): CryptoFunctions {\n // eslint-disable-next-line ts/no-use-before-define\n return crypto\n}\nconst transportOperations: TransportOperations = {\n createServer: options => createTransportEncryption(getCrypto(), options),\n createClient: options => createTransportClient({ crypto: getCrypto(), ...options }),\n protocol: TRANSPORT_PROTOCOL,\n}\n\n// ─── 服务对象 ───\n\n/**\n * 加密模块服务对象(统一入口)\n *\n * 使用前必须调用 `crypto.init()` 进行初始化。\n * 未初始化时访问 asymmetric/hash/symmetric/password 的任何方法均返回 NOT_INITIALIZED 错误。\n *\n * @example\n * ```ts\n * import { crypto } from '@h-ai/crypto'\n *\n * await crypto.init()\n * const hash = crypto.hash.hash('hello')\n * const keyPair = crypto.asymmetric.generateKeyPair()\n * await crypto.close()\n * ```\n */\nexport const crypto: CryptoFunctions = {\n /**\n * 初始化加密模块\n *\n * 创建非对称/哈希/对称/密码哈希操作实例。\n * 重复调用会先关闭再重新初始化。\n *\n * @returns 成功时返回 ok(undefined);失败时返回 INIT_FAILED\n */\n async init(): Promise<HaiResult<void>> {\n // 并发初始化防护:避免多次 init 同时执行导致资源泄漏\n if (initInProgress) {\n logger.warn('Crypto init already in progress, skipping concurrent call')\n return err(\n HaiCryptoError.INIT_FAILED,\n cryptoM('crypto_initFailed', { params: { error: 'Concurrent initialization detected' } }),\n )\n }\n initInProgress = true\n\n try {\n // 让并发调用有机会观察到 initInProgress,确保防护逻辑真实生效。\n await Promise.resolve()\n\n if (initialized) {\n logger.warn('Crypto module is already initialized, reinitializing')\n await crypto.close()\n }\n\n logger.info('Initializing crypto module')\n\n currentAsymmetric = createSM2()\n currentHash = createSM3()\n currentSymmetric = createSM4()\n currentPassword = createPasswordFunctions({ hash: currentHash })\n initialized = true\n logger.info('Crypto module initialized')\n return ok(undefined)\n }\n catch (error) {\n // 清理部分赋值的状态\n currentAsymmetric = null\n currentHash = null\n currentSymmetric = null\n currentPassword = null\n initialized = false\n logger.error('Crypto module initialization failed', { error })\n return err(\n HaiCryptoError.INIT_FAILED,\n cryptoM('crypto_initFailed', {\n params: { error: error instanceof Error ? error.message : String(error) },\n }),\n error,\n )\n }\n finally {\n initInProgress = false\n }\n },\n\n /** 非对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get asymmetric(): AsymmetricOperations { return currentAsymmetric ?? notInitializedAsymmetric },\n /** 哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get hash(): HashOperations { return currentHash ?? notInitializedHash },\n /** 对称加密操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get symmetric(): SymmetricOperations { return currentSymmetric ?? notInitializedSymmetric },\n /** 密码哈希操作(未初始化时所有方法返回 NOT_INITIALIZED) */\n get password(): PasswordOperations { return currentPassword ?? notInitializedPassword },\n /**\n * 传输加密操作(端到端混合加密)\n *\n * createServer 内部直接复用 asymmetric/symmetric,因此未初始化时\n * 自动通过 asymmetric proxy 返回 NOT_INITIALIZED 错误。\n */\n transport: transportOperations,\n /** 是否已初始化 */\n get isInitialized() { return initialized },\n\n /**\n * 关闭加密模块,释放内部状态\n *\n * 关闭后访问 asymmetric/hash/symmetric/password 会返回 NOT_INITIALIZED 错误。\n */\n async close() {\n if (!initialized) {\n logger.info('Crypto module already closed, skipping')\n return\n }\n\n logger.info('Closing crypto module')\n\n currentAsymmetric = null\n currentHash = null\n currentSymmetric = null\n currentPassword = null\n initialized = false\n\n logger.info('Crypto module closed')\n },\n}\n","/**\n * @h-ai/crypto — 传输加密 Redis key store\n *\n * 通过 `@h-ai/cache` 持久化客户端公钥;通常应传入已初始化为 Redis 的 `cache` 实例。\n * @module crypto-transport-store-redis\n */\n\nimport type { CacheFunctions } from '@h-ai/cache'\nimport type { HaiError, HaiResult } from '@h-ai/core'\nimport type { TransportKeyStore } from '../crypto-transport-types.js'\n\nconst TRANSPORT_KEY_CACHE_PREFIX = 'hai:crypto:transport:client'\n\n/** 创建 Redis 版传输 key store 的配置。 */\nexport interface CreateRedisTransportKeyStoreOptions {\n /** 已初始化的 `@h-ai/cache` 实例;生产环境通常应使用 Redis provider。 */\n readonly cache: CacheFunctions\n /** 客户端公钥的 TTL(秒);未传则保持不过期。 */\n readonly ttlSeconds?: number\n}\n\nfunction normalizeTtlSeconds(ttlSeconds: number | undefined): number | undefined {\n if (ttlSeconds === undefined || !Number.isFinite(ttlSeconds) || ttlSeconds <= 0)\n return undefined\n return Math.floor(ttlSeconds)\n}\n\nfunction createClientId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function')\n return `c_${crypto.randomUUID()}`\n\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 12)}`\n}\n\nfunction toOperationError(operation: string, error: HaiError): Error {\n const wrapped = new Error(`${operation} failed: ${error.message}`, { cause: error }) as Error & { code?: string | number }\n wrapped.code = error.code\n return wrapped\n}\n\nfunction unwrapResult<T>(operation: string, result: HaiResult<T>): T {\n if (result.success)\n return result.data\n throw toOperationError(operation, result.error)\n}\n\n/**\n * 创建基于 `@h-ai/cache` 的传输 key store。\n *\n * 说明:本实现依赖 cache 模块的 KV 语义;若要获得跨节点共享能力,应传入\n * 已连接 Redis 的 `cache` 实例,而不是内存 provider。\n */\nexport function createRedisTransportKeyStore(options: CreateRedisTransportKeyStoreOptions): TransportKeyStore {\n const ttlSeconds = normalizeTtlSeconds(options.ttlSeconds)\n\n function buildCacheKey(clientId: string): string {\n return `${TRANSPORT_KEY_CACHE_PREFIX}:${clientId}`\n }\n\n return {\n async register(publicKey) {\n const clientId = createClientId()\n unwrapResult(\n 'cache.kv.set',\n await options.cache.kv.set(\n buildCacheKey(clientId),\n publicKey,\n ttlSeconds === undefined ? undefined : { ex: ttlSeconds },\n ),\n )\n return clientId\n },\n\n async get(clientId) {\n const publicKey = unwrapResult(\n 'cache.kv.get',\n await options.cache.kv.get<string>(buildCacheKey(clientId)),\n )\n return publicKey ?? undefined\n },\n\n async delete(clientId) {\n unwrapResult('cache.kv.del', await options.cache.kv.del(buildCacheKey(clientId)))\n },\n }\n}\n","/**\n * @h-ai/crypto — 传输加密关系数据库 key store\n *\n * 通过 `@h-ai/reldb` 保存客户端公钥,适用于需要跨节点共享状态的服务端部署。\n * @module crypto-transport-store-reldb\n */\n\nimport type { HaiError, HaiResult } from '@h-ai/core'\nimport type { ReldbFunctions } from '@h-ai/reldb'\nimport type { TransportKeyStore } from '../crypto-transport-types.js'\n\nconst TRANSPORT_KEY_TABLE = 'hai_crypto_transport_client_keys'\n\ninterface TransportClientKeyRow {\n readonly public_key: string\n readonly expires_at: string | null\n}\n\n/** 创建关系数据库版传输 key store 的配置。 */\nexport interface CreateReldbTransportKeyStoreOptions {\n /** 已初始化的 `@h-ai/reldb` 实例。 */\n readonly reldb: ReldbFunctions\n /** 客户端公钥的 TTL(秒);未传则保持不过期。 */\n readonly ttlSeconds?: number\n}\n\nfunction normalizeTtlSeconds(ttlSeconds: number | undefined): number | undefined {\n if (ttlSeconds === undefined || !Number.isFinite(ttlSeconds) || ttlSeconds <= 0)\n return undefined\n return Math.floor(ttlSeconds)\n}\n\nfunction createClientId(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function')\n return `c_${crypto.randomUUID()}`\n\n return `c_${Date.now()}_${Math.random().toString(36).slice(2, 12)}`\n}\n\nfunction toOperationError(operation: string, error: HaiError): Error {\n const wrapped = new Error(`${operation} failed: ${error.message}`, { cause: error }) as Error & { code?: string | number }\n wrapped.code = error.code\n return wrapped\n}\n\nfunction unwrapResult<T>(operation: string, result: HaiResult<T>): T {\n if (result.success)\n return result.data\n throw toOperationError(operation, result.error)\n}\n\n/**\n * 创建基于 `@h-ai/reldb` 的传输 key store。\n *\n * 首次读写时会自动创建 `hai_crypto_transport_client_keys` 表。\n */\nexport function createReldbTransportKeyStore(options: CreateReldbTransportKeyStoreOptions): TransportKeyStore {\n const ttlSeconds = normalizeTtlSeconds(options.ttlSeconds)\n let ensureTablePromise: Promise<void> | null = null\n\n async function ensureTable(): Promise<void> {\n if (!ensureTablePromise) {\n ensureTablePromise = (async () => {\n unwrapResult(\n 'reldb.ddl.createTable',\n await options.reldb.ddl.createTable(TRANSPORT_KEY_TABLE, {\n client_id: { type: 'TEXT', primaryKey: true },\n public_key: { type: 'TEXT', notNull: true },\n created_at: { type: 'TIMESTAMP', notNull: true },\n expires_at: { type: 'TIMESTAMP' },\n }, true),\n )\n })()\n }\n\n return ensureTablePromise\n }\n\n async function deleteClientKey(clientId: string): Promise<void> {\n unwrapResult(\n 'reldb.sql.execute',\n await options.reldb.sql.execute(\n `DELETE FROM ${TRANSPORT_KEY_TABLE} WHERE client_id = ?`,\n [clientId],\n ),\n )\n }\n\n return {\n async register(publicKey) {\n await ensureTable()\n\n const clientId = createClientId()\n const createdAt = new Date().toISOString()\n const expiresAt = ttlSeconds === undefined\n ? null\n : new Date(Date.now() + ttlSeconds * 1000).toISOString()\n\n unwrapResult(\n 'reldb.sql.execute',\n await options.reldb.sql.execute(\n `INSERT INTO ${TRANSPORT_KEY_TABLE} (client_id, public_key, created_at, expires_at) VALUES (?, ?, ?, ?)`,\n [clientId, publicKey, createdAt, expiresAt],\n ),\n )\n\n return clientId\n },\n\n async get(clientId) {\n await ensureTable()\n\n const row = unwrapResult(\n 'reldb.sql.get',\n await options.reldb.sql.get<TransportClientKeyRow>(\n `SELECT public_key, expires_at FROM ${TRANSPORT_KEY_TABLE} WHERE client_id = ?`,\n [clientId],\n ),\n )\n\n if (!row)\n return undefined\n\n if (row.expires_at && Date.parse(row.expires_at) <= Date.now()) {\n await deleteClientKey(clientId)\n return undefined\n }\n\n return row.public_key\n },\n\n async delete(clientId) {\n await ensureTable()\n await deleteClientKey(clientId)\n },\n }\n}\n"]}
|