我正在尝试使用ocspocsp服务器发送C++请求,但是找不到任何准备请求的内容。在文档中,我发现以下功能

long SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp);
long SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len);


如何添加证书并设置请求的现时?

最佳答案

想让您尝试为openssl OCSP命令生成C ++代码:


  openssl ocsp -issuer issuer.pem -cert alice.pem -cert bob.pem -reqout
  八达通


您需要的主要OPENSSL API是:


PEM_read_bio_X509-阅读证书
OCSP_REQUEST_new-生成OCSP请求
OCSP_request_add0_id-向请求添加证书
i2d_OCSP_REQUEST_bio-以DER格式写出请求


使用的API可能会有所不同,具体取决于您希望读入和写出的证书格式。

以简单的C ++代码打开的上述openssl命令的示例是:

template<typename T, typename D>
std::unique_ptr<T, D> make_handle(T* handle, D deleter)
{
    return std::unique_ptr<T, D>{handle, deleter};
}

bool generate_ocsp_request()
{
    // load issuer certificate
    auto file = make_handle(BIO_new_file("issuer.pem", "r"), BIO_free);
    if(!file) return false;
    auto const issuer = make_handle(PEM_read_bio_X509(file.get(), nullptr, nullptr, nullptr), X509_free);
    if(!issuer) return false;

    // setup OCSP request
    auto const request = make_handle(OCSP_REQUEST_new(), OCSP_REQUEST_free);
    if(!request) return false;

    auto const cert_id_md = EVP_sha1();

    // add alice certificate to OCSP request
    file = make_handle(BIO_new_file("alice.pem", "r"), BIO_free);
    if(!file) return false;
    auto cert = PEM_read_bio_X509(file.get(), nullptr, nullptr, nullptr);

    auto id = OCSP_cert_to_id(cert_id_md, cert, issuer.get());
    if (id == nullptr) return false;
    if (!OCSP_request_add0_id(request.get(), id)) return false;

    // add bob certificate to OCSP request
    file = make_handle(BIO_new_file("bob.pem", "r"), BIO_free);
    if(!file) return false;
    cert = PEM_read_bio_X509(file.get(), nullptr, nullptr, nullptr);

    id = OCSP_cert_to_id(cert_id_md, cert, issuer.get());
    if (id == nullptr) return false;
    if (!OCSP_request_add0_id(request.get(), id)) return false;

    // write the request out in DER format
    file = make_handle(BIO_new_file("ocspreq.der", "wb"), BIO_free);
    if(!file) return false;

    // the below doesn't compile in C++ :(
    // return i2d_OCSP_REQUEST_bio(file.get(), request.get()) != 0;

    // go around the macro's that cause the problem in C++ because it will not automatically convert void* to unsigned char* like in C
    return ASN1_i2d_bio(reinterpret_cast<i2d_of_void *>(i2d_OCSP_REQUEST), file.get(), reinterpret_cast<unsigned char*>(request.get())) != 0;
}


更新:

阅读响应有点涉及。

用于处理响应的主要API是:


d2i_OCSP_RESPONSE_bio-以DER格式加载响应
OCSP_response_get1_basic-提取响应信息
OCSP_check_nonce-检查响应是否针对请求(可选)
OCSP_basic_verify-验证响应是否有效(可选)


没有可以提取的“文本”,您需要专门从响应中提取所需的内容。

以下代码基本上是此命令的示例


  openssl ocsp -respin ocspresp.der -reqin ocspreq.der -issuer
  issuer.pem -cert alice.pem -cert bob.pem


bool read_ocsp_response()
{
    // load ocsp request (der format)
    auto file = make_handle(BIO_new_file("ocspreq.der", "rb"), BIO_free);
    if(!file) return false;
    auto const request = make_handle(d2i_OCSP_REQUEST_bio(file.get(), nullptr), OCSP_REQUEST_free);
    if(!request) return false;

    // load ocsp response (der format)
    file = make_handle(BIO_new_file("ocspresp.der", "rb"), BIO_free);
    if(!file) return false;
    auto const response = make_handle(d2i_OCSP_RESPONSE_bio(file.get(), nullptr), OCSP_RESPONSE_free);
    if(!response) return false;
    file.reset();

    // was the server response ok?
    if(OCSP_response_status(response.get()) != OCSP_RESPONSE_STATUS_SUCCESSFUL) return false;

    // verify response
    auto const basic_response = make_handle(OCSP_response_get1_basic(response.get()), OCSP_BASICRESP_free);
    if(!basic_response) return false;

    // check that the response is for the expected request
    auto const nonce_check_result = OCSP_check_nonce(request.get(), basic_response.get());
    if(nonce_check_result <= 0)
    {
        if(nonce_check_result == -1)
        {
            puts("WARNING: no nonce in response");
        }
        else
        {
            return false;
        }
    }

    // verify the response against the issuer certificate
    auto const issuers_certificate_stack = make_handle(sk_X509_new_null(), [](auto handle){ sk_X509_pop_free(handle, X509_free); });
    if(!issuers_certificate_stack) return false;

    file = make_handle(BIO_new_file("issuer.pem", "r"), BIO_free);
    if(!file) return false;

    auto const issuer = PEM_read_bio_X509(file.get(), nullptr, nullptr, nullptr);
    if(!issuer) return false;
    file.reset();

    sk_X509_push(issuers_certificate_stack.get(), issuer);

    // load default certificate store
    auto const store = make_handle(X509_STORE_new(), X509_STORE_free);
    if(!store) return false;
    auto const lookup = X509_STORE_add_lookup(store.get(), X509_LOOKUP_file());
    if(lookup == nullptr) return false;

    if(OCSP_basic_verify(basic_response.get(), issuers_certificate_stack.get(), store.get(), OCSP_TRUSTOTHER) != 1) return false;

    // check that all the certificates have a status ok results
    if(OCSP_resp_count(basic_response.get() == 0) return false;
    for (auto i = 0; i < OCSP_resp_count(basic_response.get()); i++)
    {
        auto const single_response = OCSP_resp_get0(basic_response.get(), i);
        if(single_response == nullptr) return false;

        if(OCSP_single_get0_status(single_response, nullptr, nullptr, nullptr, nullptr) != V_OCSP_CERTSTATUS_GOOD) return false;
    }

    return true;
}


如果要查找诸如alice.pem之类的特定证书的状态,则可以使用从OCSP_cert_to_id返回的OCSP_CERTID(请参见生成请求),并将其与OCSP_resp_find_status API结合使用以查找该证书的状态,而不是枚举所有像我在上面的代码中所做的那样的证书。

如果您要定期查询证书,则可能希望使用从状态返回的下一个更新时间戳记来安排下一次检查呼叫的时间。

关于c++ - 如何在C++中使用openssl创建ocsp请求?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56253312/

10-11 22:35
查看更多