Vigenere 密码破坏了一些

Posted

技术标签:

【中文标题】Vigenere 密码破坏了一些【英文标题】:Vigenere cipher corrupts some 【发布时间】:2015-09-09 00:10:50 【问题描述】:

我正在 python 中制作一个简单的 vigenere 密码加密器/解密器,它在大多数情况下都有效。我没有收到任何错误,但有些字母没有正确加密或解密(或两者?)。这是我的代码:

import sys
if not len(sys.argv) == 4:
    print "Not enough arguments."
    print "Usage: python vigener.py <encrypt/decrypt> 'ciphertext' 'key'"
    sys.exit()
mode = sys.argv[1]
ctext = sys.argv[2]
key = sys.argv[3]
if mode == "encrypt":
    print "Encrypting using vigener cipher..."
elif mode == "decrypt":
    print "Decrypting using vigener cipher..."
else:
    print "Unknown function '"+str(mode)+"'."
    print "Usage: python vigener.py <encrypt/decrypt> 'ciphertext' 'key'"
MAGIC_NUMBER = 96
ctext = ctext.lower()
repeated_key = ( key * (1+len(ctext)/len(key)) )[:len(ctext)]
if mode == "encrypt":
    ctext = ctext.replace(" ", "")
    nums = [ord(ltr)-MAGIC_NUMBER for ltr in ctext]
    rk_nums = [ord(ltr)-MAGIC_NUMBER for ltr in repeated_key]
    enc_nums = [(num+rk_nums[ nums.index(num) ]) % 27 for num in nums]
    enc_ltrs = [chr(num+MAGIC_NUMBER) for num in enc_nums]
    print "".join(enc_ltrs)
elif mode == "decrypt":
    enc_nums = [ord(ltr)-MAGIC_NUMBER for ltr in ctext]
    rk_nums = [ord(ltr)-MAGIC_NUMBER for ltr in repeated_key]
    dec_nums = [(num-rk_nums[ enc_nums.index(num) ]) for num in enc_nums]
    dec_nums2 = [ (num + 27 if num < 1 else num) for num in dec_nums]
    dec_ltrs = [chr(num+MAGIC_NUMBER) for num in dec_nums2]
    dec_str = "".join(dec_ltrs)
    dec_str = dec_str.replace("", " ")
    print "".join(dec_str)

这是我的终端输出:

$ python vigener.py encrypt 'this is confidential' 'secretkey'
Encrypting using vigener cipher...
lmljeljeagsiliyslltq
$ python vigener.py decrypt 'lmljeljeagsiliyslltq' 'secretkey'
Decrypting using vigener cipher...
thts ts conftfenttal
$

似乎只对一些个字母进行了错误的加密/解密。到底是怎么回事?

【问题讨论】:

【参考方案1】:

简答——这两行需要修正:

enc_nums = [(x + y) % 27 for (x, y) in zip(nums, rk_nums)]
...
dec_nums = [(x - y) % 27 for (x, y) in zip(enc_nums, rk_nums)]

长答案:您的代码使用list.index() 的方式是一个逻辑错误。

假设我们在做加密,明文是'banana',密钥是'secretkey'。在旧代码中,会发生这种情况:

nums = [2, 1, 14, 1, 14, 1]      # 'banana'
rk_nums = [19, 5, 3, 18, 5, 20]  # 'secret'
enc_nums = [
  ( 2 + rk_nums[nums.index( 2)]) % 27,
  ( 1 + rk_nums[nums.index( 1)]) % 27,
  (14 + rk_nums[nums.index(14)]) % 27,
  ( 1 + rk_nums[nums.index( 1)]) % 27,
  (14 + rk_nums[nums.index(14)]) % 27,
  ( 1 + rk_nums[nums.index( 1)]) % 27 ]

我们可以详细说明enc_nums列表会发生什么:

enc_nums = [
  ( 2 + rk_nums[0]) % 27,
  ( 1 + rk_nums[1]) % 27,
  (14 + rk_nums[2]) % 27,
  ( 1 + rk_nums[1]) % 27,
  (14 + rk_nums[2]) % 27,
  ( 1 + rk_nums[1]) % 27 ]

当一个字母在明文中出现多次时,就会出现问题。 list.index() 方法返回第一次出现的索引。因此,错误的密钥索引(rk_nums)被用于加密字母。

简单的解决方案是使用zip() 函数,它将两个列表中相同索引处的元素配对。例如,zip([9, 8, 7, 6], [0, 1, 2, 3]) 将返回列表 [(9,0), (8,1), (7,2), (6,3)]。这样可以保证明文号码和密钥号码一直同步使用。

【讨论】:

非常感谢,我会试试的!我有 90% 的把握它会起作用——如果不起作用,我会告诉你的。我会投票赞成这个答案,但我没有足够的声誉。 哦--这很奇怪,如果我勾选你的答案,那么我也可以投票(我刚刚做了)。 是的,你需要 15 声望才能点赞。 Privileges page

以上是关于Vigenere 密码破坏了一些的主要内容,如果未能解决你的问题,请参考以下文章

C中Vigenere的密码移位问题

Java 中的 Vigenere/Polyalphabetic Cipher Decoder/Decrypter/Breaker

尝试加密和解密 vigenere 密码

python中的Vigenere密码[关闭]

Vigenere密码[关闭]

在 vigenere 密码中查找密钥的长度