2015-06-25 243 views
3

我在ArchLinux上的Windows 8.1和Qt 5.4.2上有最新的Qt 5.4.0,並得到完全相同的結果。Qt5客戶端證書認證

我有一個需要客戶端SSL證書的網站。服務器似乎因爲

openssl s_client -connect myserver:443 -cert client.crt -key client.key 

打印

Verify return code: 0 (ok) 

而且執行中適當配置,

curl --cert client.pem https://myserver/ 

的作品就好了。

服務器證書有效,瀏覽器接受它等。客戶端證書是自簽名的。爲以防萬一,服務器是nginx的,這裏是相關配置片段

listen       *:443 ssl; 

server_name     myserver; 

ssl       on; 
ssl_certificate    /etc/nginx/ssl/myserver.crt; 
ssl_certificate_key   /etc/nginx/ssl/myserver.key; 
ssl_dhparam     /etc/nginx/ssl/myserver.dh; 
ssl_protocols     TLSv1.1 TLSv1.2; 
ssl_ciphers     "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; 
ssl_prefer_server_ciphers  on; 
ssl_client_certificate   /etc/nginx/ssl/ca.crt; 
ssl_verify_client    on; 

但最簡單的QT5應用

#include <qcoreapplication.h> 
#include <qfile.h> 
#include <qnetworkaccessmanager.h> 
#include <qnetworkconfiguration.h> 
#include <qnetworkproxy.h> 
#include <qnetworkreply.h> 
#include <qnetworkrequest.h> 
#include <qsslcertificate.h> 
#include <qsslconfiguration.h> 
#include <qsslkey.h> 

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 

    QNetworkProxyFactory::setUseSystemConfiguration(true); 

    QSslConfiguration sslConfiguration; 

    QFile privateKeyFile("client.key"); 
    privateKeyFile.open(QIODevice::ReadOnly); 

    QFile certificateFile("client.crt"); 
    certificateFile.open(QIODevice::ReadOnly); 

    QSslKey privateKey(&privateKeyFile, QSsl::Opaque); 
    QSslCertificate certificate(&certificateFile); 

    qWarning() << QSslSocket::supportsSsl(); 
    qWarning() << certificate.serialNumber(); 
    qWarning() << certificate.subjectInfo(QSslCertificate::CommonName); 
    qWarning() << certificate.expiryDate(); 

    sslConfiguration.setPrivateKey(privateKey); 
    sslConfiguration.setLocalCertificate(certificate); 

    QNetworkRequest networkRequest(QUrl("https://server/")); 

    networkRequest.setSslConfiguration(sslConfiguration); 

    QNetworkAccessManager networkAccessManager; 

    QNetworkReply* networkReply = networkAccessManager.get(networkRequest); 

    QEventLoop loop; 

    QObject::connect(&networkAccessManager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit); 

    loop.exec(); 

    qWarning() << networkReply->error(); 
    qWarning() << networkReply->errorString(); 

    delete networkReply; 

    return a.exec(); 
} 

失敗,並在Windows

QSslSocket: cannot resolve TLSv1_1_client_method 
QSslSocket: cannot resolve TLSv1_2_client_method 
QSslSocket: cannot resolve TLSv1_1_server_method 
QSslSocket: cannot resolve TLSv1_2_server_method 
QSslSocket: cannot resolve SSL_select_next_proto 
QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb 
QSslSocket: cannot resolve SSL_get0_next_proto_negotiated 
true 
"01" 
("AA-00-00-00") 
QDateTime("2035-06-21 21:41:13.000 UTC Qt::UTC") 
99 
"Unable to init SSL Context: " 

和下面的控制檯輸出以下在Linux上跟隨控制檯輸出

true 
"01" 
("AA-00-00-00") 
QDateTime("2035-06-21 21:41:13.000 UTC Qt::UTC") 
99 
"Unable to init SSL Context: " 

如果我刪除「networkRequest.setSslConfiguration(sslConfiguration);」我剛剛從服務器收到400錯誤,指出我需要發送客戶端證書。

添加「sslConfiguration.setPeerVerifyMode(QSslSocket :: VerifyNone);」什麼都不變。

我很樂意得到任何建議可能導致Qt5代碼失敗的原因。

回答

1

Qt在運行時解析OpenSSL函數,這些警告是它的結果。這可能是你的程序根本找不到OpenSSL,或者它找到了過時的版本。從Qt 5.2開始,OpenSSL v1.0.0或更高版本是必需的。

Qt documentation

支持安全套接字層(SSL)通信由OpenSSL工具包,其必須被單獨獲得提供。

從Qt版本5.2開始,官方支持的OpenSSL版本是1.0.0或更高版本。版本> = 0.9.7和< 1.0.0可能有效,但不能保證。