11

我正在 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;
};
4

5 回答 5

14

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

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

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

我将我的 Apache 配置中已有的文件连接起来以创建一个.key文件。.crt.pem

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

于 2013-11-08T14:17:04.117 回答
5

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

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

当您使用Certificate Signing Request创建证书和密钥对时,您不会获得此附加信息。

于 2013-09-26T17:43:22.943 回答
4

我自己解决了这个问题。我使用适用于 Windows 的 OpenSSL 生成了 key.pem,当 CMD 提示我输入密码时,我只输入了一个 Enter,因为我不需要密码,但 key.pem 无效(也BEGIN没有END标记)。当我在 Linux 中生成私钥时,终端提示我必须输入密码,然后我就输入了。然后我使用以下命令删除密钥密码:

openssl rsa -in key.pem -out newkey.pem

之后,我在文本编辑器中打开 key.pem,它以 .pem 开头-----BEGIN RSA PRIVATE KEY-----和结尾-----END RSA PRIVATE KEY-----。SSL_CTX_use_PrivateKey_file() 工作正常!

于 2013-09-27T07:47:03.867 回答
0

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

改变:

meth = SSLv2_client_method();

在你的情况下:

meth = SSLv23_client_method();

试试这个例子,看看它在哪里失败。

您确定密钥密码是 123456 吗?

于 2013-09-26T17:44:57.440 回答
0

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

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

-----开始证书----- MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT ....

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

-----开始证书----- MIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTALVT MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKedv ....

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

-----开始证书----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE .......... -----结束证书-----

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

-----BEGIN CERTIFICATE----- MIIGLzCCBRegAwIBAgIIWI4ndTQi3MwwDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIF oDA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkaWcy

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

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

上述步骤在我的 Nginx 和 SSL 配置中对我有用

于 2019-08-22T06:35:51.497 回答