Каков самый быстрый способ реализовать следующую логику:
def xor(data, key):
l = len(key)
buff = ""
for i in range(0, len(data)):
buff += chr(ord(data[i]) ^ ord(key[i % l]))
return buff
В моем случае ключ представляет собой 20-байтовый файл sha1, а данные представляют собой двоичные данные длиной от 20 до 8 (1, 2, 3) мегабайт
UPDATE:
ОК, ребята. Здесь в 3,5 раза быстрее реализована реализация, которая разбивает данные и ключ на куски 4, 2 или 1 байт (в моем случае большую часть времени это 4-байтовое целое число):
def xor(data, key):
index = len(data) % 4
size = (4, 1, 2, 1)[index]
type = ('L', 'B', 'H', 'B')[index]
key_len = len(key)/size
data_len = len(data)/size
key_fmt = "<" + str(key_len) + type;
data_fmt = "<" + str(data_len) + type;
key_list = struct.unpack(key_fmt, key)
data_list = struct.unpack(data_fmt, data)
result = []
for i in range(data_len):
result.append (key_list[i % key_len] ^ data_list[i])
return struct.pack(data_fmt, *result)
Использует много памяти, но в моем случае это не имеет большого значения.
Любые идеи о том, как увеличить скорость еще несколько раз?: -)
ЗАКЛЮЧИТЕЛЬНОЕ ОБНОВЛЕНИЕ:
ОК, ок... numpy выполнил эту работу. Это просто быстро вспыхивает:
def xor(data, key):
import numpy, math
# key multiplication in order to match the data length
key = (key*int(math.ceil(float(len(data))/float(len(key)))))[:len(data)]
# Select the type size in bytes
for i in (8,4,2,1):
if not len(data) % i: break
if i == 8: dt = numpy.dtype('<Q8');
elif i == 4: dt = numpy.dtype('<L4');
elif i == 2: dt = numpy.dtype('<H2');
else: dt = numpy.dtype('B');
return numpy.bitwise_xor(numpy.fromstring(key, dtype=dt), numpy.fromstring(data, dtype=dt)).tostring()
Требуется начальная реализация 8 минут 50 секунд для обработки гигабайта, вторая - около 2 минут 30 секунд, а последняя - только.... 0мин 10 сек.
Спасибо всем, кто внес идеи и код. Ты отличный парень!