1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| #include <cstddef> #include <cstdint> #include <cstdio> using namespace std; #define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) #define QR(a, b, c, d) \ a += b; \ d ^= a; \ d = ROTL32(d, 16); \ c += d; \ b ^= c; \ b = ROTL32(b, 12); \ a += b; \ d ^= a; \ d = ROTL32(d, 8); \ c += d; \ b ^= c; \ b = ROTL32(b, 7)
uint32_t convert_uint8Arr_to_uint32(const uint8_t *arr) { return ((uint32_t)(arr[0] << 0)) | ((uint32_t)(arr[1] << 8)) | ((uint32_t)(arr[2] << 16)) | ((uint32_t)(arr[3] << 24)); } uint32_t state[16]; uint32_t keyStream[16]; char ChaCha20_Const[128] = "expand 32-byte k"; void ChaCha20_init(uint8_t key[32], uint8_t *nonce, uint32_t count) { state[0] = convert_uint8Arr_to_uint32((uint8_t *)ChaCha20_Const); state[1] = convert_uint8Arr_to_uint32((uint8_t *)ChaCha20_Const + 4); state[2] = convert_uint8Arr_to_uint32((uint8_t *)ChaCha20_Const + 8); state[3] = convert_uint8Arr_to_uint32((uint8_t *)ChaCha20_Const + 12); state[4] = convert_uint8Arr_to_uint32(key + 0); state[5] = convert_uint8Arr_to_uint32(key + 4); state[6] = convert_uint8Arr_to_uint32(key + 8); state[7] = convert_uint8Arr_to_uint32(key + 12); state[8] = convert_uint8Arr_to_uint32(key + 16); state[9] = convert_uint8Arr_to_uint32(key + 20); state[10] = convert_uint8Arr_to_uint32(key + 24); state[11] = convert_uint8Arr_to_uint32(key + 28); state[12] = count; state[13] = convert_uint8Arr_to_uint32(nonce + 0); state[14] = convert_uint8Arr_to_uint32(nonce + 4); state[15] = convert_uint8Arr_to_uint32(nonce + 8); } void ChaCha20_gen(uint32_t *in, uint32_t *out) { for (int i = 0; i < 16; i++) out[i] = in[i]; for (int i = 0; i < 10; i++) { QR(out[0], out[4], out[8], out[12]); QR(out[1], out[5], out[9], out[13]); QR(out[2], out[6], out[10], out[14]); QR(out[3], out[7], out[11], out[15]); QR(out[0], out[5], out[10], out[15]); QR(out[1], out[6], out[11], out[12]); QR(out[2], out[7], out[8], out[13]); QR(out[3], out[4], out[9], out[14]); } for (int i = 0; i < 16; i++) out[i] += in[i]; } void ChaCha20_enc(uint8_t *input, size_t len, uint8_t *key, uint8_t *nonce, uint32_t count = 0) { int idx = 0; ChaCha20_init(key, nonce, count); for (size_t i = 0; i < len; i++) { if (idx % 64 == 0) { ChaCha20_gen(state, keyStream); state[12]++; idx = 0; } input[i] ^= ((uint8_t *)keyStream)[idx]; idx++; } } int main() { char key[33] = "Eleven11________________________"; uint8_t nonce[12] = {0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78}; char plaintext[] = "Hello, ChaCha20!"; size_t len = sizeof(plaintext) - 1;
ChaCha20_enc((uint8_t *)plaintext, len, (uint8_t *)key, nonce); for (size_t i = 0; i < len; i++) printf("%02X ", (uint8_t)plaintext[i]); ChaCha20_enc((uint8_t *)plaintext, len, (uint8_t *)key, nonce); printf("\n%s\n", plaintext); }
|