mbedtls怎么获取当前的证书类型,const mbedtls_ssl_ciphersuite_t *cs = mbedtls_ssl_get_ciphersuite(ssl);这样可以吗?
时间: 2025-07-19 19:33:12 浏览: 5
<think>我们正在使用mbedtls库,用户想知道如何获取当前使用的证书类型。用户提到使用`mbedtls_ssl_get_ciphersuite(ssl)`函数,并询问这是否正确。
首先,我们需要明确:证书类型和密码套件(ciphersuite)是两个相关但不同的概念。
在TLS/SSL通信中,密码套件定义了整个通信过程中的一系列算法,包括密钥交换算法、认证算法(也就是证书类型)、对称加密算法和消息认证码算法等。而证书类型通常指的是用于认证的证书,比如RSA证书、ECDSA证书等。
在mbedtls中,`mbedtls_ssl_get_ciphersuite(ssl)`函数返回的是当前SSL会话所使用的密码套件的ID(一个整数)。这个密码套件ID对应着一组算法,其中就包含了认证算法(即证书类型)。
因此,我们可以通过这个函数获取到密码套件ID,然后解析该ID以得到认证算法(也就是证书类型)。
具体步骤:
1. 使用`mbedtls_ssl_get_ciphersuite(ssl)`获取当前会话的密码套件ID。
2. 使用`mbedtls_ssl_ciphersuite_from_id`函数将ID转换为`mbedtls_ssl_ciphersuite_t`结构体(该结构体包含密码套件的详细信息)。
3. 从该结构体中获取认证算法(即`key_exchange`字段,但注意这个字段实际上包含了密钥交换和认证的信息)。
但是,需要注意的是,`mbedtls_ssl_ciphersuite_t`结构体中的`key_exchange`字段是一个枚举值,它同时包含了密钥交换和认证的信息。我们需要根据这个值来判断证书类型。
例如,如果`key_exchange`的值为`MBEDTLS_KEY_EXCHANGE_RSA`,则表示使用RSA证书;如果为`MBEDTLS_KEY_EXCHANGE_ECDHE_RSA`,则表示使用ECDHE密钥交换且使用RSA证书;如果为`MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA`,则表示使用ECDHE密钥交换且使用ECDSA证书。
因此,我们可以通过解析`key_exchange`字段来得到证书类型(即认证算法)。
所以,用户使用`mbedtls_ssl_get_ciphersuite(ssl)`函数是获取证书类型的第一步,但还需要进一步解析才能得到具体的证书类型。
另外,mbedtls还提供了直接获取当前连接中使用的证书链的函数,例如`mbedtls_ssl_get_peer_cert(ssl)`可以获取对端的证书,然后我们可以通过检查证书的密钥类型来获取证书类型。但是,用户可能想获取的是当前会话协商后使用的证书类型(即密码套件中指定的认证算法),而不是证书本身。因为一个证书可能包含多种密钥(比如RSA和EC),但实际使用的认证算法由密码套件决定。
因此,我们有两种方法:
方法一:通过密码套件解析认证算法(即证书类型)。
方法二:获取对端的证书,然后检查证书的密钥类型。
用户的问题中提到了使用`mbedtls_ssl_get_ciphersuite(ssl)`,所以我们可以按照方法一进行。
示例代码:
```c
#include "mbedtls/ssl.h"
const char *get_cert_type(mbedtls_ssl_context *ssl) {
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
int ciphersuite_id = mbedtls_ssl_get_ciphersuite(ssl);
if (ciphersuite_id == 0) {
return "No ciphersuite selected";
}
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
if (ciphersuite_info == NULL) {
return "Unknown ciphersuite";
}
switch (ciphersuite_info->key_exchange) {
case MBEDTLS_KEY_EXCHANGE_RSA:
return "RSA";
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
return "ECDHE_RSA"; // 证书类型是RSA
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
return "ECDHE_ECDSA"; // 证书类型是ECDSA
case MBEDTLS_KEY_EXCHANGE_PSK:
return "PSK"; // 没有证书
// ... 其他情况
default:
return "Unknown";
}
}
```
注意:上面的代码只列举了几种常见情况,实际需要根据mbedtls定义的`key_exchange`枚举值进行完整处理。
另外,用户可能还关心自己的证书(即本端证书)的类型,但协商的密码套件中指定的认证算法是对端用来验证本端的(如果是单向认证,则只验证服务器;双向认证则双方都验证)。所以,如果用户想知道本端证书的类型,那么应该从本端的证书中获取。但是,在密码套件中,认证算法指的是在握手过程中用于签名的算法,这通常与本端证书的密钥类型一致(例如,RSA证书用于RSA签名,ECDSA证书用于ECDSA签名)。因此,通过密码套件获取的认证算法可以间接反映证书的密钥类型。
总结:使用`mbedtls_ssl_get_ciphersuite(ssl)`获取密码套件ID,然后解析其认证算法部分,从而得到证书类型(即用于认证的算法)是正确的方法。
但是,请注意,如果密码套件不涉及证书(如PSK),则没有证书类型。
因此,回答用户的问题:使用`mbedtls_ssl_get_ciphersuite(ssl)`函数是获取证书类型的第一步,但需要进一步解析密码套件信息才能得到证书类型。
另外,我们也可以直接获取证书并检查其密钥类型,例如:
```c
mbedtls_x509_crt *cert = mbedtls_ssl_get_peer_cert(ssl);
if (cert != NULL) {
// 检查证书的密钥类型
if (cert->pk.pk_type == MBEDTLS_PK_RSA) {
// RSA证书
} else if (cert->pk.pk_type == MBEDTLS_PK_ECDSA) {
// ECDSA证书
}
}
```
这种方法获取的是对端证书的实际类型,但可能和密码套件中指定的认证算法不完全一致?实际上,它们应该是一致的,因为握手过程中会检查证书是否满足密码套件的要求。
所以,两种方法都可以,取决于用户的需求:如果用户想知道协商的密码套件中指定的认证算法,则用第一种;如果用户想获取对端证书的实际类型,则用第二种。
由于用户的问题没有明确是哪种,但根据函数名“获取当前证书类型”,可能更倾向于第二种(因为证书是具体的,而密码套件指定的是算法)。但是,用户提到了`mbedtls_ssl_get_ciphersuite`,所以我们也要说明第一种方法。
因此,我们可以这样回答:
在mbedtls中,获取当前证书类型有两种常见方法:
1. 通过解析当前SSL会话所使用的密码套件中的认证算法来确定证书类型(即密码套件中指定的用于认证的算法)。
2. 直接获取对等方的证书(peer certificate),然后检查其公钥类型。
用户提到的`mbedtls_ssl_get_ciphersuite(ssl)`函数用于获取密码套件ID,然后我们可以解析该密码套件以获取认证算法(即证书类型)。因此,这是方法1的一部分。
但是,如果用户想要获取的是本端证书类型,则应该使用本端证书(但mbedtls没有直接提供获取当前连接中使用的本端证书的函数,需要在建立连接时自己保存)。或者,如果用户想获取对端证书类型,则可以使用`mbedtls_ssl_get_peer_cert`。
考虑到用户的问题,我们给出两种方法的示例。
最后,我们还需要注意,在握手完成后才能获取这些信息。
因此,回答如下:</think>在 mbedtls 中获取当前使用的证书类型,**使用 `mbedtls_ssl_get_ciphersuite(ssl)` 是正确但间接的方法**。该函数返回的是协商的密码套件 ID,而密码套件中包含了证书类型信息。以下是完整实现方案:
### 方法 1:通过密码套件解析证书类型
```c
#include "mbedtls/ssl.h"
const char *get_cert_type(mbedtls_ssl_context *ssl) {
// 获取密码套件 ID
const int ciphersuite_id = mbedtls_ssl_get_ciphersuite(ssl);
if (ciphersuite_id == 0)
return "No ciphersuite selected";
// 获取密码套件详细信息
const mbedtls_ssl_ciphersuite_t *cs_info =
mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
// 解析密钥交换算法确定证书类型
switch (cs_info->key_exchange) {
case MBEDTLS_KEY_EXCHANGE_RSA:
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
return "RSA"; // RSA 证书
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
return "ECDSA"; // ECDSA 证书
case MBEDTLS_KEY_EXCHANGE_PSK:
return "PSK"; // 预共享密钥(无证书)
default:
return "Unknown";
}
}
```
### 方法 2:直接解析对端证书(需握手完成)
```c
#include "mbedtls/x509_crt.h"
const char *get_peer_cert_type(mbedtls_ssl_context *ssl) {
// 获取对端证书
const mbedtls_x509_crt *peer_cert = mbedtls_ssl_get_peer_cert(ssl);
if (!peer_cert)
return "No peer certificate";
// 解析证书公钥类型
switch (peer_cert->pk.pk_type) {
case MBEDTLS_PK_RSA:
return "RSA";
case MBEDTLS_PK_ECDSA:
return "ECDSA";
default:
return "Unknown";
}
}
```
### 关键说明
1. **证书类型与密码套件关系**
TLS 证书类型由密码套件的密钥交换算法决定,例如:
- `ECDHE_RSA` → RSA 证书
- `ECDHE_ECDSA` → ECDSA 证书
- `PSK` → 无证书
2. **使用场景差异**
- `mbedtls_ssl_get_ciphersuite()`:获取协商算法(含证书类型)
- `mbedtls_ssl_get_peer_cert()`:直接读取证书内容(需握手完成)
3. **执行时机**
必须在 TLS 握手完成后调用(如 `MBEDTLS_SSL_HANDSHAKE_OVER` 状态)[^3]。
> **最佳实践**:优先使用方法 1(密码套件解析),因其不依赖证书解析且符合 TLS 协议规范。证书类型实际由密码套件协商决定,而非证书本身[^2]。
---
### 相关问题
1. 如何检测 mbedtls 握手阶段使用的证书类型?
2. 在双向认证场景下如何获取客户端证书的密钥类型?
3. mbedtls 密码套件中 `key_exchange` 字段与证书类型的完整映射关系是什么?
4. 如何处理 PSK 密码套件这种无证书的情况?
阅读全文
相关推荐
















