Опять делюсь универскими наработками. Задача в общем то примитивная (или по крайней мере её реализация). Надо сгенерировать N равнозначных ключей для шифрования/дешифрования сообщения. Т.е., генерируем 10 ключей, шифруем сообщение любым из этих 10, расшифровываем так же любым из этих 10. Например, зашифровали пятым ключом, расшифровали третьим, или десятым.
Для реализации поставленной задачи опять прибегнем к ксору aka XOR, исключающее или, почти шифр Вернама. Почти — потому что длинна ключа у нас по сути не равна длине сообщения. Алгоритм будет таков:
- Дано начальное значение ikey. В общем то это и будет на самом деле ключ, который используется в шифровании и расшифровке, просто он будет «спрятан» в сгенерированных ключах.
- Генерируем 10 случайных строк по длине равных ключу ikey.
- Для каждой строки из предыдущего пункта выполняем: xor(A, ikey) + A. Полученные строки и будут нашими ключами.
Теперь для шифрования нам необходимо предварительно обработать введёный ключ и извлечь из него ikey. Это можно сделать по ксорив первую половину ключа со второй. И с помощью ikey уже шифровать или расшифровывать сообщение.
Реализацию ксора в python нашёл на просторах инета (выглядит довольно красиво, я пока так не умею), остальное писал сам. Вот исходник:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | # coding: utf-8 import random import itertools import struct def generate_strings(ikey, q=10): keys = {} for i in range(q): keys[i] = "" for j in range(len(ikey)): keys[i] += chr(random.randint(0, 255)) 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 Exception as exc: print "Error: %s" % exc elif action != "q": print "Invalid action." |
Единственная поправка к алгоритму, который я описал — ключи перед выводом я перевожу в шестнадцатиричное число, чтобы не хранить ключи в бинарном виде, ну и после ввода так же перевожу обратно. На этом всё.