Qt5客户端证书认证

标签 qt ssl client-certificates qnetworkaccessmanager qt5.4

我在 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 代码失败的建议。

最佳答案

Qt 在运行时解析 OpenSSL 函数,这些警告是它的结果。可能是您的程序根本找不到 OpenSSL,或者它找到的版本太旧。从 Qt 5.2 开始,需要 OpenSSL v1.0.0 或更高版本。

来自 Qt documentation :

Support for Secure Sockets Layer (SSL) communication is provided by the OpenSSL Toolkit, which must be obtained separately.

From Qt version 5.2 onwards, the officially supported version for OpenSSL is 1.0.0 or later. Versions >= 0.9.7 and < 1.0.0 might work, but are not guaranteed to.

关于Qt5客户端证书认证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31039631/

相关文章:

c++ - QCombobox - 隐藏下拉列表中的第一项

c++ - 将函数指针插入 QMap (Qt)

c++ - 无法使用 QProcess 在 cmd.exe 中执行复制命令

c++ - 卡住在 __write_nocancel

ssl - 浏览器(例如 FF)何时发送 CONNET 方法而不是客户端问候?

cocoa - 如何在 Cocoa 中使用 WebView 连接客户端证书?

amazon-web-services - AWS EC2 应用程序负载均衡器 + 双向 SSL?

ssl - 带 SSL 的 WebSocket

python - 基于 python 证书的身份验证中的 REST 请求,在 SOAPUI 中工作

azure - 是否可以在 Windows Azure 网站中使用客户端证书