2013-09-26 18 views
5

Sto scrivendo un'applicazione client su Windows che stabilisce una connessione SSL a un server e il server richiede il certificato client per l'autenticazione. Il server mi fornisce un file con estensione pfx, allora io uso strumento a riga di comando OpenSSL per ottenere il certificato e la chiave privata in questo modo:SSL_CTX_use_PrivateKey_file() non riuscito

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

dopo, provo a caricare il certificato e la chiave privata con funzioni da openssl come sotto, ma SSL_CTX_use_PrivateKey_file() fallisce sempre, il messaggio di errore è "error:0906D06C:PEM routines:PEM_read_bio:no start line", non riesco a capirlo perché, qualcuno può darmi qualche chiarimento? Ecco il codice.

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

risposta

3

Ho risolto personalmente questo problema. Ho generato key.pem utilizzando OpenSSL per Windows, quando CMD mi ha chiesto di digitare la passphrase, Ho appena digitato un Invio poiché non ho bisogno di una frase pass, ma key.pem non era valido (né né END marcatori). Quando genero la chiave privata in Linux, il terminale richiede di digitare una pass phrase e lo faccio. Poi rimuovere la passphrase chiave utilizzando questo comando:

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

Dopo di che, ho aperto il key.pem in un editor di testo, si inizia con -----BEGIN RSA PRIVATE KEY----- e finire con -----END RSA PRIVATE KEY-----. E SSL_CTX_use_PrivateKey_file() funziona perfettamente!

+0

Trucco molto utile per rimuovere la password di un file chiave. _Aggiungi a toolbox_. – samvv

4

L'errore error:0906D06C:PEM routines:PEM_read_bio:no start line è perché sia ​​nel cert.pem così come key.pem, non iniziare con -----BEGIN CERTIFICATE----- e -----BEGIN ENCRYPTED PRIVATE KEY-----.

Se apri il tuo cert.pem e key.pem in un editor di testo e togli via qualsiasi cosa ci sia prima dei marcatori BEGIN, dovresti essere bravo.

Quando si crea un certificato e una coppia di chiavi utilizzando la richiesta di firma del certificato , non si otterranno queste informazioni aggiuntive.

0

Nella directory openssl demo/openssl c'è un esempio di client.

Cambio:

meth = SSLv2_client_method(); 

nel tuo caso per:

meth = SSLv23_client_method(); 

Prova questo esempio e vedere dove fallisce.

Sei sicuro che la password della chiave sia 123456?

+1

Non credo che importi. La distinzione tra SSLv2 e SSLv23 è importante ** solo ** quando si effettua una connessione. Nel caso precedente, l'errore viene emesso anche prima che venga stabilita una connessione. – Karthik

+0

Quindi il problema era la password della chiave come ho fatto notare? – Cyril

+0

@ Cirillo No. è la passphrase che conta. – jfly

7

Nel mio caso l'errore era dovuto al fatto che il file PEM non conteneva sia una chiave che un certificato.

Assicurarsi che il file contiene entrambe le sezioni:

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

I catenated .key e .crt file che ho già avuto nella mia configurazione di Apache per creare un file .pem.

L'errore "nessuna riga iniziale" è sicuramente fuorviante in quanto è possibile avere una linea "BEGIN" perfettamente buona nel file PEM e ottenere comunque l'errore.

+0

Grazie. Questo ha fatto il trucco per me! –