Vigenere密码密钥无法正常使用

时间:2019-08-23 19:49:15

标签: python vigenere

我构建了一个Vigenere密码功能,该功能运行得很好,除了它没有通过我需要通过的编码测试之外。

这是由于我使用的是序数值,我认为测试希望我使用的功能只是旋转一个字符串字母。

我已经解决了处理非字母字符的问题,并使它可以同时使用大写和小写字符。但是,如果键具有大写或小写字符的任何变体,即键是小写而纯文本是大写,则似乎分崩离析。

def encrypt(text, key):
    cipher_text = []
    key = list(key) 
    if len(text) == len(key): 
        return(key) 
    else: 
        for i in range(len(text) - 
                       len(key)): 
            key.append(key[i % len(key)]) 
    for i in range(len(text)): 
        a = text[i]
        if a.isalpha() and a.islower():
            x = ((ord(text[i]) + ord(key[i])-97) % 26 + 97)
            cipher_text.append(chr(x))
        elif a.isalpha() and a.isupper():
            x = ((ord(text[i]) + ord(key[i])-65) % 26 + 65)
            cipher_text.append(chr(x))
        else: 
            cipher_text.append(a) 

    return("" . join(cipher_text)) 


def main():
    mess = input(str("What is message?"))
    key = input("What is key?")
    print(encrypt(mess, key))

if __name__ == '__main__':
    main()

对于vigenere.encrypt('BaRFoo','BaZ')

    You should have returned this:         
        'CaQGon'                           

    But you actually returned this:        
        'PtDTha'

2 个答案:

答案 0 :(得分:1)

从您的单个示例来看,密钥似乎不区分大小写:

def encrypt_letter(c, k):
  if c.isupper():
    base = ord('A')
  else:
    base = ord('a')

  return chr((ord(c) - base + ord(k) - ord('a')) % 26 + base)

def encrypt(text, key):
    key = key.lower()

    return "".join([encrypt_letter(text[i], key[i % len(key)]) for i in range(len(text))])

def main():
    print(encrypt('BaRFoo', 'BaZ'))

if __name__ == '__main__':
    main()

答案 1 :(得分:0)

首先,我不使用python编程,所以请原谅我的表格。但是,我在在线编译器中测试了所有内容。

在回答您的问题之前,我不确定这一部分:

    if len(text) == len(key): 
        return(key) 
    else: 
        for i in range(len(text) - 
                       len(key)): 
            key.append(key[i % len(key)]) 

我读为“如果密钥的长度与明文的长度相同,则密钥为密文”,这显然是不正确的,除非密钥为“ aaaaaaaaa ...”。我希望这样的事情:

    if len(text) > len(key): 
        for i in range(len(text) - 
                       len(key)): 
            key.append(key[i % len(key)])
#   else:
#       I don't care - the key is long enough

根据Kfir Dadosh的回答,我还要指出,您实际上不需要此步骤,因此不妨直接以key[i % len(key)]的身份访问密钥。

关于您所提到的问题。您只需检查明文(消息)是小写还是大写,然后根据以下内容更改键(将其称为 normalization -将字母转换为0-25范围内的数字以表示其在字母表中的位置的行为)那个。

        if a.isalpha() and a.islower():
            x = ((ord(text[i]) + ord(key[i])-97) % 26 + 97)
Here you take raw      ^                ^
ascii value instead of |                |
normalized (0-25) number                |
                                        |
Here you normalize the key according to the
message case

在此之后,您会遇到一些麻烦的事情,因此,如果您了解并想自己解决问题,请在这里停止阅读。


我建议将规范化和加密步骤分开,以免造成混淆。让我们先去除特殊字符,再去除最后的特殊字符,因为它很容易做到,我们只需要担心字母:

        if not (text[i].isalpha()):
            cipher_text.append(text[i]) 
            continue; # done with this symbol - skip to the next one

然后借助内置方法将字母标准化。让我们将变量p用于纯文本,将k用于密钥,将c用于密文(后文):

        p = ord(text[i].lower()) - ord('a') # converts to lowercase, then to number
        k = ord(key[i].lower()) - ord('a')  # both key AND plaintext

我用ord('a')代替了我以前习惯的65,并发现它更清晰,但这是偏好和语言传统(我不习惯)的问题。

然后进行加密步骤:

        c = (p + k) % 26;

现在恢复大写。我们在变量p和k中销毁了它,但是我们仍然保留其源数组text []的值完整。我们可以使用它来恢复大写(假设大小写应该从纯文本继承):

        if (text[i].islower()):
            cipher_text.append(chr(c + ord('a')))
        elif (text[i].isupper()):
            cipher_text.append(chr(c + ord('A')))

这完成了主循环。随时对其进行修改,使其更加符合python。

    for i in range(len(text)):
        if not (text[i].isalpha()):
            cipher_text.append(text[i]) 
            continue;

        p = ord(text[i].lower()) - ord('a')
        k = ord(key[i].lower()) - ord('a')
        # k = ord(key[i % len(key)].lower()) - ord('a')
        # if you skipped the key lengthening process

        c = (p + k) % 26;

        if (text[i].islower()):
            cipher_text.append(chr(c + ord('a')))
        elif (text[i].isupper()):
            cipher_text.append(chr(c + ord('A')))
        else:
            # not sure if this can happen in python, but if it does, we're probably
            # in trouble
            # otherwise it might as well be merged with the elif above

    return("" . join(cipher_text))