简体   繁体   English

无法使QSslSocket工作

[英]Can't get QSslSocket to work

I'm attempting to write a simple client-server application in Qt that would comunicate over SSL. 我试图在Qt中编写一个简单的客户端-服务器应用程序,该应用程序将通过SSL通信。 I tried using QSslSockets, but I keep having variuos problems. 我尝试使用QSslSockets,但是仍然遇到各种问题。

Take a look at this: 看看这个:

Client: 客户:

#define dumpvar(x) qDebug()<<#x<<'='<<x

int main(int argc, char** argv)
{
    QApplication a(argc, argv);

    QSslSocket s;
    auto cert = QSslCertificate::fromPath("/home/piotrek/cert.pem");
    Q_ASSERT(!cert.isEmpty());
    s.setCaCertificates({cert});
    s.connectToHostEncrypted("localhost", 1234);
    qDebug()<<"waiting for encrypted";
    if (!s.waitForEncrypted(10000)){
        dumpvar(s.errorString());
        dumpvar(s.sslErrors());
        return 0;
    }

    qDebug()<<"client connected";
}

Server: 服务器:

#define dumpvar(x) qDebug()<<#x<<'='<<x

class SslServer: public QTcpServer
{
    // QTcpServer interface
protected:
    void incomingConnection(qintptr handle) override
    {
        QSslSocket s;
        if (!s.setSocketDescriptor(handle)){
            dumpvar(s.errorString());
            return;
        }
        s.setLocalCertificate("/home/piotrek/cert.pem");
        s.setPrivateKey("/home/piotrek/pkey.pem", QSsl::Rsa, QSsl::Pem, "test");
        s.startServerEncryption();
        qDebug()<<"waiting for encrypted";
        if(!s.waitForEncrypted(10000)){
            dumpvar(s.errorString());
            dumpvar(s.sslErrors());
            return;
        }

        qDebug()<<"server encrypted";

        handleConnection(&s);
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    SslServer s;

    s.listen(QHostAddress::Any, 1234);
    return a.exec();
}

The client prints: 客户端打印:

qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
waiting for encrypted
<10 second pause>
s.errorString() = "Network operation timed out"
s.sslErrors() = ()

The server prints: 服务器打印:

qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
waiting for encrypted
<10 second pause>
s.errorString() = "The remote host closed the connection"
s.sslErrors() = (

What am I doing wrong? 我究竟做错了什么?

Explanation for the warnings is that OpenSSL in Ubuntu is compiled without insecure sslv2 but Qt 5.8 tries to load those functions in runtime. 警告的解释是Ubuntu中的OpenSSL编译时没有不安全的sslv2,但Qt 5.8尝试在运行时加载这些功能。 Qt uses only secure protocols by default so these warnings don't affect you unless you explicitly call QSslSocket::setProtocol with QSsl::SslV2 (which of course doesn't work with your openssl). Qt默认情况下仅使用安全协议,因此,除非您使用QSsl::SslV2显式调用QSslSocket :: setProtocol ,否则这些警告不会对您造成影响(当然,这不适用于您的openssl)。

Obviously something is wrong with your self-signed? 显然您的自签名有问题吗? certificate . 证书 Also, connection would fail anyway with self-signed certificate unless hostname mismatch is ignored explicitly. 此外,除非使用主机签名不匹配,否则使用自签名证书进行连接都会失败。

In case, you are using self-signed certificates you could re-generate them with the instructions found here . 如果您使用的是自签名证书,则可以按照此处的说明重新生成它们。

Please, find below the working code example. 请在下面找到工作代码示例。 Tested on similar environment ( surprise! ) Ubuntu 16.10, OpenSSL 1.0.2g 1 Mar 2016, Qt 5.8.0 . 在类似环境下测试( 令人惊讶!Ubuntu 16.10, OpenSSL 1.0.2g 1 Mar 2016, Qt 5.8.0

Server 服务器

class SslServer: public QTcpServer
{
    // QTcpServer interface
protected:
    void incomingConnection(qintptr handle) override
    {
        QSslSocket s;
        if (!s.setSocketDescriptor(handle)){
            dumpvar(s.errorString());
            return;
        }
        const QString serverCertPath("/path/to/server1.pem");
        const QString serverKeyPath("/path/to/server1.key");
        s.setLocalCertificate(serverCertPath);
        s.setPrivateKey(serverKeyPath, QSsl::Rsa, QSsl::Pem, "test");
        s.startServerEncryption();
        qDebug()<<"waiting for encrypted";
        if(!s.waitForEncrypted(10000)){
            dumpvar(s.errorString());
            dumpvar(s.sslErrors());
            return;
        }
        qDebug()<<"server encrypted";
        s.write("Hello client");
        s.flush();
        s.waitForBytesWritten(3000);
        s.close();
    }
};

Client 客户

int main(int argc, char** argv)
{
    QCoreApplication a(argc, argv);

    QSslSocket s;
    const QString rootCAPath("/path/to/rootCA.pem");
    auto rootCACert = QSslCertificate::fromPath(rootCAPath);
    Q_ASSERT(!rootCACert.isEmpty());
    s.setCaCertificates(rootCACert);

    // ignore SSL host name mismatch error for server certificate
    QList<QSslError> errorsToIgnore;
    const QString serverCertPath("/path/to/server1.pem");
    auto serverCert = QSslCertificate::fromPath(serverCertPath);
    Q_ASSERT(!serverCert.isEmpty());
    errorsToIgnore<<QSslError(QSslError::HostNameMismatch, serverCert.at(0));
    s.ignoreSslErrors(errorsToIgnore);

    s.connectToHostEncrypted("localhost", 1234);
    qDebug()<<"waiting for encrypted";
    if (!s.waitForEncrypted(10000)){
        dumpvar(s.errorString());
        dumpvar(s.sslErrors());
        return 0;
    }
    qDebug()<<"client connected";
    s.waitForReadyRead(3000);
    qDebug() << "Reading: " << s.bytesAvailable();
    qDebug() << s.readAll();
    s.close();
}

Server output: 服务器输出:

qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
waiting for encrypted
server encrypted

Client output: 客户输出:

qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method
waiting for encrypted
client connected
Reading:  12
"Hello client"
Press <RETURN> to close this window...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM