Я реализую собственный iostream (т. е. с чтением, записью, поиском и закрытием), который использует потоковый шифр RC4 для шифрования и дешифрования. Одно из условий этого потока заключается в том, что он является двунаправленным, и вызывающий код должен иметь возможность произвольно искать любую позицию в потоке, прежде чем выполнять какое-либо фактическое чтение или запись.
Теперь, поскольку RC4 использует ключ, который опирается на все предыдущие операции подкачки до заданной позиции «сообщения», как я могу включить возможность произвольного поиска любой позиции?
Очевидно, я мог бы выполнить поиск до позиции данного смещения поиска (отмеченного THIS BIT в следующем примере), прежде чем выполнять фактический процесс преобразования xor-ing, что-то вроде ,:
/**
* @brief called from a stream's read or write function
* @param in the input buffer
* @param out the output buffer
* @param startPosition the current stream position (obtained via the streams
* tellg or tellp functions for read and write respectively)
* @param length the number of bytes to transform
*/
void transform(char *in, char *out,
std::ios_base::streamoff startPosition,
long length)
{
// need to reset sbox from member s_box each time this
// function is called
long sbox[256];
for (int i = 0; i<256; ++i) {
sbox[i]=m_sbox[i];
}
// ***THIS BIT***
// need to run the swap operation startPosition times
// to get sbox integer sequence in order
int i = 0, j = 0, k = 0;
for (int a=0; a < startPosition; ++a) {
i = (i + 1) % 256;
j = (j + sbox[i]) % 256;
swapints(sbox, i, j);
}
// now do the actual xoring process up to the length
// of how many bytes are being read or written
for (int a=0; a < length; ++a) {
i = (i + 1) % 256;
j = (j + sbox[i]) % 256;
swapints(sbox, i, j);
k = sbox[(sbox[i] + sbox[j]) % 256];
out[a] = in[a] ^ k;
}
}
а затем преобразование будет вызываться из чтения или записи реализации потока, что-то вроде:
MyStream&
MyStream::read(char * const buf, std::streamsize const n)
{
std::ios_base::streamoff start = m_stream.tellg();
std::vector<char> in;
in.resize(n);
(void)m_stream.read(&in.front(), n);
m_byteTransformer->transform(&in.front(), buf, start, n);
return *this;
}
РЕДАКТИРОВАТЬ: поток не должен знать, как работает функция преобразования. Функция преобразования полностью независима, и я должен иметь возможность свободно переключаться между различными реализациями преобразования.
РЕДАКТИРОВАТЬ: функция swapints выглядит так:
void swapints(long *array, long ndx1, long ndx2)
{
int temp = array[ndx1];
array[ndx1] = array[ndx2];
array[ndx2] = temp;
}
Настоящая проблема с вышеупомянутой функцией преобразования заключается в ее медлительности, поскольку она должна выполнять начальные операции подкачки startPosition до того, как будет выполнено собственно преобразование xor. Это очень проблематично, когда выполняется много операций поиска. Теперь я слышал, что RC4 должен быть быстрым, но моя (вероятно, плохая реализация) предполагает иное, учитывая начальный набор операций подкачки.
Итак, мой реальный вопрос: как можно оптимизировать приведенный выше код, чтобы уменьшить количество необходимых операций? В идеале я хотел бы исключить начальный ("ЭТОТ БИТ") набор операций подкачки.
РЕДАКТИРОВАТЬ: оптимизация начальной настройки sbox, вероятно, тривиальна (например, использование memcpy, как предложено egur). Я думаю, что важная оптимизация заключается в том, как я могу оптимизировать цикл, отмеченный ЭТОМ БИТОМ. Возможно, все эти подкачки целых чисел можно запрограммировать более лаконично, без необходимости использования цикла for.
Спасибо,
Бен