Qt5客户端证书认证

6

我在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个回答

1
Qt在运行时解析OpenSSL函数,这些警告就是其结果。可能是因为你的程序根本找不到OpenSSL,或者它发现了太老的版本。从Qt 5.2开始需要OpenSSL v1.0.0或更高版本。
来自Qt文档
“安全套接字层(SSL)通信的支持由OpenSSL Toolkit提供,该工具包必须单独获取。从Qt 5.2版本开始,官方支持的OpenSSL版本为1.0.0或更高版本。版本>=0.9.7且<1.0.0可能可用,但不能保证。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接