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 +107 -144
- package/dist/index.d.cts +19 -50
- package/dist/setup-entry.cjs +107 -144
- package/package.json +1 -1
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:
|
|
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 =
|
|
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-
|
|
18816
|
-
var
|
|
18817
|
-
var
|
|
18818
|
-
var
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
|
|
18822
|
-
|
|
18823
|
-
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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(
|
|
18859
|
-
this.
|
|
18860
|
-
this.
|
|
18861
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
*
|
|
19036
|
-
*
|
|
18999
|
+
* 确保引擎已初始化
|
|
19000
|
+
* 未初始化时抛出明确错误,避免难以排查的 SDK 内部异常
|
|
19037
19001
|
*/
|
|
19038
|
-
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
*
|
|
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()
|
|
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
|
|
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
|
-
*
|
|
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(
|
|
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
|
|
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
|
-
*
|
|
484
|
-
*
|
|
452
|
+
* 确保引擎已初始化
|
|
453
|
+
* 未初始化时抛出明确错误,避免难以排查的 SDK 内部异常
|
|
485
454
|
*/
|
|
486
|
-
private
|
|
455
|
+
private ensureInitialized;
|
|
487
456
|
}
|
|
488
457
|
|
|
489
458
|
/**
|
package/dist/setup-entry.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:
|
|
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 =
|
|
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-
|
|
18074
|
-
var
|
|
18075
|
-
var
|
|
18076
|
-
var
|
|
18077
|
-
|
|
18078
|
-
|
|
18079
|
-
|
|
18080
|
-
|
|
18081
|
-
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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(
|
|
18117
|
-
this.
|
|
18118
|
-
this.
|
|
18119
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
*
|
|
18294
|
-
*
|
|
18257
|
+
* 确保引擎已初始化
|
|
18258
|
+
* 未初始化时抛出明确错误,避免难以排查的 SDK 内部异常
|
|
18295
18259
|
*/
|
|
18296
|
-
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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;
|