2013-09-26 182 views
5

我正在寫建立一個SSL連接到服務器上的Windows客戶端應用程序和服務器進行身份驗證請求客戶端證書。服務器提供我一個.pfx文件,然後我使用OpenSSL的命令行工具來獲得證書和這樣的私鑰:SSL_CTX_use_PrivateKey_file()失敗

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; 
}; 

回答

3

我自己解決了這個問題。我生成使用OpenSSL for Windows中,當CMD提示我輸入密碼短語,我剛纔輸入的輸入,因爲我不需要通行短語的key.pem,但key.pem是無效的(既不BEGIN也不END標記)。當我在Linux中生成私鑰時,終端會提示我必須輸入密碼短語,然後才能輸入密碼。然後我用這個命令刪除密鑰密碼短語:

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

在那之後,我在一個文本編輯器打開key.pem,它開始與-----BEGIN RSA PRIVATE KEY----------END RSA PRIVATE KEY-----結束。和SSL_CTX_use_PrivateKey_file()工作正常!

+0

去除密鑰文件的密碼非常有用的技巧。 _添加到工具箱_。 – samvv

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標記之前抽出任何內容,則應該很好。

當您使用證書籤名請求創建證書和密鑰對時,您將不會獲得此附加信息。

0

在openssl目錄demo/openssl下有一個客戶端的例子。

變化:

meth = SSLv2_client_method(); 

在你的情況:

meth = SSLv23_client_method(); 

嘗試這個例子,看看它失敗。

您確定密鑰密碼是123456嗎?

+1

我不認爲它很重要。當您建立連接時,SSLv2與SSLv23的區別僅僅** **。在上述情況下,即使建立連接,也會發出錯誤。 – Karthik

+0

所以問題的關鍵密碼爲我指出了? – Cyril

+0

@Cyril號就這麼重要的密碼。 – jfly

7

在我的情況下,錯誤是因爲PEM文件不包含這兩個密鑰和證書。

確保您的文件包含兩部分:

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

我鏈中.key.crt文件,我已經在我的Apache配置作出.pem文件。

「無起點線」的錯誤肯定是誤導性的,你可以在你的PEM文件中有一個非常好的「BEGIN」行,仍然得到錯誤。

+0

謝謝。那爲我做了詭計! –