ECDH密钥协商¶
Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.
功能概述¶
ECDH(Elliptic Curve Diffie-Hellman)用于在不安全信道上协商共享密钥。通信双方分别生成椭圆曲线密钥对并交换公钥,再各自计算得到相同的共享密钥。
ECDH不直接提供数据加解密。协商出的共享密钥应通过KDF/HKDF派生出会话密钥,并配合AES-GCM或ChaCha20-Poly1305等算法保护业务数据。
主要应用场景¶
TLS/DTLS安全连接:客户端和服务器使用ECDHE协商会话密钥,再用AES-GCM/ChaCha20加密数据。ECDHE每次连接生成临时密钥,即使长期证书泄露,历史会话通常仍然安全。
IoT设备配网与首次绑定:手机与设备首次连接时交换临时公钥,协商密钥后保护Wi-Fi密码、Token、服务器地址等敏感配置。需要结合设备证书、二维码密钥或绑定码验证身份,否则容易遭受中间人攻击。
端到端加密通信:聊天、文件传输或设备间通信中,发送方和接收方使用ECDH协商密钥,使中间服务器无法读取数据。实际协议还会加入身份签名、密钥轮换和防重放机制。
设备与云平台建立安全通道:设备和云端分别持有密钥对,通过ECDH派生设备专属会话密钥,用于加密遥测数据、控制命令和固件升级信息。通常还要配合设备证书或预置公钥认证云端和设备。
安全启动和固件升级中的密钥封装:服务器针对设备公钥协商或派生临时加密密钥,用于保护固件、配置或授权数据。ECDH不能替代固件签名,固件真实性仍应通过数字签名验证。
常见问题¶
必须验证对端身份:ECDH本身不能防中间人攻击,应配合证书、数字签名或预共享密钥。
不要直接使用协商出的共享密钥加密业务数据:应通过HKDF-SHA-256等派生函数生成加密密钥、IV等不同用途的密钥材料。
校验对端公钥:检查曲线、编码、长度及公钥有效性,拒绝非法点和无穷远点。
私钥必须安全随机:使用可信随机数源,不复用临时私钥,也不得将私钥输出到日志或硬编码在代码中。
优先临时ECDH(ECDHE):每次会话生成新密钥,可提供前向保密。
选择成熟的标准曲线:优先X25519;需要兼容既有系统时使用P-256。
及时清除敏感数据:共享密钥、临时私钥和派生密钥材料使用完毕后应及时清除。
ECDH密钥协商API¶
头文件¶
mbedtls/ecdh.h
mbedtls/ecp.h
函数概览¶
函数 |
说明 |
|---|---|
mbedtls_ecdh_init() |
初始化ECDH上下文 |
mbedtls_ecdh_setup() |
配置ECDH上下文使用的椭圆曲线组 |
mbedtls_ecdh_make_public() |
生成本端密钥对并导出公钥 |
mbedtls_ecdh_read_public() |
导入并校验对端公钥 |
mbedtls_ecdh_calc_secret() |
计算并导出双方共享密钥 |
mbedtls_ecdh_free() |
清除敏感数据并释放ECDH上下文 |
mbedtls_ecdh_gen_public() |
在指定曲线组上生成ECDH密钥对 |
mbedtls_ecdh_compute_shared() |
计算ECDH共享密钥 |
mbedtls_ecdh_can_do() |
检查曲线是否支持ECDH |
mbedtls_ecdh_get_params() |
从EC密钥导入ECDH参数 |
函数详解¶
mbedtls_ecdh_init()¶
功能描述
初始化ECDH上下文。函数原型
void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
ctx |
输出 |
mbedtls_ecdh_context* |
ECDH上下文;详见 mbedtls_ecdh_context |
返回值说明
无
mbedtls_ecdh_setup()¶
功能描述
配置ECDH上下文使用的椭圆曲线组。函数原型
int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx,
mbedtls_ecp_group_id grp_id);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
ctx |
输入/输出 |
mbedtls_ecdh_context* |
已初始化的ECDH上下文;详见 mbedtls_ecdh_context |
grp_id |
输入 |
mbedtls_ecp_group_id |
椭圆曲线标识;常用 MBEDTLS_ECP_DP_SECP256R1 |
返回值说明
0:函数执行成功
其他值:函数执行失败
mbedtls_ecdh_make_public()¶
功能描述
生成本端密钥对并导出公钥。函数原型
int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
ctx |
输入/输出 |
mbedtls_ecdh_context* |
已初始化并完成曲线配置的ECDH上下文;详见 mbedtls_ecdh_context |
olen |
输出 |
size_t * |
导出的公钥长度;单位:字节 |
buf |
输出 |
unsigned char * |
保存本端公钥的缓冲区 |
blen |
输入 |
size_t |
buf 缓冲区长度;单位:字节 |
f_rng |
输入 |
int (*)(void *, unsigned char *, size_t) |
随机数生成函数;不能为NULL |
p_rng |
输入 |
void * |
随机数生成上下文;可为NULL |
返回值说明
0:函数执行成功
MBEDTLS_ERR_ECP_IN_PROGRESS:启用了可恢复椭圆曲线计算,当前计算尚未完成
其他值:函数执行失败
mbedtls_ecdh_read_public()¶
功能描述
导入并校验对端公钥。函数原型
int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
const unsigned char *buf, size_t blen);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
ctx |
输入/输出 |
mbedtls_ecdh_context* |
已生成本端密钥对的ECDH上下文;详见 mbedtls_ecdh_context |
buf |
输入 |
const unsigned char * |
对端发送的公钥数据 |
blen |
输入 |
size_t |
对端公钥数据长度;单位:字节 |
返回值说明
0:函数执行成功
其他值:函数执行失败
mbedtls_ecdh_calc_secret()¶
功能描述
计算并导出双方共享密钥。函数原型
int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
ctx |
输入/输出 |
mbedtls_ecdh_context* |
已包含本端私钥和对端公钥的ECDH上下文;详见 mbedtls_ecdh_context |
olen |
输出 |
size_t * |
共享密钥长度;单位:字节 |
buf |
输出 |
unsigned char * |
保存共享密钥的缓冲区 |
blen |
输入 |
size_t |
buf 缓冲区长度;单位:字节 |
f_rng |
输入 |
int (*)(void *, unsigned char *, size_t) |
用于侧信道防护的随机数生成函数;建议不为NULL |
p_rng |
输入 |
void * |
随机数生成上下文;可为NULL |
返回值说明
0:函数执行成功
MBEDTLS_ERR_ECP_IN_PROGRESS:当前计算尚未完成
其他值:函数执行失败
mbedtls_ecdh_free()¶
功能描述
清除敏感数据并释放ECDH上下文。函数原型
void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx);
参数说明
参数名 |
输入/输出 |
类型 |
说明 |
|---|---|---|---|
ctx |
输入/输出 |
mbedtls_ecdh_context* |
已初始化的ECDH上下文;可为NULL;详见 mbedtls_ecdh_context |
返回值说明
无
结构体定义¶
mbedtls_ecdh_context¶
ECDH上下文结构体定义如下:
typedef struct mbedtls_ecdh_context {
mbedtls_ecp_group grp;
mbedtls_mpi d;
mbedtls_ecp_point Q;
mbedtls_ecp_point Qp;
mbedtls_mpi z;
} mbedtls_ecdh_context;
参数 |
类型 |
说明 |
|---|---|---|
grp |
mbedtls_ecp_group |
保存当前ECDH使用的椭圆曲线域参数 |
d |
mbedtls_mpi |
保存本端生成的私钥 |
Q |
mbedtls_ecp_point |
保存本端根据私钥生成的公钥 |
Qp |
mbedtls_ecp_point |
保存并校验导入的对端公钥 |
z |
mbedtls_mpi |
保存ECDH计算得到的共享秘密 |
备注
业务代码不应直接访问其内部成员。
枚举定义¶
mbedtls_ecdh_side¶
EC密钥归属枚举定义如下:
typedef enum {
MBEDTLS_ECDH_OURS,
MBEDTLS_ECDH_THEIRS,
} mbedtls_ecdh_side;
成员 |
说明 |
|---|---|
MBEDTLS_ECDH_OURS |
导入本端EC密钥 |
MBEDTLS_ECDH_THEIRS |
导入对端EC公钥 |
mbedtls_ecp_group_id¶
椭圆曲线类型枚举定义如下:
typedef enum {
MBEDTLS_ECP_DP_NONE = 0,
MBEDTLS_ECP_DP_SECP192R1,
MBEDTLS_ECP_DP_SECP224R1,
MBEDTLS_ECP_DP_SECP256R1,
MBEDTLS_ECP_DP_SECP384R1,
MBEDTLS_ECP_DP_SECP521R1,
MBEDTLS_ECP_DP_BP256R1,
MBEDTLS_ECP_DP_BP384R1,
MBEDTLS_ECP_DP_BP512R1,
MBEDTLS_ECP_DP_CURVE25519,
MBEDTLS_ECP_DP_SECP192K1,
MBEDTLS_ECP_DP_SECP224K1,
MBEDTLS_ECP_DP_SECP256K1,
MBEDTLS_ECP_DP_CURVE448,
} mbedtls_ecp_group_id;
成员 |
说明 |
|---|---|
MBEDTLS_ECP_DP_NONE |
未指定椭圆曲线 |
MBEDTLS_ECP_DP_SECP192R1 |
NIST P-192,不推荐新设计使用 |
MBEDTLS_ECP_DP_SECP224R1 |
NIST P-224 |
MBEDTLS_ECP_DP_SECP256R1 |
NIST P-256,推荐通用ECDH场景使用 |
MBEDTLS_ECP_DP_SECP384R1 |
NIST P-384,安全强度更高 |
MBEDTLS_ECP_DP_SECP521R1 |
NIST P-521 |
MBEDTLS_ECP_DP_BP256R1 |
Brainpool P-256 |
MBEDTLS_ECP_DP_BP384R1 |
Brainpool P-384 |
MBEDTLS_ECP_DP_BP512R1 |
Brainpool P-512 |
MBEDTLS_ECP_DP_CURVE25519 |
Curve25519,通常用于X25519密钥协商 |
MBEDTLS_ECP_DP_SECP192K1 |
192位Koblitz曲线 |
MBEDTLS_ECP_DP_SECP224K1 |
224位Koblitz曲线 |
MBEDTLS_ECP_DP_SECP256K1 |
secp256k1,常见于区块链 |
MBEDTLS_ECP_DP_CURVE448 |
Curve448,通常用于X448密钥协商 |
错误码¶
错误码 |
说明 |
|---|---|
MBEDTLS_ERR_ECP_BAD_INPUT_DATA |
输入参数错误 |
MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL |
输出缓冲区不足 |
MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE |
当前曲线或功能未启用 |
MBEDTLS_ERR_ECP_INVALID_KEY |
对端公钥或本端密钥无效 |
MBEDTLS_ERR_ECP_RANDOM_FAILED |
随机数生成失败 |
MBEDTLS_ERR_ECP_ALLOC_FAILED |
内存分配失败 |
MBEDTLS_ERR_ECP_VERIFY_FAILED |
椭圆曲线验证失败 |
常用曲线¶
枚举值 |
曲线 |
说明 |
|---|---|---|
MBEDTLS_ECP_DP_SECP256R1 |
NIST P-256 |
推荐,兼容性较好 |
MBEDTLS_ECP_DP_SECP384R1 |
NIST P-384 |
更高安全强度,开销更大 |
MBEDTLS_ECP_DP_CURVE25519 |
Curve25519 |
适合ECDH密钥协商 |
MBEDTLS_ECP_DP_SECP256K1 |
secp256k1 |
主要用于区块链,不建议作为默认曲线 |
应用逻辑流程图¶
示例代码¶
完整示例代码请查看https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/network/crypto/ecdh_demo.c