from typing import List, Tuple, Optional, Callable
import time
import random
import hashlib
import psutil
import uuid
import os
import platform
import tkinter as tk
from tkinter import filedialog, messagebox, ttk, simpledialog
import threading
from dataclasses import dataclass
import qiskit
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel, depolarizing_error, thermal_relaxation_error
from qiskit.primitives import Sampler
try:
from pycryptodome.hazmat.primitives.asymmetric import kyber
from pycryptodome.hazmat.primitives import serialization
PQC_AVAILABLE = True
except ImportError:
PQC_AVAILABLE = False
def bytes_to_bits(data: bytes) -> List[int]:
return [(byte >> i) & 1 for byte in data for i in range(7, -1, -1)]
def bits_to_bytes(bits: List[int]) -> bytes:
bits = [b for b in bits if b in (0, 1)]
pad_length = (8 - len(bits) % 8) % 8
bits += [0] * pad_length
try:
return bytes(int(''.join(map(str, bits[i:i + 8])), 2) for i in range(0, len(bits), 8))
except Exception:
return b""
class QuantumProtocol:
"""基础量子协议类,定义协议接口和通用参数"""
def __init__(self):
self.security_level = 1 # 1-低, 2-中, 3-高
self.error_threshold = 0.1 # 错误率阈值,超过则视为不安全
def generate_bases(self, length: int) -> List[int]:
raise NotImplementedError
def basis_negotiation(self, sent_bits, recv_bits, sent_bases, recv_bases) -> Tuple[List[int], float]:
raise NotImplementedError
def get_protocol_params(self) -> Dict:
"""返回协议参数信息,用于展示和监测"""
return {
"安全级别": self.security_level,
"错误阈值": self.error_threshold
}
class BB84Protocol(QuantumProtocol):
"""BB84协议,增加光源强度和测量基选择概率参数"""
def __init__(self, light_intensity=0.8, basis_prob=None):
super().__init__()
self.light_intensity = light_intensity # 光源强度(0-1)
self.basis_prob = basis_prob or [0.5, 0.5] # Z基和X基的选择概率
def generate_bases(self, length: int) -> List[int]:
return [0 if random.random() < self.basis_prob[0] else 1 for _ in range(length)]
def basis_negotiation(self, sent_bits, recv_bits, sent_bases, recv_bases) -> Tuple[List[int], float]:
matched = [s for s, r, sb, rb in zip(sent_bits, recv_bits, sent_bases, recv_bases) if sb == rb]
error_rate = 1 - (sum(1 for s, r in zip(matched[::10], recv_bits[::10]) if s == r) / len(matched[::10])) if matched else 0.0
return matched, min(error_rate, self.error_threshold)
def get_protocol_params(self) -> Dict:
params = super().get_protocol_params()
params.update({
"光源强度": self.light_intensity,
"测量基概率(Z/X)": self.basis_prob
})
return params
class SatelliteQKDProtocol(QuantumProtocol):
"""卫星QKD协议,增加海拔角度和大气损耗参数"""
def __init__(self, elevation_angle=30, weather_factor=1.0):
super().__init__()
self.elevation_angle = elevation_angle # 海拔角度(度)
self.weather_factor = weather_factor # 天气影响因子(1.0为晴天,>1表示恶劣天气)
self.atmospheric_loss = 0.1 * (90 / elevation_angle) * weather_factor # 实时计算大气损耗
def generate_bases(self, length: int) -> List[int]:
# 低角度时增加基选择随机性以对抗大气干扰
if self.elevation_angle < 20:
return [random.randint(0, 1) for _ in range(length)]
return [0 if random.random() < 0.6 else 1 for _ in range(length)] # 高角度时偏好Z基
def basis_negotiation(self, sent_bits, recv_bits, sent_bases, recv_bases) -> Tuple[List[int], float]:
# 考虑大气损耗的匹配机制
loss_resist = [random.random() > self.atmospheric_loss for _ in range(len(sent_bits))]
matched = [s for s, r, sb, rb, lr in zip(sent_bits, recv_bits, sent_bases, recv_bases, loss_resist)
if sb == rb and lr]
# 错误率随海拔角度动态调整
error_rate = 0.04 * (90 / self.elevation_angle) * self.weather_factor if matched else 0.0
return matched[:int(len(matched)*(1-self.atmospheric_loss))], min(error_rate, self.error_threshold)
def update_weather(self, weather_factor: float):
"""实时更新天气状况"""
self.weather_factor = weather_factor
self.atmospheric_loss = 0.1 * (90 / self.elevation_angle) * weather_factor
def get_protocol_params(self) -> Dict:
params = super().get_protocol_params()
params.update({
"海拔角度(度)": self.elevation_angle,
"天气因子": self.weather_factor,
"大气损耗": f"{self.atmospheric_loss:.2f}"
})
return params
class TFQKDProtocol(QuantumProtocol):
"""时间频率QKD协议,增加频率偏移和同步精度参数"""
def __init__(self, frequency_offset=1.2, sync_precision=0.001):
super().__init__()
self.frequency_offset = frequency_offset # 频率偏移系数
self.sync_precision = sync_precision # 时间同步精度(秒)
def generate_bases(self, length: int) -> List[int]:
return [random.randint(0, 2) for _ in range(length)]
def basis_negotiation(self, sent_bits, recv_bits, sent_bases, recv_bases) -> Tuple[List[int], float]:
# 频率同步误差导致的匹配损失
sync_loss = int(len(sent_bits) * self.sync_precision * 10)
valid_range = len(sent_bits) - sync_loss
matched = [s for s, r, sb, rb in zip(sent_bits[:valid_range], recv_bits[sync_loss:],
sent_bases[:valid_range], recv_bases[sync_loss:])
if sb == rb == 2]
error_rate = 0.02 * self.frequency_offset if matched else 0.0
return matched, min(error_rate, self.error_threshold)
def get_protocol_params(self) -> Dict:
params = super().get_protocol_params()
params.update({
"频率偏移": self.frequency_offset,
"同步精度(秒)": self.sync_precision
})
return params
# 其他协议类保持结构,增加专属参数...
class B92Protocol(QuantumProtocol):
def __init__(self, encoding_strength=0.9):
super().__init__()
self.encoding_strength = encoding_strength # 编码强度
def generate_bases(self, length: int) -> List[int]:
return [random.randint(0, 1) for _ in range(length)]
def basis_negotiation(self, sent_bits, recv_bits, sent_bases, recv_bases) -> Tuple[List[int], float]:
matched = [s for s, r, sb, rb in zip(sent_bits, recv_bits, sent_bases, recv_bases)
if (s == 1 and r == 0) or (s == 0 and r == 1)]
# 编码强度影响有效密钥长度
valid_length = int(len(matched) * self.encoding_strength)
error_rate = 0.05 if matched else 0.0
return matched[:valid_length], error_rate
def get_protocol_params(self) -> Dict:
params = super().get_protocol_params()
params.update({"编码强度": self.encoding_strength})
return params
class E91Protocol(QuantumProtocol):
def __init__(self, entanglement_strength=0.85):
super().__init__()
self.entanglement_strength = entanglement_strength # 纠缠强度
def generate_bases(self, length: int) -> List[int]:
return [random.randint(0, 2) for _ in range(length)]
def basis_negotiation(self, sent_bits, recv_bits, sent_bases, recv_bases) -> Tuple[List[int], float]:
matched = []
for s, r, sb, rb in zip(sent_bits, recv_bits, sent_bases, recv_bases):
if sb == rb:
matched.append(1 - r)
# 纠缠强度影响错误率
error_rate = 0.03 * (1 - self.entanglement_strength + 0.5) if matched else 0.0
return matched, error_rate
def get_protocol_params(self) -> Dict:
params = super().get_protocol_params()
params.update({"纠缠强度": self.entanglement_strength})
return params
class KeyPostProcessing:
@staticmethod
def ldpc_correction(raw_bits: List[int], error_rate: float) -> List[int]:
if not raw_bits:
return []
correction_window = max(4, int(len(raw_bits) * error_rate * 10))
corrected = raw_bits.copy()
for i in range(0, len(corrected), correction_window):
window = corrected[i:i + correction_window]
if len(window) < 2:
continue
majority = 1 if sum(window) > len(window) // 2 else 0
for j in range(len(window)):
if random.random() < error_rate:
window[j] = majority
corrected[i:i + correction_window] = window
return corrected
@staticmethod
def privacy_amplification(bits: List[int], seed: Optional[bytes] = None) -> List[int]:
if not bits:
return [0] * 8
seed = seed or os.urandom(16)
bytes_data = bits_to_bytes(bits)
hash1 = hashlib.sha3_256(seed + bytes_data).digest()
hash2 = hashlib.sha3_512(hash1 + seed).digest()
return bytes_to_bits(hash2)[:len(bits)]
@dataclass
class QuantumChannel:
"""量子信道类,增加安全监测和警报功能"""
distance_km: float
loss_rate: float = 0.02
interception_detected: bool = False
security_alert_callback: Optional[Callable] = None # 安全警报回调函数
interception_count: int = 0 # 拦截计数
error_history: List[float] = None # 错误率历史记录
def __post_init__(self):
self.error_history = self.error_history or []
def transmit(self, sent_bits: List[int], sent_bases: List[int]) -> Tuple[List[int], List[int]]:
recv_bases = [random.choice([0, 1]) for _ in range(len(sent_bits))]
recv_bits = []
# 模拟传输损耗
for bit in sent_bits:
if random.random() < self.loss_rate * self.distance_km / 10:
continue
recv_bits.append(bit)
# 模拟噪声
noise_prob = 0.01 * self.distance_km / 10
for i in range(len(recv_bits)):
if random.random() < noise_prob:
recv_bits[i] ^= 1
# 检测潜在拦截
interception_prob = 0.02 * self.distance_km / 10
if random.random() < interception_prob:
self.interception_detected = True
self.interception_count += 1
recv_bits = [random.randint(0, 1) for _ in recv_bits]
self._alert_security_monitor() # 触发安全警报
# 记录错误率历史
if sent_bits and recv_bits:
error_rate = sum(s != r for s, r in zip(sent_bits[:len(recv_bits)], recv_bits)) / len(recv_bits)
self.error_history.append(error_rate)
# 保留最近10条记录
if len(self.error_history) > 10:
self.error_history.pop(0)
return recv_bits, recv_bases
def _alert_security_monitor(self):
"""触发安全警报,通知用户可能存在的拦截"""
if self.security_alert_callback:
self.security_alert_callback(
f"潜在安全威胁:检测到可能的量子拦截!\n"
f"拦截次数:{self.interception_count}\n"
f"信道距离:{self.distance_km}km"
)
else:
# 默认警报处理
print(f"[安全警报] 检测到可能的量子拦截!次数: {self.interception_count}")
def get_security_status(self) -> Dict:
"""获取当前信道安全状态"""
avg_error = sum(self.error_history) / len(self.error_history) if self.error_history else 0
return {
"拦截次数": self.interception_count,
"平均错误率": f"{avg_error:.4f}",
"最近错误趋势": "上升" if len(self.error_history) >= 3 and
self.error_history[-1] > self.error_history[-2] > self.error_history[-3] else "稳定"
}
class QuantumRandomSource:
@staticmethod
def get_quantum_random_bits(length: int, use_real_hardware: bool = False, protocol: str = "") -> List[int]:
start_time = time.time()
batch_size = 16
total_bits = []
if use_real_hardware and PQC_AVAILABLE:
try:
from qiskit_ibm_provider import IBMProvider
provider = IBMProvider()
backend = provider.get_backend('ibmq_qasm_simulator')
except Exception:
use_real_hardware = False
while len(total_bits) < length:
try:
if use_real_hardware:
circuit = qiskit.QuantumCircuit(batch_size, batch_size)
circuit.h(range(batch_size))
circuit.measure(range(batch_size), range(batch_size))
transpiled = qiskit.transpile(circuit, backend)
job = backend.run(transpiled, shots=1, memory=True)
result = job.result()
batch_bits = [int(bit) for bit in result.get_memory()[0]]
else:
noise_model = NoiseModel()
if protocol in ["TF-QKD", "卫星QKD"]:
noise_model.add_all_qubit_quantum_error(
thermal_relaxation_error(5e3, 2e3, 0.5), ['h', 'measure']
)
else:
noise_model.add_all_qubit_quantum_error(
depolarizing_error(0.005, 1), ['h', 'measure']
)
simulator = AerSimulator(noise_model=noise_model)
circuit = qiskit.QuantumCircuit(batch_size, batch_size)
circuit.h(range(batch_size))
circuit.measure(range(batch_size), range(batch_size))
sampler = Sampler(backend=simulator)
result = sampler.run(circuits=circuit, shots=1).result()
counts = result.quasi_dists[0]
bitstring = max(counts, key=counts.get).zfill(batch_size)
batch_bits = [int(bit) for bit in bitstring]
total_bits.extend(batch_bits)
if time.time() - start_time > 5:
raise TimeoutError
except Exception:
total_bits.extend([random.getrandbits(1) for _ in range(batch_size)])
return total_bits[:length]
class QuantumEncryptionTool:
def __init__(
self,
protocol: str = "BB84",
channel_distance_km: float = 10.0,
enable_pqc: bool = False,
use_real_quantum: bool = False,
security_alert_callback: Optional[Callable] = None
):
self.protocol_name = protocol
self.protocol = self._get_protocol(protocol)
self.channel = QuantumChannel(
distance_km=channel_distance_km,
security_alert_callback=security_alert_callback
)
self.key_processor = KeyPostProcessing()
self.hw_signature = self._get_hw_signature()
self.use_real_quantum = use_real_quantum
self.pqc_private_key = None
self.pqc_public_key = None
self.authorized_signatures = [self.hw_signature]
self._load_authorized_signatures()
if enable_pqc and PQC_AVAILABLE:
self._init_kyber()
else:
self.enable_pqc = False
def _get_protocol(self, protocol_name: str) -> QuantumProtocol:
"""根据协议名创建带专属参数的协议实例"""
protocols = {
"BB84": BB84Protocol(light_intensity=0.85, basis_prob=[0.5, 0.5]),
"B92": B92Protocol(encoding_strength=0.9),
"E91": E91Protocol(entanglement_strength=0.88),
"TF-QKD": TFQKDProtocol(frequency_offset=1.1, sync_precision=0.0008),
"卫星QKD": SatelliteQKDProtocol(elevation_angle=45, weather_factor=1.0)
}
return protocols.get(protocol_name.upper(), BB84Protocol())
def update_protocol_params(self, **kwargs):
"""更新协议专属参数"""
if hasattr(self.protocol, 'elevation_angle') and 'elevation_angle' in kwargs:
self.protocol.elevation_angle = kwargs['elevation_angle']
self.protocol.atmospheric_loss = 0.1 * (90 / self.protocol.elevation_angle) * self.protocol.weather_factor
if hasattr(self.protocol, 'weather_factor') and 'weather_factor' in kwargs:
self.protocol.update_weather(kwargs['weather_factor'])
if hasattr(self.protocol, 'light_intensity') and 'light_intensity' in kwargs:
self.protocol.light_intensity = kwargs['light_intensity']
def get_protocol_info(self) -> Dict:
"""获取当前协议信息和参数"""
return {
"协议名称": self.protocol_name,
"参数": self.protocol.get_protocol_params(),
"信道状态": self.channel.get_security_status()
}
def _get_hw_signature(self) -> bytes:
hw_info = [
(psutil.cpu_count(logical=False) or 0).to_bytes(4, 'big'),
uuid.getnode().to_bytes(6, 'big'),
platform.machine().encode(),
psutil.disk_usage('/').total.to_bytes(8, 'big')[:4]
]
return hashlib.sha3_256(b''.join(hw_info)).digest()
def _init_kyber(self):
self.enable_pqc = True
kyber_cipher = kyber.Kyber512()
self.pqc_private_key = kyber_cipher.generate_private_key()
self.pqc_public_key = self.pqc_private_key.public_key()
def _secure_xor(self, data: bytes, key: bytes) -> bytes:
key = key.ljust(len(data), b'\x00')[:len(data)]
return bytes(d ^ k for d, k in zip(data, key))
def generate_key(self, data_length: int) -> bytes:
start_time = time.time()
raw_bit_length = max(data_length * 8 * 2, 128)
for attempt in range(3):
try:
sent_bits = QuantumRandomSource.get_quantum_random_bits(
raw_bit_length,
use_real_hardware=self.use_real_quantum,
protocol=self.protocol_name
)
sent_bases = self.protocol.generate_bases(raw_bit_length)
recv_bits, recv_bases = self.channel.transmit(sent_bits, sent_bases)
matched_bits, error_rate = self.protocol.basis_negotiation(
sent_bits, recv_bits, sent_bases, recv_bases
)
# 如果错误率超过阈值,视为不安全,重新生成
if error_rate > self.protocol.error_threshold:
continue
corrected_bits = self.key_processor.ldpc_correction(matched_bits, error_rate)
if len(corrected_bits) < data_length * 8:
continue
final_bits = self.key_processor.privacy_amplification(corrected_bits)
final_key = bits_to_bytes(final_bits)[:data_length]
if len(final_key) == data_length:
return final_key
except Exception:
continue
return os.urandom(data_length)
# 以下方法保持原有功能,省略...
def encrypt_file(self, file_path: str, progress_callback=None) -> Tuple[bytes, bytes, Optional[bytes]]:
chunk_size = 4096
session_key = self.generate_key(chunk_size)
pqc_encapsulated = None
if self.enable_pqc:
pqc_encapsulated, _ = self.pqc_public_key.encrypt(session_key)
ciphertext_chunks = []
file_size = os.path.getsize(file_path)
processed = 0
with open(file_path, 'rb') as f:
while True:
chunk = f.read(chunk_size)
if not chunk:
break
ciphertext_chunks.append(self._secure_xor(chunk, session_key))
processed += len(chunk)
if progress_callback:
progress_callback(min(100, int(processed / file_size * 100)))
ciphertext = b''.join(ciphertext_chunks)
signed_key = session_key + self.hw_signature
return ciphertext, signed_key, pqc_encapsulated
def decrypt_file(self, ciphertext: bytes, signed_key: bytes, output_path: str,
pqc_encapsulated: Optional[bytes] = None, progress_callback=None) -> bool:
if len(signed_key) < len(ciphertext) + len(self.hw_signature):
return False
session_key = signed_key[:len(ciphertext)]
stored_signature = signed_key[-len(self.hw_signature):]
if stored_signature not in self.authorized_signatures:
return False
if self.enable_pqc and pqc_encapsulated:
try:
session_key = self.pqc_private_key.decrypt(pqc_encapsulated)
except Exception:
return False
chunk_size = 4096
total_chunks = (len(ciphertext) + chunk_size - 1) // chunk_size
processed = 0
with open(output_path, 'wb') as f:
for i in range(0, len(ciphertext), chunk_size):
chunk = ciphertext[i:i + chunk_size]
plaintext_chunk = self._secure_xor(chunk, session_key)
f.write(plaintext_chunk)
processed += 1
if progress_callback:
progress_callback(min(100, int(processed / total_chunks * 100)))
return True
def encrypt_text(self, plaintext: str) -> Tuple[bytes, bytes, Optional[bytes]]:
plaintext_bytes = plaintext.encode('utf-8')
session_key = self.generate_key(len(plaintext_bytes))
ciphertext = self._secure_xor(plaintext_bytes, session_key)
signed_key = session_key + self.hw_signature
pqc_encapsulated = None
if self.enable_pqc:
pqc_encapsulated, _ = self.pqc_public_key.encrypt(session_key)
return ciphertext, signed_key, pqc_encapsulated
def decrypt_text(self, ciphertext: bytes, signed_key: bytes, pqc_encapsulated: Optional[bytes] = None) -> str:
if len(signed_key) < len(ciphertext) + len(self.hw_signature):
raise ValueError("密钥长度不足")
session_key = signed_key[:len(ciphertext)]
stored_signature = signed_key[-len(self.hw_signature):]
if stored_signature not in self.authorized_signatures:
raise PermissionError("设备未授权")
if self.enable_pqc and pqc_encapsulated:
try:
session_key = self.pqc_private_key.decrypt(pqc_encapsulated)
except Exception:
raise ValueError("PQC解密失败")
plaintext_bytes = self._secure_xor(ciphertext, session_key)
return plaintext_bytes.decode('utf-8', errors='replace')
def _load_authorized_signatures(self):
if os.path.exists("authorized_devices.txt"):
with open("authorized_devices.txt", "r") as f:
self.authorized_signatures = [bytes.fromhex(line.strip()) for line in f if line.strip()]
def _save_authorized_signatures(self):
with open("authorized_devices.txt", "w") as f:
for sig in self.authorized_signatures:
f.write(sig.hex() + "\n")
def get_authorized_devices(self) -> List[str]:
return [sig.hex()[:16] + "..." for sig in self.authorized_signatures]
def revoke_authorization(self, sig_hex: str) -> bool:
full_sig = None
for sig in self.authorized_signatures:
if sig.hex().startswith(sig_hex):
full_sig = sig
break
if full_sig and full_sig != self.hw_signature:
self.authorized_signatures.remove(full_sig)
self._save_authorized_signatures()
return True
return False
def generate_authorization_code(self) -> str:
timestamp = int(time.time()).to_bytes(8, 'big')
data = timestamp + self.hw_signature
if self.enable_pqc and self.pqc_public_key:
encrypted_data = self.pqc_public_key.encrypt(data)
else:
encrypted_data = data
return encrypted_data.hex()
def add_authorized_device(self, auth_code: str) -> bool:
try:
data = bytes.fromhex(auth_code)
if self.enable_pqc and self.pqc_private_key:
data = self.pqc_private_key.decrypt(data)
timestamp = int.from_bytes(data[:8], 'big')
if time.time() - timestamp > 600:
return False
new_sig = data[8:]
if new_sig not in self.authorized_signatures:
self.authorized_signatures.append(new_sig)
self._save_authorized_signatures()
return True
return False
except Exception:
return False
class EncryptionGUI:
def __init__(self, root):
self.root = root
self.root.title("量子加密工具 v3.2")
self.root.geometry("1000x700")
self.root.resizable(True, True)
self.font_config()
self.encryption_core = None
self._init_core()
self.tab_control = ttk.Notebook(root)
self.tab_encrypt = ttk.Frame(self.tab_control)
self.tab_decrypt = ttk.Frame(self.tab_control)
self.tab_settings = ttk.Frame(self.tab_control)
self.tab_authorization = ttk.Frame(self.tab_control)
self.tab_monitor = ttk.Frame(self.tab_control) # 新增安全监测标签页
self.tab_control.add(self.tab_encrypt, text="加密")
self.tab_control.add(self.tab_decrypt, text="解密")
self.tab_control.add(self.tab_settings, text="设置")
self.tab_control.add(self.tab_authorization, text="授权管理")
self.tab_control.add(self.tab_monitor, text="安全监测") # 添加到标签页
self.tab_control.pack(expand=1, fill="both")
self._setup_encrypt_tab()
self._setup_decrypt_tab()
self._setup_settings_tab()
self._setup_authorization_tab()
self._setup_monitor_tab() # 初始化监测页面
self._add_help_text()
def font_config(self):
default_font = ('SimHei', 10)
self.root.option_add("*Font", default_font)
def _init_core(self):
# 传递安全警报回调函数
self.encryption_core = QuantumEncryptionTool(
protocol="BB84",
channel_distance_km=10.0,
enable_pqc=False,
use_real_quantum=False,
security_alert_callback=self._show_security_alert
)
def _show_security_alert(self, message: str):
"""显示安全警报对话框"""
self.root.after(0, lambda: messagebox.showerror("安全警报", message))
# 更新监测页面
self.root.after(0, self._update_monitor_data)
def _setup_monitor_tab(self):
"""安全监测页面,展示信道状态和协议参数"""
frame = ttk.Frame(self.tab_monitor, padding=10)
frame.pack(fill="both", expand=True)
# 信道安全状态
ttk.Label(frame, text="信道安全状态", font=('SimHei', 12, 'bold')).pack(anchor="w", pady=10)
self.security_status_tree = ttk.Treeview(frame, columns=["指标", "值"], show="headings", height=5)
self.security_status_tree.heading("指标", text="安全指标")
self.security_status_tree.heading("值", text="当前状态")
self.security_status_tree.column("指标", width=200)
self.security_status_tree.column("值", width=300)
self.security_status_tree.pack(fill="x", pady=5)
# 协议参数
ttk.Label(frame, text="当前协议参数", font=('SimHei', 12, 'bold')).pack(anchor="w", pady=10)
self.protocol_params_tree = ttk.Treeview(frame, columns=["参数", "值"], show="headings", height=8)
self.protocol_params_tree.heading("参数", text="协议参数")
self.protocol_params_tree.heading("值", text="参数值")
self.protocol_params_tree.column("参数", width=200)
self.protocol_params_tree.column("值", width=300)
self.protocol_params_tree.pack(fill="x", pady=5)
# 刷新按钮
ttk.Button(frame, text="刷新状态", command=self._update_monitor_data).pack(pady=10)
# 初始更新数据
self._update_monitor_data()
def _update_monitor_data(self):
"""更新监测页面数据"""
# 清空现有数据
for item in self.security_status_tree.get_children():
self.security_status_tree.delete(item)
for item in self.protocol_params_tree.get_children():
self.protocol_params_tree.delete(item)
# 获取协议和信道信息
info = self.encryption_core.get_protocol_info()
# 更新安全状态
for key, value in info["信道状态"].items():
self.security_status_tree.insert("", "end", values=[key, value])
# 更新协议参数
self.protocol_params_tree.insert("", "end", values=["协议名称", info["协议名称"]])
for key, value in info["参数"].items():
self.protocol_params_tree.insert("", "end", values=[key, value])
# 其他UI设置方法保持不变,增加协议参数配置区域...
def _setup_settings_tab(self):
frame = ttk.Frame(self.tab_settings, padding=10)
frame.pack(fill="both", expand=True)
# 协议选择
ttk.Label(frame, text="选择量子协议:", font=('SimHei', 11)).pack(anchor="w", pady=(10, 0))
self.protocol_var = tk.StringVar(value="BB84")
protocol_frame = ttk.Frame(frame)
protocol_frame.pack(fill="x", pady=5)
protocols = ["BB84", "B92", "E91", "TF-QKD", "卫星QKD"]
for proto in protocols:
ttk.Radiobutton(
protocol_frame,
text=proto,
variable=self.protocol_var,
value=proto,
command=self._update_protocol_params_ui # 切换协议时更新参数UI
).pack(side="left", padx=10)
# 协议专属参数配置区域
self.protocol_params_frame = ttk.LabelFrame(frame, text="协议专属参数")
self.protocol_params_frame.pack(fill="x", pady=10, padx=5)
self._update_protocol_params_ui() # 初始加载参数UI
# 信道设置
ttk.Label(frame, text="模拟信道距离(km):", font=('SimHei', 11)).pack(anchor="w", pady=(10, 0))
self.distance_var = tk.DoubleVar(value=10.0)
ttk.Scale(
frame,
from_=1.0,
to=100.0,
variable=self.distance_var,
command=lambda v: self._update_distance_label(v)
).pack(fill="x", pady=5)
self.distance_label = ttk.Label(frame, text="10.0 km")
self.distance_label.pack(anchor="w")
# 其他设置
self.pqc_var = tk.BooleanVar(value=False)
ttk.Checkbutton(
frame,
text="启用后量子加密(抗未来量子计算机攻击)",
variable=self.pqc_var
).pack(anchor="w", pady=10)
self.real_quantum_var = tk.BooleanVar(value=False)
ttk.Checkbutton(
frame,
text="使用真实量子硬件(需IBM账号)",
variable=self.real_quantum_var
).pack(anchor="w", pady=5)
ttk.Label(
frame,
text="提示:真实硬件可能较慢,默认使用模拟器",
foreground="gray"
).pack(anchor="w")
ttk.Button(frame, text="应用设置", command=self._apply_settings).pack(pady=20)
def _update_protocol_params_ui(self):
"""根据当前选择的协议更新参数配置UI"""
# 清空现有参数控件
for widget in self.protocol_params_frame.winfo_children():
widget.destroy()
protocol = self.protocol_var.get()
# 为不同协议创建专属参数控件
if protocol == "卫星QKD":
ttk.Label(self.protocol_params_frame, text="海拔角度(度):").pack(anchor="w", pady=5)
self.elevation_angle_var = tk.IntVar(value=45)
angle_frame = ttk.Frame(self.protocol_params_frame)
angle_frame.pack(fill="x", padx=5)
ttk.Scale(
angle_frame,
from_=5,
to=90,
variable=self.elevation_angle_var,
command=lambda v: ttk.Label(angle_frame, text=f"{int(float(v))} 度").pack(side="right")
).pack(side="left", fill="x", expand=True)
ttk.Label(self.protocol_params_frame, text="天气因子(1.0为晴天):").pack(anchor="w", pady=5)
self.weather_factor_var = tk.DoubleVar(value=1.0)
weather_frame = ttk.Frame(self.protocol_params_frame)
weather_frame.pack(fill="x", padx=5)
ttk.Scale(
weather_frame,
from_=1.0,
to=3.0,
variable=self.weather_factor_var,
command=lambda v: ttk.Label(weather_frame, text=f"{float(v):.1f}").pack(side="right")
).pack(side="left", fill="x", expand=True)
elif protocol == "BB84":
ttk.Label(self.protocol_params_frame, text="光源强度(0-1):").pack(anchor="w", pady=5)
self.light_intensity_var = tk.DoubleVar(value=0.85)
light_frame = ttk.Frame(self.protocol_params_frame)
light_frame.pack(fill="x", padx=5)
ttk.Scale(
light_frame,
from_=0.5,
to=1.0,
variable=self.light_intensity_var,
command=lambda v: ttk.Label(light_frame, text=f"{float(v):.2f}").pack(side="right")
).pack(side="left", fill="x", expand=True)
elif protocol == "TF-QKD":
ttk.Label(self.protocol_params_frame, text="频率偏移系数:").pack(anchor="w", pady=5)
self.frequency_offset_var = tk.DoubleVar(value=1.1)
freq_frame = ttk.Frame(self.protocol_params_frame)
freq_frame.pack(fill="x", padx=5)
ttk.Scale(
freq_frame,
from_=1.0,
to=2.0,
variable=self.frequency_offset_var,
command=lambda v: ttk.Label(freq_frame, text=f"{float(v):.2f}").pack(side="right")
).pack(side="left", fill="x", expand=True)
# 没有专属参数的协议显示提示
if protocol not in ["卫星QKD", "BB84", "TF-QKD"]:
ttk.Label(
self.protocol_params_frame,
text="该协议使用默认参数配置",
foreground="gray"
).pack(pady=10)
def _apply_settings(self):
try:
# 创建加密核心实例
self.encryption_core = QuantumEncryptionTool(
protocol=self.protocol_var.get(),
channel_distance_km=self.distance_var.get(),
enable_pqc=self.pqc_var.get(),
use_real_quantum=self.real_quantum_var.get(),
security_alert_callback=self._show_security_alert
)
# 更新协议专属参数
protocol = self.protocol_var.get()
if protocol == "卫星QKD":
self.encryption_core.update_protocol_params(
elevation_angle=self.elevation_angle_var.get(),
weather_factor=self.weather_factor_var.get()
)
elif protocol == "BB84":
self.encryption_core.update_protocol_params(
light_intensity=self.light_intensity_var.get()
)
elif protocol == "TF-QKD":
self.encryption_core.update_protocol_params(
frequency_offset=self.frequency_offset_var.get()
)
self._refresh_auth_list()
self._update_monitor_data() # 刷新监测数据
messagebox.showinfo("成功", "设置已应用")
except Exception as e:
messagebox.showerror("错误", f"设置应用失败:{e}")
# 其他UI方法保持不变...
def _setup_encrypt_tab(self):
frame = ttk.Frame(self.tab_encrypt, padding=10)
frame.pack(fill="both", expand=True)
ttk.Label(frame, text="文本加密:").pack(anchor="w", pady=(5, 0))
self.encrypt_text_input = tk.Text(frame, height=5, wrap=tk.WORD)
self.encrypt_text_input.pack(fill="both", expand=True, pady=5)
ttk.Label(frame, text="文件加密:").pack(anchor="w", pady=(10, 0))
file_frame = ttk.Frame(frame)
file_frame.pack(fill="x", pady=5)
self.encrypt_file_path = tk.StringVar()
entry = ttk.Entry(file_frame, textvariable=self.encrypt_file_path)
entry.pack(side="left", fill="x", expand=True, padx=5)
entry.bind("<Button-1>", lambda e: entry.focus_set())
ttk.Button(file_frame, text="选择文件", command=self._select_encrypt_file).pack(side="left", padx=5)
progress_frame = ttk.Frame(frame)
progress_frame.pack(fill="x", pady=5)
self.encrypt_progress = ttk.Progressbar(progress_frame, orient="horizontal", length=100, mode="determinate")
self.encrypt_progress.pack(side="left", fill="x", expand=True, padx=5)
self.encrypt_status = ttk.Label(progress_frame, text="就绪")
self.encrypt_status.pack(side="left", padx=5)
btn_frame = ttk.Frame(frame)
btn_frame.pack(fill="x", pady=5)
ttk.Button(btn_frame, text="加密文本", command=self._start_text_encrypt).pack(side="left", padx=5)
ttk.Button(btn_frame, text="加密文件", command=self._start_file_encrypt).pack(side="left", padx=5)
ttk.Label(frame, text="加密结果(密文):").pack(anchor="w", pady=(10, 0))
self.ciphertext_output = tk.Text(frame, height=5, wrap=tk.WORD)
self.ciphertext_output.pack(fill="both", expand=True, pady=5)
ttk.Label(frame, text="带签名密钥(请保存):").pack(anchor="w", pady=(10, 0))
self.key_output = tk.Text(frame, height=5, wrap=tk.WORD)
self.key_output.pack(fill="both", expand=True, pady=5)
def _setup_decrypt_tab(self):
frame = ttk.Frame(self.tab_decrypt, padding=10)
frame.pack(fill="both", expand=True)
ttk.Label(frame, text="文本解密:").pack(anchor="w", pady=(5, 0))
ttk.Label(frame, text="密文:").pack(anchor="w")
self.decrypt_cipher_input = tk.Text(frame, height=5, wrap=tk.WORD)
self.decrypt_cipher_input.pack(fill="both", expand=True, pady=5)
ttk.Label(frame, text="带签名密钥:").pack(anchor="w")
self.decrypt_key_input = tk.Text(frame, height=5, wrap=tk.WORD)
self.decrypt_key_input.pack(fill="both", expand=True, pady=5)
ttk.Label(frame, text="文件解密:").pack(anchor="w", pady=(10, 0))
file_frame = ttk.Frame(frame)
file_frame.pack(fill="x", pady=5)
self.decrypt_file_path = tk.StringVar()
entry = ttk.Entry(file_frame, textvariable=self.decrypt_file_path)
entry.pack(side="left", fill="x", expand=True, padx=5)
entry.bind("<Button-1>", lambda e: entry.focus_set())
ttk.Button(file_frame, text="选择密文文件", command=self._select_decrypt_file).pack(side="left", padx=5)
progress_frame = ttk.Frame(frame)
progress_frame.pack(fill="x", pady=5)
self.decrypt_progress = ttk.Progressbar(progress_frame, orient="horizontal", length=100, mode="determinate")
self.decrypt_progress.pack(side="left", fill="x", expand=True, padx=5)
self.decrypt_status = ttk.Label(progress_frame, text="就绪")
self.decrypt_status.pack(side="left", padx=5)
btn_frame = ttk.Frame(frame)
btn_frame.pack(fill="x", pady=5)
ttk.Button(btn_frame, text="解密文本", command=self._start_text_decrypt).pack(side="left", padx=5)
ttk.Button(btn_frame, text="解密文件", command=self._start_file_decrypt).pack(side="left", padx=5)
ttk.Label(frame, text="解密结果:").pack(anchor="w", pady=(10, 0))
self.decrypt_output = tk.Text(frame, height=5, wrap=tk.WORD)
self.decrypt_output.pack(fill="both", expand=True, pady=5)
def _setup_authorization_tab(self):
frame = ttk.Frame(self.tab_authorization, padding=10)
frame.pack(fill="both", expand=True)
ttk.Label(frame, text="已授权设备列表:").pack(anchor="w", pady=(10, 0))
self.auth_listbox = tk.Listbox(frame, height=10)
self.auth_listbox.pack(fill="both", expand=True, pady=5)
self._refresh_auth_list()
btn_frame = ttk.Frame(frame)
btn_frame.pack(fill="x", pady=10)
ttk.Button(btn_frame, text="生成授权码", command=self._generate_auth_code).pack(side="left", padx=5)
ttk.Button(btn_frame, text="导入授权码", command=self._import_auth_code).pack(side="left", padx=5)
ttk.Button(btn_frame, text="撤销选中授权", command=self._revoke_selected).pack(side="right", padx=5)
ttk.Label(frame, text="提示:当前设备授权无法撤销", foreground="gray").pack(anchor="w", pady=5)
def _refresh_auth_list(self):
self.auth_listbox.delete(0, tk.END)
devices = self.encryption_core.get_authorized_devices()
for i, device in enumerate(devices):
label = f"设备 {i + 1}: {device}"
if i == 0:
label += "(当前设备)"
self.auth_listbox.insert(tk.END, label)
def _add_help_text(self):
help_text = """
操作指南:
1. 加密:支持文本/文件加密,文件加密会显示进度条
2. 解密:对应输入密文/选择密文文件,输入密钥即可解密
3. 协议:不同协议有专属参数,可在设置页调整
4. 安全监测:实时查看信道状态和潜在威胁警报
5. 授权:在"授权管理"中管理设备授权
注意:检测到拦截时会触发安全警报
"""
ttk.Label(
self.tab_encrypt,
text=help_text,
foreground="gray",
justify="left"
).pack(side="bottom", fill="x", pady=10)
def _update_distance_label(self, value):
self.distance_label.config(text=f"{float(value):.1f} km")
def _select_encrypt_file(self):
file_path = filedialog.askopenfilename()
if file_path and os.path.exists(file_path):
self.encrypt_file_path.set(file_path)
self.encrypt_status.config(text=f"已选择: {os.path.basename(file_path)}")
else:
self.encrypt_status.config(text="未选择有效文件")
def _select_decrypt_file(self):
file_path = filedialog.askopenfilename()
if file_path and os.path.exists(file_path):
self.decrypt_file_path.set(file_path)
self.decrypt_status.config(text=f"已选择: {os.path.basename(file_path)}")
else:
self.decrypt_status.config(text="未选择有效文件")
def _update_encrypt_progress(self, value):
self.encrypt_progress["value"] = value
self.encrypt_status.config(text=f"处理中: {int(value)}%")
self.root.update_idletasks()
def _update_decrypt_progress(self, value):
self.decrypt_progress["value"] = value
self.decrypt_status.config(text=f"处理中: {int(value)}%")
self.root.update_idletasks()
def _start_text_encrypt(self):
plaintext = self.encrypt_text_input.get(1.0, tk.END).strip()
if not plaintext:
messagebox.showwarning("警告", "请输入要加密的文本")
return
self.ciphertext_output.delete(1.0, tk.END)
self.key_output.delete(1.0, tk.END)
self.encrypt_status.config(text="加密中...")
def encrypt_thread():
try:
ciphertext, signed_key, pqc_data = self.encryption_core.encrypt_text(plaintext)
self.root.after(0, lambda: self.ciphertext_output.insert(tk.END, ciphertext.hex()))
self.root.after(0, lambda: self.key_output.insert(tk.END, signed_key.hex()))
self.root.after(0, lambda: self.encrypt_status.config(text="加密完成"))
self.root.after(0, lambda: messagebox.showinfo("成功", "文本加密完成,请保存密文和密钥"))
except Exception as e:
self.root.after(0, lambda: self.encrypt_status.config(text="加密失败"))
self.root.after(0, lambda: messagebox.showerror("错误", f"加密失败:{str(e)}"))
threading.Thread(target=encrypt_thread, daemon=True).start()
def _start_file_encrypt(self):
file_path = self.encrypt_file_path.get()
if not file_path or not os.path.exists(file_path):
messagebox.showwarning("警告", "请选择有效的文件")
return
self.encrypt_progress["value"] = 0
self.encrypt_status.config(text="准备加密...")
self.ciphertext_output.delete(1.0, tk.END)
self.key_output.delete(1.0, tk.END)
def encrypt_thread():
try:
ciphertext, signed_key, pqc_data = self.encryption_core.encrypt_file(
file_path, progress_callback=self._update_encrypt_progress
)
def save_file():
save_path = filedialog.asksaveasfilename(defaultextension=".enc")
if save_path:
with open(save_path, 'wb') as f:
f.write(ciphertext)
self.key_output.insert(tk.END, signed_key.hex())
self.encrypt_status.config(text="加密完成")
messagebox.showinfo(
"成功", f"文件加密完成,密文已保存到:\n{save_path}\n请保存密钥"
)
else:
self.encrypt_status.config(text="已取消保存")
self.root.after(0, save_file)
except Exception as e:
self.root.after(0, lambda: self.encrypt_status.config(text="加密失败"))
self.root.after(0, lambda: messagebox.showerror("错误", f"文件加密失败:{str(e)}"))
finally:
self.root.after(0, lambda: self.encrypt_progress.config(value=0))
threading.Thread(target=encrypt_thread, daemon=True).start()
def _start_text_decrypt(self):
ciphertext_hex = self.decrypt_cipher_input.get(1.0, tk.END).strip()
key_hex = self.decrypt_key_input.get(1.0, tk.END).strip()
if not ciphertext_hex or not key_hex:
messagebox.showwarning("警告", "请输入密文和密钥")
return
try:
ciphertext = bytes.fromhex(ciphertext_hex)
signed_key = bytes.fromhex(key_hex)
except ValueError:
messagebox.showerror("错误", "密文或密钥格式错误(请输入16进制字符串)")
return
self.decrypt_status.config(text="解密中...")
self.decrypt_output.delete(1.0, tk.END)
def decrypt_thread():
try:
decrypted = self.encryption_core.decrypt_text(ciphertext, signed_key)
self.root.after(0, lambda: self.decrypt_output.insert(tk.END, decrypted))
self.root.after(0, lambda: self.decrypt_status.config(text="解密完成"))
except PermissionError:
self.root.after(0, lambda: self.decrypt_status.config(text="解密失败"))
self.root.after(0, lambda: messagebox.showerror("错误", "设备未授权,无法解密(请导入授权码)"))
except Exception as e:
self.root.after(0, lambda: self.decrypt_status.config(text="解密失败"))
self.root.after(0, lambda: messagebox.showerror("错误", f"解密失败:{str(e)}"))
threading.Thread(target=decrypt_thread, daemon=True).start()
def _start_file_decrypt(self):
file_path = self.decrypt_file_path.get()
key_hex = self.decrypt_key_input.get(1.0, tk.END).strip()
if not file_path or not os.path.exists(file_path) or not key_hex:
messagebox.showwarning("警告", "请选择密文文件并输入密钥")
return
try:
with open(file_path, 'rb') as f:
ciphertext = f.read()
signed_key = bytes.fromhex(key_hex)
except ValueError:
messagebox.showerror("错误", "密钥格式错误(请输入16进制字符串)")
return
except Exception as e:
messagebox.showerror("错误", f"读取文件失败:{e}")
return
self.decrypt_progress["value"] = 0
self.decrypt_status.config(text="准备解密...")
def decrypt_thread():
try:
def save_file():
save_path = filedialog.asksaveasfilename()
if not save_path:
self.root.after(0, lambda: self.decrypt_status.config(text="已取消保存"))
return
success = self.encryption_core.decrypt_file(
ciphertext, signed_key, save_path,
progress_callback=self._update_decrypt_progress
)
if success:
self.root.after(0, lambda: self.decrypt_status.config(text="解密完成"))
self.root.after(0, lambda: messagebox.showinfo("成功", f"文件解密完成,已保存到:\n{save_path}"))
else:
self.root.after(0, lambda: self.decrypt_status.config(text="解密失败"))
self.root.after(0, lambda: messagebox.showerror("错误", "解密失败(密钥无效或设备未授权)"))
self.root.after(0, save_file)
except Exception as e:
self.root.after(0, lambda: self.decrypt_status.config(text="解密失败"))
self.root.after(0, lambda: messagebox.showerror("错误", f"文件解密失败:{e}"))
finally:
self.root.after(0, lambda: self.decrypt_progress.config(value=0))
threading.Thread(target=decrypt_thread, daemon=True).start()
def _generate_auth_code(self):
try:
code = self.encryption_core.generate_authorization_code()
messagebox.showinfo("授权码", f"此授权码10分钟内有效,请发送给需要授权的设备:\n{code}")
except Exception as e:
messagebox.showerror("错误", f"生成授权码失败:{e}")
def _import_auth_code(self):
code = simpledialog.askstring("导入授权码", "请输入授权码:")
if code and self.encryption_core.add_authorized_device(code):
self._refresh_auth_list()
messagebox.showinfo("成功", "设备已授权,可解密对应内容")
else:
messagebox.showerror("错误", "授权码无效或已过期")
def _revoke_selected(self):
selected = self.auth_listbox.curselection()
if not selected:
messagebox.showwarning("警告", "请选择要撤销的设备")
return
index = selected[0]
if index == 0:
messagebox.showwarning("警告", "当前设备授权无法撤销")
return
device_text = self.auth_listbox.get(index)
sig_hex = device_text.split(": ")[1].split("...")[0]
if self.encryption_core.revoke_authorization(sig_hex):
self._refresh_auth_list()
messagebox.showinfo("成功", "已撤销选中设备的授权")
else:
messagebox.showerror("错误", "撤销授权失败")
if __name__ == "__main__":
try:
import sys
if len(sys.argv) > 1 and sys.argv[1] == "--cli":
tool = QuantumEncryptionTool(protocol="BB84", enable_pqc=False)
secret = input("请输入要加密的内容:")
ciphertext, signed_key, pqc_data = tool.encrypt_text(secret)
print(f"\n密文:{ciphertext.hex()}")
print(f"带签名密钥:{signed_key.hex()}")
decrypt_choice = input("\n是否立即解密?(y/n):")
if decrypt_choice.lower() == 'y':
decrypted = tool.decrypt_text(ciphertext, signed_key, pqc_data)
print(f"\n解密结果:{decrypted}")
else:
root = tk.Tk()
app = EncryptionGUI(root)
root.mainloop()
except Exception as e:
print(f"程序运行失败:{e}")