refactor: 优化 NBPF 模块 - 缓存导入/合并重复方法/减少I/O
- crypto.py: 8个_imp_*方法改为_ModuleCache类缓存导入 - crypto.py: outer/inner加解密合并为_layer_encrypt/decrypt - crypto.py: 提取公共摘要计算方法,拆分长方法 - compiler.py: 删除_obfuscate_code中未使用的死代码 - loader.py: 3次ZIP扫描合并为1次缓存读取 - format.py: 更新为使用_ModuleCache - 合计减少205行代码(1707→1502)
This commit is contained in:
@@ -79,8 +79,11 @@ class NBPFLoader:
|
||||
|
||||
try:
|
||||
with zipfile.ZipFile(nbpf_path, 'r') as zf:
|
||||
# 0. 一次扫描,缓存 NIR 模块数据
|
||||
nir_modules = self._read_nir_modules(zf)
|
||||
|
||||
# 1. 外层验签(先用包内公钥验签,再查信任状态)
|
||||
signer_pub_key, is_trusted, trusted_name = self._verify_outer_signature(zf)
|
||||
signer_pub_key, is_trusted, trusted_name = self._verify_outer_signature(zf, nir_modules)
|
||||
status = "已信任" if is_trusted else "未信任"
|
||||
Log.info("NBPF", f"外层签名验证通过 (signer: {trusted_name or 'unknown'}, {status})")
|
||||
|
||||
@@ -89,7 +92,7 @@ class NBPFLoader:
|
||||
key1_buf = bytearray(key1)
|
||||
|
||||
# 3. 中层验签(传入外层签名者名称,确保内外签名者一致)
|
||||
rsa_signer = self._verify_inner_signature(zf, meta_inf, trusted_name)
|
||||
rsa_signer = self._verify_inner_signature(nir_modules, meta_inf, trusted_name)
|
||||
Log.info("NBPF", f"中层签名验证通过 (signer: {rsa_signer})")
|
||||
|
||||
# 4. 中层解密
|
||||
@@ -102,7 +105,7 @@ class NBPFLoader:
|
||||
self.crypto._secure_wipe(key2_buf)
|
||||
|
||||
# 6. 解密 NIR 数据
|
||||
nir_data = self._decrypt_nir_data(zf, key2)
|
||||
nir_data = self._decrypt_nir_data_raw(nir_modules, key2)
|
||||
|
||||
# 7. 内层验签
|
||||
self._verify_module_signatures(nir_data, meta_inf, hmac_key)
|
||||
@@ -145,9 +148,19 @@ class NBPFLoader:
|
||||
except Exception as e:
|
||||
raise NBPFLoadError(f"加载失败: {type(e).__name__}: {e}") from e
|
||||
|
||||
@staticmethod
|
||||
def _read_nir_modules(zf: zipfile.ZipFile) -> dict[str, dict]:
|
||||
"""一次扫描 ZIP 中所有 NIR 模块,缓存结果"""
|
||||
modules = {}
|
||||
for info in zf.infolist():
|
||||
if info.filename.startswith(NBPFFormatter.NIR_DIR) and not info.filename.endswith("/"):
|
||||
mod_name = info.filename[len(NBPFFormatter.NIR_DIR):]
|
||||
modules[mod_name] = json.loads(zf.read(info.filename).decode("utf-8"))
|
||||
return modules
|
||||
|
||||
# ── 外层验签 ──
|
||||
|
||||
def _verify_outer_signature(self, zf: zipfile.ZipFile) -> tuple[bytes, bool, str | None]:
|
||||
def _verify_outer_signature(self, zf: zipfile.ZipFile, nir_modules: dict[str, dict]) -> tuple[bytes, bool, str | None]:
|
||||
"""外层 Ed25519 签名验证
|
||||
|
||||
先用包内公钥验签(不依赖外部信任列表),验签通过后再检查信任状态。
|
||||
@@ -157,9 +170,6 @@ class NBPFLoader:
|
||||
|
||||
Returns:
|
||||
(signer_pub_key_bytes, is_trusted, trusted_name)
|
||||
- signer_pub_key_bytes: 签名者 Ed25519 公钥(用于上层判断信任)
|
||||
- is_trusted: 公钥是否在本地信任列表中
|
||||
- trusted_name: 信任列表中的名称(不信任时为 None)
|
||||
"""
|
||||
if NBPFFormatter.SIGNATURE not in zf.namelist():
|
||||
raise NBPFLoadError("缺少外层签名文件")
|
||||
@@ -169,29 +179,16 @@ class NBPFLoader:
|
||||
signature_b64 = zf.read(NBPFFormatter.SIGNATURE).decode().strip()
|
||||
signer_pub_key = zf.read(NBPFFormatter.SIGNER_PEM)
|
||||
|
||||
# 计算包摘要(与 full_encrypt_package 一致)
|
||||
# 计算包摘要(使用缓存的 nir_modules)
|
||||
encryption_data = json.loads(zf.read(NBPFFormatter.ENCRYPTION).decode("utf-8"))
|
||||
digest = hashlib.sha256()
|
||||
digest.update(json.dumps(encryption_data["data"]).encode())
|
||||
digest = NBPCrypto._build_package_digest(encryption_data["data"], nir_modules)
|
||||
|
||||
# 按模块名排序,添加模块名和密文
|
||||
nir_modules = {}
|
||||
for info in zf.infolist():
|
||||
if info.filename.startswith(NBPFFormatter.NIR_DIR) and not info.filename.endswith("/"):
|
||||
mod_name = info.filename[len(NBPFFormatter.NIR_DIR):]
|
||||
mod_data = json.loads(zf.read(info.filename).decode("utf-8"))
|
||||
nir_modules[mod_name] = mod_data
|
||||
|
||||
for mod_name in sorted(nir_modules.keys()):
|
||||
digest.update(mod_name.encode())
|
||||
digest.update(nir_modules[mod_name]["ciphertext"].encode())
|
||||
|
||||
# 直接用包内公钥验签(不依赖外部信任列表)
|
||||
# 直接用包内公钥验签
|
||||
signature = base64.b64decode(signature_b64)
|
||||
if not self.crypto.outer_verify(digest.digest(), signature, signer_pub_key):
|
||||
if not self.crypto.outer_verify(digest, signature, signer_pub_key):
|
||||
raise NBPFLoadError("外层签名验证失败,包可能被篡改")
|
||||
|
||||
# 验签通过后,检查公钥是否在本地信任列表中
|
||||
# 检查公钥是否在本地信任列表中
|
||||
is_trusted = False
|
||||
trusted_name = None
|
||||
for name, trusted_key in self.trusted_ed25519_keys.items():
|
||||
@@ -224,7 +221,7 @@ class NBPFLoader:
|
||||
|
||||
# ── 中层验签 ──
|
||||
|
||||
def _verify_inner_signature(self, zf: zipfile.ZipFile, meta_inf: dict, ed25519_signer: str = None) -> str:
|
||||
def _verify_inner_signature(self, nir_modules: dict[str, dict], meta_inf: dict, ed25519_signer: str = None) -> str:
|
||||
"""中层 RSA-4096 签名验证,返回签名者名称
|
||||
|
||||
签名计算方式与 full_encrypt_package 一致。
|
||||
@@ -232,7 +229,7 @@ class NBPFLoader:
|
||||
否则遍历所有信任的 RSA 密钥。
|
||||
|
||||
Args:
|
||||
zf: 打开的 ZIP 文件
|
||||
nir_modules: 缓存的 NIR 模块数据
|
||||
meta_inf: 解密后的 META-INF 数据
|
||||
ed25519_signer: 外层 Ed25519 签名者名称
|
||||
|
||||
@@ -246,20 +243,8 @@ class NBPFLoader:
|
||||
if not inner_sig_b64:
|
||||
raise NBPFLoadError("缺少中层签名")
|
||||
|
||||
# 计算 NIR 数据摘要(与 full_encrypt_package 一致)
|
||||
nir_modules = {}
|
||||
for info in zf.infolist():
|
||||
if info.filename.startswith(NBPFFormatter.NIR_DIR) and not info.filename.endswith("/"):
|
||||
mod_name = info.filename[len(NBPFFormatter.NIR_DIR):]
|
||||
mod_data = json.loads(zf.read(info.filename).decode("utf-8"))
|
||||
nir_modules[mod_name] = mod_data
|
||||
|
||||
nir_digest = hashlib.sha256()
|
||||
for mod_name in sorted(nir_modules.keys()):
|
||||
nir_digest.update(mod_name.encode())
|
||||
nir_digest.update(nir_modules[mod_name]["ciphertext"].encode())
|
||||
|
||||
# 查找匹配的 RSA 公钥
|
||||
# 使用缓存的 nir_modules 计算摘要
|
||||
nir_digest = NBPCrypto._build_nir_digest(nir_modules)
|
||||
inner_sig = base64.b64decode(inner_sig_b64)
|
||||
|
||||
# 优先使用与外层签名者同名的 RSA 密钥
|
||||
@@ -267,11 +252,10 @@ class NBPFLoader:
|
||||
if ed25519_signer and ed25519_signer in self.trusted_rsa_keys:
|
||||
candidates.append((ed25519_signer, self.trusted_rsa_keys[ed25519_signer]))
|
||||
else:
|
||||
# 未指定或未找到同名密钥,遍历全部
|
||||
candidates = list(self.trusted_rsa_keys.items())
|
||||
|
||||
for name, rsa_pub_key in candidates:
|
||||
if self.crypto.inner_verify(nir_digest.digest(), inner_sig, rsa_pub_key):
|
||||
if self.crypto.inner_verify(nir_digest, inner_sig, rsa_pub_key):
|
||||
return name
|
||||
|
||||
raise NBPFLoadError("中层签名验证失败,无法匹配任何信任的 RSA 公钥")
|
||||
@@ -291,21 +275,12 @@ class NBPFLoader:
|
||||
|
||||
# ── 解密 NIR 数据 ──
|
||||
|
||||
def _decrypt_nir_data(self, zf: zipfile.ZipFile, key2: bytes) -> dict[str, bytes]:
|
||||
"""解密 NIR 数据,返回 {module_name: nir_bytes}"""
|
||||
nir_data = {}
|
||||
for info in zf.infolist():
|
||||
if not info.filename.startswith(NBPFFormatter.NIR_DIR):
|
||||
continue
|
||||
if info.filename.endswith("/"):
|
||||
continue
|
||||
|
||||
module_name = info.filename[len(NBPFFormatter.NIR_DIR):]
|
||||
enc_info = json.loads(zf.read(info.filename).decode("utf-8"))
|
||||
mod_data = self.crypto.inner_decrypt(enc_info, key2)
|
||||
nir_data[module_name] = mod_data
|
||||
|
||||
return nir_data
|
||||
def _decrypt_nir_data_raw(self, nir_modules: dict[str, dict], key2: bytes) -> dict[str, bytes]:
|
||||
"""解密 NIR 数据,使用缓存的模块数据"""
|
||||
return {
|
||||
mod_name: self.crypto.inner_decrypt(enc_info, key2)
|
||||
for mod_name, enc_info in nir_modules.items()
|
||||
}
|
||||
|
||||
# ── 内层验签 ──
|
||||
|
||||
|
||||
Reference in New Issue
Block a user