mbedTLS RSA 加密解密示例
源码位置: samples/security/mbedtls/rsa 查看源码
功能说明
演示如何使用 mbedTLS 库进行 RSA 加密、解密、签名和验证操作。本示例展示了 RSA 密钥的导入(或生成)、PKCS#1 加密解密、以及基于 SHA1 的签名和验证功能。
RSA 是一种非对称加密算法,广泛用于数据加密和数字签名。
硬件连接
无需外部连接,mbedTLS 为纯软件加密库。如果启用硬件加速(CONFIG_MBEDTLS_HARDWARE_MPI_MODULAR_EXPONENTIATION=y),可以使用硬件加速的模幂运算。
示例内容
初始化随机数生成器(CTR_DRBG)和熵源
初始化 RSA 上下文(使用 PKCS#1 v2.1 填充和 SHA256)
密钥处理(根据
IS_GENERATE_KEY宏):如果
IS_GENERATE_KEY == 0:从预定义的十六进制字符串导入 RSA 密钥(支持 1024、2048、4096、8192 位)如果
IS_GENERATE_KEY == 1:生成新的 2048 位 RSA 密钥对
打印 RSA 密钥对信息(N, E, D, P, Q, DP, DQ, QP)
加密解密测试:
使用公钥加密消息 “Hello, World!”
使用私钥解密加密后的数据
验证解密结果与原始消息一致
签名验证测试:
计算消息的 SHA1 哈希值
使用私钥对哈希值进行签名
使用公钥验证签名
编译
重要提示:在编译前,请先确认您使用的开发板型号。SDK 目前支持以下开发板:
arcs_evb - ARCS EVB 评估板
arcs_mini - ARCS Mini 开发板
根据您的开发板型号,选择对应的编译命令:
在示例目录下执行编译:
# 使用 arcs_evb 开发板
./build.sh -C -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -DBOARD=arcs_mini
Note
如果在 SDK 根目录执行,需要指定示例路径:
# 使用 arcs_evb 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_evb
# 或使用 arcs_mini 开发板
./build.sh -C -S samples/<示例路径> -DBOARD=arcs_mini
Note
确保已安装对应的工具链。
烧录
编译完成后,使用 SDK tools 目录下的 cskburn 工具烧录固件:
./tools/burn/cskburn -s /dev/ttyUSB0 -b 3000000 0x0 build/arcs.bin -C arcs
Note
烧录参数说明:
-s /dev/ttyUSB0:串口设备路径,需要根据实际情况修改 - Linux 系统:通常是/dev/ttyUSB0或/dev/ttyACM0- 可通过ls /dev/tty*命令查看可用串口设备 - 不同开发板或 USB 转串口芯片可能使用不同的设备名-b 3000000:烧录波特率(3Mbps)0x0:烧录起始地址build/arcs.bin:编译生成的固件路径-C arcs:芯片类型
注意事项:
确保开发板已正确连接到电脑
如果无法识别串口设备,请检查 USB 连接线是否正常,或尝试其他 USB 端口
预期输出
********Arcs SDK 0.1.0 @ v0.0.23.temp.docs-96-gf56c5084660d********
Running on hart-id: 1
I/elog [1034:42:44.159 1 elog_async] EasyLogger V2.2.99 is initialize success.
Hello, world!
mbedtls rsa test
. setup rng ... ok
1. RSA generate key ... ok
+++++++++++++++++ rsa keypair +++++++++++++++++
N: [RSA 模数,十六进制]
E: [公钥指数,十六进制]
D: [私钥指数,十六进制]
P: [质数 P,十六进制]
Q: [质数 Q,十六进制]
DP: [DP 值,十六进制]
DQ: [DQ 值,十六进制]
QP: [QP 值,十六进制]
+++++++++++++++++ rsa keypair +++++++++++++++++
2. RSA encryption ... ok
[加密后的数据,十六进制]
3. RSA decryption ... ok
Hello, World!
4. RSA Compare results and plaintext ... ok
5. PKCS#1 data sign : passed
PKCS#1 sig. verify: all passed
说明:
输出开头包含系统启动信息和日志系统初始化信息
RSA 密钥对信息以十六进制格式输出
加密后的数据以十六进制格式输出
解密后的明文直接输出
签名和验证操作的结果会显示
核心 API
API |
说明 |
|---|---|
|
初始化 RSA 上下文 |
|
生成 RSA 密钥对 |
|
导入 RSA 密钥组件 |
|
完成 RSA 密钥设置(计算 DP, DQ, QP) |
|
PKCS#1 加密 |
|
PKCS#1 解密 |
|
PKCS#1 签名 |
|
PKCS#1 验证 |
|
计算 SHA1 哈希值 |
关键代码
/* 初始化 RSA 上下文 */
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
/* 导入 RSA 密钥(从十六进制字符串) */
mbedtls_mpi N, E, D, P, Q, DP, DQ, QP;
mbedtls_mpi_init(&N);
mbedtls_mpi_init(&E);
mbedtls_mpi_init(&D);
mbedtls_mpi_init(&P);
mbedtls_mpi_init(&Q);
mbedtls_mpi_init(&DP);
mbedtls_mpi_init(&DQ);
mbedtls_mpi_init(&QP);
mbedtls_mpi_read_string(&N, 16, S_N); // 从十六进制字符串读取
mbedtls_mpi_read_string(&E, 16, S_E);
mbedtls_mpi_read_string(&D, 16, S_D);
mbedtls_mpi_read_string(&P, 16, S_P);
mbedtls_mpi_read_string(&Q, 16, S_Q);
// 注意:虽然代码读取了 DP, DQ, QP,但 mbedtls_rsa_import() 不使用它们
mbedtls_mpi_read_string(&DP, 16, S_DP);
mbedtls_mpi_read_string(&DQ, 16, S_DQ);
mbedtls_mpi_read_string(&QP, 16, S_QP);
// mbedtls_rsa_import() 只使用 N, P, Q, D, E
mbedtls_rsa_import(&ctx, &N, &P, &Q, &D, &E);
// mbedtls_rsa_complete() 会自动计算 DP, DQ, QP
mbedtls_rsa_complete(&ctx);
/* 加密 */
const char *msg = "Hello, World!";
uint8_t out[256];
mbedtls_rsa_pkcs1_encrypt(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg,
MBEDTLS_RSA_PUBLIC, strlen(msg), msg, out);
/* 解密 */
uint8_t out1[256];
size_t olen;
mbedtls_rsa_pkcs1_decrypt(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg,
MBEDTLS_RSA_PRIVATE, &olen, out, out1, sizeof(out1));
/* 签名 */
unsigned char sha1sum[20];
mbedtls_sha1_ret(msg, strlen(msg), sha1sum);
uint8_t sign[256];
mbedtls_rsa_pkcs1_sign(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg,
MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0,
sha1sum, sign);
/* 验证 */
mbedtls_rsa_pkcs1_verify(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg,
MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20,
sha1sum, sign);
RSA 密钥格式说明
密钥组件
N: RSA 模数(公钥和私钥共有)
E: 公钥指数(通常为 65537 或 0x010001)
D: 私钥指数
P: 质数 P(N = P × Q)
Q: 质数 Q(N = P × Q)
DP: D mod (P-1)
DQ: D mod (Q-1)
QP: Q^(-1) mod P
支持的密钥长度
代码中预定义了以下密钥长度(通过 RSA_KEY_SIZE 宏选择):
1024 位:
RSA_KEY_SIZE == 10242048 位:
RSA_KEY_SIZE == 2048(默认)4096 位:
RSA_KEY_SIZE == 40968192 位:
RSA_KEY_SIZE == 8192
注意:代码虽然读取了 DP, DQ, QP 值,但 mbedtls_rsa_import() 只使用 N, P, Q, D, E,然后通过 mbedtls_rsa_complete() 自动计算 DP, DQ, QP,因此预定义的 DP, DQ, QP 值实际上不会被使用
配置说明
必需配置
CONFIG_SDK_MODULE_MBEDTLS=y: 启用 mbedTLS 模块CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=y: 启用 RSA 密钥交换CONFIG_MBEDTLS_GENPRIME_ENABLED=y: 启用质数生成(如果使用IS_GENERATE_KEY == 1)CONFIG_MBEDTLS_HASH_ALL_ENABLED=y: 启用所有哈希算法(用于签名)
硬件加速配置(可选)
CONFIG_MBEDTLS_HARDWARE_ENTROPY=y: 启用硬件熵源CONFIG_MBEDTLS_HARDWARE_MPI_MODULAR_EXPONENTIATION=y: 启用硬件模幂运算加速
注意事项
密钥生成: 如果
IS_GENERATE_KEY == 1,生成大质数可能需要较长时间,特别是对于 4096 位或更大的密钥填充方式: 代码使用 PKCS#1 v2.1(OAEP)填充进行加密,使用 PKCS#1 v1.5 填充进行签名。代码中初始化时使用
MBEDTLS_RSA_PKCS_V21,虽然注释中有MBEDTLS_RSA_PKCS_V15的示例,但实际运行使用的是 v2.1哈希算法: 签名使用 SHA1 哈希算法,实际应用中建议使用更安全的算法(如 SHA256)
密钥导入: 从十六进制字符串导入密钥时,确保所有密钥组件格式正确
资源清理: 使用完 RSA 上下文和 MPI 后,必须调用相应的
free()函数释放资源加密数据大小: RSA 加密的数据大小受密钥长度限制,2048 位密钥最多可加密 245 字节(使用 OAEP 填充)
随机数生成器: 加密和签名操作需要随机数,必须正确初始化 CTR_DRBG
密钥安全: 预定义的密钥仅用于测试,实际应用中应使用安全生成的密钥