我正在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;
};
答案 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中遇到了相同的问题,我使用以下步骤解决了问题:
ca-bundle.crt
文件并复制所有内容,sudo nano your fileName
全选并复制。文件看起来像-----开始证书----- MIIE0DCCA7igAwIBAgIBBzzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT ..........
-----结束证书-----
----- BEGIN证书----- MIIEfTCCA2WgAwIBAgIDG + cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVT MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKEdv ..........
-----结束证书-----
----- BEGIN证书----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE .......... -----结束证书-----
sudo nano your fileName.pem
----- BEGIN证书----- MIIGLzCCBRegAwIBAgIIWI4ndTQi3MwwDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB / wQEAwIF oDA4BgNVHR8EMTAvMC2gK6AphidodHRwOi8vY3JsLmdvZGFkZHkuY29tL2dkaWcy
-----结束证书-----
-----END CERTIFICATE-----
之后粘贴从ca-bundle.crt
文件复制的所有代码并将其保存Nginx
重新启动sudo service nginx restart
服务器以上步骤对我的Nginx和SSL配置都有效