Я написал следующую реализацию алгоритма RC4, где key
является структурой RC4_KEY, как указано в OpenSSL библиотека. m_key
это QByteArray
содержащий установленный ключ. Для этого теста я использовал «teste» в качестве ключа. Как видите, у меня есть еще два QByteArrays
один из них содержит исходные (входные) данные, а другой — зашифрованные (выходные) данные.
void rc4SetKey() {
for (int i = 0; i < 256; ++i) {
key.data[i] = i;
}
for (int i = 0; i < 256; ++i) {
int j = (j + key.data[i] + m_key[i % m_key.length()]) % 256;
std::swap(key.data[i], key.data[j]);
}
}
void rc4Encrypt(QByteArray &in, QByteArray &out) {
out.clear();
out.resize(in.length());
for (int n = 0; n < in.length(); ++n) {
int i = (i + 1) % 256;
int j = (j + key.data[i]) % 256;
std::swap(key.data[i], key.data[j]);
int rand = key.data[(key.data[i] + key.data[j]) % 256];
out[n] = rand ^ in[n];
}
}
В целях тестирования я использую текстовый файл со следующими данными (в шестнадцатеричном виде):
31 32 33 34 35 36 37 38 38 39 31 30 0a
Используя онлайн инструмент или функция OpenSSL, я получаю следующий вывод (ключ: «teste»):
6a 9d ae b6 17 61 7b 71 5f f7 46 f0 ab
Однако, используя мою собственную реализацию, я получаю следующее:
52 ec c2 b1 3d ca 6b 55 50 54 30 e7 ed
Я потратил довольно много времени сейчас и посмотрел на различные псевдокоды или реализации, но я до сих пор не могу понять, где я ошибся.
Это выражение (как в функции set-key, так и в функции encrypt) недопустимо (компиляция со всеми включенными предупреждениями должна была указывать на это):
int j = (j + ...
Помимо бессмыслицы (попытки ссылаться на значение переменной при ее инициализации), она не соответствует определению алгоритма — j
должен быть объявлен вне цикла и не сбрасываться на каждой итерации.
Следующее должно исправить функцию набора ключей. Исправление для функции шифрования будет почти таким же (это также необходимо i
быть зафиксирован таким же образом).
int j = 0;
for (int i = 0; i < 256; ++i) {
j = (j + key.data[i] + m_key[i % m_key.length()]) % 256;
std::swap(key.data[i], key.data[j]);
}