ECDH密钥协商

Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.


功能概述

ECDH(Elliptic Curve Diffie-Hellman)用于在不安全信道上协商共享密钥。通信双方分别生成椭圆曲线密钥对并交换公钥,再各自计算得到相同的共享密钥。

ECDH不直接提供数据加解密。协商出的共享密钥应通过KDF/HKDF派生出会话密钥,并配合AES-GCM或ChaCha20-Poly1305等算法保护业务数据。

主要应用场景

  1. TLS/DTLS安全连接:客户端和服务器使用ECDHE协商会话密钥,再用AES-GCM/ChaCha20加密数据。ECDHE每次连接生成临时密钥,即使长期证书泄露,历史会话通常仍然安全。

  2. IoT设备配网与首次绑定:手机与设备首次连接时交换临时公钥,协商密钥后保护Wi-Fi密码、Token、服务器地址等敏感配置。需要结合设备证书、二维码密钥或绑定码验证身份,否则容易遭受中间人攻击。

  3. 端到端加密通信:聊天、文件传输或设备间通信中,发送方和接收方使用ECDH协商密钥,使中间服务器无法读取数据。实际协议还会加入身份签名、密钥轮换和防重放机制。

  4. 设备与云平台建立安全通道:设备和云端分别持有密钥对,通过ECDH派生设备专属会话密钥,用于加密遥测数据、控制命令和固件升级信息。通常还要配合设备证书或预置公钥认证云端和设备。

  5. 安全启动和固件升级中的密钥封装:服务器针对设备公钥协商或派生临时加密密钥,用于保护固件、配置或授权数据。ECDH不能替代固件签名,固件真实性仍应通过数字签名验证。

常见问题

  1. 必须验证对端身份:ECDH本身不能防中间人攻击,应配合证书、数字签名或预共享密钥。

  2. 不要直接使用协商出的共享密钥加密业务数据:应通过HKDF-SHA-256等派生函数生成加密密钥、IV等不同用途的密钥材料。

  3. 校验对端公钥:检查曲线、编码、长度及公钥有效性,拒绝非法点和无穷远点。

  4. 私钥必须安全随机:使用可信随机数源,不复用临时私钥,也不得将私钥输出到日志或硬编码在代码中。

  5. 优先临时ECDH(ECDHE):每次会话生成新密钥,可提供前向保密。

  6. 选择成熟的标准曲线:优先X25519;需要兼容既有系统时使用P-256。

  7. 及时清除敏感数据:共享密钥、临时私钥和派生密钥材料使用完毕后应及时清除。

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

主要用于区块链,不建议作为默认曲线

应用逻辑流程图

../../../_images/image_KFTAbsvC8oIICxxIuW0cyTotn9b.webp

示例代码

完整示例代码请查看https://github.com/UniRTOS/UniRTOS-Doc-Examples/blob/main/network/crypto/ecdh_demo.c