计算简单、轻量级的 SSL/TLS 替代品

信息安全 密码学 加密 验证 tls 公钥基础设施
2021-08-24 09:20:46

目标硬件是一个相当低功耗的 MCU(ARM Cortex-M3 @72MHz,只有大约 64KB SRAM 和 256KB 闪存),所以在这里走细线。我的主板确实有以太网,我最终将在其上运行 lwIP(轻量级 TCP/IP FOSS 套件)(目前正在苦苦挣扎)。但是,我还需要某种超轻量级的 SSL/TLS 替代方案。我知道此类 MCU 有多个 GPL 的 SSL/TLS 实现,但它们的足迹仍然相当大。虽然他们确实适合,但考虑到其他一切,不要给其他人留下太多空间。

我的流量不是 HTTP,所以我不用担心 HTTPS,而且我的客户端/服务器通信可以是完全专有的,所以非标准的解决方案是可以的。寻找可能是简约但强大的建议(弱安全性毫无价值),可以帮助我的替代方案 -

Encrypt my communication (C->S & S->C)
Do 2-way authentication (C->S & S->C)
Avoid man-in-middle attacks

我将无法在 ARMv7 汇编级别优化库,因此完全依靠我的编程技能和 GNU-ARM 编译器的优化。鉴于上述,任何可能是最佳选择的指针?

C:客户端,S:服务器。我的通信都是二进制数据。

4个回答

编辑:经过一番努力,我确实重新实现了一个 RAM 高效的 SSL 库,它可以在下面指示的 RAM 数量中运行。它比我以前的创作具有更多的功能和灵活性,但它仍然非常小。更重要的是,它也是开源的(MIT 许可)。欣赏:https ://www.bearssl.org/


可以在大约 21 kB 的 ARM 代码 (thumb) 中实现 SSL/TLS 客户端(或服务器),运行时需要少于 20 kB 的 RAM (*)。我知道它可以做到,因为我做到了(对不起,不是开源的)。TLS 的大部分复杂性来自于它对多种加密算法的支持,这些算法是在初始握手期间协商的;如果您只专注于一组加密算法,那么您可以将代码剥离到非常小的东西。我建议将TLS 1.2TLS_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 的记录并且仍然有高效的通信。

TLS 似乎仍然是完成这项工作的工具,只需明智地选择密码,然后分析哪种密码实现在您的平台上运行良好。此外,与黑客工具(如John The Ripper的算法)相比,加密库的官方实现往往非常缓慢,所以也许你可以使用这些。你试过MatrixSSL了吗?

无论您做什么,我都会使用已经存在了一段时间的现有协议,并剥离/硬编码一些选项以使其轻巧,而不是发明自己的协议。

如果您的需求足够简单,您可以使用预共享的对称密钥来满足,那么将 IPSEC 的子集添加到 TCP/IP 堆栈似乎是可行的,而无需大量代码占用。甚至可能保持互操作性。

同样,精简的 SSL 或 Kerberos 可能是一种选择,因为您不需要大多数更高级的身份验证和密钥管理方面,也不需要大多数密码。

您可以查看 MST(最小安全传输)https://github.com/DiplIngFrankGerlach/MST

它提供与 TLS 相同的安全保证,但需要预共享密钥。此外,它非常小(小于 1000 LoC,没有 AES),因此可以很容易地由专家进行审查。