2016-10-23 2 views
1

У меня есть код, чтобы получить все корневые сертификаты в хранилище сертификатов Windows, для текущего пользователя:Boost.Asio SSL контекст load_verify_paths не загружается сертификат (ы)

#include <windows.h> 
#include <Wincrypt.h> 

inline std::vector<std::string> system_root_certificates() 
{ 
    std::vector<std::string> certs; 

    HCERTSTORE hStore; 
    PCCERT_CONTEXT pCertContext = NULL; 

    if (!(hStore = ::CertOpenStore(
       CERT_STORE_PROV_SYSTEM_A, 
       0, 
       NULL, 
       CERT_SYSTEM_STORE_CURRENT_USER, 
       "Root"))) 
     return certs; 

    do 
    { 
     if (pCertContext = ::CertFindCertificateInStore(
        hStore, 
        X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 
        0, 
        CERT_FIND_ANY, 
        NULL, 
        pCertContext)) 
     { 
      certs.push_back("-----BEGIN CERTIFICATE-----\n" + 
          Base64::encode_copy(std::string((char *) pCertContext->pbCertEncoded, (size_t) pCertContext->cbCertEncoded), true) + 
          "\n-----END CERTIFICATE-----\n"); 
     } 
    } while (pCertContext); 

    if (!pCertContext) 
     ::CertFreeCertificateContext(pCertContext); 

    ::CertCloseStore(
       hStore, 
       CERT_CLOSE_STORE_FORCE_FLAG); 

    return certs; 
} 

Затем я пишу сертификаты в файл:

... 
for (size_t i = 0; i < certs.size(); ++i) 
    certFile << certs[i]; 
... 

Я проверял, что файл написан правильно.

Образец первых двух сертификатов из файла:

-----BEGIN CERTIFICATE----- 
MIIFMIIDoAMCAgIQrRahoKWtc1j0Ey5lDQYJhkiGDQEBBQAwMRMwBgoJJomTLGQBFgNjbTEZFwYK 
kiaJ8ixkGRYJaWNyc29mMS0wBgNVAxMkaWNyc29mIFJvdCBDcnRpaWNhZSBBdGhvaXR5HhcNMTA1 
OTIzOTIyFw0yMDUwMjMyMTNaXzETEQYKkiaJ8ixkGRYDb20xMBcGCZImk/IsARkWbWljb3NvdDEt 
KwYDBAMTTWljb3NvdCBSb3QgZXJ0ZmljdGUgdXRocml0MIICMA0GKoZI9w0BAQUAggIPMIICAoIC 
APNdgGfUp6kMkCDQCDx1zbcHnInazsNgkWhalHEpdnzCyCV2Dlj6NDbmr/eA6VgLk+Wd43ci9zRk 
IpEd4QmQFP78WBnhtweSrohZ2J8HA1j8KW0y0qjL/OELMk/muK1PXG8TmduVdduot5SRd1v1DI9q 
fRRwfW2v9dpwR7e/L2znt+ERrHmRfMXW5OF+w37l0jwANoLe4W3zbvifyctSc5g2i6FrlZeb3sJN 
/waWJQbIrOTuM5UxyDUINMp51bW+MllAwKVOTT3bBzPkv+8/ZNhCNVf9RXwkTZ7WdBGXkM5odJJv 
S2+w48c2oND8wFr5YbkwcZYKsJHAle8QKGrjH7HkAz93BMcgSQ8diKTXfoitLexFxFEEKvzsnpoR 
W97OiObi/ayVKEDbBJDfMznZRaUjBqVVMbsGYA5BfR8ul8sRFdUklO8Vif1L+jJb0TMAWWJwMuou 
QC173SFnMJmPqiOo0bBumzbEQHScWGXBHnpbyI+7JnzUQOW2bKqGAL/ONQIDAAGjME8wBgNVDwQE 
AgHGDwYDHRMB/wQFAwEBMB0GVR0OFgQUrIJgVieXJRP84QpTWeSkEAYJBgEEgjcVBAMCADANCSqG 
hvcNAQUFA4ICAMURAzpgXVIRj7K7yLIFtLeoIJ1cA7Yc+gYTtshjmkdvV9JVBLEm1qlQoLzSbszD 
rN8ZeKxZrGY0xBs+OEwzMBINJv5RAP+vToQNH+RtLk6FjWwzVNJkv1Cvejmg7WMD/BMGFjbUO5Ub 
YjrlF9QFkponW6q9u77jiWBxVrOl0G0OfpUDaD3yY7hrtugw4cqU96KqmTCyp8JRKCABJytLt50R 
cL6ygrwMaNCNJIeqKHKdX1mQ9d6TOmJaOeKIHbkGwYlr12nDEjaEyaDaL2l45Xra1wzAvWMXORM4 
Nlt7hVZqZGLB4qq/ZqKUEpxmEGvyMJItKfA9FENo8Zwpy844JW18834kJAMIR+yll/UYz7vVdpbv 
zttWlaBCl1jhMSLTWeY+IgDqhLYl2fMIaMBkHXzsk6Jibi7YWI/ESSbdKTWHMHFwFDxpiRJ9LqP+ 
f56CUgorQyvZiJ/I+4mNoYV1fmyecxNkaaUvypZt+ARNkj1uFCHJ4MP9a51K0aGdQ3c/2g== 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
MIICMIICoAMCAgIBMA0GKoZI9w0BBAUAgYsxMAkGVQQGAlpBFTATA1UEEwxXc3RlbiBDcGUxMBIG 
VQQHC0R1YmFuaWxsMQ8wBgNVChMGaGF3ZTEdGwYDBAsTVGhhdGUgZXJ0ZmljdGlvMR8wBgNVAxMW 
aGF3ZSBUbWVzYW1wbmcgQTAeDTk3MTAxMDAwMFoXMjAxMzEyNTk1WjCBMQswBgNVBhMCQTEVEwYD 
BAgTV2VzZXJuQ2FwMRQwBgNVBxMLdXJibnZpbGUxMA0GVQQKBlRod3RlHTAbA1UEExRUYXd0IENl 
dGlmY2F0b24xMB0GVQQDFlRod3RlVGltc3RhcGluIENBgZ8wBgkqSIb3AQEBAAOBADCBAoGB1itY 
YUWG6jR7nO2wLhgO4F+o07TJfFlODnNUwX/2Luk6JBU8RwRjnsSUWt9M89lDPBB6JduQ8FHn1kEA 
nyjfvpS7thTjhdep4EyksCsa8vg7PkWskgC0QZj77fq3iviIAgMBAaMTETAPA1UdAQH/BTADAf8w 
BgkqSIb3AQEEAAOBAGfbwuaHQIOGNX0fmsMMIKi6BImG9RAIv8uiitBNPvTXacZesJRvuefeiLZ7 
4yflw/A1y7UnM3ncpgCe+vzNlEIW0xxov1zdqXsQMnRUMYuFhJG3ATAUryjKsVAZCayJ0w== 
-----END CERTIFICATE----- 

