2015-09-09 3 views
0

Я делаю простой шифр-шифр/дешифратор vigenere в python, и он работает по большей части. Я не получаю никаких ошибок, но некоторые буквы не зашифрованы или дешифрованы (или и то?) Должным образом. Вот мой код:Vigenere cipher развращает некоторые

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)]. Таким образом, вы можете гарантировать, что номера открытого текста и номера ключей используются синхронно все время.

+0

Большое вам спасибо, я попробую! Я на 90% уверен, что это сработает - я скажу вам, если это не так. Я бы проголосовал за этот ответ, но у меня недостаточно репутации. –

+0

О, это странно, если я проверю ваш ответ, тогда мне разрешено также голосовать за него (что я только что сделал). –

+0

Yup, вам нужно 15 репутации, чтобы перевернуть вещи. [Страница привилегий] (http://stackoverflow.com/help/privileges) – Nayuki

 Смежные вопросы

  • Нет связанных вопросов^_^