import base64 import json import os import time from datetime import datetime class EncryptionSystem: def __init__(self, key_file=None, key_password=None): self.key_file = key_file self.key_password = key_password self.keys_loaded = False self.special_encrypt = { '+': '.', '/': "'", '=': '' } self.special_decrypt = { '.': '+', "'": '/' } self.flip_pattern = None if key_file: if os.path.exists(key_file): if key_password is None: key_password = input(f"请输入密钥文件 {key_file} 的密码: ") self._load_keys(key_file, key_password) self.keys_loaded = True else: print(f"⚠️ 密钥文件 {key_file} 不存在") self.keys_loaded = False else: default_key = "encryption.key" if os.path.exists(default_key): self.key_file = default_key if key_password is None: key_password = input(f"请输入密钥文件 {default_key} 的密码: ") self._load_keys(default_key, key_password) self.keys_loaded = True else: print("=" * 60) print("首次启动,请先生成密钥文件") print("=" * 60) self.keys_loaded = False def _generate_random_alphabet(self, lowercase=False): chars = list("abcdefghijklmnopqrstuvwxyz" if lowercase else "ABCDEFGHIJKLMNOPQRSTUVWXYZ") n = len(chars) for i in range(n - 1, 0, -1): j = int.from_bytes(os.urandom(1), 'big') % (i + 1) chars[i], chars[j] = chars[j], chars[i] return ''.join(chars) def _generate_random_digit_mapping(self): digits = list("0123456789") mapping_chars = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") n = len(mapping_chars) for i in range(n - 1, 0, -1): j = int.from_bytes(os.urandom(1), 'big') % (i + 1) mapping_chars[i], mapping_chars[j] = mapping_chars[j], mapping_chars[i] mapping = {} for i, d in enumerate(digits): mapping[d] = mapping_chars[i] return mapping def _generate_random_equal_mapping(self): chars = list("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") n = len(chars) for i in range(n - 1, 0, -1): j = int.from_bytes(os.urandom(1), 'big') % (i + 1) chars[i], chars[j] = chars[j], chars[i] mapping = { '0': chars[0], '1': chars[1], '2': chars[2], '3': chars[3] } return mapping def _generate_random_flip_pattern(self): pattern = [] for _ in range(10): bit = int.from_bytes(os.urandom(1), 'big') % 2 pattern.append(bit) return pattern def _generate_long_key(self, length=4096): chars = "0123456789abcdef" result = [] for _ in range(length): idx = int.from_bytes(os.urandom(1), 'big') % 16 result.append(chars[idx]) return ''.join(result) def _generate_short_key(self, length=512): chars = "0123456789abcdef" result = [] for _ in range(length): idx = int.from_bytes(os.urandom(1), 'big') % 16 result.append(chars[idx]) return ''.join(result) def _obfuscate_keys(self, keys_data): json_str = json.dumps(keys_data) b64 = base64.b64encode(json_str.encode()).decode() reversed_b64 = b64[::-1] shifted = ''.join([chr((ord(c) + 1) % 128) for c in reversed_b64]) final = base64.b64encode(shifted.encode()).decode() return final def _deobfuscate_keys(self, obfuscated_data): try: shifted = base64.b64decode(obfuscated_data.encode()).decode() reversed_b64 = ''.join([chr((ord(c) - 1) % 128) for c in shifted]) b64 = reversed_b64[::-1] json_str = base64.b64decode(b64.encode()).decode() return json.loads(json_str) except Exception: raise Exception("密钥文件损坏") def _xor_encrypt_data(self, data, password): result = [] key_len = len(password) for i, char in enumerate(data): xor_result = ord(char) ^ ord(password[i % key_len]) result.append(f"{xor_result:02x}") return ''.join(result) def _xor_decrypt_data(self, hex_data, password): try: result = [] key_len = len(password) for i in range(0, len(hex_data), 2): if i + 1 < len(hex_data): hex_byte = hex_data[i:i+2] xor_result = int(hex_byte, 16) ^ ord(password[(i//2) % key_len]) result.append(chr(xor_result)) return ''.join(result) except Exception: return None def generate_keys(self, save_path=None, key_password=None): if key_password is None: key_password = input("请设置密钥文件密码: ") confirm = input("请再次输入密码确认: ") if key_password != confirm: print("❌ 密码不匹配") return None print("=" * 60) print("正在生成随机密钥...") print("=" * 60) self.upper_mapping = self._generate_random_alphabet(lowercase=False) self.lower_mapping = self._generate_random_alphabet(lowercase=True) self.digit_mapping = self._generate_random_digit_mapping() self.equal_mapping = self._generate_random_equal_mapping() self.flip_pattern = self._generate_random_flip_pattern() self.long_key = self._generate_long_key(4096) self.short_key = self._generate_short_key(512) self.digit_reverse = {v: k for k, v in self.digit_mapping.items()} self.equal_reverse = {v: k for k, v in self.equal_mapping.items()} keys_data = { 'upper_mapping': self.upper_mapping, 'lower_mapping': self.lower_mapping, 'digit_mapping': self.digit_mapping, 'equal_mapping': self.equal_mapping, 'flip_pattern': self.flip_pattern, 'long_key': self.long_key, 'short_key': self.short_key, 'generated_at': datetime.now().isoformat() } obfuscated = self._obfuscate_keys(keys_data) encrypted = self._xor_encrypt_data(obfuscated, key_password) if save_path is None: save_path = "encryption.key" with open(save_path, 'w') as f: f.write(encrypted) self.key_file = save_path self.key_password = key_password self.keys_loaded = True self._build_maps() print(f"✅ 密钥已生成并保存到: {save_path}") print("=" * 60) return save_path def _build_maps(self): self.upper_original = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" self.lower_original = "abcdefghijklmnopqrstuvwxyz" self.encrypt_map = {} self.decrypt_map = {} for i in range(26): self.encrypt_map[self.upper_original[i]] = self.upper_mapping[i] self.encrypt_map[self.lower_original[i]] = self.lower_mapping[i] self.decrypt_map[self.upper_mapping[i]] = self.upper_original[i] self.decrypt_map[self.lower_mapping[i]] = self.lower_original[i] def _load_keys(self, key_file, key_password): try: with open(key_file, 'r') as f: encrypted_data = f.read() decrypted = self._xor_decrypt_data(encrypted_data, key_password) if decrypted is None: print("❌ 密码错误") self.keys_loaded = False return keys_data = self._deobfuscate_keys(decrypted) self.upper_mapping = keys_data['upper_mapping'] self.lower_mapping = keys_data['lower_mapping'] self.digit_mapping = keys_data['digit_mapping'] self.equal_mapping = keys_data['equal_mapping'] self.flip_pattern = keys_data['flip_pattern'] self.long_key = keys_data['long_key'] self.short_key = keys_data['short_key'] self.digit_reverse = {v: k for k, v in self.digit_mapping.items()} self.equal_reverse = {v: k for k, v in self.equal_mapping.items()} self.key_password = key_password self._build_maps() self.keys_loaded = True print(f"✅ 密钥已从 {key_file} 加载") except Exception: print("❌ 加载失败") self.keys_loaded = False def _ensure_printable(self, text): result = [] for c in text: val = ord(c) if val == 124: result.append('|') elif val < 32 or val > 126: val = val % 95 + 32 result.append(chr(val)) else: result.append(c) return ''.join(result) def _mix_keys(self, user_password, target_length): if not self.keys_loaded: raise Exception("密钥未加载") mixed = [] max_len = max(len(user_password), len(self.short_key)) for i in range(max_len): if i < len(user_password): mixed.append(ord(user_password[i])) if i < len(self.short_key): mixed.append(ord(self.short_key[i])) for i in range(len(mixed)): if i % 3 == 0: mixed[i] = (mixed[i] << 1) & 0xFF elif i % 3 == 1: mixed[i] = (mixed[i] >> 1) & 0xFF else: mixed[i] = mixed[i] ^ 0x5A for i in range(0, len(mixed) - 3, 4): mixed[i], mixed[i+3] = mixed[i+3], mixed[i] mixed[i+1], mixed[i+2] = mixed[i+2], mixed[i+1] mixed.reverse() result = [] for x in mixed: if x < 32 or x > 126: x = x % 95 + 32 result.append(chr(x)) result_str = ''.join(result) if len(result_str) < target_length: base_key = result_str final_key = base_key iteration = 0 while len(final_key) < target_length: if iteration % 3 == 0: next_chunk = base_key[::-1] elif iteration % 3 == 1: next_chunk = base_key[::-1] next_chunk = ''.join([chr((ord(c) + iteration) % 95 + 32) for c in next_chunk]) else: next_chunk = base_key[::-1] next_chunk = ''.join([chr((ord(c) ^ iteration) % 95 + 32) for c in next_chunk]) final_key += next_chunk iteration += 1 result_str = final_key[:target_length] return self._ensure_printable(result_str) def _derive_final_key(self, user_password, text_length): mixed_key = self._mix_keys(user_password, text_length * 2) hex_key = ''.join([f"{ord(c):02x}" for c in mixed_key]) reversed_hex = hex_key[::-1] final_key = [] for i in range(0, len(reversed_hex), 2): if i + 1 < len(reversed_hex): hex_byte = reversed_hex[i:i+2] try: val = int(hex_byte, 16) if val < 32 or val > 126: val = val % 95 + 32 final_key.append(chr(val)) except ValueError: final_key.append('x') final_key_str = ''.join(final_key) if len(final_key_str) < text_length: base_key = final_key_str iteration = 0 while len(final_key_str) < text_length: if iteration % 3 == 0: next_chunk = base_key[::-1] elif iteration % 3 == 1: next_chunk = base_key[::-1] next_chunk = ''.join([chr((ord(c) + iteration) % 95 + 32) for c in next_chunk]) else: next_chunk = base_key[::-1] next_chunk = ''.join([chr((ord(c) ^ iteration) % 95 + 32) for c in next_chunk]) final_key_str += next_chunk iteration += 1 final_key_str = final_key_str[:text_length] final_key_str = self._ensure_printable(final_key_str) return final_key_str def _apply_flip(self, text): if self.flip_pattern is None: return text result = [] for i, ch in enumerate(text): idx = i % len(self.flip_pattern) if ch.isalpha() and self.flip_pattern[idx] == 1: result.append(ch.swapcase()) else: result.append(ch) return ''.join(result) def _xor_encrypt_with_final_key(self, text, user_password): final_key = self._derive_final_key(user_password, len(text)) key_len = len(final_key) result = [] for i, char in enumerate(text): xor_result = ord(char) ^ ord(final_key[i % key_len]) result.append(f"{xor_result:02x}") return ''.join(result) def _xor_decrypt_with_final_key(self, hex_text, user_password): try: text_length = len(hex_text) // 2 final_key = self._derive_final_key(user_password, text_length) key_len = len(final_key) result = [] for i in range(0, len(hex_text), 2): if i + 1 < len(hex_text): hex_byte = hex_text[i:i+2] try: xor_result = int(hex_byte, 16) ^ ord(final_key[(i//2) % key_len]) if xor_result < 32 or xor_result > 126: xor_result = xor_result % 95 + 32 result.append(chr(xor_result)) except ValueError: result.append('?') return ''.join(result) except Exception: return None def _substitute_letters(self, text, mapping): result = [] for char in text: if char in mapping: result.append(mapping[char]) else: result.append(char) return ''.join(result) def _encode_digit(self, num_str): result = [] for char in num_str: if char in self.digit_mapping: result.append(self.digit_mapping[char]) else: result.append(char) return ''.join(result) def _decode_digit(self, encoded_str): result = [] for char in encoded_str: if char in self.digit_reverse: result.append(self.digit_reverse[char]) else: result.append(char) return ''.join(result) def _get_dynamic_key(self, text_length): key = self.long_key while len(key) < text_length: key += self.long_key return key[:text_length] def _xor_encrypt_with_key(self, text, key): key_len = len(key) result = [] for i, char in enumerate(text): xor_result = ord(char) ^ ord(key[i % key_len]) result.append(f"{xor_result:02x}") return ''.join(result) def _xor_decrypt_with_key(self, hex_text, key): try: key_len = len(key) result = [] for i in range(0, len(hex_text), 2): if i + 1 < len(hex_text): hex_byte = hex_text[i:i+2] try: xor_result = int(hex_byte, 16) ^ ord(key[(i//2) % key_len]) if xor_result < 32 or xor_result > 126: xor_result = xor_result % 95 + 32 result.append(chr(xor_result)) except ValueError: result.append('?') return ''.join(result) except Exception: return None def encrypt(self, plaintext, user_password): if not self.keys_loaded: return "❌ 错误:密钥未加载" b64 = base64.b64encode(plaintext.encode('utf-8')).decode('utf-8') equal_count = b64.count('=') processed = b64 for old, new in self.special_encrypt.items(): processed = processed.replace(old, new) processed = processed.rstrip('=') sub = self._substitute_letters(processed, self.encrypt_map) flipped = self._apply_flip(sub) reversed_text = flipped[::-1] equal_char = self.equal_mapping[str(equal_count)] with_equal = f"{reversed_text}|{equal_char}" key_length_str = str(len(with_equal)) key_length_encoded = self._encode_digit(key_length_str) dynamic_key = self._get_dynamic_key(len(with_equal)) encrypted_by_dynamic = self._xor_encrypt_with_key(with_equal, dynamic_key) combined = f"{encrypted_by_dynamic}|{key_length_encoded}" final_encrypted = self._xor_encrypt_with_final_key(combined, user_password) return final_encrypted def decrypt(self, ciphertext, user_password): if not self.keys_loaded: return "❌ 解密失败" try: combined = self._xor_decrypt_with_final_key(ciphertext, user_password) if combined is None: return "❌ 解密失败" if '|' in combined: parts = combined.split('|') if len(parts) >= 2: hex_data = parts[0] key_length_encoded = parts[1] else: hex_data = parts[0] key_length_encoded = 'g' else: hex_data = combined key_length_encoded = 'g' key_length_str = self._decode_digit(key_length_encoded) try: key_length = int(key_length_str) except ValueError: key_length = 16 dynamic_key = self._get_dynamic_key(key_length) xor_decrypted = self._xor_decrypt_with_key(hex_data, dynamic_key) if xor_decrypted is None: return "❌ 解密失败" if '|' in xor_decrypted: main_part, equal_char = xor_decrypted.split('|') equal_count = int(self.equal_reverse.get(equal_char, '0')) else: main_part = xor_decrypted equal_count = 0 reversed_text = main_part[::-1] flipped = self._apply_flip(reversed_text) sub = self._substitute_letters(flipped, self.decrypt_map) for old, new in self.special_decrypt.items(): sub = sub.replace(old, new) b64_with_equal = sub + '=' * equal_count if len(b64_with_equal) % 4 != 0: return "❌ 解密失败" decoded = base64.b64decode(b64_with_equal.encode('utf-8')).decode('utf-8') return decoded except Exception: return "❌ 解密失败" def print_keys(self): if not self.keys_loaded: print("❌ 未加载密钥") return print("=" * 60) print("密钥信息") print("=" * 60) print(f"密钥文件: {self.key_file}") print(f"大写映射表: {self.upper_mapping}") print(f"小写映射表: {self.lower_mapping}") print(f"翻转模式: {self.flip_pattern}") print(f"长密钥长度: {len(self.long_key)} 位") print(f"短密钥长度: {len(self.short_key)} 位") print("=" * 60) def main(): print("=" * 60) print("欢迎使用加密系统") print("=" * 60) crypto = None key_password = None if os.path.exists("encryption.key"): key_password = input("请输入默认密钥文件 (encryption.key) 的密码: ") crypto = EncryptionSystem("encryption.key", key_password) if not crypto.keys_loaded: print("❌ 加载失败") crypto = None else: print("\n未找到默认密钥文件,请先生成") choice = input("是否生成默认密钥文件?(y/n): ").strip().lower() if choice == 'y': crypto = EncryptionSystem() key_password = crypto.generate_keys("encryption.key") if key_password is None: print("❌ 生成失败") crypto = None else: print("⚠️ 请使用模式4或5指定密钥文件,或模式6生成新密钥") while True: print("\n请选择操作:") print("1. 使用默认密钥加密") print("2. 使用默认密钥解密") print("3. 生成新密钥(覆盖默认)") print("4. 使用指定密钥文件加密") print("5. 使用指定密钥文件解密") print("6. 生成密钥并保存到当前文件夹") print("7. 查看当前密钥信息") print("8. 退出") choice = input("\n请选择操作 (1-8): ").strip() if choice == '1': if crypto is None or not crypto.keys_loaded: if os.path.exists("encryption.key"): if key_password is None: key_password = input("请输入默认密钥文件密码: ") crypto = EncryptionSystem("encryption.key", key_password) if not crypto.keys_loaded: print("❌ 加载失败") continue else: print("❌ 密钥文件不存在") continue password = input("请输入加密密码: ") text = input("请输入要加密的文本: ") if text and password: encrypted = crypto.encrypt(text, password) print(f"\n✅ 加密结果: {encrypted}") elif choice == '2': if crypto is None or not crypto.keys_loaded: if os.path.exists("encryption.key"): if key_password is None: key_password = input("请输入默认密钥文件密码: ") crypto = EncryptionSystem("encryption.key", key_password) if not crypto.keys_loaded: print("❌ 加载失败") continue else: print("❌ 密钥文件不存在") continue password = input("请输入加密密码: ") text = input("请输入要解密的密文: ") if text and password: decrypted = crypto.decrypt(text, password) print(f"\n✅ 解密结果: {decrypted}") elif choice == '3': crypto = EncryptionSystem() key_password = crypto.generate_keys("encryption.key") if key_password is None: print("❌ 生成失败") else: print("✅ 默认密钥已更新") elif choice == '4': key_file = input("请输入密钥文件路径: ") if not os.path.exists(key_file): print(f"❌ 文件不存在") continue kp = input(f"请输入密钥文件密码: ") crypto = EncryptionSystem(key_file, kp) if not crypto.keys_loaded: print("❌ 加载失败") continue password = input("请输入加密密码: ") text = input("请输入要加密的文本: ") if text and password: encrypted = crypto.encrypt(text, password) print(f"\n✅ 加密结果: {encrypted}") elif choice == '5': key_file = input("请输入密钥文件路径: ") if not os.path.exists(key_file): print(f"❌ 文件不存在") continue kp = input(f"请输入密钥文件密码: ") crypto = EncryptionSystem(key_file, kp) if not crypto.keys_loaded: print("❌ 加载失败") continue password = input("请输入加密密码: ") text = input("请输入要解密的密文: ") if text and password: decrypted = crypto.decrypt(text, password) print(f"\n✅ 解密结果: {decrypted}") elif choice == '6': timestamp = int(time.time()) filename = f"key_{timestamp}.key" crypto = EncryptionSystem() kp = crypto.generate_keys(filename) if kp is None: print("❌ 生成失败") else: print(f"✅ 密钥已保存到: {filename}") elif choice == '7': if crypto is None or not crypto.keys_loaded: if os.path.exists("encryption.key"): if key_password is None: key_password = input("请输入默认密钥文件密码: ") crypto = EncryptionSystem("encryption.key", key_password) if not crypto.keys_loaded: print("❌ 加载失败") continue else: print("❌ 未加载密钥") continue crypto.print_keys() elif choice == '8': print("感谢使用,再见!") break else: print("❌ 无效选择") if __name__ == "__main__": main()