PDA

View Full Version : Qt5 client certificate authentication



adontz
25th June 2015, 03:37
I have Qt 5.4.0 on Windows 8.1 and Qt 5.4.2 on ArchLinux latest and get exactly the same result.

I have web-site which requires client SSL certificate. Server seems to be configured properly since execution of


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

prints


Verify return code: 0 (ok)

Also,


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

works just fine.

Server certificate is valid, browsers accept it, etc. Client certificate is self signed. Just in case, server is nginx and here is relevant config fragment


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;


But the following simplest Qt5 application


#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(tr ue);

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::CommonNam e);
qWarning() << certificate.expiryDate();

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

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

networkRequest.setSslConfiguration(sslConfiguratio n);

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

fails with the following console output on 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: "

and the following console output on Linux


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


If I remove "networkRequest.setSslConfiguration(sslConfiguratio n);" I just get 400 error from server stating I need to send client certificate.

Adding "sslConfiguration.setPeerVerifyMode(QSslSocket::Ver ifyNone);" changes nothing.

I will be happy to get any advice what can be cause of Qt5 code failure.