You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多映射加密场景下的密文-明文精准解密匹配方案问询

加密程序解密歧义问题解决方案

这是一项课堂作业,目标实现一个加密系统:每个明文字符对应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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 22:54:56