新增简易的8080面板😊
This commit is contained in:
99
tools/sign_core_plugins.py
Normal file
99
tools/sign_core_plugins.py
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
为 dependency 和 signature-verifier 插件签名
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
# ========== 配置 ==========
|
||||
PROJECT_ROOT = Path(__file__).parent.parent
|
||||
PRIVATE_KEY_FILE = PROJECT_ROOT / "data" / "signature-verifier" / "keys" / "private" / "futureoss_private.pem"
|
||||
|
||||
PLUGINS = ["dependency", "signature-verifier"]
|
||||
|
||||
|
||||
def compute_plugin_hash(plugin_dir: Path) -> str:
|
||||
"""计算插件目录的内容哈希"""
|
||||
hasher = hashlib.sha256()
|
||||
files_to_hash = []
|
||||
for file_path in sorted(plugin_dir.rglob("*")):
|
||||
if file_path.is_file() and file_path.name != "SIGNATURE":
|
||||
rel_path = file_path.relative_to(plugin_dir)
|
||||
files_to_hash.append((str(rel_path), file_path))
|
||||
|
||||
for rel_path, file_path in files_to_hash:
|
||||
hasher.update(rel_path.encode("utf-8"))
|
||||
hasher.update(file_path.read_bytes())
|
||||
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def sign_plugin(plugin_dir: Path):
|
||||
"""为插件签名"""
|
||||
# 加载私钥
|
||||
print(f"加载私钥: {PRIVATE_KEY_FILE}")
|
||||
private_key = serialization.load_pem_private_key(
|
||||
PRIVATE_KEY_FILE.read_bytes(),
|
||||
password=None,
|
||||
backend=default_backend()
|
||||
)
|
||||
|
||||
# 计算插件哈希
|
||||
print(f"计算插件目录哈希: {plugin_dir.name}...")
|
||||
plugin_hash = compute_plugin_hash(plugin_dir)
|
||||
print(f"哈希: {plugin_hash}")
|
||||
|
||||
# 签名
|
||||
signed_data = f"FutureOSS:{plugin_hash}".encode("utf-8")
|
||||
signature = private_key.sign(
|
||||
signed_data,
|
||||
padding.PSS(
|
||||
mgf=padding.MGF1(hashes.SHA256()),
|
||||
salt_length=padding.PSS.MAX_LENGTH
|
||||
),
|
||||
hashes.SHA256()
|
||||
)
|
||||
|
||||
# 写入签名文件
|
||||
sig_data = {
|
||||
"signature": base64.b64encode(signature).decode(),
|
||||
"signer": "FutureOSS",
|
||||
"algorithm": "RSA-SHA256",
|
||||
"timestamp": time.time(),
|
||||
"plugin_hash": plugin_hash,
|
||||
"author": "FutureOSS"
|
||||
}
|
||||
|
||||
signature_file = plugin_dir / "SIGNATURE"
|
||||
signature_file.write_text(json.dumps(sig_data, indent=2))
|
||||
print(f"✓ 已签名: {plugin_dir.name}")
|
||||
|
||||
|
||||
def main():
|
||||
if not PRIVATE_KEY_FILE.exists():
|
||||
print(f"错误: 私钥文件不存在: {PRIVATE_KEY_FILE}")
|
||||
sys.exit(1)
|
||||
|
||||
store_dir = PROJECT_ROOT / "store" / "@{FutureOSS}"
|
||||
|
||||
for plugin_name in PLUGINS:
|
||||
plugin_dir = store_dir / plugin_name
|
||||
if plugin_dir.exists():
|
||||
sign_plugin(plugin_dir)
|
||||
else:
|
||||
print(f"警告: 插件目录不存在: {plugin_dir}")
|
||||
|
||||
print("\n完成!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
102
tools/sign_plugin_loader.py
Normal file
102
tools/sign_plugin_loader.py
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
为 plugin-loader 插件签名
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
# ========== 配置 ==========
|
||||
PROJECT_ROOT = Path(__file__).parent.parent
|
||||
PRIVATE_KEY_FILE = PROJECT_ROOT / "data" / "signature-verifier" / "keys" / "private" / "futureoss_private.pem"
|
||||
PLUGIN_DIR = PROJECT_ROOT / "store" / "@{FutureOSS}" / "plugin-loader"
|
||||
|
||||
|
||||
def compute_plugin_hash(plugin_dir: Path) -> str:
|
||||
"""计算插件目录的内容哈希"""
|
||||
hasher = hashlib.sha256()
|
||||
files_to_hash = []
|
||||
for file_path in sorted(plugin_dir.rglob("*")):
|
||||
if file_path.is_file() and file_path.name != "SIGNATURE":
|
||||
rel_path = file_path.relative_to(plugin_dir)
|
||||
files_to_hash.append((str(rel_path), file_path))
|
||||
|
||||
for rel_path, file_path in files_to_hash:
|
||||
hasher.update(rel_path.encode("utf-8"))
|
||||
hasher.update(file_path.read_bytes())
|
||||
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def sign_plugin():
|
||||
"""为插件签名"""
|
||||
# 加载私钥
|
||||
print(f"加载私钥: {PRIVATE_KEY_FILE}")
|
||||
private_key = serialization.load_pem_private_key(
|
||||
PRIVATE_KEY_FILE.read_bytes(),
|
||||
password=None,
|
||||
backend=default_backend()
|
||||
)
|
||||
|
||||
# 计算插件哈希
|
||||
print(f"计算插件目录哈希...")
|
||||
plugin_hash = compute_plugin_hash(PLUGIN_DIR)
|
||||
print(f"哈希: {plugin_hash}")
|
||||
|
||||
# 签名
|
||||
signed_data = f"FutureOSS:{plugin_hash}".encode("utf-8")
|
||||
signature = private_key.sign(
|
||||
signed_data,
|
||||
padding.PSS(
|
||||
mgf=padding.MGF1(hashes.SHA256()),
|
||||
salt_length=padding.PSS.MAX_LENGTH
|
||||
),
|
||||
hashes.SHA256()
|
||||
)
|
||||
|
||||
# 写入签名文件
|
||||
sig_data = {
|
||||
"signature": base64.b64encode(signature).decode(),
|
||||
"signer": "FutureOSS",
|
||||
"algorithm": "RSA-SHA256",
|
||||
"timestamp": time.time(),
|
||||
"plugin_hash": plugin_hash,
|
||||
"author": "FutureOSS"
|
||||
}
|
||||
|
||||
signature_file = PLUGIN_DIR / "SIGNATURE"
|
||||
signature_file.write_text(json.dumps(sig_data, indent=2))
|
||||
print(f"\n✓ 签名成功!")
|
||||
print(f" 插件: {PLUGIN_DIR.name}")
|
||||
print(f" 签名文件: {signature_file}")
|
||||
print(f" 算法: RSA-SHA256")
|
||||
print(f" 时间戳: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
except ImportError:
|
||||
print("错误: 未安装 cryptography 库")
|
||||
print("运行: pip install cryptography")
|
||||
sys.exit(1)
|
||||
|
||||
if not PLUGIN_DIR.exists():
|
||||
print(f"错误: 插件目录不存在: {PLUGIN_DIR}")
|
||||
sys.exit(1)
|
||||
|
||||
if not PRIVATE_KEY_FILE.exists():
|
||||
print(f"错误: 私钥文件不存在: {PRIVATE_KEY_FILE}")
|
||||
sys.exit(1)
|
||||
|
||||
sign_plugin()
|
||||
193
tools/sign_plugins.py
Normal file
193
tools/sign_plugins.py
Normal file
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
密钥生成与插件签名工具
|
||||
- 生成 Falck 官方密钥对
|
||||
- 为所有官方插件签名
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding, rsa
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
# ========== 配置 ==========
|
||||
PROJECT_ROOT = Path(__file__).parent.parent # 修复:tools 的上级目录
|
||||
KEY_DIR = PROJECT_ROOT / "data" / "signature-verifier" / "keys"
|
||||
STORE_DIR = PROJECT_ROOT / "store"
|
||||
|
||||
# 官方作者目录
|
||||
OFFICIAL_AUTHORS = ["FutureOSS", "Falck"]
|
||||
|
||||
|
||||
def generate_keypair(author: str):
|
||||
"""生成 4096 位 RSA 密钥对"""
|
||||
print(f"\n{'='*60}")
|
||||
print(f"生成 {author} 的密钥对...")
|
||||
print(f"{'='*60}")
|
||||
|
||||
private_key = rsa.generate_private_key(
|
||||
public_exponent=65537,
|
||||
key_size=4096,
|
||||
backend=default_backend()
|
||||
)
|
||||
public_key = private_key.public_key()
|
||||
|
||||
# 保存私钥
|
||||
private_pem = private_key.private_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PrivateFormat.PKCS8,
|
||||
encryption_algorithm=serialization.NoEncryption()
|
||||
)
|
||||
priv_dir = KEY_DIR / "private"
|
||||
priv_dir.mkdir(parents=True, exist_ok=True)
|
||||
priv_file = priv_dir / f"{author.lower()}_private.pem"
|
||||
priv_file.write_bytes(private_pem)
|
||||
print(f"私钥已保存: {priv_file}")
|
||||
|
||||
# 保存公钥
|
||||
public_pem = public_key.public_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PublicFormat.SubjectPublicKeyInfo
|
||||
)
|
||||
pub_dir = KEY_DIR / "public"
|
||||
pub_dir.mkdir(parents=True, exist_ok=True)
|
||||
pub_file = pub_dir / f"{author}.pem"
|
||||
pub_file.write_bytes(public_pem)
|
||||
print(f"公钥已保存: {pub_file}")
|
||||
|
||||
# 显示公钥(用于嵌入代码)
|
||||
print(f"\n--- 公钥 PEM (用于嵌入 main.py) ---")
|
||||
print(public_pem.decode())
|
||||
print(f"--- END ---\n")
|
||||
|
||||
return private_key, public_key
|
||||
|
||||
|
||||
def compute_plugin_hash(plugin_dir: Path) -> str:
|
||||
"""计算插件目录的内容哈希"""
|
||||
hasher = hashlib.sha256()
|
||||
files_to_hash = []
|
||||
for file_path in sorted(plugin_dir.rglob("*")):
|
||||
if file_path.is_file() and file_path.name != "SIGNATURE":
|
||||
rel_path = file_path.relative_to(plugin_dir)
|
||||
files_to_hash.append((str(rel_path), file_path))
|
||||
|
||||
for rel_path, file_path in files_to_hash:
|
||||
hasher.update(rel_path.encode("utf-8"))
|
||||
hasher.update(file_path.read_bytes())
|
||||
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def sign_plugin(plugin_dir: Path, private_key, signer_name: str, author: str):
|
||||
"""为插件生成签名"""
|
||||
plugin_hash = compute_plugin_hash(plugin_dir)
|
||||
|
||||
# 签名
|
||||
signed_data = f"{author}:{plugin_hash}".encode("utf-8")
|
||||
signature = private_key.sign(
|
||||
signed_data,
|
||||
padding.PSS(
|
||||
mgf=padding.MGF1(hashes.SHA256()),
|
||||
salt_length=padding.PSS.MAX_LENGTH
|
||||
),
|
||||
hashes.SHA256()
|
||||
)
|
||||
|
||||
# 写入签名文件
|
||||
sig_data = {
|
||||
"signature": base64.b64encode(signature).decode(),
|
||||
"signer": signer_name,
|
||||
"algorithm": "RSA-SHA256",
|
||||
"timestamp": time.time(),
|
||||
"plugin_hash": plugin_hash,
|
||||
"author": author
|
||||
}
|
||||
|
||||
signature_file = plugin_dir / "SIGNATURE"
|
||||
signature_file.write_text(json.dumps(sig_data, indent=2))
|
||||
print(f" ✓ 已签名: {plugin_dir.name} (哈希: {plugin_hash[:16]}...)")
|
||||
|
||||
|
||||
def sign_all_plugins(private_key):
|
||||
"""为所有官方插件签名"""
|
||||
for author in OFFICIAL_AUTHORS:
|
||||
author_dir = STORE_DIR / f"@{{{author}}}"
|
||||
if not author_dir.exists():
|
||||
print(f"\n警告: 作者目录不存在: {author_dir}")
|
||||
continue
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"为 @{{{author}}} 的插件签名...")
|
||||
print(f"{'='*60}")
|
||||
|
||||
count = 0
|
||||
for plugin_dir in sorted(author_dir.iterdir()):
|
||||
if plugin_dir.is_dir() and (plugin_dir / "manifest.json").exists():
|
||||
sign_plugin(plugin_dir, private_key, author, author)
|
||||
count += 1
|
||||
|
||||
print(f"\n完成: 已签名 {count} 个 @{author} 插件")
|
||||
|
||||
|
||||
def main():
|
||||
print("="*60)
|
||||
print("FutureOSS 插件签名工具")
|
||||
print("="*60)
|
||||
|
||||
# 检查 cryptography
|
||||
try:
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding, rsa
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
except ImportError:
|
||||
print("错误: 未安装 cryptography 库")
|
||||
print("运行: pip install cryptography")
|
||||
sys.exit(1)
|
||||
|
||||
# 步骤 1: 生成密钥对
|
||||
print("\n步骤 1: 生成 Falck 官方密钥对...")
|
||||
falck_priv, falck_pub = generate_keypair("Falck")
|
||||
|
||||
print("\n步骤 1b: 生成 FutureOSS 官方密钥对...")
|
||||
foss_priv, foss_pub = generate_keypair("FutureOSS")
|
||||
|
||||
# 步骤 2: 为所有官方插件签名(使用对应的密钥)
|
||||
print("\n步骤 2: 为所有官方插件签名...")
|
||||
|
||||
# Falck 的插件用 Falck 密钥签名
|
||||
falck_dir = STORE_DIR / "@{Falck}"
|
||||
if falck_dir.exists():
|
||||
print(f"\n{'='*60}")
|
||||
print("为 @{Falck} 的插件使用 Falck 密钥签名...")
|
||||
print(f"{'='*60}")
|
||||
for plugin_dir in sorted(falck_dir.iterdir()):
|
||||
if plugin_dir.is_dir() and (plugin_dir / "manifest.json").exists():
|
||||
sign_plugin(plugin_dir, falck_priv, "Falck", "Falck")
|
||||
|
||||
# FutureOSS 的插件用 FutureOSS 密钥签名
|
||||
foss_dir = STORE_DIR / "@{FutureOSS}"
|
||||
if foss_dir.exists():
|
||||
print(f"\n{'='*60}")
|
||||
print("为 @{FutureOSS} 的插件使用 FutureOSS 密钥签名...")
|
||||
print(f"{'='*60}")
|
||||
for plugin_dir in sorted(foss_dir.iterdir()):
|
||||
if plugin_dir.is_dir() and (plugin_dir / "manifest.json").exists():
|
||||
sign_plugin(plugin_dir, foss_priv, "FutureOSS", "FutureOSS")
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("全部完成!")
|
||||
print("="*60)
|
||||
print(f"\n密钥位置: {KEY_DIR}")
|
||||
print("请将公钥嵌入 signature-verifier/main.py 的 FALCK_PUBLIC_KEY_PEM 变量")
|
||||
print("并妥善保管私钥,不要提交到版本控制系统!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
102
tools/sign_single_plugin.py
Normal file
102
tools/sign_single_plugin.py
Normal file
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
为单个插件签名
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
# ========== 配置 ==========
|
||||
PROJECT_ROOT = Path(__file__).parent.parent
|
||||
PRIVATE_KEY_FILE = PROJECT_ROOT / "data" / "signature-verifier" / "keys" / "private" / "futureoss_private.pem"
|
||||
PLUGIN_DIR = PROJECT_ROOT / "store" / "@{FutureOSS}" / "log-terminal"
|
||||
|
||||
|
||||
def compute_plugin_hash(plugin_dir: Path) -> str:
|
||||
"""计算插件目录的内容哈希"""
|
||||
hasher = hashlib.sha256()
|
||||
files_to_hash = []
|
||||
for file_path in sorted(plugin_dir.rglob("*")):
|
||||
if file_path.is_file() and file_path.name != "SIGNATURE":
|
||||
rel_path = file_path.relative_to(plugin_dir)
|
||||
files_to_hash.append((str(rel_path), file_path))
|
||||
|
||||
for rel_path, file_path in files_to_hash:
|
||||
hasher.update(rel_path.encode("utf-8"))
|
||||
hasher.update(file_path.read_bytes())
|
||||
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def sign_plugin():
|
||||
"""为插件签名"""
|
||||
# 加载私钥
|
||||
print(f"加载私钥: {PRIVATE_KEY_FILE}")
|
||||
private_key = serialization.load_pem_private_key(
|
||||
PRIVATE_KEY_FILE.read_bytes(),
|
||||
password=None,
|
||||
backend=default_backend()
|
||||
)
|
||||
|
||||
# 计算插件哈希
|
||||
print(f"计算插件目录哈希...")
|
||||
plugin_hash = compute_plugin_hash(PLUGIN_DIR)
|
||||
print(f"哈希: {plugin_hash}")
|
||||
|
||||
# 签名
|
||||
signed_data = f"FutureOSS:{plugin_hash}".encode("utf-8")
|
||||
signature = private_key.sign(
|
||||
signed_data,
|
||||
padding.PSS(
|
||||
mgf=padding.MGF1(hashes.SHA256()),
|
||||
salt_length=padding.PSS.MAX_LENGTH
|
||||
),
|
||||
hashes.SHA256()
|
||||
)
|
||||
|
||||
# 写入签名文件
|
||||
sig_data = {
|
||||
"signature": base64.b64encode(signature).decode(),
|
||||
"signer": "FutureOSS",
|
||||
"algorithm": "RSA-SHA256",
|
||||
"timestamp": time.time(),
|
||||
"plugin_hash": plugin_hash,
|
||||
"author": "FutureOSS"
|
||||
}
|
||||
|
||||
signature_file = PLUGIN_DIR / "SIGNATURE"
|
||||
signature_file.write_text(json.dumps(sig_data, indent=2))
|
||||
print(f"\n✓ 签名成功!")
|
||||
print(f" 插件: {PLUGIN_DIR.name}")
|
||||
print(f" 签名文件: {signature_file}")
|
||||
print(f" 算法: RSA-SHA256")
|
||||
print(f" 时间戳: {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
except ImportError:
|
||||
print("错误: 未安装 cryptography 库")
|
||||
print("运行: pip install cryptography")
|
||||
sys.exit(1)
|
||||
|
||||
if not PLUGIN_DIR.exists():
|
||||
print(f"错误: 插件目录不存在: {PLUGIN_DIR}")
|
||||
sys.exit(1)
|
||||
|
||||
if not PRIVATE_KEY_FILE.exists():
|
||||
print(f"错误: 私钥文件不存在: {PRIVATE_KEY_FILE}")
|
||||
sys.exit(1)
|
||||
|
||||
sign_plugin()
|
||||
199
tools/test_signature.py
Normal file
199
tools/test_signature.py
Normal file
@@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
签名验证测试脚本
|
||||
测试签名验证功能是否正常工作
|
||||
"""
|
||||
|
||||
import sys
|
||||
import json
|
||||
import base64
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
# 添加项目路径
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent / "store/@{FutureOSS}/signature-verifier"))
|
||||
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
|
||||
# 导入签名验证插件
|
||||
from main import SignatureVerifier, SignatureSigner
|
||||
|
||||
|
||||
def test_verify_official_plugins():
|
||||
"""测试验证所有已签名的官方插件"""
|
||||
print("="*60)
|
||||
print("测试 1: 验证所有官方插件签名")
|
||||
print("="*60)
|
||||
|
||||
store_dir = Path(__file__).parent.parent / "store"
|
||||
verifier = SignatureVerifier(key_dir="./data/signature-verifier/keys")
|
||||
|
||||
authors = ["FutureOSS", "Falck"]
|
||||
total = 0
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for author in authors:
|
||||
author_dir = store_dir / f"@{{{author}}}"
|
||||
if not author_dir.exists():
|
||||
continue
|
||||
|
||||
print(f"\n--- @{author} ---")
|
||||
for plugin_dir in sorted(author_dir.iterdir()):
|
||||
if plugin_dir.is_dir() and (plugin_dir / "manifest.json").exists():
|
||||
total += 1
|
||||
valid, msg = verifier.verify_plugin(plugin_dir, author)
|
||||
status = "✅ 通过" if valid else "❌ 失败"
|
||||
print(f" {status}: {plugin_dir.name} - {msg}")
|
||||
if valid:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"\n{'='*60}")
|
||||
print(f"结果: {passed}/{total} 通过, {failed} 失败")
|
||||
print(f"{'='*60}")
|
||||
return failed == 0
|
||||
|
||||
|
||||
def test_tamper_detection():
|
||||
"""测试篡改检测"""
|
||||
print("\n" + "="*60)
|
||||
print("测试 2: 篡改检测")
|
||||
print("="*60)
|
||||
|
||||
store_dir = Path(__file__).parent.parent / "store"
|
||||
verifier = SignatureVerifier(key_dir="./data/signature-verifier/keys")
|
||||
|
||||
# 选择一个测试插件
|
||||
test_plugin = store_dir / "@{FutureOSS}" / "dashboard"
|
||||
if not test_plugin.exists():
|
||||
print("跳过: dashboard 插件不存在")
|
||||
return True
|
||||
|
||||
# 验证原始签名
|
||||
valid_before, msg_before = verifier.verify_plugin(test_plugin, "FutureOSS")
|
||||
print(f"\n篡改前: {'✅ 有效' if valid_before else '❌ 无效'} - {msg_before}")
|
||||
|
||||
if not valid_before:
|
||||
print("警告: 原始签名已无效,跳过篡改测试")
|
||||
return False
|
||||
|
||||
# 创建一个临时篡改文件
|
||||
tamper_file = test_plugin / "__tamper_test__.tmp"
|
||||
tamper_file.write_text("tampered content")
|
||||
|
||||
# 验证篡改后的签名
|
||||
valid_after, msg_after = verifier.verify_plugin(test_plugin, "FutureOSS")
|
||||
print(f"篡改后: {'✅ 有效' if valid_after else '❌ 无效'} - {msg_after}")
|
||||
|
||||
# 清理
|
||||
tamper_file.unlink()
|
||||
|
||||
# 再次验证应该恢复有效
|
||||
valid_clean, msg_clean = verifier.verify_plugin(test_plugin, "FutureOSS")
|
||||
print(f"清理后: {'✅ 有效' if valid_clean else '❌ 无效'} - {msg_clean}")
|
||||
|
||||
# 预期:篡改后无效,清理后有效
|
||||
success = not valid_after and valid_clean
|
||||
print(f"\n{'='*60}")
|
||||
print(f"篡改检测: {'✅ 成功' if success else '❌ 失败'}")
|
||||
print(f"{'='*60}")
|
||||
return success
|
||||
|
||||
|
||||
def test_missing_signature():
|
||||
"""测试缺失签名文件"""
|
||||
print("\n" + "="*60)
|
||||
print("测试 3: 缺失签名检测")
|
||||
print("="*60)
|
||||
|
||||
store_dir = Path(__file__).parent.parent / "store"
|
||||
verifier = SignatureVerifier(key_dir="./data/signature-verifier/keys")
|
||||
|
||||
# 选择一个插件并临时移除签名
|
||||
test_plugin = store_dir / "@{FutureOSS}" / "json-codec"
|
||||
if not test_plugin.exists():
|
||||
print("跳过: json-codec 插件不存在")
|
||||
return True
|
||||
|
||||
sig_file = test_plugin / "SIGNATURE"
|
||||
if not sig_file.exists():
|
||||
print("跳过: json-codec 没有签名文件")
|
||||
return True
|
||||
|
||||
# 备份签名
|
||||
backup = sig_file.read_text()
|
||||
sig_file.unlink()
|
||||
|
||||
# 验证
|
||||
valid, msg = verifier.verify_plugin(test_plugin, "FutureOSS")
|
||||
print(f"无签名: {'✅ 有效' if valid else '❌ 无效'} - {msg}")
|
||||
|
||||
# 恢复
|
||||
sig_file.write_text(backup)
|
||||
|
||||
valid_restored, msg_restored = verifier.verify_plugin(test_plugin, "FutureOSS")
|
||||
print(f"恢复后: {'✅ 有效' if valid_restored else '❌ 无效'} - {msg_restored}")
|
||||
|
||||
success = not valid and valid_restored
|
||||
print(f"\n{'='*60}")
|
||||
print(f"缺失签名检测: {'✅ 成功' if success else '❌ 失败'}")
|
||||
print(f"{'='*60}")
|
||||
return success
|
||||
|
||||
|
||||
def test_official_check():
|
||||
"""测试 is_official_plugin 方法"""
|
||||
print("\n" + "="*60)
|
||||
print("测试 4: 官方插件识别")
|
||||
print("="*60)
|
||||
|
||||
store_dir = Path(__file__).parent.parent / "store"
|
||||
verifier = SignatureVerifier(key_dir="./data/signature-verifier/keys")
|
||||
|
||||
# 测试官方插件
|
||||
official_plugin = store_dir / "@{FutureOSS}" / "dashboard"
|
||||
is_official = verifier.is_official_plugin(official_plugin)
|
||||
print(f"dashboard 是官方插件: {'✅ 是' if is_official else '❌ 否'}")
|
||||
|
||||
success = is_official
|
||||
print(f"\n{'='*60}")
|
||||
print(f"官方插件识别: {'✅ 成功' if success else '❌ 失败'}")
|
||||
print(f"{'='*60}")
|
||||
return success
|
||||
|
||||
|
||||
def main():
|
||||
print("FutureOSS 签名验证系统测试")
|
||||
print("="*60)
|
||||
|
||||
results = []
|
||||
|
||||
results.append(("官方插件验证", test_verify_official_plugins()))
|
||||
results.append(("篡改检测", test_tamper_detection()))
|
||||
results.append(("缺失签名检测", test_missing_signature()))
|
||||
results.append(("官方插件识别", test_official_check()))
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("测试总结")
|
||||
print("="*60)
|
||||
|
||||
for name, passed in results:
|
||||
status = "✅ 通过" if passed else "❌ 失败"
|
||||
print(f" {status}: {name}")
|
||||
|
||||
all_passed = all(r[1] for r in results)
|
||||
print(f"\n{'='*60}")
|
||||
print(f"总体结果: {'✅ 全部通过' if all_passed else '❌ 有失败'}")
|
||||
print(f"{'='*60}")
|
||||
|
||||
return 0 if all_passed else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user