ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

RIOT 中 PSA Crypto EdDSA(Ed25519)配置与测试实战:从模块裁剪到源码级验证

2026/9/20 12:29:03 拓冰建站 浏览量
RIOT 中 PSA Crypto EdDSA(Ed25519)配置与测试实战:从模块裁剪到源码级验证 RIOT 中 PSA Crypto EdDSAEd25519配置与测试实战从模块裁剪到源码级验证【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT本篇技术指南以 RIOT 仓库中的 tests/sys/psa_crypto_eddsa 配置测试为核心讲解如何仅启用 PSA Crypto 模块中的 EdDSAEd25519 曲线功能完成密钥生成、签名、验签的完整流程并介绍后端自动选择机制、内存配置要点与自动化测试方法。读完本文你将能够在自己的 RIOT 应用中按需裁剪 PSA Crypto 模块、理解psa_asymmetric_ecc_ed25519的后端解析逻辑并掌握用testrunner验证签名结果正确性的实践方案。测试定位为什么单独为 EdDSA 建一个测试tests/sys/psa_crypto_eddsa/README.md 明确指出这是一个仅针对 PSA Crypto 模块中 eddsa 功能的配置测试configuration test其内容基于 examples/advanced/psa_crypto 示例演化而来。RIOT 的 PSA Crypto 实现支持 AES、HMAC、ECDSA、EdDSA 等多种运算而本例刻意把范围收敛到 EdDSA 一项其目的是验证模块级裁剪是否可行PSA Crypto 采用基础模块 按操作拆分的架构本测试证明只选psa_asymmetric与psa_asymmetric_ecc_ed25519两个模块即可独立完成 Ed25519 签名运算无需引入对称加密、哈希等其他功能模块验证后端自动解析Ed25519 在支持硬件加速的平台上自动走periph_ecc_ed25519后端否则回退到软件实现monocypher这一依赖关系在 sys/psa_crypto/Makefile.dep 中有明确体现作为配置正确性的回归保障通过测试框架自动断言程序输出 All Done确保模块配置组合在 CI 环境中持续可用。最小化模块配置Makefile 剖析测试的构建配置位于 tests/sys/psa_crypto_eddsa/Makefile内容非常精简是理解 PSA Crypto 模块依赖关系的绝佳样例include ../Makefile.sys_common USEMODULE ztimer USEMODULE ztimer_usec USEMODULE psa_crypto USEMODULE psa_asymmetric USEMODULE psa_asymmetric_ecc_ed25519 CFLAGS -DCONFIG_PSA_ASYMMETRIC_KEYPAIR_COUNT1 CFLAGS -DCONFIG_PSA_SINGLE_KEY_COUNT1 CFLAGS -DTHREAD_STACKSIZE_MAIN4096 include $(RIOTBASE)/Makefile.include基础模块与依赖链psa_cryptoPSA Crypto 基础模块是任何 PSA 运算的前提。根据 sys/psa_crypto/Makefile.dep 的依赖规则它会自动附带random与prng_sha256prng密钥生成需要随机数ifneq (,$(filter psa_crypto,$(USEMODULE))) USEMODULE random USEMODULE prng_sha256prng endifpsa_asymmetric非对称运算基模块依赖规则为USEMODULE psa_key_management进而再依赖psa_key_slot_mgmt见 sys/psa_crypto/Makefile.dep 与 L498-L501即密钥槽管理是签名运算的隐含前置。psa_asymmetric_ecc_ed25519Ed25519 运算模块是本测试的核心。后端自动解析硬件优先软件兜底这是整个测试最有价值的部分。查看 sys/psa_crypto/Makefile.dep 的 Ed25519 分支## ECC_ED25519 backend ifneq (,$(filter psa_asymmetric_ecc_ed25519,$(USEMODULE))) ifeq (,$(filter psa_asymmetric_ecc_ed25519_custom_backend,$(USEMODULE))) FEATURES_OPTIONAL periph_ecc_ed25519 include $(RIOTMAKE)/features_check.inc.mk ifneq (,$(filter periph_ecc_ed25519,$(FEATURES_USED))) USEMODULE psa_asymmetric_ecc_ed25519_backend_periph else USEMODULE psa_asymmetric_ecc_ed25519_backend_monocypher endif endif endif ifneq (,$(filter psa_asymmetric_ecc_ed25519_backend_c25519,$(USEMODULE))) USEPKG c25519 USEMODULE psa_c25519 USEMODULE psa_c25519_edsign endif ifneq (,$(filter psa_asymmetric_ecc_ed25519_backend_monocypher,$(USEMODULE))) USEPKG monocypher USEMODULE psa_monocypher USEMODULE psa_monocypher_ed25519 endif ifneq (,$(filter psa_asymmetric_ecc_ed25519_backend_periph,$(USEMODULE))) FEATURES_REQUIRED periph_ecc_ed25519 endif逻辑解读只要用户选了psa_asymmetric_ecc_ed25519且没有显式指定psa_asymmetric_ecc_ed25519_custom_backend构建系统就声明一个可选特性periph_ecc_ed25519若目标板提供该硬件加速特性FEATURES_USED命中则启用psa_asymmetric_ecc_ed25519_backend_periph外设硬件加速后端若目标板不提供该特性则自动回退到软件后端psa_asymmetric_ecc_ed25519_backend_monocypher该模块通过USEPKG monocypher引入 monocypher 密码库并启用psa_monocypher/psa_monocypher_ed25519除默认路径外还支持显式选择psa_asymmetric_ecc_ed25519_backend_c25519引入 c25519 包与psa_c25519_edsign。因此同一份 Makefile 在native平台会编译 monocypher 软件实现在具备硬件加速的板上则自动切换为 periph 后端无需改动任何应用代码。这也印证了 examples/advanced/psa_crypto/README.md 中不指定任何配置时PSA Crypto 会依据目标平台自动选择默认后端的描述。所有可选模块名伪模块都登记在 sys/psa_crypto/Makefile.include并且该文件还强制了一个算法必须且只能选一个后端的约束ifneq (,$(filter psa_asymmetric_ecc_ed25519,$(USEMODULE))) ifneq (1,$(call backends, psa_asymmetric_ecc_ed25519)) $(error One (and only one) backend should be selected for psa_asymmetric_ecc_ed25519) endif endif关键内存配置项Makefile 中的三个编译期宏对应 PSA Crypto 的资源配置宏取值作用CONFIG_PSA_ASYMMETRIC_KEYPAIR_COUNT1非对称密钥对槽位数量。EdDSA 测试中需要 1 个私钥签名故设为 1CONFIG_PSA_SINGLE_KEY_COUNT1单钥槽位数量。用于存放导入的公钥PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR归入单钥槽故设为 1THREAD_STACKSIZE_MAIN4096主线程栈大小。软件后端如 monocypher在栈上做运算时需要更大的栈空间依据 sys/psa_crypto/doc.md 的说明PSA 内部把密钥槽分为三类Single Key Slot单钥/非结构化数据、Asymmetric Key Slot本地非对称密钥对、Protected Key Slot安全元件或硬件保护内存中的密钥。本例的example_eddsa.c同时生成了私钥对并导入了公钥正好同时触及前两类槽位因此两个计数都需要显式配置。需要特别说明的是槽位数量是 RAM 中缓存的密钥上限不代表持久化存储的密钥总数上限本实现暂不支持持久化见 sys/psa_crypto/doc.md 的说明。Makefile.ci中列出的nucleo-c031c6、nucleo-l011k4、samd10-xmini、stm32f030f4-demo等小内存板卡被标记为BOARD_INSUFFICIENT_MEMORY见 Makefile.ci正是因为这些板卡的 RAM 不足以承载完整的 PSA Crypto 签名栈。完整 EdDSA 流程example_eddsa.c 逐段解析测试的核心运算实现在 example_eddsa.c文件头注明其内容复制自examples/advanced/psa_crypto。它演示了使用 PSA Crypto API 完成一次 Ed25519 签名的标准五步走。算法与密钥参数定义#define EDDSA_MESSAGE_SIZE (127) #define ECC_KEY_SIZE (255) #define ECC_KEY_TYPE (PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_TWISTED_EDWARDS)) #define ECC_ALG (PSA_ALG_PURE_EDDSA)曲线族为Twisted EdwardsPSA_ECC_FAMILY_TWISTED_EDWARDS即 Edwards25519算法标识为纯 EdDSAPSA_ALG_PURE_EDDSA对应 RFC 8032 中的 PureEdDSA 模式与先哈希再签名的 Ed25519ph 相对密钥位长 255 bit待签名消息固定为 127 字节msg数组初始化为0x0b。第一步配置私钥属性并生成密钥对psa_key_usage_t usage PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE; psa_set_key_algorithm(privkey_attr, ECC_ALG); psa_set_key_usage_flags(privkey_attr, usage); psa_set_key_type(privkey_attr, ECC_KEY_TYPE); psa_set_key_bits(privkey_attr, ECC_KEY_SIZE); status psa_generate_key(privkey_attr, privkey_id);psa_key_attributes_t结构必须先用psa_key_attributes_init()清零初始化——依据 sys/psa_crypto/doc.md未初始化的结构会被 PSA 视为active而无法用于新操作。psa_generate_key()由 PSA 在内部完成随机密钥生成私钥材料不会暴露给应用层这正是 PSA Crypto 密钥管理设计的关键点。第二步导出公钥uint8_t public_key[PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(ECC_KEY_TYPE, ECC_KEY_SIZE)] { 0 }; size_t pubkey_length; status psa_export_public_key(privkey_id, public_key, sizeof(public_key), pubkey_length);缓冲区大小由宏PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(ECC_KEY_TYPE, ECC_KEY_SIZE)在编译期计算避免手动估算出错。第三步以公钥属性导入公开密钥psa_set_key_algorithm(pubkey_attr, ECC_ALG); psa_set_key_usage_flags(pubkey_attr, PSA_KEY_USAGE_VERIFY_MESSAGE); psa_set_key_bits(pubkey_attr, PSA_BYTES_TO_BITS(pubkey_length)); psa_set_key_type(pubkey_attr, PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(ECC_KEY_TYPE)); status psa_import_key(pubkey_attr, public_key, pubkey_length, pubkey_id);注意这里不能直接复用私钥属性公钥的用途标记仅为PSA_KEY_USAGE_VERIFY_MESSAGE不能签名类型用PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR()派生位数则根据导出的实际长度经PSA_BYTES_TO_BITS()换算。第四、五步签名与验签status psa_sign_message(privkey_id, ECC_ALG, msg, sizeof(msg), signature, sizeof(signature), sig_length); return psa_verify_message(pubkey_id, ECC_ALG, msg, sizeof(msg), signature, sig_length);签名使用私钥privkey_id验签使用导入的公钥pubkey_id算法均为ECC_ALG。example_eddsa()的返回值即psa_verify_message()的结果只有当签名通过验证时才返回PSA_SUCCESS这使整个函数天然具备自校验能力。运行入口与计时main.c 与 ztimermain.c 是标准的 RIOT 测试入口#include psa/crypto.h #include ztimer.h extern psa_status_t example_eddsa(void); int main(void) { bool failed false; psa_status_t status; ztimer_acquire(ZTIMER_USEC); ztimer_now_t start ztimer_now(ZTIMER_USEC); start ztimer_now(ZTIMER_USEC); status example_eddsa(); printf(EdDSA took %d us\n, (int)(ztimer_now(ZTIMER_USEC) - start)); if (status ! PSA_SUCCESS) { failed true; printf(EdDSA failed: %s\n, psa_status_to_humanly_readable(status)); } ztimer_release(ZTIMER_USEC); if (failed) { puts(Tests failed...); } else { puts(All Done); } return 0; }实现要点用ztimer_acquire(ZTIMER_USEC)/ztimer_release(ZTIMER_USEC)获取微秒级计时器对应 Makefile 中的ztimer与ztimer_usec模块测量单次 EdDSA生成密钥 导出/导入公钥 签名 验签的整体耗时并打印失败时通过psa_status_to_humanly_readable(status)输出人类可读的错误状态便于定位无论成功失败最终都会输出All Done或Tests failed...供测试框架断言。从源码结构可以推断计时输出同时起到了后端性能对比的辅助作用——examples/advanced/psa_crypto/README.md 中给出了不同后端的预期运行时间对比例如硬件 CryptoCell 310 与软件实现、ATECC608A 安全元件之间的数量级差异本例沿用这一模式便于开发者在实际板卡上核对后端是否按预期生效。运行与自动化验证手工运行在任意支持 PSA Crypto 的平台上编译并烧录make -C tests/sys/psa_crypto_eddsa BOARDnative flash term使用真实硬件时替换BOARD例如BOARDnrf52840dk该板具备硬件加速后端。程序启动后会打印类似EdDSA took xxx us的耗时信息并以All Done结束表示签名-验签链路全部成功。自动化测试测试脚本 基于 RIOT 的testrunner框架#!/usr/bin/env python3 import sys from testrunner import run def testfunc(child): child.expect_exact(All Done) print([TEST PASSED]) if __name__ __main__: sys.exit(run(testfunc))脚本的核心断言只有一行期望串口输出精确匹配All Done。由于main.c只有在psa_generate_key、psa_export_public_key、psa_import_key、psa_sign_message、psa_verify_message全部返回PSA_SUCCESS时才会走到该分支因此这一断言实质上覆盖了整条 EdDSA 链路。配合测试框架运行make -C tests/sys/psa_crypto_eddsa BOARDnative flash test脚本退出码为 0 表示通过输出[TEST PASSED]。移植到自己应用中的配置清单综合以上分析若要在自己的 RIOT 应用中只启用 PSA Crypto 的 EdDSA 功能最小配置如下# 基础模块必须 USEMODULE psa_crypto USEMODULE psa_asymmetric USEMODULE psa_asymmetric_ecc_ed25519 # 后端默认自动选择硬件 periph 优先否则 monocypher 软件实现 # 也可显式指定 # USEMODULE psa_asymmetric_ecc_ed25519_custom_backend # USEMODULE psa_asymmetric_ecc_ed25519_backend_c25519 # 或 # USEMODULE psa_asymmetric_ecc_ed25519_backend_monocypher # 密钥槽配置按需调整 CFLAGS -DCONFIG_PSA_ASYMMETRIC_KEYPAIR_COUNT1 CFLAGS -DCONFIG_PSA_SINGLE_KEY_COUNT1 # 软件后端运算需要更大的栈 CFLAGS -DTHREAD_STACKSIZE_MAIN4096若偏好 Kconfig 方式可在应用目录的app.config.test中写成CONFIG_MODULE_PSA_CRYPTOy CONFIG_MODULE_PSA_ASYMMETRICy CONFIG_MODULE_PSA_ASYMMETRIC_ECC_ED25519y并在menuconfig的System - PSA Crypto菜单下调整密钥槽数量对应CONFIG_PSA_ASYMMETRIC_KEYPAIR_COUNT、CONFIG_PSA_SINGLE_KEY_COUNT。更多可用模块与后端清单参见 sys/psa_crypto/doc.md 的 Available Modules 章节。小结tests/sys/psa_crypto_eddsa虽是一个规模很小的配置测试却完整承载了 RIOT PSA Crypto 模块化设计的核心思想通过psa_asymmetricpsa_asymmetric_ecc_ed25519两个模块即可独立启用 Ed25519 签名能力后端由构建系统依据板级特性自动在硬件加速与 monocypher 软件实现之间切换。其 Makefile 是模块裁剪与密钥槽配置的现成范本example_eddsa.c 则是 PSA Crypto 密钥生成、导入、签名、验签的标准 API 用法配合 main.c 的 ztimer 计时与 testrunner 断言形成了一套可复用的最小 EdDSA 验证闭环。读者可直接将本文的配置清单与代码模式移植到自己的安全启动、固件签名校验、消息认证等场景中。【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考