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
openssl s_client -connect myserver:443 -cert client.crt -key client.key
To copy to clipboard, switch view to plain text mode
prints
Verify return code: 0 (ok)
Verify return code: 0 (ok)
To copy to clipboard, switch view to plain text mode
Also,
curl --cert client.pem https://myserver/
curl --cert client.pem https://myserver/
To copy to clipboard, switch view to plain text mode
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;
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;
To copy to clipboard, switch view to plain text mode
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[])
{
QNetworkProxyFactory::setUseSystemConfiguration(true);
QSslConfiguration sslConfiguration;
QFile privateKeyFile
("client.key");
QFile certificateFile
("client.crt");
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);
QObject::connect(&networkAccessManager,
&QNetworkAccessManager
::finished,
&loop,
&QEventLoop
::quit);
loop.exec();
qWarning() << networkReply->error();
qWarning() << networkReply->errorString();
delete networkReply;
return a.exec();
}
#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();
}
To copy to clipboard, switch view to plain text mode
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: "
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: "
To copy to clipboard, switch view to plain text mode
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: "
true
"01"
("AA-00-00-00")
QDateTime("2035-06-21 21:41:13.000 UTC Qt::UTC")
99
"Unable to init SSL Context: "
To copy to clipboard, switch view to plain text mode
If I remove "networkRequest.setSslConfiguration(sslConfigurati on);" I just get 400 error from server stating I need to send client certificate.
Adding "sslConfiguration.setPeerVerifyMode(QSslSocket::Ve rifyNone);" changes nothing.
I will be happy to get any advice what can be cause of Qt5 code failure.
Bookmarks