Qt Server+Client App:加密失败(更新代码) [英] Qt Server+Client App: encryption fails (updated with code)

查看:48
本文介绍了Qt Server+Client App:加密失败(更新代码)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Qt 中设计具有安全 TSL 连接的服务器 + 客户端时,我一直在努力解决各种问题.我正在使用:

I have been struggling with all sorts of problems when designing the Server+Client with secure TSL connection in Qt. I am using:

Qt 5.2.0 (QSslSocket)XCA(基于 OpenSSL 32 位)

Qt 5.2.0 (QSslSocket) XCA (based on OpenSSL 32-bit)

为了测试,我创建了私钥(RSA,1024)和 CA.然后由该 CA 使用另一个私钥(RSA,1024)签名的证书.当我在一台机器上测试时,通用名称设置为localhost".我在客户端和服务器应用程序中都有所需的 OpenSSL DLL.

For testing I have created private key (RSA, 1024) and CA. Then a certificate signed by this CA with another private key (RSA, 1024). Common name set to 'localhost' as I am testing on one machine. I have the needed DLLs of OpenSSL in both client and server apps.

但是,无论我如何设置,加密连接都不起作用.常规连接工作正常,但尝试加密总是会导致错误.最常见的错误:

However no matter how I set things up the encrypted connection just does not work. Regular connection works fine but attempting the encryption always results in errors. Most common errors:

QSskError::CertificateSignatureFailed "The signature of the certificate is invalid"
QAbstractSocket::SslInternalError
QAbstractSocket::SslHandshakeFailedError

我可能遗漏了一些明显的东西或忽略了一些东西,但我已经不知所措,试图解决这个问题有一段时间了.特别是因为我不知道问题是否出在我的代码、滥用 openSSL、证书或这些的组合或其他我不知道的组合中.

I might be missing something obvious or have overlooked something but I am at my wits end trying to solve this for some time now. Especially since I don't know if the problem is in my code, misusing openSSL, certificates or combination of these or something else in the mix I am not aware of.

如果您能提供有关常见错误的指示,以及如何正确执行此操作的特别可靠指南,我将不胜感激.

I would appreciate any pointers to both common errors and especially reliable guides how to do this properly.

谢谢!

提供了极简代码来演示问题.

Provided minimalist code to demonstrate the problem.

如果我在建立连接之前在客户端移动 CA 证书的加载并在连接后立即开始握手,它实际上可以工作.然而,延迟握手仍然不会出现与之前相同的错误(SslHandshakeFailedError).文档仅说明必须在握手之前加载 CA,而不是在连接之前加载...

If I move the loading of the CA certificate on client side before the connection is made and start the handshake immidiatelly after connection it actually works. However delayed handshake still does not with the same error as before (SslHandshakeFailedError). Documentation states only that CA must be loaded before handshake, not before connection...

此命令成功验证证书(Verify return 0 (Ok)):

This command succeeded in verifying the certificate (Verify return 0 (Ok)):

openssl s_client -connect <host>:<port> -CAfile <ca-file>

根据要求,我使用与实际生产中相同的代码创建了客户端应用程序和服务器应用程序,并减去了它周围的所有内容,如线程、日志记录等.

On request, I have whipped up client app and server app using the same code as in real production minus all the stuff around it like threading, logging etc.

客户

主窗口.h

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_pushButton_Connect_released();
    void on_pushButton_Encrypt_released();

    void socketEncrypted() { qDebug() << "Encrypted"; }

private:
    QSslSocket m_Socket;
    Ui::MainWindow *ui;

    void socketWrite(const QByteArray &data);
};

mainwindow.cpp

mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    connect(&m_Socket,&QSslSocket::encrypted,
            this,&MainWindow::socketEncrypted);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_Connect_released()
{
    m_Socket.connectToHost("localhost", 1234);
}

void MainWindow::on_pushButton_Encrypt_released()
{
    QFile file("PM_Client_CA.crt");
    file.open(QIODevice::ReadOnly);
    QSslCertificate certificate(&file);

    m_Socket.addCaCertificate(certificate);
    m_Socket.startClientEncryption();

    QByteArray data("encrypt");
    socketWrite(data);
}

void MainWindow::socketWrite(const QByteArray &data)
{
    m_Socket.write(data);
    m_Socket.flush();
}

服务器

server.h

class Server : public QTcpServer
{
    Q_OBJECT
public:
    explicit Server(QObject *parent = 0);

public slots:
    void clientEncrypted() { qDebug() << "Encrypted"; }
    void clientRead();

protected:
    void incomingConnection(qintptr handle);

private:
    QSslSocket m_Socket;
};

server.cpp

Server::Server(QObject *parent) :
    QTcpServer(parent)
{
    QFile file("PM_Server.crt");
    file.open(QIODevice::ReadOnly);
    QSslCertificate certificate(&file);
    file.close();

    file.setFileName("PM_Server.pem");
    file.open(QIODevice::ReadOnly);
    QSslKey key(&file, QSsl::Rsa);

    m_Socket.setLocalCertificate(certificate);
    m_Socket.setPrivateKey(key);

    connect(&m_Socket,&QSslSocket::encrypted,
            this,&Server::clientEncrypted);

    listen(QHostAddress::Any, 1234);
}

void Server::incomingConnection(qintptr handle)
{
    m_Socket.setSocketDescriptor(handle);

    connect(&m_Socket,&QSslSocket::readyRead,
            this,&Server::clientRead);
}

void Server::clientRead()
{
    disconnect(&m_Socket,&QSslSocket::readyRead,
               this,&Server::clientRead);

    m_Socket.startServerEncryption();
}

推荐答案

看来我已经想通了.首先我必须感谢@jww 帮助我验证问题不是证书.

It seems I have figured it out. First I must thank @jww for helping me verify that the issue were not the certificates.

事实上,问题在于我以错误的顺序设置了套接字并读取了加密数据并在此基础上进行了操作(例如开始第二次握手等).

In fact, the issue was me setting up the socket in the wrong order AND reading up the encryption data and doing stuff based on that (like starting second handshake etc.).

无论如何,这似乎现在得到了回答,但我在握手时遇到了新的问题.我已经为它打开了 Qt 论坛帖子:http://qt-project.org/forums/viewthread/41293/

Anyway, this seems to be answered now but I have run into new load of issues with the handshake. I have opened the Qt forum thread for it: http://qt-project.org/forums/viewthread/41293/

再次感谢所有试图提供帮助的人!

Thanks again to everyone who tried to help!

这篇关于Qt Server+Client App:加密失败(更新代码)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