huolong blog

对称加密有两大类的算法。以AES、DES为代表的块加密(也叫分组加密)算法,和以ChaCha20、RC4为代表的流加密算法。ChaCha20 是 TLS 1.3 中唯一留存的流密码算法,用以替代已经不再安全的 RC4 算法。在执行效率方面,ChaCha20 在没有 AES 硬件优化的设备上速度可达其三倍,因此非常适用于移动设备。

算法原理

ChaCha20 的算法处理流程非常简单,主要分为两部分:

  1. 状态矩阵生成
  2. 20 轮状态变换

状态矩阵生成

将固定常量、密钥、计数器和随机数(或者叫 IV)按照如下方式排列组成矩阵:

0x61707865 0x3320646e 0x79622d32 0x6b206574
KEY KEY KEY KEY
KEY KEY KEY KEY
COUNTER NONCE NONCE NONCE

状态变换

这部分直接用代码说明:

#include <stdint.h>
#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 1
		QR(x[1], x[5], x[ 9], x[13]); // column 2
		QR(x[2], x[6], x[10], x[14]); // column 3
		QR(x[3], x[7], x[11], x[15]); // column 4
		// 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];
}

此后便获得了 512 bit 的字节流,直接将明文与等长的字节流进行异或操作便可以得到密文。如果明文长度大于 512 bit,则将 counter 递增并生成新的字节流,直至字节流的长度大于明文长度。