编辑:经过一番努力,我确实重新实现了一个 RAM 高效的 SSL 库,它可以在下面指示的 RAM 数量中运行。它比我以前的创作具有更多的功能和灵活性,但它仍然非常小。更重要的是,它也是开源的(MIT 许可)。欣赏:https ://www.bearssl.org/
可以在大约 21 kB 的 ARM 代码 (thumb) 中实现 SSL/TLS 客户端(或服务器),运行时需要少于 20 kB 的 RAM (*)。我知道它可以做到,因为我做到了(对不起,不是开源的)。TLS 的大部分复杂性来自于它对多种加密算法的支持,这些算法是在初始握手期间协商的;如果您只专注于一组加密算法,那么您可以将代码剥离到非常小的东西。我建议将TLS 1.2与TLS_RSA_WITH_AES_128_CBC_SHA256
密码套件:对于那个,您只需要 RSA、AES 和 SHA-256 的实现(对于 TLS 1.1 和更早版本,您还需要 MD5 和 SHA-1 的实现,这并不难,但会花费一些额外的千字节的代码)。此外,您可以使其同步(在普通 TLS 中,客户端和服务器可以同时说话,但没有什么能强迫他们这样做)并省略“握手重新协商”部分(客户端和服务器执行初始握手,但他们可以稍后重做在连接期间打开)。
协议实现中最棘手的部分是关于证书的。服务器和客户端使用各自的私钥相互验证——使用 RSA,服务器执行 RSA 解密,而客户端计算 RSA 签名。只要客户端和服务器彼此知道公钥,这就提供了身份验证;因此,他们将自己的公钥发送给对方,并用签名的 blob证书包裹起来。证书在使用前必须经过验证,即它的签名关于先验已知的公钥(通常称为“根 CA”或“信任锚”)进行验证。客户端不能盲目使用服务器刚刚发送的公钥,因为它会允许中间人攻击。
X.509 证书解析和验证有点复杂(在我的实现中,它是 21 kB 中的 6 kB 代码)。根据您的设置,您可能有更轻的选择;例如,如果您可以在客户端硬编码服务器公钥,那么客户端可以简单地使用该密钥并丢弃服务器证书,这“只是一个 blob”:无需解析,无需认证,非常健壮的协议。您还可以定义自己的“证书”格式。另一种可能性是使用SRP,这是一种密钥交换机制,双方就共享秘密值的知识相互验证(SRP 的魔力在于即使共享秘密的熵相对较低,它也很健壮,例如是密码);使用TLS_SRP_SHA_WITH_AES_128_CBC_SHA
.
这里的重点是,即使使用自定义协议,你也不会得到比精简 TLS 更轻的东西,至少如果你想保持它的健壮性的话。设计一个健壮的协议一点也不容易;经过多年的血与泪,TLS 已经达到了被认为足够安全的地步。因此,重用 TLS 确实比发明自己的协议要好。此外,这使得代码更容易测试(您可以与现有的 SSL/TLS 实现互操作)。
(*) 在 20 kB 的 RAM 中,有一个 16.5 kB 的缓冲区用于传入“记录”,因为 TLS 声明记录可能会达到该大小。如果您同时控制客户端和服务器代码,则可以安排较小的最大记录大小,从而节省 RAM 需求。每条记录的开销并不多——平均不到 50 字节——所以你可以使用 4 kB 的记录并且仍然有高效的通信。