多映射加密场景下的密文-明文精准解密匹配方案问询
加密程序解密歧义问题解决方案
这是一项课堂作业,目标实现一个加密系统:每个明文字符对应3个可选的加密字符(例如
a = [#, S, 2],b = [&, =, @])。但当前代码的解密环节存在歧义问题。
原代码
import string import random import json question = input("Would you like to Encrypt or Decrypt a string?\n") if question == "Encrypt": # We choose our random characters from encryptionList, and also create the dictionary from the same string using dict.fromkeys(). encryptionList = string.ascii_letters + string.digits + string.punctuation + " " dictionary1 = dict.fromkeys(encryptionList, ) dictionary2 = dict.fromkeys(encryptionList, ) # Adding the three random characters to our Dictionary by random, while loop checks whether each index is similar, and chooses another one if it is. for key in dictionary1: listOfLetters1 = list() listOfLetters2 = list() for i in range(3): listOfLetters1.append(random.choice(encryptionList)) for i in range(3): listOfLetters2.append(random.choice(encryptionList)) for j in range(3): while (listOfLetters1[j] == listOfLetters2[j]): listOfLetters1[j] = random.choice(encryptionList) dictionary1[key] = listOfLetters1 dictionary2[key] = listOfLetters2 # Asking for the string. toEncrypt = input("Please enter a string to ecrypt:\n") methodEncrypt = input("Which encryption method would you like? (1, 2)\n") # Creating the encrypted message. randomLetter = list() if methodEncrypt == "1": encryptedString = "" for letter in toEncrypt: dictLetter = dictionary1[letter] randomLetter.append(random.choice(dictLetter)) key1 = open("Key1.txt", "w") key1.write(json.dumps(dictionary1)) if methodEncrypt == "2": encryptedString = "" for letter in toEncrypt: dictLetter = dictionary2[letter] randomLetter.append(random.choice(dictLetter)) key2 = open("Key2.txt", "w") key2.write(json.dumps(dictionary2)) # Using str(e) for e in randomLetter to swap everything inside the list into a string. ''.join() will join the elements of the list together. encryptedMessage = ''.join(str(e) for e in randomLetter) if methodEncrypt == "1": print(f"Your encrypted message is now: {encryptedMessage}\nYour key is 'Key1'\nTo decrypt your message you will need this information.") elif methodEncrypt == "2": print(f"Your encrypted message is now: {encryptedMessage}\nYour key is 'Key2'\nTo decrypt your message you will need this information.") elif question == "Decrypt": # Asking for the string. toDecrypt = input("Please enter a string to decrypt:\n") methodDecrypt = input("Which method did you use to encrypt the string with? (1, 2)\n") # Decrypting the message. keyFile = input("Please enter the name of your Key:\n") decryptKey = open(keyFile, "r") decryptFile = decryptKey.read() print(decryptFile) decryptDict = json.loads(decryptFile) decryptedString = "" for letter in toDecrypt: for char in decryptDict: charList = decryptDict[char] if letter in charList: decryptedString += char print(f"Your decrypted message is now: {decryptedString}\n")
核心问题
解密时,同一个密文字符可能属于多个明文的加密列表(例如 & 同时出现在a、b、c的加密选项中),导致程序无法判断密文对应的正确明文,解密结果出现错误(如明文ab加密为&2,解密可能得到cbb而非ab)。曾考虑用数字作为信号码,但明文可能包含数字,该方案不可行。
解决方法1:生成唯一映射的加密字典
修改加密字典的生成逻辑,确保每个加密字符仅分配给一个明文的加密列表,从根源上消除歧义。
修改后的字典生成代码
# 替换原加密字典生成部分 import string import random import json question = input("Would you like to Encrypt or Decrypt a string?\n") if question == "Encrypt": encryptionList = string.ascii_letters + string.digits + string.punctuation + " " # 生成3倍长度的字符池并打乱,保证每个字符唯一分配 pool1 = (encryptionList * 3) random.shuffle(pool1) pool2 = (encryptionList * 3) random.shuffle(pool2) dictionary1 = {} dictionary2 = {} # 为每个明文分配3个唯一的加密字符 for idx, key in enumerate(encryptionList): start_pos = idx * 3 dictionary1[key] = pool1[start_pos:start_pos+3] dictionary2[key] = pool2[start_pos:start_pos+3] # 后续加密逻辑保持不变...
解密逻辑优化
构建反向映射字典,直接通过密文字符查找明文:
elif question == "Decrypt": toDecrypt = input("Please enter a string to decrypt:\n") methodDecrypt = input("Which method did you use to encrypt the string with? (1, 2)\n") keyFile = input("Please enter the name of your Key:\n") with open(keyFile, "r") as f: decryptDict = json.load(f) # 构建反向映射:密文字符 -> 明文 reverse_dict = {} for plain_char, cipher_chars in decryptDict.items(): for c in cipher_chars: reverse_dict[c] = plain_char decryptedString = ''.join([reverse_dict[c] for c in toDecrypt]) print(f"Your decrypted message is now: {decryptedString}\n")
解决方法2:附加无歧义索引标记
如果必须保留加密字符重复的设计,可以在每个加密字符后添加不会与加密字符冲突的标记(如Unicode emoji,原加密列表仅包含ASCII字符,emoji不会出现在其中),用于标记该字符在明文加密列表中的位置。
加密逻辑修改
# 加密部分添加索引标记 index_markers = ["🔴", "🟡", "🟢"] # 用ASCII外的字符当标记 if methodEncrypt == "1": encrypted_parts = [] for letter in toEncrypt: cipher_chars = dictionary1[letter] idx = random.randint(0, 2) # 拼接加密字符和对应索引标记 encrypted_parts.append(cipher_chars[idx] + index_markers[idx]) encryptedMessage = ''.join(encrypted_parts) # 保存字典...
解密逻辑修改
elif question == "Decrypt": toDecrypt = input("Please enter a string to decrypt:\n") methodDecrypt = input("Which method did you use to encrypt the string with? (1, 2)\n") keyFile = input("Please enter the name of your Key:\n") with open(keyFile, "r") as f: decryptDict = json.load(f) index_markers = ["🔴", "🟡", "🟢"] marker_to_idx = {marker: idx for idx, marker in enumerate(index_markers)} # 拆分密文为加密字符+标记的单元 parts = [] current_cipher = "" for c in toDecrypt: if c in marker_to_idx: parts.append( (current_cipher, c) ) current_cipher = "" else: current_cipher += c decryptedString = "" for cipher_char, marker in parts: target_idx = marker_to_idx[marker] # 查找对应索引位置匹配的明文 for plain_char, cipher_list in decryptDict.items(): if cipher_list[target_idx] == cipher_char: decryptedString += plain_char break print(f"Your decrypted message is now: {decryptedString}\n")
解决方法3:双字符加密单元
将加密范围和索引范围拆分到不同的字符集(比如加密用小写、数字、标点,索引用大写字母),每个明文加密后变成"加密字符+索引字符"的双字符单元,解密时通过字符集区分索引和加密字符。
加密逻辑修改
# 修改加密列表和索引字符集 encryptionList = string.ascii_lowercase + string.digits + string.punctuation + " " index_chars = ["A", "B", "C"] # 大写字母作为索引,与加密字符集无重叠 if methodEncrypt == "1": encrypted_parts = [] for letter in toEncrypt: cipher_chars = dictionary1[letter] idx = random.randint(0,2) encrypted_parts.append(cipher_chars[idx] + index_chars[idx]) encryptedMessage = ''.join(encrypted_parts)
解密逻辑修改
elif question == "Decrypt": toDecrypt = input("Please enter a string to decrypt:\n") methodDecrypt = input("Which method did you use to encrypt the string with? (1, 2)\n") keyFile = input("Please enter the name of your Key:\n") with open(keyFile, "r") as f: decryptDict = json.load(f) index_chars = ["A", "B", "C"] char_to_idx = {c:i for i,c in enumerate(index_chars)} # 按双字符拆分密文 parts = [toDecrypt[i:i+2] for i in range(0, len(toDecrypt), 2)] decryptedString = "" for part in parts: cipher_char = part[0] idx_char = part[1] target_idx = char_to_idx[idx_char] for plain_char, cipher_list in decryptDict.items(): if cipher_list[target_idx] == cipher_char: decryptedString += plain_char break print(f"Your decrypted message is now: {decryptedString}\n")
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

