Comments 18
Код может быть вы и понятно написали «даже для самого начинающего в Python», но вот сам алгоритм я так и не вспомнил по коду. Вы бы побольше комментировали, поменьше приводили куски кода. Код всегда можно самому написать, если алгоритм понятен.
Как это делал когда-то я: pastebin.com/Tf1dWXtk
Но я взял в качестве алфавита всю таблицу ASCII…
Но я взял в качестве алфавита всю таблицу ASCII…
Я решил что можно будет немножко усложнить задачу по взлому, если взять определенный набор символов (диапазон ASCII). Тут конечно придется учитывать еще что вы хотите зашифровать — если только англ. текст то сойдет, если еще и русские символы — брать больший диапазон. Ну это сугубо в качестве дополнительной плюшки.
Простите, но если мы все же пишем на питоне, то давайте писать на питоне:
… а не изображать basic-style.
from itertools import cycle
def form_dict():
return dict([(i, chr(i)) for i in range(128)])
def comparator(value, key):
return dict([(idx, [ch[0], ch[1]])
for idx, ch in enumerate(zip(value, cycle(key)))])
def encode_val(word):
d = form_dict()
return [k for c in word for k,v in d.items() if v == c]
def full_encode(value, key):
d = comparator(value, key)
l = len(form_dict())
return [(v[0] + v[1]) % l for v in d.values()]
def decode_val(list_in):
l = len(list_in)
d = form_dict()
return [d[i] for i in list_in if i in d]
def full_decode(value, key):
d = comparator(value, key)
l = len(form_dict())
return [(v[0] - v[1]) % l for v in d.values()]
… а не изображать basic-style.
А давайте писать все однострочниками на перле.
Вопрос не столько в однострочниках, сколько в неправильном использовании языковых средств.
Не зачем обращаться к символам строки по индексу, чтобы сравнить два символа, когда можно итерировать строку посимвольно и сравнивать символы. Не зачем итерировать ключи словаря, чтобы проверить, что искомое значение есть в их списке — hash-lookup будет быстрее и правильней и т.д.
То, что после устранения этих проблем все функции прекрасно описались через list comprehensions — случайность =)
Не зачем обращаться к символам строки по индексу, чтобы сравнить два символа, когда можно итерировать строку посимвольно и сравнивать символы. Не зачем итерировать ключи словаря, чтобы проверить, что искомое значение есть в их списке — hash-lookup будет быстрее и правильней и т.д.
То, что после устранения этих проблем все функции прекрасно описались через list comprehensions — случайность =)
Или так:
from itertools import cycle
LEN = 127
def full_encode(value, key):
return ''.join(map(lambda x: chr((ord(x[0]) + ord(x[1])) % LEN), zip(value, cycle(key))))
def full_decode(value, key):
return ''.join(map(lambda x: chr((ord(x[0]) - ord(x[1]) + LEN) % LEN), zip(value, cycle(key))))
if __name__ == "__main__":
word = 'Hello world'
key = 'key'
print 'Слово: '+ word
print 'Ключ: '+ key
shifre = full_encode(word, key)
print 'Шифр=', shifre
decoded = full_decode(shifre, key)
print 'Word=', decoded
Как-то мало тут всего. О чем статья — о том как (Pi+Ki) mod 26 на питоне написать? Да и «данный алгоритм шифрования больше не является на 100% надежным» — явное преуменьшение.
Вот если будет вторая часть — как ломать шифр Виженера — тогда да, уже поинтересней будет.
Вот если будет вторая часть — как ломать шифр Виженера — тогда да, уже поинтересней будет.
Так вот ведь: habrahabr.ru/post/103055/
Если копируете куски вместе с формулами из википедии, то добавили бы от себя, что есть Ci, Pi и Ki в формулах.
Алгоритмический смысл шифрования заключается в индивидуальном сдвиге для каждого символа исходного текста. А величина этого сдвига берется из символа словаря (его позиции, кода), соотвествующего позиции рассматриваемого символа текста. Вот и получается, что результирующий символ это наш исходный плюс смещение, задаваемое позицией символа из словаря. При этом учитываем размер словаря и не выходим за его пределы. И получаем итоговые формулы.
Да и код получился очень запутанным. Можно было подобное сделать как-то так:
Алгоритмический смысл шифрования заключается в индивидуальном сдвиге для каждого символа исходного текста. А величина этого сдвига берется из символа словаря (его позиции, кода), соотвествующего позиции рассматриваемого символа текста. Вот и получается, что результирующий символ это наш исходный плюс смещение, задаваемое позицией символа из словаря. При этом учитываем размер словаря и не выходим за его пределы. И получаем итоговые формулы.
Да и код получился очень запутанным. Можно было подобное сделать как-то так:
# -*- coding: utf-8 -*-
d = [chr(i) for i in range(127)]
dl = len(d)
prepval = lambda val: zip( range(0,len(val)), val )
enc = lambda ch,key: (ch+key) % dl
dec = lambda ch,key: (ch-key+dl) % dl
def vigenere(value, key, func):
kl = len(key)
value = prepval( value )
e = [ func( ord(c), ord(key[i%kl]) ) for (i,c) in value ]
return ''.join( [ d[c] for c in e ] )
src = 'Hello world'
key = 'key'
tmp = vigenere( src, key, enc )
print tmp
print vigenere( tmp, key, dec )
prepval(value) можно заменить на enumerate(value).
range(0, x) эквивалентно range(x).
Плюс вы упростили исходную задачу, предположив, что мы используем ASCII (это следует из того, что номер символа вы получаете с помощью ord, а не из словаря d).
Мой вариант:
range(0, x) эквивалентно range(x).
Плюс вы упростили исходную задачу, предположив, что мы используем ASCII (это следует из того, что номер символа вы получаете с помощью ord, а не из словаря d).
Мой вариант:
# -*- coding: utf-8 -*-
from itertools import cycle, count
from functools import partial
def get_cypher(my_ord, my_chr, al_size):
def process(func, value, key):
key = cycle(map(my_ord, key))
value = map(my_ord, value)
result = map(func, zip(value, key))
return ''.join(map(my_chr, result))
encrypt = lambda x: (x[0] + x[1]) % al_size
decrypt = lambda x: (x[0] - x[1] + al_size) % al_size
return partial(process, encrypt), partial(process, decrypt)
# Используем ASCII в качестве алфавита
encrypt, decrypt = get_cypher(ord, chr, 256)
# Либо предоставляем свой словарь d
d = map(chr, range(128))
rd = dict(zip(d, count()))
encrypt, decrypt = get_cypher(rd.get, d.__getitem__, len(d))
Немного странно выглядит формула P = (C — K + 26) mod 26.
Почему не написать P = C — K mod 26?
Почему не написать P = C — K mod 26?
Разница может быть меньше нуля.
Это не важно. Для деления по модулю есть замечательное свойство a ≡ a ± n (mod n)
Sign up to leave a comment.
Шифр Виженера. Разбор алгоритма на Python