首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >mbedtls无法解析有效的x509证书。

mbedtls无法解析有效的x509证书。
EN

Stack Overflow用户
提问于 2022-01-11 16:21:32
回答 1查看 1.2K关注 0票数 0

本人持有下列证书:

代码语言:javascript
复制
-----BEGIN CERTIFICATE-----
MIIDWjCCAkKgAwIBAgIVAJ3wzBnLSnQvYi31rNVQRAXDUO/zMA0GCSqGSIb3DQEB
CwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t
IEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0yMDA3MjgxMTMz
MTJaFw00OTEyMzEyMzU5NTlaMB4xHDAaBgNVBAMME0FXUyBJb1QgQ2VydGlmaWNh
dGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDHc2tmezGoekLjkQlb
+YOBKFyPswYR+GLq/JRVbFX2k4OrHF5js4GTfbHm1oQ733KbcnIugdejtQnRhtnr
1HRk3pqedVhRKGRo2DFDYyuX3K1UR6xna1poJF+6WNy6vXGxIQYKi7SNS5LtzkRT
1FCziOLBaxfcCRNgR1NBHjlcFsUWyL4evMok6h/wU7HA3/dfKEisyLdh3sMy7Yox
Im/ldvyX+9pH7Hj0TrGGTd5f8GtX8npNuSKdkntuag95r+vAaAPp6bQVyPWm8T/G
SUN8N7Nvc9DOcJ8ZhvB/Ubq+Fa/eoUnr3SgXInufLHhrfxJW7dyrBTlw/1kdXgYw
YiKnAgMBAAGjYDBeMB8GA1UdIwQYMBaAFP4UzdqnzQ4l89+D7UhXC5MKWnOJMB0G
A1UdDgQWBBSn95OHFqTn3DrE3anpNq5RoOsT+DAMBgNVHRMBAf8EAjAAMA4GA1Ud
DwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEA2Hvrxy2N0xt3I/w/7JIyoTH4
ixUKMaD1QXe+g6LrsQSCVVsaq0L468OpyydVzQLQONXvDDRv3rqIEel1hPAJNG0y
dp3g+WC1dPl7E44btM+59gBf1369lFwV6FbJMwCltVBUJ4hFAjt3QTkWRHq6DlFQ
wa896aSr5UUiVNAJjf/hLVjERlVG4wDjPN7YifQssRqlNcYDgok3UhVsBfKIGnct
WFbisX+0ONMyNnE1Qq6bX5g4sLN7VlwFhADiz1Xp2rUtLECR1NSPutYibWyvJJ8d
htYYV1a0FSkg7JKyvOIJ8IYKEPsKE+UYo1Z8DwkmHHcap+h0OMWAnKQgRXn6QQ==
-----END CERTIFICATE-----

我把它输入了几个证书读取站点,它们都能够解析和显示它的内容。

我尝试使用mbedtls来使用以下代码解析此证书:

代码语言:javascript
复制
mbedtls_x509_crt certificate;
mbedtls_x509_crt_init(&certificate);
        
char certificate_string[] = "-----BEGIN CERTIFICATE--..."
            
int result_code = mbedtls_x509_crt_parse(&certificate, (unsigned char*)certificate_string, strlen(certificate_string));
        
if(result_code != 0) {
    char err_str[256];
    mbedtls_strerror(result_code, err_str, 256);
    printf("Could not read the certificate. Error: %s\n", err_str);
    return -1;
}

然后,我将检查result_code中的0,如果不是,则打印错误消息。每当我试图解析此证书时,我都会收到以下错误消息:“无法读取证书。错误: X509 - CRT/CRL/CSR格式无效,例如预期的不同类型。”

我试着查看mbedtls_x509_crt_parse代码,看看是什么导致了这条消息,然后我修改了代码,转而使用了以下mbedtls_x509_crt_parse片段:

代码语言:javascript
复制
mbedtls_pem_context pem;
size_t use_len;
mbedtls_pem_init(&pem);

