簡體   English   中英

mbedtls 無法解析有效的 x509 證書

[英]mbedtls cannot parse valid x509 certificate

我有以下證書:

-----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 使用以下代碼解析此證書:

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 片段:

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;
}

當我運行程序時,我得到以下 output:

491231235959Z010�Uzon Web 服務 O=Amazon.com Inc. L=Seattle ST=Washington C=US0 *�H�� AWS IoT Certificate0�"0

我一直在尋找可能有什么問題的答案,我發現一個帖子說 mbedtls 默認配置為使用 RSA 1024,所以如果你的密鑰是 2048(它在我的里面),那么 mbedtls 解析時會出錯. 我修改了配置文件以使用 2048 並重建了庫,但仍然出現錯誤。

有任何想法嗎? 我覺得我真的很接近,因為 mbedtls_x509_crt_parse 幾乎全程執行。 我很確定我根據我看到的代碼示例正確使用了該庫。

謝謝!

最初,使用以下代碼解析 PEM 格式證書字符串:

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的最后一個參數應該是輸入的長度,包括 null 終止符 將最后一個參數更改為1 + strlen(certificate_string)解決了這個問題。


成功解析后,使用以下命令打印頒發者字符串:

printf("The issuer is: %s\n", certificate.issuer.val.p);

這產生了一些垃圾 output 看起來好像發行者字符串的初始部分已被覆蓋,但實際上是由於發行者字符串中缺少 null 終止符。 發行者字符串之后的數據字節包括 ASCII CR 字符,導致終端 cursor position 移動到行首並打印在 Z78E6221F6393D1356681DB398F14CED6 的初始部分。 (例如,通過| od -c管道 output 可以看到 CR 字符,因此它們顯示為\r 。)

將 output 管道通過| od -c | od -c產生:

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調用更改為以下內容:

printf("The issuer is: %.*s\n", (int)certificate.issuer.val.len, certificate.issuer.val.p);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM