Qt5客户端证书认证
Posted
技术标签:
【中文标题】Qt5客户端证书认证【英文标题】:Qt5 client certificate authentication 【发布时间】:2015-06-25 01:12:15 【问题描述】:我在 Windows 8.1 上安装了 Qt 5.4.0,在 ArchLinux 上安装了 Qt 5.4.2,并且得到了完全相同的结果。
我有需要客户端 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:
OpenSSL Toolkit 提供对安全套接字层 (SSL) 通信的支持,必须单独获取。
从 Qt 5.2 版开始,官方支持的 OpenSSL 版本是 1.0.0 或更高版本。 >= 0.9.7 和
【讨论】:
以上是关于Qt5客户端证书认证的主要内容,如果未能解决你的问题,请参考以下文章