2012-02-29 39 views
25

Một số mã C++ đang hoạt động mà tôi đang chuyển từ Linux sang Windows không hoạt động trên cửa sổ vì SSL_get_verify_result() đang trả về X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY.Có thể OpenSSL trên Windows sử dụng kho chứng chỉ hệ thống không?

Mã đang sử dụng SSL_CTX_set_default_verify_paths() trên Linux để yêu cầu SSL chỉ xem trong các vị trí mặc định chuẩn cho kho chứng chỉ.

Có thể sử dụng OpenSSL để sử dụng kho chứng chỉ hệ thống không?

Trả lời

34

Tôi đã thực hiện nó trước đó. Hy vọng điều này sẽ hữu ích, nếu đây chính xác là những gì bạn đang tìm kiếm.

  1. Tải chứng chỉ của bạn (trong cấu trúc PCCERT_CONTEXT) từ Windows Cert store bằng API Crypto.
  2. Nhận nội dung được mã hóa của nó ở định dạng nhị phân. [PCCERT_CONTEXT->pbCertEncoded].
  3. Phân tích cú pháp bộ đệm nhị phân này thành chứng chỉ X509 Đối tượng sử dụng phương pháp d2i_X509() của OpenSSL.
  4. Xử lý cửa hàng tin cậy của OpenSSL bằng phương pháp SSL_CTX_get_cert_store().
  5. Tải chứng chỉ X509 được phân tích ở trên vào cửa hàng tin cậy này bằng phương pháp X509_STORE_add_cert().
  6. Bạn đã hoàn tất!
+0

Cảm ơn thông tin. Tôi nên thêm một vài lưu ý về điều này: 1. cửa sổ enum của cửa hàng với "ROOT" (không phải "CA"). 2. Bạn cần phải thêm cert trước khi kết nối/bắt tay và xác minh sau khi kết nối/bắt tay, nếu không xác minh sẽ không thành công. –

2

No. Không ra khỏi hộp.

Không có không thể ngoài hộp. Nó sẽ yêu cầu lập trình bổ sung. Với OpenSSL bạn có hai (out of the box) lựa chọn:

    cửa hàng cert riêng
  1. Sử dụng OpenSSL của (nó là một hệ thống các thư mục được tạo ra bởi kịch bản perl cung cấp với OpenSSL)
  2. Chỉ sử dụng một tập tin chuỗi chứng chỉ được tạo ra bởi bạn (nó là một tập tin văn bản với tất cả các chứng chỉ mã hóa PEM trong một chuỗi tin cậy). Tạo một tệp như vậy thật dễ dàng (chỉ cần thêm nó)
+0

nó có thể là có thể tạo ra một tập tin PEM trong bộ nhớ từ các cửa sổ tệp pkcs? Sau đó tải nó? Tôi tìm thấy: http://marc.info/?l=openssl-users&m=119583966725315 mô tả việc tạo tệp PEM từ gói pkcs ... Và http://stackoverflow.com/questions/5052563/c-openssl-use -root-ca-từ-đệm-thay vì-file-ssl-ctx-load-xác minh-locat mô tả một cơ chế tải một tập tin PEM từ một bộ đệm ...? – dicroce

+0

Vâng, điều đó chắc chắn là có thể. – sirgeorge

+0

Yuck ... Vì lý do nào đó, nó không giống như tập tin của tôi (được thực hiện với mã từ trang đó) ... Tôi đã có thể nghĩ ai đó trước khi tôi đã làm điều này? – dicroce

2

Có thể sử dụng OpenSSL cho các hoạt động như bình thường, và sử dụng CryptoAPI chỉ cho quá trình xác minh chứng chỉ. Tôi thấy một số chủ đề xung quanh đây về chủ đề này, và hầu hết là tiptoed xung quanh/thông qua.

Với CryptoAPI bạn phải:

  • decode PEM để DER với CryptStringToBinary(),
  • tạo ra một đối tượng CERT_CONTEXT với CertCreateCertificateContext()
  • và kiểm tra Giấy chứng nhận theo hình thức này bằng cách nổi tiếng/thủ tục dạng văn. (Ví dụ here at ETutorials.)

    Đối với bước cuối cùng để làm việc, bạn cũng cần phải khởi tạo HCERTSTORE cho một trong MY, ROOT, CA cửa hàng hệ thống, hoặc lặp qua chúng ... tùy thuộc vào những gì bạn muốn.

10

Đối với những người bạn vẫn phải vật lộn với điều này như tôi có được, đây là một mẫu mã để giúp bạn bắt đầu:

#include <stdio.h> 
#include <windows.h> 
#include <wincrypt.h> 
#include <cryptuiapi.h> 
#include <iostream> 
#include <tchar.h> 

#include "openssl\x509.h" 

#pragma comment (lib, "crypt32.lib") 
#pragma comment (lib, "cryptui.lib") 

#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING) 

int main(void) 
{ 
    HCERTSTORE hStore; 
    PCCERT_CONTEXT pContext = NULL; 
    X509 *x509; 
    X509_STORE *store = X509_STORE_new(); 

    hStore = CertOpenSystemStore(NULL, L"ROOT"); 

    if (!hStore) 
     return 1; 

    while (pContext = CertEnumCertificatesInStore(hStore, pContext)) 
    { 
     //uncomment the line below if you want to see the certificates as pop ups 
     //CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pContext, NULL, NULL, 0, NULL); 

     x509 = NULL; 
     x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded); 
     if (x509) 
     { 
      int i = X509_STORE_add_cert(store, x509); 

      if (i == 1) 
       std::cout << "certificate added" << std::endl; 

      X509_free(x509); 
     } 
    } 

CertFreeCertificateContext(pContext); 
CertCloseStore(hStore, 0); 
system("pause"); 
return 0; 

} 
+1

Việc sử dụng 'd2i_X509' của bạn không hợp lệ vì' d2i_X509' tăng '* in' đối số (bạn sử dụng phép đúc để tránh lỗi trình biên dịch). Bạn phải sử dụng biến tạm thời để tránh các vấn đề về bộ nhớ, như sau: 'const unsigned char * encoded_cert = win_cert_context-> pbCertEncoded; d2i_X509 (nullptr, & encoded_cert, ... ' – herolover

Các vấn đề liên quan