火柴棍密码学:如何将 ECDSA 塞进廉价的微控制器
在保护物联网或廉价硬件中的数据时,开发者经常碰壁。试着在某些 8 位 AVR 或弱小的 ARM Cortex-M0 上部署完整的 OpenSSL。十有八九,你的固件根本塞不进内存,即使塞进去了,也不会给主应用程序逻辑留下任何资源。这就是 micro-ecc 项目的用武之地——它只做一件事,但做得相当漂亮。
这个项目的意义是什么
micro-ecc 是一个紧凑的 ECDH(密钥交换)和 ECDSA(数字签名)算法 C 语言实现。项目作者 Ken MacKay 明确的目标是创建一个能在任何有处理器的地方运行的库。
这里的主要技巧是完全放弃动态内存分配。没有 malloc 和堆,只有栈和静态存储。对于嵌入式系统来说,这至关重要:你可以在编译时精确知道密码学操作会消耗多少内存,不必担心碎片化或运行时泄漏。
这个库能做什么
该库支持五种标准曲线,包括流行的 secp256r1(也称为 P-256)和"比特币" secp256k1。
主要特性如下:
- 适用于 8 位、32 位和 64 位架构。
- 针对已知的侧信道攻击有防护措施。
- 纯 C 语言编写,但为 AVR 和 ARM 提供了汇编代码片段以获得最大速度。
- 采用宽松的 BSD 2-clause 许可证分发。
顺便说一句,如果你使用 Arduino,项目可以直接在库管理器中找到。无需手动下载任何东西——只需找到 micro-ecc 并将其添加到你的 sketch 中即可。
小代码完成大任务
作者声称代码针对体积进行了优化。在微控制器的世界里,这往往比原始速度更重要。如果你只是每月验证一次固件更新签名,耗时 100ms 还是 500ms 并不重要。重要的是验证代码不会占用你 80% 的闪存空间。
也就是说,代码中有可选的优化。例如,通过 uECC_OPTIMIZATION_LEVEL 可以调整性能。但要小心:对于 ARM 平台的高优化级别,GCC 可能需要特定的标志如 -fomit-frame-pointer,否则一切可能会出问题。
代码中的样子
该库有一个极简的接口。要开始使用,只需将几个文件复制到你的项目中并包含头文件即可。
曲线点默认以未压缩形式表示,不带 0x04 前缀。如果你在通过无线电传输时需要节省每一个字节,该库提供了 uECC_compress() 和 uECC_decompress() 函数。
谁需要这个
我看到几种 micro-ecc 绝对不可或缺的场景。首先,设备认证。例如,当你的传感器需要向服务器证明它就是它本身,而不是假冒产品时。ECDSA 非常适合生成这样的签名。
其次,安全启动。如果你正在为 STM32 或某些 AVR 编写自定义引导程序,micro-ecc 将帮助你在将新固件镜像写入闪存之前验证其签名。
第三,如果你正在创建可穿戴设备或电池供电的传感器。用于计算的 CPU 周期越少,设备续航时间越长。ARM 和 AVR 的汇编代码片段在这里会非常有用。
几点补充说明
尽管它很出色,这个项目也有其独特之处。README 相当简洁,所以每个函数的详细信息你得深入研究 uECC.h。文档就在代码注释中。
如果你计划在 Windows 上构建项目,别忘了链接系统库 advapi32.lib——它需要用于处理熵。对于 AVR,请确保启用编译器优化(-O1 及更高),否则由于栈处理的具体细节,库可能无法正常工作。
总的来说,这是一个专业库应该有的样子:狭窄的关注点、最少的依赖关系以及可预测的行为。如果你的硬件太弱无法运行 TLS,但你又需要安全性——micro-ecc 绝对值得在你的 src/lib 中占有一席之地。