既然 TLS 用了 AEAD 加密算法,那 AEAD 加密算法应该是密码学里安全且成熟的。

  AEAD 算法可以验证明文信息,保证明文信息不被修改。因为加密和解密的内容都不是一个字节一个字节的,所以内容的长度必须是明文,一般放在内容的前面,作为 AEAD 的验证信息。

key

  • 算法用到的 key 一般是由密码派生而来,key 的长度是固定的,但是密码的长度是任意的。PBKDF2、Scrypt、Bcrypt、ARGON2 都是常用的密码派生算法。

nonce

  • 算法用到的 nonce 必须保证每次都不同,nonce 的长度一般是 12 个字节,可以把前四个字节作为 uint32,后八个字节作为 uint64,然后每次用完之后加一就行了。

  • 但还有一个问题,如果服务端处理多个客户端的加密信息,而 nonce 都是从零开始自相加,那么 nonce 就会重复。可以这样,nonce 不是从零开始的,而是随机的。服务端收到的第一个 nonce 作为 salt 去派生 key,这样的话虽然 nonce 会重复,但是 nonce 对于每个 key 都是独一无二的。

tag

  • 当然 AEAD 还有 tag,一般是 16 个字节,但是这个一般是被算法库自动处理的,只需要注意内容被加密后长度会增加一个 tag 的长度就好了,因为 tag 被附加到了加密内容的后面。

其他

  • 小小地计算一下,nonce 是 12 个字节,tag 是 16 个字节,长度一般是 2 个字节网络序,每加密一次就要多花费 30 个字节。手机上消耗的流量更多了,消耗的电量也更多了,好在是现在新的 arm 架构有 aes 指令集了,虽然 chacha20 也很快但终究是相差一段距离。