I was playing around with stream ciphers an found this Wikipedia ChaCha20 page (the ChaCha variant). What I'm lost with is how to test this code. There are no testvectors anywhere on that page and I cannot find any. I wrote the following C code:
#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 ROUNDS 20
void chacha_block(uint32_t out[16], uint32_t const in[16])
{
int i;
uint32_t x[16];
for (i = 0; i < 16; ++i)
x[i] = in[i];
// 10 loops × 2 rounds/loop = 20 rounds
for (i = 0; i < ROUNDS; i += 2) {
// Odd round
QR(x[0], x[4], x[ 8], x[12]); // column 0
QR(x[1], x[5], x[ 9], x[13]); // column 1
QR(x[2], x[6], x[10], x[14]); // column 2
QR(x[3], x[7], x[11], x[15]); // column 3
// Even round
QR(x[0], x[5], x[10], x[15]); // diagonal 1 (main diagonal)
QR(x[1], x[6], x[11], x[12]); // diagonal 2
QR(x[2], x[7], x[ 8], x[13]); // diagonal 3
QR(x[3], x[4], x[ 9], x[14]); // diagonal 4
}
for (i = 0; i < 16; ++i)
out[i] = x[i] + in[i];
}
}
void main(){
const char* constant = "expand 32-byte k";
uint32_t inwhole[16];
inwhole[0] = ((uint32_t*)constant)[0];
inwhole[1] = ((uint32_t*)constant)[1];
inwhole[2] = ((uint32_t*)constant)[2];
inwhole[3] = ((uint32_t*)constant)[3];
inwhole[4] = 0;//key[0];
inwhole[5] = 0;//key[1];
inwhole[6] = 0;//key[2];
inwhole[7] = 0;//key[3];
inwhole[8] = 0;//key[4];
inwhole[9] = 0;//key[5];
inwhole[10] = 0;//key[6];
inwhole[11] = 0;//key[7];
//Zero counter and nonce
inwhole[12] = 0;
inwhole[13] = 0;
inwhole[14] = 0;
inwhole[15] = 0;
uint32_t out[16];
chacha_block(out, inwhole);
printHex((char*)out2,16*4);
//This prints out:
//76b8e0ada0f13d90405d6ae55386bd28bdd219b8a08ded1aa836efcc8b770dc7da41597c5157488d7724e03fb8d84a376a43b8f41518a11cc387b669b2ee6586
}
I could not find any test vectors to validate this first keystream block against.
Also I found it confusing that is the next keystream block meant to be generated by passing the previous output back to the chacha_block
function?
Also is this cipher meat to be used to xor the keystream blocks with the data (this was not explicitly mentioned in the article)?