// If we get there, we know the string is null-terminated 
int ret = mbedtls_pem_read_buffer(&pem, 
                                "-----BEGIN CERTIFICATE-----", 
                                "-----END CERTIFICATE-----",
                                (unsigned char *)certificate_string, 
                                NULL, 
                                0, 
                                &use_len);

if(ret != 0) {
    printf("we could not pem read the string\n");
    return -1;
}
else {
    printf("We pem read the certificate\n");
}

ret = mbedtls_x509_crt_parse_der(&certificate, pem.buf, pem.buflen);

if(ret != 0) {
    printf("crt parse der has failed\n");
}
else {
    printf("The issuer is: %s\n", certificate.issuer.val.p);
    return 0;
}

当我运行程序时,我得到以下输出:

491231235959Z010 O=Amazon.com Inc. L=Seattle ST=Washington C=US0 *�H��AWS IoT Certificate0 0�“0�

我一直在寻找可能出错的答案,我发现一个帖子说mbedtls默认配置为使用RSA 1024,所以如果您的密钥是2048 (它在我的中),那么mbedtls在解析时就会出错。我修改了配置文件以使用2048,并重新构建了库,但仍然会出现错误。

有什么想法吗?我觉得我真的很亲近,因为mbedtls_x509_crt_parse几乎一直在执行。我非常肯定,基于我看到的代码示例,我正确地使用了这个库。

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-11 18:29:00

最初,PEM格式证书字符串被解析为以下代码:

代码语言:javascript
复制
mbedtls_x509_crt certificate;
mbedtls_x509_crt_init(&certificate);
        
char certificate_string[] = "-----BEGIN CERTIFICATE--..."; // actually much longer
            
int result_code = mbedtls_x509_crt_parse(&certificate, (unsigned char*)certificate_string, strlen(certificate_string));

这导致解析错误,因为对于PEM格式输入,调用mbedtls_x509_crt certificate的最后一个参数应该是输入的长度,包括空终止符。将最后参数更改为1 + strlen(certificate_string)解决了这个问题。

成功解析后,将使用以下方法打印颁发者字符串:

代码语言:javascript
复制
printf("The issuer is: %s\n", certificate.issuer.val.p);

这产生了一些垃圾输出,看起来好像发行者字符串的初始部分被覆盖了,但实际上是由于发行者字符串中缺少一个空终止符。发出者字符串后的数据字节包括ASCII CR字符,导致终端光标位置移动到行的开头,并在输出的初始部分进行打印。(例如,CR字符可以通过| od -c管道显示输出,并将它们显示为\r。)

通过| od -c输出管道产生:

代码语言:javascript
复制
0000000   T   h   e       i   s   s   u   e   r       i   s   :       A
0000020   m   a   z   o   n       W   e   b       S   e   r   v   i   c
0000040   e   s       O   =   A   m   a   z   o   n   .   c   o   m
0000060   I   n   c   .       L   =   S   e   a   t   t   l   e       S
0000100   T   =   W   a   s   h   i   n   g   t   o   n       C   =   U
0000120   S   0 036 027  \r   2   0   0   7   2   8   1   1   3   3   1
0000140   2   Z 027  \r   4   9   1   2   3   1   2   3   5   9   5   9
0000160   Z   0 036   1 034   0 032 006 003   U 004 003  \f 023   A   W
0000200   S       I   o   T       C   e   r   t   i   f   i   c   a   t
0000220   e   0 202 001   "   0  \r 006  \t   * 206   H 206 367  \r 001
0000240 001 001 005  \n
0000244

它将不可打印的字节显示为3位八进制代码或C反斜杠转义代码,这取决于字节值。

若要打印不带垃圾信息的发行者字符串,请将printf调用更改为:

代码语言:javascript
复制
printf("The issuer is: %.*s\n", (int)certificate.issuer.val.len, certificate.issuer.val.p);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70670070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档