验证SSL客户端的真实性因SSL3_GET_CLIENT_CERTIFICATE而失败:未返回证书

时间:2015-01-09 23:58:56

标签: c++ ssl openssl

我正在使用OpenSSL API for C ++。通信是在嵌入式Linux设备(SSL服务器)和Windows软件(SSL客户端)之间进行的。

我想确保目标服务器和客户端只能相互通信。我已为服务器生成了根密钥,以及以下内容:

  • 根CA(由客户端用于授权服务器)
  • 服务器证书
  • 服务器私钥

只有在握手期间授权服务器证书时,我的SSL连接才能正常工作。

但是,我还要验证客户端的真实性,因此我为客户端生成了另一个根密钥,以及以下内容:

  • 根CA(由服务器用于授权客户端)
  • 客户证书
  • 客户私钥

使用下面的代码,由于以下错误,我的服务器无法接受客户端连接:

  

724428760:错误:140890B2:SSL例程:SSL3_GET_CLIENT_CERTIFICATE:未返回证书:s3_srvr.c:3291:

以下是与SSL证书相关的服务器代码:

bool SSLServer::loadCertificates(const char * sCertFile,
                                 const char * sKeyFile,
                                 const char * sCAFile)
{
    // set server certificate
    if (SSL_CTX_use_certificate_file(_pCTX, sCertFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // set the private key
    if (SSL_CTX_use_PrivateKey_file(_pCTX, sKeyFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // verify private key
    if (!SSL_CTX_check_private_key(_pCTX))
    {
        qWarning() << "Private key does not match the public certificate.";
        return false;
    }

    SSL_CTX_set_verify(_pCTX, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);

    // load the trusted client CA certificate into context
    if (SSL_CTX_load_verify_locations(_pCTX, sCAFile, NULL) != 1)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // allow this CA to be sent to the client during handshake
    STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(sCAFile);
    if (NULL == list)
    {
        qWarning() << "Failed to load SSL client CA file.";
        return false;
    }
    SSL_CTX_set_client_CA_list(_pCTX, list);
    SSL_CTX_set_verify_depth(_pCTX, 1);

    return true;
}

这是我的客户代码:

bool SSLClient::LoadCertificates(const char * sCAFile,
                                 const char * sClientCertFile,
                                 const char * sClientKeyFile)
{
    ASSERT(NULL != sCAFile && NULL != sClientCertFile && NULL != sClientKeyFile);

    // load RSA CA certificate into context to let client verify server's authenticity
    // (will be used with server certificate and private key)
    if (!SSL_CTX_load_verify_locations(_pCTX, sCAFile, NULL))
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // load client certificate into context to let server verify client's authenticity
    // (will be used with server's RSA CA certificate)
    if (SSL_CTX_use_certificate_file(_pCTX, sClientCertFile, SSL_FILETYPE_PEM) != 1)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // load client certificate private key into context
    if (SSL_CTX_use_PrivateKey_file(_pCTX, sClientKeyFile, SSL_FILETYPE_PEM) != 1)
    {
        ERR_print_errors_fp(stderr);
        return false;
    }

    // verify that client cert and private key match
    if (!SSL_CTX_check_private_key(_pCTX))
    {
        OutputDebugString("Private key does not match the certificate public key\n");
        return false;
    }

    // require server certificate verification
    SSL_CTX_set_verify(_pCTX, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
    SSL_CTX_set_verify_depth(_pCTX, 1);

    return true;
}

同样,如果我删除与验证客户端证书相关的代码,它的工作完全正常。我错过了什么,或做了一些完全错误的事情?

2 个答案:

答案 0 :(得分:3)

代码的工作副本以及证书:http://files.webfile.ru/567c28b8973091cbdad036f3e43e989b

如果生成证书只是按“进入”状态,那么您的问题就可以重现了。回答问题。你已经签了自己的签名&#39;没有任何意图的证书。与OpenSSL - error 18 at 0 depth lookup:self signed certificate完全相同的问题 当窥探ssl问题时,你应该使用wireshark而不是ssldump。

答案 1 :(得分:3)

  

724428760:错误:140890B2:SSL例程:SSL3_GET_CLIENT_CERTIFICATE:未返回证书:s3_srvr.c:3291:

错误消息具有误导性。虽然它说客户端没有返回任何证书,但如果客户端发送服务器无法验证的证书,也会发生。请确保客户端发送的证书实际上可以针对服务器sCAFile进行验证。