SSL_CTX_use_PrivateKey_file()失败

时间:2013-09-26 13:26:55

标签: c++ ssl openssl

我正在Windows上编写一个客户端应用程序,它建立与服务器的SSL连接,服务器请求客户端证书进行身份验证。服务器提供了一个.pfx文件,然后我使用openssl命令行工具来获取证书和私钥,如下所示:

openssl pkcs12 -in filename.pfx -clcerts -nokeys -out cert.pem
openssl pkcs12 -in filename.pfx -nocerts -out key.pem

之后,我尝试使用openssl中的函数加载证书和私钥,如下所示,但SSL_CTX_use_PrivateKey_file()总是失败,错误消息为“error:0906D06C:PEM routines:PEM_read_bio:no start line”,我无法理解为什么,谁能给我一些启示? 这是代码。

#include "openssl/ssl.h"
#include "openssl/err.h"
#include <stdio.h>
#include <string>

int InitClientCtx()
{
    OpenSSL_add_ssl_algorithms();

    SSL_CTX* m_pClientCtx;
    m_pClientCtx = SSL_CTX_new(SSLv23_method());

    if(!m_pClientCtx)
    {
        return -1;
    }

    ::SSL_CTX_set_options(m_pClientCtx, SSL_OP_ALL);  //for well-known bugs

    int nRet = 0;

    std::string sCertFilePath = "C:\\cert.pem";

    nRet = SSL_CTX_use_certificate_chain_file(m_pClientCtx, sCertFilePath.c_str());

    std::string sKeyPassWord = "123456";

    SSL_CTX_set_default_passwd_cb_userdata(m_pClientCtx, (void*)(sKeyPassWord.c_str()));

    std::string sKeyFilePath = "C:\\key.pem";

    // this method returned 0, which means it failed.
    nRet = SSL_CTX_use_PrivateKey_file(m_pClientCtx, sKeyFilePath.c_str(), SSL_FILETYPE_PEM);

    SSL_load_error_strings();
    unsigned long n = ERR_get_error();
    char buf[1024];
    printf("%s\n", ERR_error_string(n, buf));

    nRet = SSL_CTX_check_private_key(m_pClientCtx);
    if (nRet <= 0)
    {
        return -1;
    }

    /*std::string sCACertFilePath;

    nRet = SSL_CTX_load_verify_locations(m_pClientCtx, sCACertFilePath.c_str(), NULL);*/

    return 0;
}

int main()
{
    InitClientCtx();
    return 0;
};

5 个答案:

答案 0 :(得分:11)

在我的情况下,错误是因为PEM文件不包含密钥和证书。

确保您的文件包含以下两个部分:

-----BEGIN PRIVATE KEY----- jhajk838383jks.....
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE----- yoe55wjcxnshre.....
-----END CERTIFICATE KEY-----

我链接了我在Apache配置中已有的.key.crt个文件来制作.pem文件。

'无起始线'错误肯定会产生误导,因为您可以在PEM文件中有一个非常好的“BEGIN”行,但仍然会收到错误。

答案 1 :(得分:4)

错误error:0906D06C:PEM routines:PEM_read_bio:no start line是因为在cert.pem和key.pem中都不要以-----BEGIN CERTIFICATE----------BEGIN ENCRYPTED PRIVATE KEY-----开头。

如果你在文本编辑器中打开cert.pem和key.pem并在BEGIN标记之前抽出任何内容,那么你应该很好。

使用证书签名请求创建证书和密钥对时,您将无法获得此附加信息。

答案 2 :(得分:4)

我自己解决了这个问题。我使用OpenSSL for Windows生成了key.pem,当CMD提示我输入密码时,我只输入了一个Enter,因为我不需要密码,但key.pem无效(两者都没有{ {1}}也不是BEGIN标记。当我在Linux中生成私钥时,终端提示我必须输入一个密码短语而且我这样做。然后我使用此命令删除密钥密码:

END

之后,我在文本编辑器中打开key.pem,它从openssl rsa -in key.pem -out newkey.pem开始,最后以-----BEGIN RSA PRIVATE KEY-----结束。并且SSL_CTX_use_PrivateKey_file()工作正常!

答案 3 :(得分:0)

在openssl目录demo / openssl下有一个客户端示例。

变化:

meth = SSLv2_client_method();

在你的情况下:

meth = SSLv23_client_method();

试试这个例子,看看它失败了。

您确定密码是123456吗?

答案 4 :(得分:0)

在安装SSL证书时,我在NGINX中遇到了相同的问题,我使用以下步骤解决了问题:

  • 转到具有证书和pem文件的文件夹
  • 打开您的ca-bundle.crt文件并复制所有内容,sudo nano your fileName全选并复制。文件看起来像
  

-----开始证书----- MIIE0DCCA7igAwIBAgIBBzzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx   EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT   ..........

     

-----结束证书-----

     

----- BEGIN证书----- MIIEfTCCA2WgAwIBAgIDG + cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVT   MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKEdv   ..........

     

-----结束证书-----

     

----- BEGIN证书----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh   MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE   ..........   -----结束证书-----

  • 使用sudo nano your fileName.pem
  • 打开您的pem文件
  • 您将看到类似的代码
  

----- BEGIN证书----- MIIGLzCCBRegAwIBAgIIWI4ndTQi3MwwDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV   MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB / wQEAwIF   oDA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkaWcy

     

-----结束证书-----

  • -----END CERTIFICATE-----之后粘贴从ca-bundle.crt文件复制的所有代码并将其保存
  • 使用以下命令Nginx重新启动sudo service nginx restart服务器

以上步骤对我的Nginx和SSL配置都有效