Я затем закрыть файл, и вызовите

sslContext->load_verify_file(filename); 

load_verify_file функция завершается с ошибкой too long. Функция также терпит неудачу, если я пишу только один сертификат в файл с тем же кодом ошибки.

openssl verify <cert_filename> возвращает следующий (полный) вывод:

unable to load certificate 
2404:error:0D07209B:asn1 encoding routines:ASN1_get_object:too long:.\crypto\asn1\asn1_lib.c:142: 
2404:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object header:.\crypto\asn1\tasn_dec.c:1303: 
2404:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:.\crypto\asn1\tasn_dec.c:380:Type=X509 
2404:error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib:.\crypto\pem\pem_oth.c:83: 

ли ошибка вызвана тем форматом, который я пишу в файл в? Что еще может вызвать эту ошибку?

+2

Добавить разрывы строк в кодировку Base64. Я считаю, что OpenSSL отклоняет строку больше 72 или 80. Также убедитесь, что первая новая строка в '' \ n ----- END CERTIFICATE ----- \ n "' не добавляет дополнительную новую строку. – jww

+0

Можете ли вы загрузить/проверить, используя эту коллекцию сертификатов, используя клиент командной строки openssl? – sehe

+0

@jww У меня есть разрывы строк каждые 76 символов, стандарт. Кодер Base64 также не добавляет дополнительную строку новой строки. – owacoder

ответ

2

Использовать base64 -d для декодирования сертификата, он отображает двоичный формат форматирования, но длина неправильная, например. первый формат сертификата der указывает 0x0530 + 4 байтов. Файл der должен иметь 1332 байт, но на самом деле это всего лишь 1078 байт.

Значит, это означает, что сертификат поврежден.

Google В этой теме обнаружено, что CryptBinaryToString() - лучший вариант для преобразования pbCertEncoded вместо прямого вызова функции Base64 для получения строки.

Смежные вопросы