Vigenere密码破坏了一些
Vigenere cipher corrupts some
我正在 python 中制作一个简单的 vigenere 密码 encrypter/decrypter,它在大多数情况下都有效。我没有收到任何错误,但有些字母没有正确加密或解密(或两者都没有?)。这是我的代码:
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
$
好像只有encrypt/decrypt一些个字母错了。这到底是怎么回事?
简答 - 这两行需要修正:
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()
returns 第一次出现的索引。因此密钥的错误索引 (rk_nums
) 用于加密字母。
简单的解决方案是使用 zip()
函数,该函数将两个列表中的元素在同一索引处配对。例如,zip([9, 8, 7, 6], [0, 1, 2, 3])
将 return 列表 [(9,0), (8,1), (7,2), (6,3)]
。这样就可以保证明文数字和密钥数字始终同步使用。
我正在 python 中制作一个简单的 vigenere 密码 encrypter/decrypter,它在大多数情况下都有效。我没有收到任何错误,但有些字母没有正确加密或解密(或两者都没有?)。这是我的代码:
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
$
好像只有encrypt/decrypt一些个字母错了。这到底是怎么回事?
简答 - 这两行需要修正:
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()
returns 第一次出现的索引。因此密钥的错误索引 (rk_nums
) 用于加密字母。
简单的解决方案是使用 zip()
函数,该函数将两个列表中的元素在同一索引处配对。例如,zip([9, 8, 7, 6], [0, 1, 2, 3])
将 return 列表 [(9,0), (8,1), (7,2), (6,3)]
。这样就可以保证明文数字和密钥数字始终同步使用。