liangzimixin 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2233,7 +2233,7 @@ var require_websocket = __commonJS({
2233
2233
  var http = require("http");
2234
2234
  var net = require("net");
2235
2235
  var tls = require("tls");
2236
- var { randomBytes: randomBytes2, createHash } = require("crypto");
2236
+ var { randomBytes: randomBytes3, createHash } = require("crypto");
2237
2237
  var { Duplex, Readable } = require("stream");
2238
2238
  var { URL: URL2 } = require("url");
2239
2239
  var PerMessageDeflate = require_permessage_deflate();
@@ -2763,7 +2763,7 @@ var require_websocket = __commonJS({
2763
2763
  }
2764
2764
  }
2765
2765
  const defaultPort = isSecure ? 443 : 80;
2766
- const key = randomBytes2(16).toString("base64");
2766
+ const key = randomBytes3(16).toString("base64");
2767
2767
  const request = isSecure ? https.request : http.request;
2768
2768
  const protocolSet = /* @__PURE__ */ new Set();
2769
2769
  let perMessageDeflate;
@@ -18812,54 +18812,104 @@ var quantumImPlugin = {
18812
18812
  }
18813
18813
  };
18814
18814
 
18815
- // src/crypto/quantun-plug-adapter.ts
18816
- var import_node_module = require("module");
18817
- var import_meta = {};
18818
- var log14 = createLogger("crypto/quantun-plug-adapter");
18819
- var SM4_MODE = {
18820
- ECB_NOPADDING: 1,
18821
- ECB_PKCS7PADDING: 2,
18822
- CBC_NOPADDING: 3,
18823
- CBC_PKCS7PADDING: 4
18815
+ // src/crypto/quantun-plug-mock.ts
18816
+ var import_node_crypto = require("crypto");
18817
+ var log14 = createLogger("crypto/quantun-plug-mock");
18818
+ var MOCK_KEY = Buffer.alloc(32, 0);
18819
+ MOCK_KEY.write("quantum-mock-key-2026", 0);
18820
+ var MOCK_KEY_ID = "mock-key-v1";
18821
+ var initialized = false;
18822
+ var quantunPlugMock = {
18823
+ /**
18824
+ * 初始化 Mock SDK
18825
+ * 幂等操作 — 重复调用不会报错
18826
+ */
18827
+ async init() {
18828
+ if (initialized) return;
18829
+ initialized = true;
18830
+ log14.warn("\u26A0\uFE0F MOCK MODE \u2014 \u4F7F\u7528 AES-256-GCM \u6A21\u62DF\u91CF\u5B50\u52A0\u5BC6");
18831
+ },
18832
+ /**
18833
+ * 加密明文 → 密文 + 密钥标识
18834
+ *
18835
+ * 内部流程:
18836
+ * 1. 生成 12 字节随机 IV (确保每次加密结果不同)
18837
+ * 2. AES-256-GCM 加密明文
18838
+ * 3. 获取 16 字节 AuthTag (认证标签,防篡改)
18839
+ * 4. 拼接 [IV(12) | Tag(16) | Ciphertext] → Base64 编码
18840
+ */
18841
+ async encrypt(plaintext, mode) {
18842
+ if (!initialized) {
18843
+ throw new Error("quantunPlug not initialized \u2014 call init() first");
18844
+ }
18845
+ const iv = (0, import_node_crypto.randomBytes)(12);
18846
+ const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", MOCK_KEY, iv);
18847
+ const encrypted = Buffer.concat([
18848
+ cipher.update(plaintext, "utf-8"),
18849
+ cipher.final()
18850
+ ]);
18851
+ const tag = cipher.getAuthTag();
18852
+ const combined = Buffer.concat([iv, tag, encrypted]);
18853
+ return {
18854
+ ciphertext: combined.toString("base64"),
18855
+ keyId: MOCK_KEY_ID
18856
+ };
18857
+ },
18858
+ /**
18859
+ * 解密密文 → 明文
18860
+ *
18861
+ * 内部流程:
18862
+ * 1. Base64 解码
18863
+ * 2. 拆分 IV(12) + Tag(16) + Ciphertext
18864
+ * 3. AES-256-GCM 解密 + AuthTag 验证
18865
+ * 4. 返回 UTF-8 明文
18866
+ *
18867
+ * @throws AuthTag 验证失败时抛出异常 (数据被篡改)
18868
+ */
18869
+ async decrypt(ciphertext, keyId, mode) {
18870
+ if (!initialized) {
18871
+ throw new Error("quantunPlug not initialized \u2014 call init() first");
18872
+ }
18873
+ const combined = Buffer.from(ciphertext, "base64");
18874
+ const iv = combined.subarray(0, 12);
18875
+ const tag = combined.subarray(12, 28);
18876
+ const encrypted = combined.subarray(28);
18877
+ const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", MOCK_KEY, iv);
18878
+ decipher.setAuthTag(tag);
18879
+ const decrypted = Buffer.concat([
18880
+ decipher.update(encrypted),
18881
+ decipher.final()
18882
+ // 此处 Tag 验证失败会抛出异常
18883
+ ]);
18884
+ return {
18885
+ plaintext: decrypted.toString("utf-8")
18886
+ };
18887
+ }
18824
18888
  };
18825
- var DEFAULT_ENCRYPT_MODE = SM4_MODE.CBC_PKCS7PADDING;
18826
- var require2 = (0, import_node_module.createRequire)(import_meta.url);
18827
- var quantunPlug = null;
18828
- try {
18829
- quantunPlug = require2("./sdk/index.min.cjs");
18830
- log14.info("Quantum SDK loaded from sdk/index.min.cjs");
18831
- } catch (err) {
18832
- const msg = err instanceof Error ? err.message : String(err);
18833
- log14.warn("Quantum SDK missing, only passthrough mode will work:", msg);
18834
- }
18835
- var quantun_plug_adapter_default = quantunPlug;
18889
+ var quantun_plug_mock_default = quantunPlugMock;
18836
18890
 
18837
18891
  // src/crypto/crypto-engine.ts
18838
18892
  var log15 = createLogger("crypto/crypto-engine");
18839
18893
  var PASSTHROUGH_KEY_ID = "passthrough";
18840
- var FILE_CHUNK_SIZE = 10 * 1024 * 1024;
18841
- var FILE_DECRYPT_CHUNK_SIZE = FILE_CHUNK_SIZE + 16;
18842
18894
  var CryptoEngine = class _CryptoEngine {
18843
- /** 底层量子加密 SDK 实例, 透传模式下为 null */
18895
+ /** 底层量子加密 SDK 实例 (Mock 或真实), 透传模式下为 null */
18844
18896
  plug;
18845
18897
  /** SDK 是否已完成初始化 */
18846
- initialized;
18898
+ initialized = false;
18847
18899
  /** 是否为透传模式 (不加密, 明文直接透传) */
18848
18900
  passthrough;
18849
18901
  /**
18850
- * 构造加密引擎
18902
+ * 构造加密引擎 (加密模式)
18851
18903
  *
18852
- * @param passthrough - true 为透传模式 (不加密); false 为加密模式 (默认)
18904
+ * 当前默认使用 Mock SDK。
18905
+ * 待真实 SDK 交付后,此处替换为 require('./quantunPlug.ejs')。
18853
18906
  *
18854
- * 请使用静态工厂方法:
18855
- * - new CryptoEngine() → 加密模式, 使用量子 SDK
18856
- * - CryptoEngine.createPassthrough() → 透传模式, 无需 init()
18907
+ * 如需透传模式,请使用静态方法 CryptoEngine.createPassthrough()。
18857
18908
  */
18858
- constructor(passthrough = false) {
18859
- this.passthrough = passthrough;
18860
- this.plug = passthrough ? null : quantun_plug_adapter_default;
18861
- this.initialized = passthrough;
18862
- log15.info(`CryptoEngine created (${passthrough ? "passthrough mode \u2014 crypto disabled" : "quantum SDK mode"})`);
18909
+ constructor() {
18910
+ this.plug = quantun_plug_mock_default;
18911
+ this.passthrough = false;
18912
+ log15.info("CryptoEngine created (mock mode)");
18863
18913
  }
18864
18914
  /**
18865
18915
  * 创建透传模式的加密引擎 (静态工厂方法)
@@ -18873,12 +18923,17 @@ var CryptoEngine = class _CryptoEngine {
18873
18923
  * 上层模块 (TokenStore, MessagePipe) 无需感知加密是否开启。
18874
18924
  */
18875
18925
  static createPassthrough() {
18876
- return new _CryptoEngine(true);
18926
+ const instance = Object.create(_CryptoEngine.prototype);
18927
+ instance.plug = null;
18928
+ instance.passthrough = true;
18929
+ instance.initialized = true;
18930
+ log15.info("CryptoEngine created (passthrough mode \u2014 crypto disabled)");
18931
+ return instance;
18877
18932
  }
18878
18933
  /**
18879
18934
  * 初始化加密引擎
18880
18935
  *
18881
- * 加密模式: 调用 SDK 的 init() 方法完成密服入网、密钥协商等初始化操作。
18936
+ * 加密模式: 调用 SDK 的 init() 方法完成密钥协商等初始化操作。
18882
18937
  * 透传模式: 空操作 (already initialized)。
18883
18938
  * 幂等操作 — 重复调用安全。
18884
18939
  */
@@ -18888,9 +18943,6 @@ var CryptoEngine = class _CryptoEngine {
18888
18943
  this.initialized = true;
18889
18944
  return;
18890
18945
  }
18891
- if (!this.plug) {
18892
- throw new Error("Quantum encryption SDK is missing. Cannot initialize in encryption mode (check dist/index.min.cjs).");
18893
- }
18894
18946
  await this.plug.init();
18895
18947
  this.initialized = true;
18896
18948
  log15.info("CryptoEngine initialized \u2713");
@@ -18898,24 +18950,22 @@ var CryptoEngine = class _CryptoEngine {
18898
18950
  /**
18899
18951
  * 加密明文
18900
18952
  *
18901
- * 加密模式: 调用底层 SDK 加密 (SM4_CBC_PKCS7PADDING), 返回密文 + keyId
18953
+ * 加密模式: 调用底层 SDK 加密, 返回 Base64 密文 + keyId
18902
18954
  * 透传模式: 直接返回明文作为 "密文", keyId = 'passthrough'
18903
18955
  *
18904
- * 注意: SDK 返回驼峰 cipherText, 此方法对外统一为小写 ciphertext
18905
- *
18906
18956
  * @param plaintext - 要加密的明文字符串
18907
18957
  * @returns { ciphertext: 密文字符串, keyId: 密钥标识 }
18908
18958
  * @throws 加密模式下未初始化时抛出错误
18909
18959
  */
18910
18960
  async encrypt(plaintext) {
18961
+ this.ensureInitialized();
18911
18962
  if (this.passthrough) {
18912
18963
  log15.debug("Encrypt (passthrough)", { length: plaintext.length });
18913
18964
  return { ciphertext: plaintext, keyId: PASSTHROUGH_KEY_ID };
18914
18965
  }
18915
- const plug = this.requirePlug();
18916
- const result = await plug.encrypt(plaintext, DEFAULT_ENCRYPT_MODE);
18966
+ const result = await this.plug.encrypt(plaintext, 1);
18917
18967
  log15.debug("Encrypted", { length: plaintext.length, keyId: result.keyId });
18918
- return { ciphertext: result.cipherText, keyId: result.keyId };
18968
+ return result;
18919
18969
  }
18920
18970
  /**
18921
18971
  * 解密密文
@@ -18929,100 +18979,14 @@ var CryptoEngine = class _CryptoEngine {
18929
18979
  * @throws 加密模式下未初始化、密文损坏或 keyId 不匹配时抛出错误
18930
18980
  */
18931
18981
  async decrypt(ciphertext, keyId) {
18982
+ this.ensureInitialized();
18932
18983
  if (this.passthrough) {
18933
18984
  log15.debug("Decrypt (passthrough)", { keyId });
18934
18985
  return ciphertext;
18935
18986
  }
18936
- const plug = this.requirePlug();
18937
- const result = await plug.decrypt(ciphertext, keyId, DEFAULT_ENCRYPT_MODE);
18987
+ const result = await this.plug.decrypt(ciphertext, keyId, 1);
18938
18988
  log15.debug("Decrypted", { keyId });
18939
- return result.plainText;
18940
- }
18941
- /**
18942
- * 加密文件数据
18943
- *
18944
- * 自动处理 10MB 分片编排:
18945
- * - ≤10MB: 单次调用 SDK encryptFile
18946
- * - >10MB: 按 10MB 分片, 首片无需传密钥参数, 后续片传入前一片返回的 { keyId, sessionKey, fillKey }
18947
- *
18948
- * 透传模式: 直接返回原数据
18949
- *
18950
- * @param fileData - 文件数据 Buffer
18951
- * @returns { fileBuffer: 加密后的文件 Buffer, keyId: 密钥标识 }
18952
- */
18953
- async encryptFile(fileData) {
18954
- if (this.passthrough) {
18955
- log15.debug("EncryptFile (passthrough)", { size: fileData.length });
18956
- return { fileBuffer: fileData, keyId: PASSTHROUGH_KEY_ID };
18957
- }
18958
- if (fileData.length === 0) {
18959
- return { fileBuffer: Buffer.alloc(0), keyId: PASSTHROUGH_KEY_ID };
18960
- }
18961
- const chunks = [];
18962
- const total = Math.ceil(fileData.length / FILE_CHUNK_SIZE);
18963
- let keyId;
18964
- let sessionKey;
18965
- let fillKey;
18966
- const plug = this.requirePlug();
18967
- log15.debug("EncryptFile", { size: fileData.length, chunks: total });
18968
- for (let i = 0; i < total; i++) {
18969
- const start = i * FILE_CHUNK_SIZE;
18970
- const end = Math.min(start + FILE_CHUNK_SIZE, fileData.length);
18971
- const chunk = fileData.subarray(start, end);
18972
- const result = await plug.encryptFile(chunk, DEFAULT_ENCRYPT_MODE, {
18973
- keyId,
18974
- sessionKey,
18975
- fillKey
18976
- });
18977
- chunks.push(result.fileBuffer);
18978
- keyId = result.keyId;
18979
- sessionKey = result.sessionKey;
18980
- fillKey = result.fillKey;
18981
- }
18982
- log15.debug("EncryptFile done", { keyId, chunks: total });
18983
- return { fileBuffer: Buffer.concat(chunks), keyId: keyId ?? "" };
18984
- }
18985
- /**
18986
- * 解密文件数据
18987
- *
18988
- * 自动处理 (10MB + 16) 分片编排:
18989
- * - ≤(10MB+16): 单次调用 SDK decryptFile
18990
- * - >(10MB+16): 按 (10MB+16) 分片, 首片传 keyId, 后续片传入前一片返回的 { sessionKey, fillKey }
18991
- *
18992
- * 透传模式: 直接返回原数据
18993
- *
18994
- * @param fileData - 加密后的文件 Buffer
18995
- * @param keyId - 加密时返回的密钥标识
18996
- * @returns 解密后的文件 Buffer
18997
- */
18998
- async decryptFile(fileData, keyId) {
18999
- if (this.passthrough) {
19000
- log15.debug("DecryptFile (passthrough)", { keyId });
19001
- return fileData;
19002
- }
19003
- if (fileData.length === 0) {
19004
- return Buffer.alloc(0);
19005
- }
19006
- const plug = this.requirePlug();
19007
- const chunks = [];
19008
- const total = Math.ceil(fileData.length / FILE_DECRYPT_CHUNK_SIZE);
19009
- let sessionKey;
19010
- let fillKey;
19011
- log15.debug("DecryptFile", { size: fileData.length, chunks: total, keyId });
19012
- for (let i = 0; i < total; i++) {
19013
- const start = i * FILE_DECRYPT_CHUNK_SIZE;
19014
- const end = Math.min(start + FILE_DECRYPT_CHUNK_SIZE, fileData.length);
19015
- const chunk = fileData.subarray(start, end);
19016
- const result = await plug.decryptFile(chunk, keyId, DEFAULT_ENCRYPT_MODE, {
19017
- sessionKey,
19018
- fillKey
19019
- });
19020
- chunks.push(result.fileBuffer);
19021
- sessionKey = result.sessionKey;
19022
- fillKey = result.fillKey;
19023
- }
19024
- log15.debug("DecryptFile done", { keyId, chunks: total });
19025
- return Buffer.concat(chunks);
18989
+ return result.plaintext;
19026
18990
  }
19027
18991
  /**
19028
18992
  * 查询当前是否为透传模式
@@ -19032,14 +18996,13 @@ var CryptoEngine = class _CryptoEngine {
19032
18996
  return this.passthrough;
19033
18997
  }
19034
18998
  /**
19035
- * 确保引擎已初始化,同时返回非空 plug 实例
19036
- * (通过 init() 守卫保证:加密模式下 init() 成功后 plug 一定非 null)
18999
+ * 确保引擎已初始化
19000
+ * 未初始化时抛出明确错误,避免难以排查的 SDK 内部异常
19037
19001
  */
19038
- requirePlug() {
19002
+ ensureInitialized() {
19039
19003
  if (!this.initialized) {
19040
19004
  throw new Error("CryptoEngine not initialized \u2014 call init() first");
19041
19005
  }
19042
- return this.plug;
19043
19006
  }
19044
19007
  };
19045
19008
 
@@ -19258,7 +19221,7 @@ var SealClient = class {
19258
19221
  var import_promises = require("fs/promises");
19259
19222
  var import_node_fs = require("fs");
19260
19223
  var import_node_path = require("path");
19261
- var import_node_crypto = require("crypto");
19224
+ var import_node_crypto2 = require("crypto");
19262
19225
  var log17 = createLogger("auth/token-store");
19263
19226
  var TokenStore = class {
19264
19227
  /** 存储目录路径 */
@@ -19314,7 +19277,7 @@ var TokenStore = class {
19314
19277
  const storage = { ciphertext, keyId };
19315
19278
  const storageJson = JSON.stringify(storage);
19316
19279
  const targetPath = this.filePath(key);
19317
- const tmpSuffix = (0, import_node_crypto.randomBytes)(4).toString("hex");
19280
+ const tmpSuffix = (0, import_node_crypto2.randomBytes)(4).toString("hex");
19318
19281
  const tmpPath = `${targetPath}.${tmpSuffix}.tmp`;
19319
19282
  try {
19320
19283
  await (0, import_promises.writeFile)(tmpPath, storageJson, { mode: 384 });
@@ -19753,7 +19716,7 @@ var MessageDedup = class {
19753
19716
  };
19754
19717
 
19755
19718
  // src/transport/message-pipe.ts
19756
- var import_node_crypto2 = require("crypto");
19719
+ var import_node_crypto3 = require("crypto");
19757
19720
  var log21 = createLogger("transport/message-pipe");
19758
19721
  var MessagePipe = class {
19759
19722
  wsClient;
@@ -19901,7 +19864,7 @@ var MessagePipe = class {
19901
19864
  if (timestamp && nonce && signature) {
19902
19865
  const token = await this.tokenFn();
19903
19866
  const signatureInput = timestamp + nonce + frame.data;
19904
- const expected = (0, import_node_crypto2.createHmac)("sha256", token).update(signatureInput).digest("hex");
19867
+ const expected = (0, import_node_crypto3.createHmac)("sha256", token).update(signatureInput).digest("hex");
19905
19868
  if (expected !== signature) {
19906
19869
  log21.warn("inbound:signature-fail", { timestamp, nonce });
19907
19870
  return;
package/dist/index.d.cts CHANGED
@@ -338,12 +338,12 @@ declare class SealClient {
338
338
  /**
339
339
  * openclaw-liangzimixin — 加密引擎
340
340
  *
341
- * 封装量子加密 SDK 的加解密操作。
341
+ * 封装量子加密 SDK (当前为 Mock) 的加解密操作。
342
342
  * 上层模块 (TokenStore, MessagePipe) 通过此类完成所有加解密,
343
343
  * 不直接接触底层 SDK,实现 SDK 可替换性。
344
344
  *
345
345
  * 两种运行模式:
346
- * 1. 加密模式 (默认): 通过量子加密 SDK 进行 SM4 加解密
346
+ * 1. 加密模式 (默认): 通过量子加密 SDK 进行真正的加解密
347
347
  * 2. 透传模式 (passthrough): 不做加密,明文直接透传,用于 crypto.enabled=false 场景
348
348
  *
349
349
  * 使用方式:
@@ -357,45 +357,46 @@ declare class SealClient {
357
357
  * const engine = CryptoEngine.createPassthrough();
358
358
  * // 无需 init(), encrypt/decrypt 直接透传明文
359
359
  *
360
- * SDK:
361
- * 真实量子加密 SDK (dist/index.min.cjs) SM4 加密, KMS 密钥管理
360
+ * SDK 切换:
361
+ * 当前: import quantunPlugMock AES-256-GCM Mock
362
+ * 未来: const quantunPlug = require('./quantunPlug.ejs') → 真实量子 SDK
362
363
  */
363
364
  /**
364
365
  * 加密引擎 — 统一的加解密入口。
365
366
  *
366
367
  * 封装底层量子加密 SDK 的调用细节,
368
+ * 屏蔽 Mock 与真实 SDK 的差异,
367
369
  * 上层模块无需关心底层实现。
368
370
  *
369
371
  * 支持两种模式:
370
- * - 加密模式: 使用量子加密 SDK 进行加解密
372
+ * - 加密模式: 使用量子加密 SDK (Mock 或真实) 进行加解密
371
373
  * - 透传模式: encrypt/decrypt 直接透传明文, 不做任何加密操作
372
374
  *
373
375
  * 生命周期 (加密模式):
374
376
  * 1. 构造: new CryptoEngine()
375
377
  * 2. 初始化: await init() — 调用 SDK 的 init()
376
- * 3. 使用: encrypt() / decrypt() / encryptFile() / decryptFile()
378
+ * 3. 使用: encrypt() / decrypt()
377
379
  *
378
380
  * 生命周期 (透传模式):
379
381
  * 1. 构造: CryptoEngine.createPassthrough()
380
382
  * 2. 直接使用: encrypt() / decrypt() — 无需 init()
381
383
  */
382
384
  declare class CryptoEngine {
383
- /** 底层量子加密 SDK 实例, 透传模式下为 null */
385
+ /** 底层量子加密 SDK 实例 (Mock 或真实), 透传模式下为 null */
384
386
  private readonly plug;
385
387
  /** SDK 是否已完成初始化 */
386
388
  private initialized;
387
389
  /** 是否为透传模式 (不加密, 明文直接透传) */
388
390
  private readonly passthrough;
389
391
  /**
390
- * 构造加密引擎
392
+ * 构造加密引擎 (加密模式)
391
393
  *
392
- * @param passthrough - true 为透传模式 (不加密); false 为加密模式 (默认)
394
+ * 当前默认使用 Mock SDK。
395
+ * 待真实 SDK 交付后,此处替换为 require('./quantunPlug.ejs')。
393
396
  *
394
- * 请使用静态工厂方法:
395
- * - new CryptoEngine() → 加密模式, 使用量子 SDK
396
- * - CryptoEngine.createPassthrough() → 透传模式, 无需 init()
397
+ * 如需透传模式,请使用静态方法 CryptoEngine.createPassthrough()。
397
398
  */
398
- constructor(passthrough?: boolean);
399
+ constructor();
399
400
  /**
400
401
  * 创建透传模式的加密引擎 (静态工厂方法)
401
402
  *
@@ -411,7 +412,7 @@ declare class CryptoEngine {
411
412
  /**
412
413
  * 初始化加密引擎
413
414
  *
414
- * 加密模式: 调用 SDK 的 init() 方法完成密服入网、密钥协商等初始化操作。
415
+ * 加密模式: 调用 SDK 的 init() 方法完成密钥协商等初始化操作。
415
416
  * 透传模式: 空操作 (already initialized)。
416
417
  * 幂等操作 — 重复调用安全。
417
418
  */
@@ -419,11 +420,9 @@ declare class CryptoEngine {
419
420
  /**
420
421
  * 加密明文
421
422
  *
422
- * 加密模式: 调用底层 SDK 加密 (SM4_CBC_PKCS7PADDING), 返回密文 + keyId
423
+ * 加密模式: 调用底层 SDK 加密, 返回 Base64 密文 + keyId
423
424
  * 透传模式: 直接返回明文作为 "密文", keyId = 'passthrough'
424
425
  *
425
- * 注意: SDK 返回驼峰 cipherText, 此方法对外统一为小写 ciphertext
426
- *
427
426
  * @param plaintext - 要加密的明文字符串
428
427
  * @returns { ciphertext: 密文字符串, keyId: 密钥标识 }
429
428
  * @throws 加密模式下未初始化时抛出错误
@@ -444,46 +443,16 @@ declare class CryptoEngine {
444
443
  * @throws 加密模式下未初始化、密文损坏或 keyId 不匹配时抛出错误
445
444
  */
446
445
  decrypt(ciphertext: string, keyId: string): Promise<string>;
447
- /**
448
- * 加密文件数据
449
- *
450
- * 自动处理 10MB 分片编排:
451
- * - ≤10MB: 单次调用 SDK encryptFile
452
- * - >10MB: 按 10MB 分片, 首片无需传密钥参数, 后续片传入前一片返回的 { keyId, sessionKey, fillKey }
453
- *
454
- * 透传模式: 直接返回原数据
455
- *
456
- * @param fileData - 文件数据 Buffer
457
- * @returns { fileBuffer: 加密后的文件 Buffer, keyId: 密钥标识 }
458
- */
459
- encryptFile(fileData: Buffer): Promise<{
460
- fileBuffer: Buffer;
461
- keyId: string;
462
- }>;
463
- /**
464
- * 解密文件数据
465
- *
466
- * 自动处理 (10MB + 16) 分片编排:
467
- * - ≤(10MB+16): 单次调用 SDK decryptFile
468
- * - >(10MB+16): 按 (10MB+16) 分片, 首片传 keyId, 后续片传入前一片返回的 { sessionKey, fillKey }
469
- *
470
- * 透传模式: 直接返回原数据
471
- *
472
- * @param fileData - 加密后的文件 Buffer
473
- * @param keyId - 加密时返回的密钥标识
474
- * @returns 解密后的文件 Buffer
475
- */
476
- decryptFile(fileData: Buffer, keyId: string): Promise<Buffer>;
477
446
  /**
478
447
  * 查询当前是否为透传模式
479
448
  * 上层模块可通过此方法判断加密是否真正启用
480
449
  */
481
450
  isPassthrough(): boolean;
482
451
  /**
483
- * 确保引擎已初始化,同时返回非空 plug 实例
484
- * (通过 init() 守卫保证:加密模式下 init() 成功后 plug 一定非 null)
452
+ * 确保引擎已初始化
453
+ * 未初始化时抛出明确错误,避免难以排查的 SDK 内部异常
485
454
  */
486
- private requirePlug;
455
+ private ensureInitialized;
487
456
  }
488
457
 
489
458
  /**
@@ -2233,7 +2233,7 @@ var require_websocket = __commonJS({
2233
2233
  var http = require("http");
2234
2234
  var net = require("net");
2235
2235
  var tls = require("tls");
2236
- var { randomBytes: randomBytes2, createHash } = require("crypto");
2236
+ var { randomBytes: randomBytes3, createHash } = require("crypto");
2237
2237
  var { Duplex, Readable } = require("stream");
2238
2238
  var { URL: URL2 } = require("url");
2239
2239
  var PerMessageDeflate = require_permessage_deflate();
@@ -2763,7 +2763,7 @@ var require_websocket = __commonJS({
2763
2763
  }
2764
2764
  }
2765
2765
  const defaultPort = isSecure ? 443 : 80;
2766
- const key = randomBytes2(16).toString("base64");
2766
+ const key = randomBytes3(16).toString("base64");
2767
2767
  const request = isSecure ? https.request : http.request;
2768
2768
  const protocolSet = /* @__PURE__ */ new Set();
2769
2769
  let perMessageDeflate;
@@ -18070,54 +18070,104 @@ function buildPluginConfig(accountConfig, internalOverrides) {
18070
18070
  };
18071
18071
  }
18072
18072
 
18073
- // src/crypto/quantun-plug-adapter.ts
18074
- var import_node_module = require("module");
18075
- var import_meta = {};
18076
- var log5 = createLogger("crypto/quantun-plug-adapter");
18077
- var SM4_MODE = {
18078
- ECB_NOPADDING: 1,
18079
- ECB_PKCS7PADDING: 2,
18080
- CBC_NOPADDING: 3,
18081
- CBC_PKCS7PADDING: 4
18073
+ // src/crypto/quantun-plug-mock.ts
18074
+ var import_node_crypto = require("crypto");
18075
+ var log5 = createLogger("crypto/quantun-plug-mock");
18076
+ var MOCK_KEY = Buffer.alloc(32, 0);
18077
+ MOCK_KEY.write("quantum-mock-key-2026", 0);
18078
+ var MOCK_KEY_ID = "mock-key-v1";
18079
+ var initialized = false;
18080
+ var quantunPlugMock = {
18081
+ /**
18082
+ * 初始化 Mock SDK
18083
+ * 幂等操作 — 重复调用不会报错
18084
+ */
18085
+ async init() {
18086
+ if (initialized) return;
18087
+ initialized = true;
18088
+ log5.warn("\u26A0\uFE0F MOCK MODE \u2014 \u4F7F\u7528 AES-256-GCM \u6A21\u62DF\u91CF\u5B50\u52A0\u5BC6");
18089
+ },
18090
+ /**
18091
+ * 加密明文 → 密文 + 密钥标识
18092
+ *
18093
+ * 内部流程:
18094
+ * 1. 生成 12 字节随机 IV (确保每次加密结果不同)
18095
+ * 2. AES-256-GCM 加密明文
18096
+ * 3. 获取 16 字节 AuthTag (认证标签,防篡改)
18097
+ * 4. 拼接 [IV(12) | Tag(16) | Ciphertext] → Base64 编码
18098
+ */
18099
+ async encrypt(plaintext, mode) {
18100
+ if (!initialized) {
18101
+ throw new Error("quantunPlug not initialized \u2014 call init() first");
18102
+ }
18103
+ const iv = (0, import_node_crypto.randomBytes)(12);
18104
+ const cipher = (0, import_node_crypto.createCipheriv)("aes-256-gcm", MOCK_KEY, iv);
18105
+ const encrypted = Buffer.concat([
18106
+ cipher.update(plaintext, "utf-8"),
18107
+ cipher.final()
18108
+ ]);
18109
+ const tag = cipher.getAuthTag();
18110
+ const combined = Buffer.concat([iv, tag, encrypted]);
18111
+ return {
18112
+ ciphertext: combined.toString("base64"),
18113
+ keyId: MOCK_KEY_ID
18114
+ };
18115
+ },
18116
+ /**
18117
+ * 解密密文 → 明文
18118
+ *
18119
+ * 内部流程:
18120
+ * 1. Base64 解码
18121
+ * 2. 拆分 IV(12) + Tag(16) + Ciphertext
18122
+ * 3. AES-256-GCM 解密 + AuthTag 验证
18123
+ * 4. 返回 UTF-8 明文
18124
+ *
18125
+ * @throws AuthTag 验证失败时抛出异常 (数据被篡改)
18126
+ */
18127
+ async decrypt(ciphertext, keyId, mode) {
18128
+ if (!initialized) {
18129
+ throw new Error("quantunPlug not initialized \u2014 call init() first");
18130
+ }
18131
+ const combined = Buffer.from(ciphertext, "base64");
18132
+ const iv = combined.subarray(0, 12);
18133
+ const tag = combined.subarray(12, 28);
18134
+ const encrypted = combined.subarray(28);
18135
+ const decipher = (0, import_node_crypto.createDecipheriv)("aes-256-gcm", MOCK_KEY, iv);
18136
+ decipher.setAuthTag(tag);
18137
+ const decrypted = Buffer.concat([
18138
+ decipher.update(encrypted),
18139
+ decipher.final()
18140
+ // 此处 Tag 验证失败会抛出异常
18141
+ ]);
18142
+ return {
18143
+ plaintext: decrypted.toString("utf-8")
18144
+ };
18145
+ }
18082
18146
  };
18083
- var DEFAULT_ENCRYPT_MODE = SM4_MODE.CBC_PKCS7PADDING;
18084
- var require2 = (0, import_node_module.createRequire)(import_meta.url);
18085
- var quantunPlug = null;
18086
- try {
18087
- quantunPlug = require2("./sdk/index.min.cjs");
18088
- log5.info("Quantum SDK loaded from sdk/index.min.cjs");
18089
- } catch (err) {
18090
- const msg = err instanceof Error ? err.message : String(err);
18091
- log5.warn("Quantum SDK missing, only passthrough mode will work:", msg);
18092
- }
18093
- var quantun_plug_adapter_default = quantunPlug;
18147
+ var quantun_plug_mock_default = quantunPlugMock;
18094
18148
 
18095
18149
  // src/crypto/crypto-engine.ts
18096
18150
  var log6 = createLogger("crypto/crypto-engine");
18097
18151
  var PASSTHROUGH_KEY_ID = "passthrough";
18098
- var FILE_CHUNK_SIZE = 10 * 1024 * 1024;
18099
- var FILE_DECRYPT_CHUNK_SIZE = FILE_CHUNK_SIZE + 16;
18100
18152
  var CryptoEngine = class _CryptoEngine {
18101
- /** 底层量子加密 SDK 实例, 透传模式下为 null */
18153
+ /** 底层量子加密 SDK 实例 (Mock 或真实), 透传模式下为 null */
18102
18154
  plug;
18103
18155
  /** SDK 是否已完成初始化 */
18104
- initialized;
18156
+ initialized = false;
18105
18157
  /** 是否为透传模式 (不加密, 明文直接透传) */
18106
18158
  passthrough;
18107
18159
  /**
18108
- * 构造加密引擎
18160
+ * 构造加密引擎 (加密模式)
18109
18161
  *
18110
- * @param passthrough - true 为透传模式 (不加密); false 为加密模式 (默认)
18162
+ * 当前默认使用 Mock SDK。
18163
+ * 待真实 SDK 交付后,此处替换为 require('./quantunPlug.ejs')。
18111
18164
  *
18112
- * 请使用静态工厂方法:
18113
- * - new CryptoEngine() → 加密模式, 使用量子 SDK
18114
- * - CryptoEngine.createPassthrough() → 透传模式, 无需 init()
18165
+ * 如需透传模式,请使用静态方法 CryptoEngine.createPassthrough()。
18115
18166
  */
18116
- constructor(passthrough = false) {
18117
- this.passthrough = passthrough;
18118
- this.plug = passthrough ? null : quantun_plug_adapter_default;
18119
- this.initialized = passthrough;
18120
- log6.info(`CryptoEngine created (${passthrough ? "passthrough mode \u2014 crypto disabled" : "quantum SDK mode"})`);
18167
+ constructor() {
18168
+ this.plug = quantun_plug_mock_default;
18169
+ this.passthrough = false;
18170
+ log6.info("CryptoEngine created (mock mode)");
18121
18171
  }
18122
18172
  /**
18123
18173
  * 创建透传模式的加密引擎 (静态工厂方法)
@@ -18131,12 +18181,17 @@ var CryptoEngine = class _CryptoEngine {
18131
18181
  * 上层模块 (TokenStore, MessagePipe) 无需感知加密是否开启。
18132
18182
  */
18133
18183
  static createPassthrough() {
18134
- return new _CryptoEngine(true);
18184
+ const instance = Object.create(_CryptoEngine.prototype);
18185
+ instance.plug = null;
18186
+ instance.passthrough = true;
18187
+ instance.initialized = true;
18188
+ log6.info("CryptoEngine created (passthrough mode \u2014 crypto disabled)");
18189
+ return instance;
18135
18190
  }
18136
18191
  /**
18137
18192
  * 初始化加密引擎
18138
18193
  *
18139
- * 加密模式: 调用 SDK 的 init() 方法完成密服入网、密钥协商等初始化操作。
18194
+ * 加密模式: 调用 SDK 的 init() 方法完成密钥协商等初始化操作。
18140
18195
  * 透传模式: 空操作 (already initialized)。
18141
18196
  * 幂等操作 — 重复调用安全。
18142
18197
  */
@@ -18146,9 +18201,6 @@ var CryptoEngine = class _CryptoEngine {
18146
18201
  this.initialized = true;
18147
18202
  return;
18148
18203
  }
18149
- if (!this.plug) {
18150
- throw new Error("Quantum encryption SDK is missing. Cannot initialize in encryption mode (check dist/index.min.cjs).");
18151
- }
18152
18204
  await this.plug.init();
18153
18205
  this.initialized = true;
18154
18206
  log6.info("CryptoEngine initialized \u2713");
@@ -18156,24 +18208,22 @@ var CryptoEngine = class _CryptoEngine {
18156
18208
  /**
18157
18209
  * 加密明文
18158
18210
  *
18159
- * 加密模式: 调用底层 SDK 加密 (SM4_CBC_PKCS7PADDING), 返回密文 + keyId
18211
+ * 加密模式: 调用底层 SDK 加密, 返回 Base64 密文 + keyId
18160
18212
  * 透传模式: 直接返回明文作为 "密文", keyId = 'passthrough'
18161
18213
  *
18162
- * 注意: SDK 返回驼峰 cipherText, 此方法对外统一为小写 ciphertext
18163
- *
18164
18214
  * @param plaintext - 要加密的明文字符串
18165
18215
  * @returns { ciphertext: 密文字符串, keyId: 密钥标识 }
18166
18216
  * @throws 加密模式下未初始化时抛出错误
18167
18217
  */
18168
18218
  async encrypt(plaintext) {
18219
+ this.ensureInitialized();
18169
18220
  if (this.passthrough) {
18170
18221
  log6.debug("Encrypt (passthrough)", { length: plaintext.length });
18171
18222
  return { ciphertext: plaintext, keyId: PASSTHROUGH_KEY_ID };
18172
18223
  }
18173
- const plug = this.requirePlug();
18174
- const result = await plug.encrypt(plaintext, DEFAULT_ENCRYPT_MODE);
18224
+ const result = await this.plug.encrypt(plaintext, 1);
18175
18225
  log6.debug("Encrypted", { length: plaintext.length, keyId: result.keyId });
18176
- return { ciphertext: result.cipherText, keyId: result.keyId };
18226
+ return result;
18177
18227
  }
18178
18228
  /**
18179
18229
  * 解密密文
@@ -18187,100 +18237,14 @@ var CryptoEngine = class _CryptoEngine {
18187
18237
  * @throws 加密模式下未初始化、密文损坏或 keyId 不匹配时抛出错误
18188
18238
  */
18189
18239
  async decrypt(ciphertext, keyId) {
18240
+ this.ensureInitialized();
18190
18241
  if (this.passthrough) {
18191
18242
  log6.debug("Decrypt (passthrough)", { keyId });
18192
18243
  return ciphertext;
18193
18244
  }
18194
- const plug = this.requirePlug();
18195
- const result = await plug.decrypt(ciphertext, keyId, DEFAULT_ENCRYPT_MODE);
18245
+ const result = await this.plug.decrypt(ciphertext, keyId, 1);
18196
18246
  log6.debug("Decrypted", { keyId });
18197
- return result.plainText;
18198
- }
18199
- /**
18200
- * 加密文件数据
18201
- *
18202
- * 自动处理 10MB 分片编排:
18203
- * - ≤10MB: 单次调用 SDK encryptFile
18204
- * - >10MB: 按 10MB 分片, 首片无需传密钥参数, 后续片传入前一片返回的 { keyId, sessionKey, fillKey }
18205
- *
18206
- * 透传模式: 直接返回原数据
18207
- *
18208
- * @param fileData - 文件数据 Buffer
18209
- * @returns { fileBuffer: 加密后的文件 Buffer, keyId: 密钥标识 }
18210
- */
18211
- async encryptFile(fileData) {
18212
- if (this.passthrough) {
18213
- log6.debug("EncryptFile (passthrough)", { size: fileData.length });
18214
- return { fileBuffer: fileData, keyId: PASSTHROUGH_KEY_ID };
18215
- }
18216
- if (fileData.length === 0) {
18217
- return { fileBuffer: Buffer.alloc(0), keyId: PASSTHROUGH_KEY_ID };
18218
- }
18219
- const chunks = [];
18220
- const total = Math.ceil(fileData.length / FILE_CHUNK_SIZE);
18221
- let keyId;
18222
- let sessionKey;
18223
- let fillKey;
18224
- const plug = this.requirePlug();
18225
- log6.debug("EncryptFile", { size: fileData.length, chunks: total });
18226
- for (let i = 0; i < total; i++) {
18227
- const start = i * FILE_CHUNK_SIZE;
18228
- const end = Math.min(start + FILE_CHUNK_SIZE, fileData.length);
18229
- const chunk = fileData.subarray(start, end);
18230
- const result = await plug.encryptFile(chunk, DEFAULT_ENCRYPT_MODE, {
18231
- keyId,
18232
- sessionKey,
18233
- fillKey
18234
- });
18235
- chunks.push(result.fileBuffer);
18236
- keyId = result.keyId;
18237
- sessionKey = result.sessionKey;
18238
- fillKey = result.fillKey;
18239
- }
18240
- log6.debug("EncryptFile done", { keyId, chunks: total });
18241
- return { fileBuffer: Buffer.concat(chunks), keyId: keyId ?? "" };
18242
- }
18243
- /**
18244
- * 解密文件数据
18245
- *
18246
- * 自动处理 (10MB + 16) 分片编排:
18247
- * - ≤(10MB+16): 单次调用 SDK decryptFile
18248
- * - >(10MB+16): 按 (10MB+16) 分片, 首片传 keyId, 后续片传入前一片返回的 { sessionKey, fillKey }
18249
- *
18250
- * 透传模式: 直接返回原数据
18251
- *
18252
- * @param fileData - 加密后的文件 Buffer
18253
- * @param keyId - 加密时返回的密钥标识
18254
- * @returns 解密后的文件 Buffer
18255
- */
18256
- async decryptFile(fileData, keyId) {
18257
- if (this.passthrough) {
18258
- log6.debug("DecryptFile (passthrough)", { keyId });
18259
- return fileData;
18260
- }
18261
- if (fileData.length === 0) {
18262
- return Buffer.alloc(0);
18263
- }
18264
- const plug = this.requirePlug();
18265
- const chunks = [];
18266
- const total = Math.ceil(fileData.length / FILE_DECRYPT_CHUNK_SIZE);
18267
- let sessionKey;
18268
- let fillKey;
18269
- log6.debug("DecryptFile", { size: fileData.length, chunks: total, keyId });
18270
- for (let i = 0; i < total; i++) {
18271
- const start = i * FILE_DECRYPT_CHUNK_SIZE;
18272
- const end = Math.min(start + FILE_DECRYPT_CHUNK_SIZE, fileData.length);
18273
- const chunk = fileData.subarray(start, end);
18274
- const result = await plug.decryptFile(chunk, keyId, DEFAULT_ENCRYPT_MODE, {
18275
- sessionKey,
18276
- fillKey
18277
- });
18278
- chunks.push(result.fileBuffer);
18279
- sessionKey = result.sessionKey;
18280
- fillKey = result.fillKey;
18281
- }
18282
- log6.debug("DecryptFile done", { keyId, chunks: total });
18283
- return Buffer.concat(chunks);
18247
+ return result.plaintext;
18284
18248
  }
18285
18249
  /**
18286
18250
  * 查询当前是否为透传模式
@@ -18290,14 +18254,13 @@ var CryptoEngine = class _CryptoEngine {
18290
18254
  return this.passthrough;
18291
18255
  }
18292
18256
  /**
18293
- * 确保引擎已初始化,同时返回非空 plug 实例
18294
- * (通过 init() 守卫保证:加密模式下 init() 成功后 plug 一定非 null)
18257
+ * 确保引擎已初始化
18258
+ * 未初始化时抛出明确错误,避免难以排查的 SDK 内部异常
18295
18259
  */
18296
- requirePlug() {
18260
+ ensureInitialized() {
18297
18261
  if (!this.initialized) {
18298
18262
  throw new Error("CryptoEngine not initialized \u2014 call init() first");
18299
18263
  }
18300
- return this.plug;
18301
18264
  }
18302
18265
  };
18303
18266
 
@@ -18516,7 +18479,7 @@ var SealClient = class {
18516
18479
  var import_promises = require("fs/promises");
18517
18480
  var import_node_fs = require("fs");
18518
18481
  var import_node_path = require("path");
18519
- var import_node_crypto = require("crypto");
18482
+ var import_node_crypto2 = require("crypto");
18520
18483
  var log8 = createLogger("auth/token-store");
18521
18484
  var TokenStore = class {
18522
18485
  /** 存储目录路径 */
@@ -18572,7 +18535,7 @@ var TokenStore = class {
18572
18535
  const storage = { ciphertext, keyId };
18573
18536
  const storageJson = JSON.stringify(storage);
18574
18537
  const targetPath = this.filePath(key);
18575
- const tmpSuffix = (0, import_node_crypto.randomBytes)(4).toString("hex");
18538
+ const tmpSuffix = (0, import_node_crypto2.randomBytes)(4).toString("hex");
18576
18539
  const tmpPath = `${targetPath}.${tmpSuffix}.tmp`;
18577
18540
  try {
18578
18541
  await (0, import_promises.writeFile)(tmpPath, storageJson, { mode: 384 });
@@ -19011,7 +18974,7 @@ var MessageDedup = class {
19011
18974
  };
19012
18975
 
19013
18976
  // src/transport/message-pipe.ts
19014
- var import_node_crypto2 = require("crypto");
18977
+ var import_node_crypto3 = require("crypto");
19015
18978
  var log12 = createLogger("transport/message-pipe");
19016
18979
  var MessagePipe = class {
19017
18980
  wsClient;
@@ -19159,7 +19122,7 @@ var MessagePipe = class {
19159
19122
  if (timestamp && nonce && signature) {
19160
19123
  const token = await this.tokenFn();
19161
19124
  const signatureInput = timestamp + nonce + frame.data;
19162
- const expected = (0, import_node_crypto2.createHmac)("sha256", token).update(signatureInput).digest("hex");
19125
+ const expected = (0, import_node_crypto3.createHmac)("sha256", token).update(signatureInput).digest("hex");
19163
19126
  if (expected !== signature) {
19164
19127
  log12.warn("inbound:signature-fail", { timestamp, nonce });
19165
19128
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "liangzimixin",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Quantum-encrypted IM channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",