自制加密通信协议(一):对称加密算法
自古以来,有大量信息需要隐秘地传输,例如军事机密。密码学也随之发展起来。一种常用的加密算法是对称加密算法,它由加密函数E和解密函数D构成:
C=E(T,K)
T=D(C,K)
其中T为明文,C为密文。信息的传输双方事先约定一个共用的密钥K。密文可以在不安全的信道中传递,即使被敌人截获,在未知密码的情况下也很难恢复出原文。
ChaCha20 算法
我尝试使用名为 ChaCha20 的算法来处理互联网上传输的信息。该算法的详细描述可以参阅 RFC 8439。 ChaCha20 使用的核心部分是由 16 个 32 位整数构成的状态:
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
之后用一种“四分之一轮” (quarter round) 算法 QR 来操作这个状态:
QR(a, b, c, d) ::
a += b; d ^= a; d <<= 16;
c += d; b ^= c; b <<= 12;
a += b; d ^= a; d <<= 8;
c += d; b ^= c; b <<= 7;
一“轮”由 4 个“四分之一轮”构成, 奇数轮为:
QR(0, 4, 8, 12);
QR(1, 5, 9, 13);
QR(2, 6, 10, 14);
QR(3, 7, 11, 15);
即对每列执行 QR 操作。 偶数轮为:
QR(0, 5, 10, 15);
QR(1, 6, 11, 12);
QR(2, 7, 8, 13);
QR(3, 4, 9, 14);
即沿着主对角线的方向执行 QR 操作。
初始时,0-3 是常数 expand 32-byte k
(共 16 字节),4-11 是密钥 K(共 32 字节),12 是计数器 B, 13-15 是一次性随机数 N (nonce):
cccccccc cccccccc cccccccc cccccccc
kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk
kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk
bbbbbbbb nnnnnnnn nnnnnnnn nnnnnnnn
运行一次 ChaCha20 算法执行 20 “轮”, 即 80 次 QR 操作,然后再和初始状态逐位相加(目的是使计算过程不可逆)。这样得到的的状态和明文(密文)逐位异或,就得到了密文(明文)。注意,解密过程和加密过程完全等价。
这样的计算一次只能处理 64 字节的明文。每处理 64 字节的明文,计数器 B 自加一。这样,每次用于异或的状态都不相同。
给每个明文加密应采用不同的一次性随机数,理由类似。一次性随机数应当在双方通信时协商,可以采用明文方式发送。
密钥则应以其他的安全方式分享。例如,当面分享。也可以采用密钥交换算法(如 Diffie-Hellman)。