如何使用 mbedtls 验证证书是不是验证密钥?

Posted

技术标签:

【中文标题】如何使用 mbedtls 验证证书是不是验证密钥?【英文标题】:How can I verify with mbedtls, that a cert validates a key?如何使用 mbedtls 验证证书是否验证密钥? 【发布时间】:2020-03-23 07:36:08 【问题描述】:

Mbedtls 可以使用其mbedtls_x509_crt_verify(...) 函数 (link) 验证 x509 证书。

但是,我有什么:

公钥/私钥对(保存在mbedtls_pk_context 中)。 我从其他来源获得的证书(因此,不能保证它不包含任何可能的智能修改)。

证书的验证没有问题。

但是,如果该证书验证了不同的密钥怎么办?(可能是软件问题和破解尝试的结果。)当然,这样的密钥/证书对将无法tls 握手,但我认为我不需要为此建立一个 tcp 连接。

还有一个mbedtls_pk_verify(...) 函数(ref),但在我看来,它主要与签名一起使用。但是我没有签名,我有一个证书(以 pem 格式获得)和我的密钥(我也有一个 pem 格式的密钥)。将它们处理成内部 mbedtls 数据结构(mbedtls_x509_crtmbedtls_pk_context)不是问题,但我如何验证它们是否匹配?

【问题讨论】:

注意,这个问题不问示例代码,也不是“做我的工作”的问题。这个问题的本质是:如何验证我的mbedtls_pk_context和我的mbedtls_x509_cert匹配 【参考方案1】:

正如thissecurity.SE 回答所说,如果证书中的公钥和私钥文件中的公钥相同,那么验证就足够了。这是因为它是他们唯一共同的共享信息。

因此,我们需要从mbedtls_pk_contentmbedtls_x509_cert中挖掘出公钥并进行比较。

mbedtls 对此任务没有通用 API 调用,但可以通过特定算法的解决方案来完成。步骤如下。假设我们有

mbedtls_x509_cert crt;
mbedtls_pk_context pk;

crt 拥有证书,pk 是我们的公私钥对。

    我们从两者获得密钥对。在椭圆曲线密码的情况下,它由mbedtls_pk_ec(...) 宏完成。在 rsa 的情况下,需要mbedtls_rsa_context(...)

    mbedtls_ecp_keypair* crt_pair = mbedtls_pk_ec(crt->pk);
    mbedtls_ecp_keypair* pk_pair = mbedtls_pk_ec(*pk);
    

注意,虽然crt_pair 现在是一个密钥对,但只有它的公共部分是非零的,因为证书显然没有私钥部分。 mbedtls_pk_ec(...) 在我看来有点像宏,因为它不使用指向结构的指针,而是直接使用结构。

    然后,我们比较密钥对中的公钥:

    mbedtls_mpi *pk_pub_X = &pk_pair->Q.X;
    mbedtls_mpi *pk_pub_Y = &pk_pair->Q.Y;
    mbedtls_mpi *crt_pub_X = &crt_pair->Q.X;
    mbedtls_mpi *crt_pub_Y = &crt_pair->Q.Y;
    

在其他算法 (RSA) 的情况下,这些部分可能会有所不同,但是我们总是需要一组大数字 (mbedtls_mpi),然后比较这些大数字。

    然后,我们使用 mbedtls 大数功能来比较它们:

    bool does_it_differ = mbedtls_mpi_cmp_mpi(pk_pub_X, crt_pub_X) || mbedtls_mpi_cmp_mpi(pk_pub_Y, crt_pub_Y);

注意:验证证书匹配并不足以验证证书的有效性,它只是需要。证书的验证可以通过已经更加愉快和简单的mbedtls_x509_crt_verify(...)函数来完成。

【讨论】:

【参考方案2】:

我知道这是一个较老的问题,但也许 mbedtls_pk_check_pair 是您正在寻找的。将您的私钥/公钥对和证书公钥传递给它。

/**
 * \brief           Check if a public-private pair of keys matches.
 *
 * \param pub       Context holding a public key.
 * \param prv       Context holding a private (and public) key.
 *
 * \return          \c 0 on success (keys were checked and match each other).
 * \return          #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not
 *                  be checked - in that case they may or may not match.
 * \return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid.
 * \return          Another non-zero value if the keys do not match.
 */
int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv );

【讨论】:

以上是关于如何使用 mbedtls 验证证书是不是验证密钥?的主要内容,如果未能解决你的问题,请参考以下文章

具有基于 ssl 证书的身份验证的 m2e

使用 mbedtls 生成的 RSA 签名,无法使用 C# (bouncycastle) 应用程序进行验证

APNS:如果使用 Auth Key,是不是需要 APNS 证书?

Apache 2 中的虚拟主机上是不是可以有多个密钥/证书?

即使在 SpringMVC 中包含密钥库证书后也无法验证服务器

如何在 NodeJs 中使用 .pfx 证书和密码验证 Bearer 令牌?