Я играл с потоковыми шифрами и нашел это Страница Википедии ChaCha20 (вариант ChaCha). Что я потерял, так это то, как проверить этот код. На этой странице нигде нет тестовых векторов, и я не могу их найти. Я написал следующий код C:
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
#define QR(a, b, c, d) ( \
a += b, d ^= a, d = ROTL(d,16), \
c += d, b ^= c, b = ROTL(b,12), \
a += b, d ^= a, d = ROTL(d, 8), \
c += d, b ^= c, b = ROTL(b, 7))
#define РАУНДЫ 20
void chacha_block (uint32_t out[16], uint32_t const in[16])
{
инт я;
uint32_t х[16];
для (я = 0; я < 16; ++ я)
х [я] = в [я];
// 10 петель Ã 2 ряд/петля = 20 рядов
для (я = 0; я < ОКРУГЛ; я += 2) {
// Нечетный раунд
QR(х[0], х[4], х[8], х[12]); // столбец 0
QR(х[1], х[5], х[9], х[13]); // столбец 1
QR(х[2], х[6], х[10], х[14]); // столбец 2
QR(х[3], х[7], х[11], х[15]); // столбец 3
// Чётное округление
QR(х[0], х[5], х[10], х[15]); // диагональ 1 (главная диагональ)
QR(х[1], х[6], х[11], х[12]); // диагональ 2
QR(x[2], x[7], x[8], x[13]); // диагональ 3
QR(x[3], x[4], x[9], x[14]); // диагональ 4
}
для (я = 0; я < 16; ++ я)
выход[я] = х[я] + вход[я];
}
}
пустая функция(){
const char* константа = "расширить 32-байтовый k";
uint32_t в целом[16];
inwhole[0] = ((uint32_t*)константа)[0];
inwhole[1] = ((uint32_t*)константа)[1];
inwhole[2] = ((uint32_t*)константа)[2];
inwhole[3] = ((uint32_t*)константа)[3];
в целом[4] = 0;//ключ[0];
в целом[5] = 0;//ключ[1];
в целом[6] = 0;//ключ[2];
в целом[7] = 0;//ключ[3];
в целом[8] = 0;//ключ[4];
в целом[9] = 0;//ключ[5];
в целом[10] = 0;//ключ[6];
в целом[11] = 0;//ключ[7];
//Нулевой счетчик и одноразовый номер
в целом[12] = 0;
в целом[13] = 0;
в целом[14] = 0;
в целом[15] = 0;
uint32_t вне[16];
chacha_block (вне, внутри);
printHex((char*)out2,16*4);
// Это распечатывает:
//76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586
}
Я не смог найти никаких тестовых векторов для проверки этого первого блока ключевого потока.
Также меня сбивает с толку тот факт, что следующий блок ключевого потока должен генерироваться путем передачи предыдущего вывода обратно в чача_блок
функция?
Также следует ли использовать это шифровальное мясо для исключения блоков потока ключей с данными (это не было явно упомянуто в статье)?