0

https://en.wikipedia.org/wiki/Caesar_cipher

大家好,我正在为 Uni 做这个任务。我非常接近完成,但我被困在最后一部分。我确信这是一些基本的东西,但我已经花了将近四个小时试图使用打印语句和所有内容来查找我的错误。

基本上这个想法是,它会通过循环遍历所有 -26 个偏移量来强力解密用户的加密消息。我的问题是我可以让代码循环 26 次,但它根本不会解密每个偏移量的消息。如果这有意义的话。

正确的样本输出:

Please enter string to decrypt: ykixkz&yw{oxxkr

Offset: -1 = Decrypted string: xjhwjy%xvznwwjq
Offset: -2 = Decrypted string: wigvix$wuymvvip
Offset: -3 = Decrypted string: vhfuhw#vtxluuho
Offset: -4 = Decrypted string: ugetgv"uswkttgn
Offset: -5 = Decrypted string: tfdsfu!trvjssfm
Offset: -6 = Decrypted string: secret squirrel
Offset: -7 = Decrypted string: rdbqds}rpthqqdk
Offset: -8 = Decrypted string: qcapcr|qosgppcj
Offset: -9 = Decrypted string: pb`obq{pnrfoobi
Offset: -10 = Decrypted string: oa_napzomqennah
Offset: -11 = Decrypted string: n`^m`oynlpdmm`g
Offset: -12 = Decrypted string: m_]l_nxmkocll_f
Offset: -13 = Decrypted string: l^\k^mwljnbkk^e
Offset: -14 = Decrypted string: k][j]lvkimajj]d
Offset: -15 = Decrypted string: j\Zi\kujhl`ii\c
Offset: -16 = Decrypted string: i[Yh[jtigk_hh[b
Offset: -17 = Decrypted string: hZXgZishfj^ggZa
Offset: -18 = Decrypted string: gYWfYhrgei]ffY`
Offset: -19 = Decrypted string: fXVeXgqfdh\eeX_
Offset: -20 = Decrypted string: eWUdWfpecg[ddW^
Offset: -21 = Decrypted string: dVTcVeodbfZccV]
Offset: -22 = Decrypted string: cUSbUdncaeYbbU\
Offset: -23 = Decrypted string: bTRaTcmb`dXaaT[
Offset: -24 = Decrypted string: aSQ`Sbla_cW``SZ
Offset: -25 = Decrypted string: `RP_Rak`^bV__RY
Offset: -26 = Decrypted string: _QO^Q`j_]aU^^QX

我的输出:

Please enter string to decrypt: ff

Offset: -1 = Decrypted string: ff
Offset: -2 = Decrypted string: ff
Offset: -3 = Decrypted string: ff
Offset: -4 = Decrypted string: ff
Offset: -5 = Decrypted string: ff
Offset: -6 = Decrypted string: ff
Offset: -7 = Decrypted string: ff
Offset: -8 = Decrypted string: ff
Offset: -9 = Decrypted string: ff
Offset: -10 = Decrypted string: ff
Offset: -11 = Decrypted string: ff
Offset: -12 = Decrypted string: ff
Offset: -13 = Decrypted string: ff
Offset: -14 = Decrypted string: ff
Offset: -15 = Decrypted string: ff
Offset: -16 = Decrypted string: ff
Offset: -17 = Decrypted string: ff
Offset: -18 = Decrypted string: ff
Offset: -19 = Decrypted string: ff
Offset: -20 = Decrypted string: ff
Offset: -21 = Decrypted string: ff
Offset: -22 = Decrypted string: ff
Offset: -23 = Decrypted string: ff
Offset: -24 = Decrypted string: ff
Offset: -25 = Decrypted string: ff
Offset: -26 = Decrypted string: ff

我的代码(我已经删掉了大部分程序)

choice = 0

print ('*** Menu ***\n')

print ('1. Encrypt string')
print ('2. Decrypt string')
print ('3. Brute force decryption')
print ('4. Quit\n')

    elif choice == 3:
        print ('In command 3 - Brute force')
        userString = input('\nPlease enter string to decrypt: ')
        userList = list(userString)
        offsetValue = 0
        decryptIndex = 0
        while offsetValue != -26 : # Once the count reaches -26 stop, hammer time
            while decryptIndex < len(userList):
                decryptChr = chr(ord(userList[decryptIndex]) + offsetValue)
                userList[decryptIndex] = decryptChr
                decryptIndex += 1
                offsetValue -= 1
            userString = ''.join(userList)
            print ('Offset',offsetValue,' = Decrypted string:' ,userString)
        print ('\n*** Menu ***\n')
        print ('1. Encrypt string')
        print ('2. Decrypt string')
        print ('3. Brute force decryption')
        print ('4. Quit\n')
        choice = int(input('What would you like to do? [1,2,3,4]? '))
        while choice != 1 and choice != 2 and choice != 3 and choice != 4:
            choice = int(input('\nPlease re-enter either [1,2,3,4] '))

print ('\nGoodbye.')

有任何想法吗?!

4

5 回答 5

2

更容易使用str.translate

chars = "abcdefghijklmnopqrstuvwxyz"
rot1 = str.maketrans(chars, chars[1:]+chars[0])

message = input()

for i in chars:
    print(message)
    message = message.translate(rot1)
于 2013-04-30T04:01:42.173 回答
1

在 Python 中解码 Caesar 密码的一种更简洁的方法是使用字符串切片。

以字母表为例,即:

src = 'abcdefghijklmnopqrstuvwxyz'

现在,对于每种可能性,使用 shift n = 0, ..., 25,我们可以为密码构建一个新的字符集:

for n in range(26):
    dest = src[n:] + src[:n]

然后,您可以s通过查找源集中和目标集中每个字符的位置来解码字符串:

    decoded = ''.join(dest[src.index(c)] for c in s)
于 2013-04-30T03:51:28.057 回答
1

您原始程序的问题在于该行

offsetValue -= 1

缩进不当。

您不会重新初始化循环计数器,而且您可能会导致 chr 由于ord(userList[decryptIndex]) + offsetValue是无效字符而引发错误。

转换为列表并返回是笨拙且不必要的。使用字符串连接要干净得多。尽管对于一个非常干净的解决方案,其他解决方案显示了解决此问题的 Python 方法。

所以你的程序应该是:

choice = 0

print ('*** Menu ***\n')

print ('1. Encrypt string')
print ('2. Decrypt string')
print ('3. Brute force decryption')
print ('4. Quit\n')

    elif choice == 3:
        print ('In command 3 - Brute force')
        userString = input('\nPlease enter string to decrypt: ')
        offsetValue = 0

        while offsetValue != -26 : # Once the count reaches -26 stop, hammer time
            decryptIndex = 0
            decryptedString = ""
            while decryptIndex < len(userString):
                c = ord(userString[decryptIndex]) + offsetValue 
                if c < 0: c += 128
                decryptChr = chr(c)
                decryptedString += decryptChr
                decryptIndex += 1
            offsetValue -= 1
            print ('Offset',offsetValue,' = Decrypted string:' ,decryptedString)
        print ('\n*** Menu ***\n')
        print ('1. Encrypt string')
        print ('2. Decrypt string')
        print ('3. Brute force decryption')
        print ('4. Quit\n')
        choice = int(input('What would you like to do? [1,2,3,4]? '))
        while choice != 1 and choice != 2 and choice != 3 and choice != 4:
            choice = int(input('\nPlease re-enter either [1,2,3,4] '))

print ('\nGoodbye.')
于 2013-04-30T04:01:27.427 回答
1

您可以按照以下方式做一些事情:

from string import ascii_lowercase as alphabet 
import string

def caesar(plaintext, shift):
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    table = string.maketrans(alphabet, shifted_alphabet)
    return plaintext.translate(table)

plain='hello there'  
shift=3
coded=caesar(plain,shift)  
decoded=caesar(coded,-shift)    
print plain
print coded
print decoded  

印刷:

hello there
khoor wkhuh
hello there
于 2013-04-30T04:02:37.067 回答
0

我会无耻地从 gnibbler 那里偷东西,因为他是迄今为止最好的答案。

不过,我有点担心你的菜单处理。您打印出您的菜单,然后在选项中再次打印。也许这样一个“老派”的 CLI 菜单可以更优雅地处理。

我没有为 gnibbler 的实际答案做出贡献(他肯定得到了我的支持),但我尝试解决另一个问题,这可能并希望可以帮助您获得“更好”的代码。

这是我的想法:

#! /usr/bin/python3.2

import sys
from collections import defaultdict

menu = '''
*** Menu ***
[1] Encrypt
[2] Decrypt
[3] Brute force
[4] Quit
'''

def caesar (s, offset):
    chars = 'abcdefghijklmnopqrstuvwxyz'
    return s.translate (str.maketrans (chars, chars [offset:] + chars [:offset] ) )

def decrypt ():
    s = input ('Enter string to decrypt: ')
    offset = int (input ('Enter offset: ') )
    print (caesar (s, (-offset) % 26) )

def encrypt ():
    s = input ('Enter string to encrypt: ')
    offset = int (input ('Enter offset: ') )
    print (caesar (s, offset) )

def bruteForce ():
    s = input ('Enter string to brute force: ')
    for offset in range (26):
        print ('Offset {}:\t{}'.format (offset, caesar (s, (-offset) % 26) ) )

def unrecognized ():
    print ('unrecognized command')

options = {'1': encrypt,
           '2': decrypt,
           '3': bruteForce,
           '4': sys.exit}

options = defaultdict (lambda: unrecognized, options)

while ...: options [input (menu) ] ()

(inb4“奇怪的空白”)

于 2013-04-30T05:36:17.840 回答