我有以下三个文件: key.pem , cert.pem , ca.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错误:主机名与此证书的任何有效主机都不匹配。 当我用cert切换ca时,它花了更长时间才能失败,但我没有收到任何错误。
答案 0 :(得分:1)
openssl genrsa 2048 > server.key
<块引用>openssl req -new -x509 -nodes -sha256 -days 365 -key server.key -out server.cert
当openssl问你常用名时请输入localhost,其他可以空白。
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 );
}
为每个项目添加 QT += network
到 *.pro 文件
构建ssl_server和ssl_client项目
复制server.key和server.cert到ssl_server项目的bin目录
只复制server.cert到ssl_client项目的bin目录
先运行 ssl_server,然后运行 ssl_client,您可以在 ssl_server 的控制台中看到下一个结果:
start listening "192.168.31.46" on port 8000
encrypted
"hello world!"
答案 1 :(得分: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文件。
答案 2 :(得分:0)
我有同样的任务:BOOST的SSL服务器:ASIO, Qt的SSL客户端 5.8。对于服务器端,我使用了给定的示例。 对于Qt客户端,我有很长时间尝试,但同时发现了一个解决方案 - 连接加密但不完整的同行识别。 这是一段代码剪辑 - 对不起q&amp; 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;
}