最近在国民技术的一颗 M4 上,把 ED25519 的验签流程完整跑了一遍。其实一开始也没抱太大期望,这类非对称算法大家都知道安全性高,但放到 MCU 上,很多时候就是“理论可以,工程不行”。所以我干脆自己跑一轮,看看到底是个什么水平。
测试方式很简单,我没有在 MCU 上做签名,只做验签。上位机用 Python 生成公钥、私钥和签名,然后把 message、signature、公钥传到单片机里去验证。消息我就用了一个最简单的字符串 “i am alive”,目的也很明确,就是把变量压到最低,只看算法本身的性能和资源占用。
//使用ed25519进行验签//这里先定义公钥,签名和原文uint8_t public_key[32] = {0x81, 0x86, 0x72, 0x91, 0xF5, 0x67, 0x85, 0x9D,0x7C, 0x03, 0x86, 0x08, 0x57, 0x46, 0xA0, 0xA1,0x7C, 0x35, 0x94, 0xCB, 0x3B, 0x80, 0xA2, 0x19,0x12, 0x5D, 0xE3, 0x7A, 0x66, 0xA2, 0x50, 0xC3};uint8_t signature[64] = {0x66, 0x7C, 0xD1, 0xFB, 0x10, 0x1F, 0x8B, 0xC4,0x4A, 0x14, 0xE0, 0xBF, 0xB9, 0x42, 0xD3, 0xC9,0xCB, 0x82, 0x61, 0x37, 0xE4, 0x39, 0x49, 0x32,0x0D, 0x49, 0x6C, 0x38, 0x9B, 0xA8, 0x47, 0x36,0x84, 0x75, 0x75, 0x9E, 0x76, 0x2C, 0x5E, 0x22,0x41, 0x6B, 0x28, 0x91, 0x70, 0x02, 0x70, 0xDB,0x25, 0xD4, 0x4A, 0x90, 0xD6, 0x35, 0x52, 0xA5,0x04, 0x4C, 0x21, 0x56, 0xA9, 0xB7, 0x49, 0x0C};uint8_t message[10] = {0x69, 0x20, 0x61, 0x6D, 0x20, 0x61, 0x6C, 0x69, 0x76, 0x65};void ed25519_verify(uint8_t *signature, uint8_t *public_key, uint8_t *message, uint16_t message_len){int ok = crypto_ed25519_check(signature, public_key, message, message_len);if (ok == 0){LOG("ed25519 verify pass message is %sn", message);}else{LOG("ed25519 verify failn");}}
结果打印出来,红框里是 1s 内做验签的次数。
跑出来的结果还挺稳定,一秒大概能做 15 次验签,基本就是 60 多毫秒一次。这个数据出来之后,其实心里就有数了,这东西在 MCU 上不是不能用,但绝对不是拿来随便调的函数,它是一个有明显算力成本的操作。你要是想在通信里每条消息都验签,那基本就是自己给系统找麻烦;但如果只是开机校验一次,或者 OTA 的时候验一次,那这个性能是完全够用的。
不过,还要考虑单片机的 Flash 够不够用。
资源这块我也看了一下,原始工程代码大概 7KB,在 O3 优化下把验签加进去之后,整个程序变成了 16KB 多一点,相当于增加了 10KB。这个量级说大不大,说小也不小,如果是那种 Flash 本来就很紧的项目,这一步是需要认真评估的。好在 RAM 占用很低,大概也就一百字节左右,这一点倒是挺友好,不会对系统运行造成什么压力。
做完这轮测试之后,其实有一个很明确的感受,就是很多人对这类算法的定位是有偏差的。ED25519 这种东西,本质上是用来做签名和验签的,是解决“这东西是不是我发的,有没有被改过”的问题,而不是拿来加密大数据的。你看现在这个性能,一秒 15 次,其实已经把它的使用边界画得很清楚了,它就不适合出现在高频路径里。
所以在工程上,我更倾向于把它当成一个“兜底”的安全机制来用。真正跑数据的部分,还是应该交给 AES 这种对称算法去做,效率高、成本低;ED25519 只在关键节点用一下,比如建立信任、校验固件,这样既把安全性补上了,也不会把系统拖慢。
这次我也刻意只在 MCU 上做验签,没有做签名,这其实也是一个比较标准的用法。私钥这种东西没必要也不应该放在设备侧,一旦进了设备,就总有被拿走的风险。再加上签名本身比验签更耗资源,让 MCU 去做这件事意义也不大。所以更合理的分工就是,上位机或者云端负责签名,设备只保留公钥做验证。
结合设备的 OTA 系统,这套东西其实是可以直接用起来的。升级包在生成的时候做一次签名,设备在写入之前做一次验签,通过了再刷,不通过就直接丢掉,这一步能挡掉很多乱七八糟的风险。
这一轮跑下来,对 ED25519 在 MCU 上的定位基本就清楚了。它是能用的,而且成本也不算离谱,但前提是你得把它放在对的位置上。用来做低频、关键的安全校验,它是很合适的;但如果指望它去承担高频或者大数据量的任务,那基本就是用错地方了。
说到底,这东西不是用来让系统看起来“更高级”的,而是在关键时候,能让你心里更有底。
951
