在QT中创建成功的SSL握手的正确方法是什么?

问题描述 投票:0回答:4

我有以下三个文件:key.pemcert.pemca.pem以及创建与我的服务器的SSL连接的工作代码。它是使用 boost 库创建的。

工作升压代码:

ssl::context ctx(io_service, ssl::context::sslv23);
ctx.set_password_callback(password_callback);
ctx.load_verify_file("ca.pem");
ctx.set_verify_mode(ssl::context_base::verify_peer);
ctx.use_certificate_file("cert.pem", ssl::context::pem);
ctx.use_private_key_file("key.pem", ssl::context::pem);

我必须使用 Qt5 及其 QSslSocket 重写此客户端代码。

到目前为止,我创建了这段代码(有许多小的变化 - 切换文件、更改密码编码):

    QSslSocket ssl;
    QList<QSslCertificate> certy = QSslCertificate::fromPath("C:\\ssltest\\cert.pem");

    ssl.setCaCertificates(certy);
    ssl.setLocalCertificate(QString("C:\\ssltest\\ca.pem"));
   ssl.setPrivateKey(QString("C:\\ssltest\\key.pem"),QSsl::Rsa,QSsl::Pem,QString("password").toUtf8());


    ssl.connectToHostEncrypted(QString("192.168.90.41"),6500);

    if(ssl.waitForEncrypted()){
        cout << "SSL handsake succesful!" << endl;
    } else {
        cout << "Something went terribly wrong!" << endl;
    }

但是我的Qt代码无法成功实现SSL握手(TCP连接成功)。 我做错了什么?

我立即收到此 SSL 错误:主机名与此证书的任何有效主机都不匹配。 当我用证书切换 ca 时,它需要更长的时间才能失败,但我没有收到任何错误。

c++ qt ssl boost
4个回答
1
投票
  1. 创建密钥和证书。我在 Linux 控制台中使用以下命令:

openssl genrsa 2048 > server.key

openssl req -new -x509 -nodes -sha256 -days 365 -key server.key -out server.cert

当 openssl 询问您常用名称时,请输入 localhost,其他可以是 blanc。

2.0。创建 qt 项目 ssl_client 并将下一个代码添加到 main.c

#include <QCoreApplication>
#include "ssl_client.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ssl_client client(8000);
    return a.exec();
}

2.1。使用下一个代码创建ssl_client.h

#include <QtNetwork>

class ssl_client : public QObject
{
    Q_OBJECT
public:
    ssl_client(quint16 port);
private:
    void setUp();
    QSslSocket socket;
};

2.2。使用下一个代码创建 ssl_client.cpp

#include "ssl_client.h"

ssl_client::ssl_client(quint16 port): socket(this)
{
    setUp();
    socket.connectToHostEncrypted("localhost", port);
    socket.write("hello world!");
}

void ssl_client::setUp(){
    QByteArray cert;

    QFile file_cert("server.cert");
    if(file_cert.open(QIODevice::ReadOnly)){
        cert = file_cert.readAll();
        file_cert.close();
    }
    else{
        qDebug() << file_cert.errorString();
    }
    QSslCertificate ssl_cert(cert);

    QList<QSslCertificate> listCA;
    listCA.append(ssl_cert);
    QSslConfiguration conf;
    conf.setCaCertificates(listCA);
    socket.setSslConfiguration(conf);
}

3.0。创建 qt 项目 ssl_server 并将下一个代码添加到 main.c

#include <QCoreApplication>
#include "ssl_server.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ssl_server server(8000);
    return a.exec();
}

2.1。使用下一个代码创建 ssl_server.h

#include <QtNetwork>

class ssl_server: public QTcpServer
{
    Q_OBJECT
public:
    ssl_server(quint16 port);
protected:
    void incomingConnection(qintptr socketDescriptor) override;
private slots:
    void ready();
    void printData();
private:
    void setUp();
    QSslSocket serverSocket;
};

2.2。使用下一个代码创建ssl_server.cpp

#include "ssl_server.h" ssl_server::ssl_server(quint16 port): QTcpServer(), serverSocket(this) { if (!this->listen(QHostAddress::LocalHost, port)) { qDebug() << "start listen port" << port << "failed"; this->close(); return; } else{ foreach (const QNetworkInterface &netInterface, QNetworkInterface::allInterfaces()) { QNetworkInterface::InterfaceFlags flags = netInterface.flags(); if( (bool)(flags & QNetworkInterface::IsRunning) && !(bool)(flags & QNetworkInterface::IsLoopBack)){ foreach (const QNetworkAddressEntry &address, netInterface.addressEntries()) { if(address.ip().protocol() == QAbstractSocket::IPv4Protocol){ qDebug() << "start listening " << address.ip().toString() << " on port" << port; } } } } } setUp(); } void ssl_server::incomingConnection(qintptr socketDescriptor) { if (serverSocket.setSocketDescriptor(socketDescriptor)) { addPendingConnection(&serverSocket); serverSocket.startServerEncryption(); } else { serverSocket.close(); } } void ssl_server::ready(){ qDebug() << "encrypted"; } void ssl_server::printData(){ QByteArray array = serverSocket.read(serverSocket.bytesAvailable()); qDebug() << array; } void ssl_server::setUp(){ QByteArray key; QByteArray cert; QFile file_key("server.key"); if(file_key.open(QIODevice::ReadOnly)) { key = file_key.readAll(); file_key.close(); } else{ qDebug() << file_key.errorString(); } QFile file_cert("server.cert"); if(file_cert.open(QIODevice::ReadOnly)){ cert = file_cert.readAll(); file_cert.close(); } else{ qDebug() << file_cert.errorString(); } QSslKey ssl_key(key, QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,"localhost"); QSslCertificate ssl_cert(cert); serverSocket.setLocalCertificate(ssl_cert); serverSocket.setPrivateKey(ssl_key); connect(&serverSocket, SIGNAL(encrypted()), this, SLOT(ready())); connect(&serverSocket, SIGNAL(readyRead()), this, SLOT(printData()) ); serverSocket.setSocketOption(QAbstractSocket::KeepAliveOption, true ); }

  1. 将每个项目的

    QT += network

     添加到 *.pro 文件

  2. 构建

    ssl_serverssl_client 项目

  3. server.keyserver.cert复制到ssl_server项目的bin目录下

  4. 仅将

    server.cert 复制到 ssl_client 项目的 bin 目录

  5. 先运行

    ssl_server,然后运行ssl_client,您可以在控制台中看到ssl_server的下一个结果:

start listening "192.168.31.46" on port 8000


encrypted


"hello world!"


    


0
投票
这是一个示例 SSL 客户端和服务器,它使用 server.key 和 server.crt 文件进行加密:

服务器端:

#include <QtNetwork> #include <QMessageBox> class server : public QTcpServer { Q_OBJECT public: explicit server(QObject *parent = 0); ~server(); QSslSocket server_socket; public slots: void tcpReady(); void encrypted(); void sslError( QList<QSslError> errors ); bool start_listen(int port_no); protected: void incomingConnection( int descriptor ); }; server::server(QObject *parent) : QTcpServer(parent) { server_socket.setProtocol(QSsl::SslV3); QByteArray key; QByteArray cert; QFile file_key("server.key"); if(file_key.open(QIODevice::ReadOnly)) { key = file_key.readAll(); file_key.close(); } else { qDebug() << file_key.errorString(); } QFile file_cert("server.crt"); if(file_cert.open(QIODevice::ReadOnly)) { cert = file_cert.readAll(); file_cert.close(); } else { qDebug() << file_cert.errorString(); } QSslKey ssl_key(key, QSsl::Rsa,QSsl::Pem,QSsl::PrivateKey,"server"); QSslCertificate ssl_cert(cert); server_socket.addCaCertificate(ssl_cert); server_socket.setLocalCertificate(ssl_cert); server_socket.setPrivateKey(ssl_key); connect( &server_socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslError(QList<QSslError>)) ); connect(&server_socket,SIGNAL(encrypted()),this,SLOT(encrypted())); server_socket.setSocketOption(QAbstractSocket::KeepAliveOption, true ); } server::~server() { server_socket.disconnectFromHost(); server_socket.waitForDisconnected(); } void server::tcpReady() { QByteArray array = server_socket.read( server_socket.bytesAvailable() ); //... } void server::encrypted() { connect( &server_socket, SIGNAL(readyRead()), this, SLOT(tcpReady()) ); emit connection_established(); } void server::sslError(QList<QSslError> errors) { QString erroStr=""; foreach (const QSslError &e, errors) erroStr.append(e.errorString()).append("\n"); QMessageBox::warning( (QWidget *)this->parent(), tr("Error"),erroStr ); server_socket.ignoreSslErrors(); } bool server::start_listen(int port_no) { if( !this->listen( QHostAddress::Any, port_no ) ) { QMessageBox::warning( (QWidget *)this->parent(), tr("Error!"), tr("Cannot listen to port %1").arg(port_no) ); } else return true; } void server::incomingConnection(int descriptor) { if(server_socket.state()!=QAbstractSocket::UnconnectedState) return; if( !server_socket.setSocketDescriptor( descriptor ) ) { QMessageBox::warning( (QWidget *)this->parent(), tr("Error!"), tr("Socket error!") ); return; } else { server_socket.startServerEncryption(); } }

客户端:

class Client : public QObject { Q_OBJECT public: explicit Client(QObject *parent = 0); ~Client(); QSslSocket client_socket; private slots: void tcpReady(); void sslError( QList<QSslError> errors ); void TCPError( QAbstractSocket::SocketError error ); void connectToServer(); }; Client::Client(QObject *parent) : QObject(parent) { client_socket.setProtocol(QSsl::SslV3); connect( &client_socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(TCPError(QAbstractSocket::SocketError)) ); connect( &client_socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslError(QList<QSslError>)) ); connect( &client_socket, SIGNAL(readyRead()), this, SLOT(tcpReady()) ); } Client::~Client() { } void Client::tcpReady() { QByteArray array = client_socket.read( client_socket.bytesAvailable() ); //... } void Client::sslError(QList<QSslError> errors) { client_socket.ignoreSslErrors(); } void Client::TCPError(QAbstractSocket::SocketError error) { } void Client::connectToServer() { client_socket.abort(); client_socket.connectToHostEncrypted("192.168.0.10", 8000 ); }

您应该为您的应用程序生成一个 server.key 和一个 server.crt 文件。


0
投票
我有同样的任务:SSL Server by BOOST:ASIO,

SSL Client by Qt 5.8。对于服务器端,我使用了给定的示例。 对于 Qt 客户端,我花了很长时间尝试,但同时找到了一个解决方案 - 连接加密但不完整的对等识别。 这是一个代码片段 - 对于 q&d 表示抱歉:

CQtSsl::CQtSsl() { m_SslSocket = NULL; QString SCertificatePath = "ca.pem"; m_nSslError = -1; m_sSslError = ""; if (QSslSocket::supportsSsl()) { m_nSslError = 0; m_sSslError = "SSL is installed."; } else { m_nSslError = -101; m_sSslError = "Missing SSL installation."; } QList<QSslCertificate> CertList = QSslCertificate::fromPath(SCertificatePath); if (CertList.count() < 1) { m_nSslError = -11; m_sSslError = "No valid CA-Certifacte found: " + SCertificatePath; } m_caCertificate = CertList.at(0); QString sCertInfo = m_caCertificate.toText(); if (m_nSslError == 0) { m_SslSocket = new QSslSocket(); if (!m_SslSocket) { m_nSslError = -2; m_sSslError = "Creation of SSL-Socket failed!"; } } if (m_nSslError == 0) { m_SslSocket->addCaCertificates(SCertificatePath); } if (m_nSslError == 0) { QSslConfiguration sslConfig = m_SslSocket->sslConfiguration(); sslConfig.setPeerVerifyMode(QSslSocket::QueryPeer); //sslConfig.setProtocol(QSsl::SslV2); sslConfig.setSslOption(QSsl::SslOptionDisableServerNameIndication, true); m_SslSocket->setSslConfiguration(sslConfig); } if (m_nSslError == 0) { m_nSslError = 0; m_sSslError = "Client SSL-Socket established sucessfully."; } } int CQtSsl::Connect1(QString spHost, int npPort) { if (m_nSslError != 0) { m_sSslError = "Client SSL-Socket not initialized properly"; return m_nSslError; } m_nSslError = -10; connect(m_SslSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(socketStateChanged(QAbstractSocket::SocketState))); connect(m_SslSocket, SIGNAL(encrypted()), this, SLOT(connection_encrypted())); connect(m_SslSocket, SIGNAL(disconnected()), this, SLOT(connection_disconnected())); connect(m_SslSocket, SIGNAL(encrypted()), this, SLOT(ready())); connect(m_SslSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>))); connect(m_SslSocket, SIGNAL(readyRead()), this, SLOT(readyRead())); m_SslSocket->connectToHostEncrypted(spHost, npPort, "client", QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol); if (!m_SslSocket->waitForEncrypted()) { QList<QSslError> errList = m_SslSocket->sslErrors(); QAbstractSocket::SocketError err = m_SslSocket->error(); m_sSslError = m_SslSocket->errorString() + "."; m_sSslError += " Connection failed."; m_nSslError = -10; } m_nSslError = 0; return m_nSslError; } int CQtSsl::Send(QByteArray paBuffer) { int nReturn = -1; if (m_nSslError != 0) { return m_nSslError; } bool bEncrypted = m_SslSocket->isEncrypted(); nReturn = m_SslSocket->write(paBuffer); bool bFlush = m_SslSocket->flush(); return nReturn; } int CQtSsl::Send(QString spToSend) { QByteArray aBuffer = spToSend.toUtf8(); aBuffer.append((char)0); return Send(aBuffer); } void CQtSsl::connection_encrypted() { int nDebug = 1; // Do something (log...) } void CQtSsl::connection_disconnected() { int nDebug = 1; // Do something (log...) } void CQtSsl::ready() { int nDebug = 1; // Do something (log...) } void CQtSsl::readyRead() { ReadBuffer = m_SslSocket->readAll(); } void sslErrors(QList<QSslError> sslErrors) { int nDebug = 1; // Do something (log...) } int CQtSsl::GetLastError() { return m_nSslError; } QString CQtSsl::GetLastErrorDesc() { return m_sSslError; }
    

0
投票
只是在这里感谢您提供的示例,该示例有效:)

© www.soinside.com 2019 - 2024. All rights reserved.