Python: генерация группы ключей.
Опять делюсь универскими наработками. Задача в общем то примитивная (или по крайней мере её реализация). Надо сгенерировать N равнозначных ключей для шифрования/дешифрования сообщения. Т.е., генерируем 10 ключей, шифруем сообщение любым из этих 10, расшифровываем так же любым из этих 10. Например, зашифровали пятым ключом, расшифровали третьим, или десятым.
Для реализации поставленной задачи опять прибегнем к ксору aka XOR, исключающее или, почти шифр Вернама. Почти — потому что длина ключа у нас по сути не равна длине сообщения. Алгоритм будет таков:
- Дано начальное значение ikey. В общем то это и будет на самом деле ключ, который используется в шифровании и расшифровке, просто он будет «спрятан» в сгенерированных ключах.
- Генерируем 10 случайных строк по длине равных ключу ikey.
- Для каждой строки из предыдущего пункта выполняем: xor(A, ikey) + A. Полученные строки и будут нашими ключами.
Теперь для шифрования нам необходимо предварительно обработать введёный ключ и извлечь из него ikey. Это можно сделать поксорив первую половину ключа со второй. И с помощью ikey уже шифровать или расшифровывать сообщение.
Реализацию ксора в python нашёл на просторах инета (выглядит довольно красиво, я пока так не умею :-)), остальное писал сам. Вот исходник:
# -*- coding: utf-8 -*-
import random, itertools, struct
def generate_strings(ikey, q=10):
keys = {}
for i in range(q):
#print "%d." % i,
keys[i] = ""
for j in range(len(ikey)):
#keys[i] += hex(random.randint(0, 15))[2 : ]
keys[i] += chr(random.randint(0, 255))
#print keys[i]
return keys
def xor (s, key):
key = itertools.cycle(key)
return ».join(chr(ord(x) ^ ord(y)) for (x,y) in itertools.izip(s, key))
def generate_keys(ikey):
keys = generate_strings(ikey)
for i in range(len(keys)):
keys[i] = xor(keys[i], ikey) + keys[i] #xor(keys[i], b) + b
return keys
def bs2s(bs):
ss = ""
for i in bs:
s = hex(ord(i))[2 : ]
if len(s) == 1:
ss += "0"
ss += s
return ss
def s2bs(ss):
bs = ""
for i in range(0, len(ss), 2):
bs += chr(int(ss[i : i +2], 16))
return bs
def restore_key(key):
c = len(key) / 2
return xor(key[ : c], key[c : ])
if __name__ == "__main__":
action = ""
print "Select action:\ng — generate keys\nc — encrypt or decrypt file\nq — quit"
while action != "q":
action = raw_input("> ")
if action == "g":
ikey = raw_input("Enter initial key value: ")
keys = generate_keys(ikey)
print "Generated keys:"
for i in range(len(keys)):
print "%d. %s" % (i, bs2s(keys[i]))
elif action == "c":
f_in_name = raw_input("Enter input file name: ")
f_out_name = raw_input("Enter output file name: ")
key = raw_input("Enter key: ")
try:
key = restore_key(s2bs(key))
f = open(f_in_name, "rb")
c = xor(f.read(), key)
f.close()
f = open(f_out_name, "wb")
f.write(c)
f.close()
except:
print "Errors :-(."
elif action != "q":
print "Invalid action."
Единственная поправка к алгоритму, который я описал — ключи перед выводом я перевожу в шестнадцатиричное число, чтобы не хранить ключи в бинарном виде, ну и после ввода так же перевожу обратно. На этом всё.
Ссылки к статье:
http://code.activestate.com/recipes/496970/ — «Recipe 496970: xor for strings».


Последние комментарии