【问题标题】:Decryption by key substitution - Python通过密钥替换解密 - Python
【发布时间】:2018-11-07 13:40:26
【问题描述】:

[在写完这篇文章后,我意识到我正在替换已经部分解密的消息,所以我似乎找到了错误,但现在我似乎无法弄清楚如何在没有的情况下一个一个地替换字母使用一堆看起来非常低效的 if-else 语句。有什么建议吗?]

部分加密消息

THEXMUNITIONSXFACTORYXREPORTEDXDAMAGEDXINXBOMBINGXRAIDXSTOPXKEEPXLOWXPROFILEXSTOPXURGENTXMESSAGESXCOMPROMISEDXSWITCHXTOXENCRYPTEDXURGENTXSTOPASJHXBLDZBLVZJXWZBHDFFVMYHSJYDMBJDOSUBGJDKBFSPWBHDMJSHJBAYJXBSRWMJBDZSMRWBGJDKBSNDYOBJXWBDJXWZBHDMJSHJBSJBSIIBHDGJGBGJDKBSHJYNSJWBDKWZSJYDMBEIVWBGKDDMBGJDKBZWKDZJBDMBJXWBKDIYHWBGJSJYDMBGJDKBSHJYNSJWBDKWZSJYDMBMDZJXADDOGBGJDKBZWKDZJBDMBUDVZBGJSJVGBGJDKBSBESJJIWGXYKBGWWMBOWKSZJYMRBLZDFBOWWKBXSZEDVZBGJDKBMWBJBFWWJYMRBSJBCICCBTVIVBJDMYRXJBJXWBKSZPBVMOWZBJXWBDSPBGJDKBPWWKBIDABKZDLYIWBGJDKBOYGZWRSZOBISGJBFWGGSRWBGJDKBYMNWGJYRSJWBZVFDVZGBDLBGJZYPWGBGJDKBPWWKBIDABKZDLYIWBGJDKBVMPMDAMBNWGGWIBYGBODHPWOBSJBOWWKBXSZEDVZBGJDKBJXWBODRBJZSYMWZBFSUBEWBODVEIWBSRWMJBWBWZHYGWBHSVJYDMBGJDKBDKWZSJYDMBMDZ P>

我需要通过密钥替换来解密消息。根据每个字母在以前未加密的消息中出现的频率,我得到了一个有序字符串,然后我被告知要解密它所需要做的就是用最常见的替换加密文本中最常见的字母过去的非加密文本等等。

我还被告知忽略前 141 个字符,因为这些字符已经被解密。

从上面的代码可以看出,我做了以下事情:

  1. 从第 142 个字符开始复制加密字符串,只处理仍然加密的位

  2. 用字母和它们在消息中出现的次数创建一个字典

  3. 将该字典转换为列表,并按降序排序

  4. 1234563列表。并使用 replace() 字符串方法替换它们

加密 = 消息[142:] 频率字符串 = "XTOEASRINPDCLHUMGBFYWVKZJQ" print(orderedChars) #用于调试目的

def counter(chars):
    d = {}
    for char in message:
        d[char] = d.get(char,0) + 1
    return d

charCount = counter(message)

def sortChars(charCount):
    orderedChars = []
    for k in charCount:
        orderedChars.append([charCount[k],k])
    orderedChars = sorted(orderedChars, reverse=True)
    return orderedChars

orderedChars = sortChars(charCount)

def charMatch(orderedChars, frequencyString):
    global encrypted
    i=-1
    for char in frequencyString:
        i+=1
        print(orderedChars[i][1]+"->"+char,end=" $ ") #for debuging purposes
        encrypted = encrypted.replace(orderedChars[i][1],char)
    encrypted = encrypted.replace("X"," ")
    print()
    print()#for debuging purposes
    print(encrypted) #for debuging purposes
    return encrypted
print()
charMatch(orderedChars,frequencyString)

输出

[[1449, 'B'], [830, 'J'], [784, 'D'], [748, 'W'], [578, 'S'], [530, 'G' ], [469, 'Z'], [413, 'Y'], [403, 'M'], [343, 'K'], [251, 'O'], [233, 'X'], [232, 'H'], [229, 'I'], [191, 'V'], [190, 'F'], [145, 'E'], [142, 'R'], [111 , 'L'], [95, 'U'], [86, 'A'], [77, 'N'], [70, 'P'], [22, 'T'], [11, ' C'], [6, 'Q']]

B->X$J->T$D->O$W->E$S->A$G->S$Z->R$Y->I$M->N$K- >P $ O->D $ X->C $ H->L $ I->H $ V->U $ F->M $ E->G $ R->B $ L->F $ U- >Y$A->W$N->V$P->K$T->Z$C->J$Q->Q$

WZFJJFDBJFYBZJGBJFDMMYVHFWZHDVJZDDWYJSZDKJMWKGJFDVZWFZJWHZJJWBGVZJDBWVBGJSZDKJWVDHDJZJGJDZJGBJFDVZWFZJWZJWHHJFDSZSJSZDKJWFZHVWZGJDKGBWZHDVJGHYGJSKDDVJSZDKJBGKDBZJDVJZJGJKDHHFGJSZWZHDVJSZDKJWFZHVWZGJDKGBWZHDVJVDBZJWDDDSJSZDKJBGKDBZJDVJYDYBJSZWZYSJSZDKJWJGWZZHGSJHKJSGGVJDGKWBZHVBJFBDMJDGGKJJWBGDYBJSZDKJVGJZJMGGZHVBJWZJJHJJJZYHYJZDVHBJZJZJGJKWBKJYVDGBJZJGJDWKJSZDKJKGGKJHDWJKBDFHHGJSZDKJDHSBGBWBDJHWSZJMGSSWBGJSZDKJHVVGSZHBWZGJBYMDYBSJDFJSZBHKGSJSZDKJKGGKJHDWJKBDFHHGJSZDKJYVKVDWVJVGSSGHJHSJDDFKGDJWZJDGGKJJWBGDYBJSZDKJZJGJDDBJZBWHVGBJMWYJGGJDDYGHGJWBGVZJGJGBFHSGJFWYZHDVJSZDKJDKGBWZHDVJVDBZJWDDDSJJWSJGGGVJSYFFGSSFYHJSZDKJVGJZJMGGZHVBJWZJKBJJJZYHYJZDMDBBDWJWZJZJGJDHDJHHDVJSZDKJDDJVDZJMWKGJFDVZWFZJYVZHHJZJGJYSYWHJDWYJSZDKJDDJVDZJMWKGJ P>

【问题讨论】:

标签: python encryption


【解决方案1】:

您已经准备好大部分代码来查找字符频率。您提到您发现进行就地替换是行不通的。所以你需要创建一个单独的缓冲区来存储解密的消息。我发现创建 2 个频率字符串的映射更容易:

# Your other code....
# orderedChars needs to be converted to string like frequencyString...
# Zip the 2 frequency strings to a dictionary
letterMap = dict(zip(orderedChars, frequencyString))
# Create an empty array to hold decrypted msg
decrypted = [''] * len(encrypted)
# Decrypt the message letter by letter
for i,c in enumerate(encrypted):
    decrypted[i] = letterMap[c]
# Convert to string and print   
print(''.join(decrypted).replace('X', ' '))

如 cmets 中所述,您也可以使用 translate 执行此操作。

# Build the translation table
translationTable = str.maketrans(orderedChars, frequencyString)
# Decrypt and print
print(encrypted.translate(translationTable).replace('X', ' '))

两个代码产生相同的输出。

【讨论】: