QDtls 类
此类为 UDP 套接字提供加密。 更多...
头文件 | #include <QDtls> |
CMake | find_package(Qt6 REQUIRED COMPONENTS Network) target_link_libraries(mytarget PRIVATE Qt6::Network) |
qmake | QT += network |
继承 | QObject |
- 所有成员列表,包括继承成员
- QDtls 是网络编程 API 的一部分。网络编程 API.
公共类型
GeneratorParameters | |
枚举 | HandshakeState { HandshakeNotStarted, HandshakeInProgress, PeerVerificationFailed, HandshakeComplete } |
公共函数
QDtls(QSslSocket::SslMode mode, QObject *parent = nullptr) | |
虚拟 | ~QDtls() |
bool | abortHandshake(QUdpSocket *socket) |
QDtls::GeneratorParameters | cookieGeneratorParameters() const |
QByteArray | decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) |
bool | doHandshake(QUdpSocket *socket, const QByteArray &dgram = {}) |
QSslConfiguration | dtlsConfiguration() const |
QDtlsError | dtlsError() const |
QString | dtlsErrorString() const |
bool | handleTimeout(QUdpSocket *socket) |
QDtls::HandshakeState | handshakeState() const |
void | ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore) |
bool | isConnectionEncrypted() const |
quint16 | mtuHint() const |
QHostAddress | peerAddress() const |
quint16 | peerPort() const |
QList<QSslError> | peerVerificationErrors() const |
QString | peerVerificationName() const |
bool | resumeHandshake(QUdpSocket *socket) |
QSslCipher | sessionCipher() const |
QSsl::SslProtocol | sessionProtocol() const |
bool | setCookieGeneratorParameters(const QDtls::GeneratorParameters ¶ms) |
bool | setDtlsConfiguration(const QSslConfiguration &configuration) |
void | setMtuHint(quint16 mtuHint) |
bool | setPeer(const QHostAddress &address, quint16 port, const QString &verificationName = {}) |
bool | setPeerVerificationName(const QString &name) |
bool | shutdown(QUdpSocket *socket) |
QSslSocket::SslMode | sslMode() const |
qint64 | writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) |
信号
void | 握手超时() |
void | pskRequired(QSslPreSharedKeyAuthenticator *authenticator) |
相关非成员
枚举类 | QDtlsError { NoError, InvalidInputParameters, InvalidOperation, UnderlyingSocketError, RemoteClosedConnectionError, …, TlsNonFatalError } |
详细描述
QDtls类可用来通过用户数据报协议(UDP)与网络对等实体建立安全连接。在无连接的UDP上进行的DTLS连接意味着两个对等实体必须首先成功完成TLS握手,通过调用doHandshake()。握手完成后,可以使用writeDatagramEncrypted()向对等实体发送加密数据报。来自对等实体的加密数据报可以通过decryptDatagram()进行解密。
QDtls设计用于与QUdpSocket协同工作。由于QUdpSocket可以接收来自不同对等实体的数据报,应用程序必须实现多路复用,将来自不同对等实体的数据报转发到它们对应的QDtls实例。可以使用对等实体的地址和端口号建立网络对等实体与其QDtls对象之间的关联。在开始握手之前,必须使用setPeer()设置对等实体的地址和端口号。
QDtls不会从QUdpSocket中读取数据报,这应由应用程序来完成,例如,附加在QUdpSocket::readyRead()信号上的槽中。然后必须由QDtls处理这些数据报。
注意:QDtls不会保留QUdpSocket对象的所有权。
通常,在握手阶段,对等双方将接收和发送多个数据报。在读取数据报时,服务器和客户端必须将这些数据报传递给doHandshake(),直到发现错误或handshakeState()返回HandshakeComplete。
// A client initiates a handshake: QUdpSocket clientSocket; QDtls clientDtls; clientDtls.setPeer(address, port, peerName); clientDtls.doHandshake(&clientSocket); // A server accepting an incoming connection; address, port, clientHello are // read by QUdpSocket::readDatagram(): QByteArray clientHello(serverSocket.pendingDatagramSize(), Qt::Uninitialized); QHostAddress address; quin16 port = {}; serverSocket.readDatagram(clientHello.data(), clientHello.size(), &address, &port); QDtls serverDtls; serverDtls.setPeer(address, port); serverDtls.doHandshake(&serverSocket, clientHello); // Handshake completion, both for server and client: void DtlsConnection::continueHandshake(const QByteArray &datagram) { if (dtls.doHandshake(&udpSocket, datagram)) { // Check handshake status: if (dtls.handshakeStatus() == QDlts::HandshakeComplete) { // Secure DTLS connection is now established. } } else { // Error handling. } }
对于服务器,对doHandshake()的第一个调用需要一个包含ClientHello消息的非空数据报。如果服务器还部署了QDtlsClientVerifier,则期望第一个ClientHello消息是由QDtlsClientVerifier验证的。
如果在握手过程中无法验证对等实体的身份,则必须检查peerVerificationErrors()返回的错误,然后通过调用ignoreVerificationErrors()忽略错误,或通过调用abortHandshake()终止握手。如果忽略错误,则可以通过调用resumeHandshake()来恢复握手。
握手完成后,可以安全地向网络对等实体发送和接收数据报
// Sending an encrypted datagram: dtlsConnection.writeDatagramEncrypted(&clientSocket, "Hello DTLS server!"); // Decryption: QByteArray encryptedMessage(dgramSize); socket.readDatagram(encryptedMessage.data(), dgramSize); const QByteArray plainText = dtlsConnection.decryptDatagram(&socket, encryptedMessage);
可以使用shutdown()关闭DTLS连接。
DtlsClient::~DtlsClient() { clientDtls.shutdown(&clientSocket); }
警告:如果您计划稍后重新使用相同的端口号连接到服务器,则建议在销毁客户端的QDtls对象之前调用shutdown()。否则,服务器可能会丢弃传入的ClientHello消息,有关更多信息和建议,请参阅RFC 6347,第4.2.8节。
如果服务器不使用QDtlsClientVerifier,它必须配置其QDtls对象以禁用cookie验证程序。
auto config = QSslConfiguration::defaultDtlsConfiguration(); config.setDtlsCookieVerificationEnabled(false); // Some other customization ... dtlsConnection.setDtlsConfiguration(config);
使用非默认生成器参数进行cookie验证的服务器必须在开始握手之前为其QDtls对象设置相同的参数。
注意:DTLS协议将最大传输单元(PMTU)发现留给应用程序。应用程序可以使用setMtuHint()()提供QDtls的MTU。此提示仅影响握手阶段,因为只有握手消息可以被DTLS进行分段和重新组装。应用程序发送的所有其他消息必须适合单个数据报。
注意:DTLS特定标题会增加应用程序数据的一些开销,从而进一步减小可能的消息大小。
警告:配置为用HelloVerifyRequest进行回复的服务器将丢弃所有分段客户端Hello消息,永远不启动握手。
另请参阅:QUdpSocket、QDtlsClientVerifier、HandshakeState、QDtlsError和QSslConfiguration。
成员类型文档
[别名]
QDtls::GeneratorParameters
enum QDtls::HandshakeState
描述DTLS握手当前状态。
此枚举描述了QDtls连接的DTLS握手的当前状态。
常量 | 值 | 描述 |
---|---|---|
QDtls::HandshakeNotStarted | 0 | 尚未进行任何操作。 |
QDtls::HandshakeInProgress | 1 | 握手已启动且迄今为止未发现任何错误。 |
QDtls::PeerVerificationFailed | 2 | 无法建立对等方的身份。 |
QDtls::HandshakeComplete | 3 | 握手成功完成并建立了加密连接。 |
成员函数文档
[显式]
QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent = nullptr)
创建一个QDtls对象,parent传递给QObject构造函数。 mode为服务器端DTLS连接的QSslSocket::SslServerMode或客户端的QSslSocket::SslClientMode。
另请参阅:sslMode()和QSslSocket::SslMode。
[虚拟 noexcept]
QDtls::~QDtls()
销毁QDtls对象。
bool QDtls::abortHandshake(QUdpSocket *socket)
中止当前的握手。如果socket上正在进行一个,则返回true;否则,设置合适的错误并返回false。
另请参阅:doHandshake()和resumeHandshake。
QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const
返回当前的哈希算法和密钥,为默认值或通过setCookieGeneratorParameters()()提前设置的。
默认的哈希算法是QCryptographicHash::Sha256,如果Qt配置支持它,否则是QCryptographicHash::Sha1。默认密钥从后端特定的密码学强伪随机数生成器获得。
另请参阅 setCookieGeneratorParameters(),QDtlsClientVerifier和cookieGeneratorParameters()。
QByteArray QDtls::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram)
解密dgram并返回其纯文本内容。必须在完成握手之前才能解密数据报。根据TLS消息的类型,连接可能会写入socket,它必须是一个有效的指针。
bool QDtls::doHandshake(QUdpSocket *socket, const QByteArray &dgram = {})
开始或继续一个DTLS握手。必须有效指针的socket。在启动服务器端DTLS握手时,dgram必须包含从QUdpSocket读取的初始ClientHello消息。此函数在没有发现错误的情况下返回true
。可以使用handshakeState()测试握手状态。false
返回值表示发生了某些错误,请使用dtlsError()获取更详细的信息。
注意:如果无法建立对等方的身份,错误将被设置为QDtlsError::PeerVerificationError。如果您想忽略验证错误并继续连接,必须调用ignoreVerificationErrors()然后调用resumeHandshake()。如果错误不能忽略,您必须调用abortHandshake()。
if (!dtls.doHandshake(&socket, dgram)) { if (dtls.dtlsError() == QDtlsError::PeerVerificationError) dtls.abortAfterError(&socket); }
另请参阅 handshakeState(),dtlsError(),ignoreVerificationErrors(),resumeHandshake()和abortHandshake()。
QSslConfiguration QDtls::dtlsConfiguration() const
返回默认DTLS配置,或先前的调用中设置的配置setDtlsConfiguration()。
另请参阅 setDtlsConfiguration()和QSslConfiguration::defaultDtlsConfiguration()。
QDtlsError QDtls::dtlsError() const
返回连接遇到的最后一个错误或QDtlsError::NoError。
另请参阅 dtlsErrorString()和QDtlsError。
QString QDtls::dtlsErrorString() const
返回连接遇到的最后一个错误的文本描述,或空字符串。
另请参阅 dtlsError。
bool QDtls::handleTimeout(QUdpSocket *socket)
如果在握手过程中发生超时,会发出 handshakeTimeout() 信号。应用程序必须调用 handleTimeout() 以重新发送握手消息;如果发生超时,handleTimeout() 返回 true
,否则返回 false。 socket 必须是一个有效的指针。
另请参阅handshakeTimeout。
QDtls::HandshakeState QDtls::handshakeState() const
返回此 QDtls 的当前握手状态。
另请参阅doHandshake() 和 QDtls::HandshakeState。
[信号]
void QDtls::handshakeTimeout()
数据包丢失可能导致握手阶段出现超时。在这种情况下,QDtls 会发出 handshakeTimeout() 信号。调用 handleTimeout() 重新发送握手消息
DtlsClient::DtlsClient() { // Some initialization code here ... connect(&clientDtls, &QDtls::handshakeTimeout, this, &DtlsClient::handleTimeout); } void DtlsClient::handleTimeout() { clientDtls.handleTimeout(&clientSocket); }
另请参阅handleTimeout。
void QDtls::ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore)
此方法告诉 QDtls 忽略仅在 errorsToIgnore 中给出的错误。
例如,如果您想连接到使用自签名证书的服务器,请考虑以下片段
QList<QSslCertificate> cert = QSslCertificate::fromPath("server-certificate.pem"_L1); QSslError error(QSslError::SelfSignedCertificate, cert.at(0)); QList<QSslError> expectedSslErrors; expectedSslErrors.append(error); QDtls dtls; dtls.ignoreVerificationErrors(expectedSslErrors); dtls.doHandshake(udpSocket);
您还可以在 doHandshake() 遇到 QDtlsError::PeerVerificationError 错误后调用此函数,然后通过调用 resumeHandshake() 继续握手。
稍后对此函数的调用将替换先前调用中传入的错误列表。您可以通过调用此函数并传入空列表来清除要忽略的错误列表。
另请参阅doHandshake、resumeHandshake 和 QSslError。
bool QDtls::isConnectionEncrypted() const
如果 DTLS 握手成功完成,则返回 true
。
另请参阅doHandshake 和 handshakeState。
quint16 QDtls::mtuHint() const
返回先前由 setMtuHint() 设置的值。默认值为 0。
另请参阅setMtuHint。
QHostAddress QDtls::peerAddress() const
返回对端地址,由 setPeer() 设置,或 QHostAddress::Null。
另请参阅setPeer。
quint16 QDtls::peerPort() const
返回对端端口号,由 setPeer() 设置,或 0。
另请参阅setPeer。
QList<QSslError> QDtls::peerVerificationErrors() const
返回在建立对端身份时找到的错误。
如果您希望在发生错误的情况下继续连接,您必须调用ignoreVerificationErrors()。
QString QDtls::peerVerificationName() const
返回由setPeer()或setPeerVerificationName()设置的域名。默认值是一个空字符串。
另见 setPeerVerificationName()和setPeer()。
[信号]
void QDtls::pskRequired(QSslPreSharedKeyAuthenticator *authenticator)
QDtls在协商PSK加密套件时发出此信号,因此需要PSK认证。
当使用PSK时,客户端必须向服务器发送有效的身份和有效的预共享密钥,以便TLS握手继续。应用程序可以通过将连接到此信号的槽中提供此信息,并根据需要填充传递的authenticator对象来实现。
注意: 忽略此信号或未能提供所需的凭据,将导致握手失败,因此连接将被终止。
注意: authenticator对象由QDtls所有,应用程序不得删除。
另见 QSslPreSharedKeyAuthenticator。
bool QDtls::resumeHandshake(QUdpSocket *socket)
如果在握手过程中忽略了对方验证错误,resumeHandshake()将恢复并完成握手并返回true
。socket必须是一个有效的指针。如果无法恢复握手,则返回false
。
另见 doHandshake(),abortHandshake(),peerVerificationErrors()和ignoreVerificationErrors。
QSslCipher QDtls::sessionCipher() const
返回此连接使用的加密加密器,如果不是加密连接,则返回空加密器。在握手阶段选择会话加密器。加密用于加密和解密数据。
QSslConfiguration提供了设置握手阶段最终选择会话加密器的加密器顺序列表的函数。此有序列表必须在握手阶段开始之前就绪。
另见 QSslConfiguration,setDtlsConfiguration和dtlsConfiguration。
QSsl::SslProtocol QDtls::sessionProtocol() const
返回此连接使用的DTLS协议版本,如果连接尚未加密,则返回UnknownProtocol。连接的协议是在握手阶段选择的。
在握手开始之前,可以使用setDtlsConfiguration设置首选版本。
另见 setDtlsConfiguration,QSslConfiguration,QSslConfiguration::defaultDtlsConfiguration和QSslConfiguration::setProtocol。
bool QDtls::setCookieGeneratorParameters(const QDtls::GeneratorParameters ¶ms)
从params设置加密散列算法和密钥。此函数仅用于服务器端QDtls连接。如果成功,则返回true。
注意:此函数必须在握手开始前调用。
另请参阅:cookieGeneratorParameters(),doHandshake(),QDtlsClientVerifier和QDtlsClientVerifier::cookieGeneratorParameters。
bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)
从configuration设置连接的TLS配置并返回成功的true。
注意:此函数必须在握手开始前调用。
另请参阅:dtlsConfiguration()和doHandshake。
void QDtls::setMtuHint(quint16 mtuHint)
mtuHint是最大传输单元(MTU),可以是应用程序发现或猜测的。应用程序不必设置此值。
另请参阅:mtuHint()和QAbstractSocket::PathMtuSocketOption。
bool QDtls::setPeer(const QHostAddress &address, quint16 port, const QString &verificationName = {})
设置对等方的地址、端口和主机名,如果成功则返回true。address不得为空、组播或多播。verificationName是进行证书验证所使用的主机名。
另请参阅:peerAddress,peerPort和peerVerificationName。
bool QDtls::setPeerVerificationName(const QString &name)
设置用于证书验证的名称,如果成功则返回true。
注意:此函数必须在握手开始前调用。
另请参阅:peerVerificationName和setPeer。
bool QDtls::shutdown(QUdpSocket *socket)
发送加密的关闭警告消息并关闭DTLS连接。握手状态更改为QDtls::HandshakeNotStarted。socket必须是一个有效的指针。此函数成功时返回true。
另请参阅:doHandshake()。
QSslSocket::SslMode QDtls::sslMode() const
对于服务器端连接,返回QSslSocket::SslServerMode,对于客户端则返回QSslSocket::SslClientMode。
另请参阅:QDtls和QSslSocket::SslMode。
qint64 QDtls::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram)
对dgram进行加密并将其加密数据写入socket。返回写入的字节数,或者在出错的情况下返回-1。必须完成握手才能写入加密数据。socket必须是一个有效的指针。
另请参阅doHandshake(),handshakeState(),isConnectionEncrypted()和dtlsError()。
相关非成员
枚举类QDtlsError
描述QDtls和QDtlsClientVerifier可以找到的错误。
此枚举描述了QDtlsClientVerifier类和QDtls类对象可能遇到的通用和TLS特定错误。
常量 | 值 | 描述 |
---|---|---|
QDtls::QDtlsError::NoError | 0 | 没有发生错误,上次操作成功。 |
QDtls::QDtlsError::InvalidInputParameters | 1 | 调用者提供的输入参数无效。 |
QDtls::QDtlsError::InvalidOperation | 2 | 在一个不允许该操作的状态下尝试了一个操作。 |
QDtls::QDtlsError::UnderlyingSocketError | 3 | QUdpSocket::writeDatagram()失败,QUdpSocket::error()和QUdpSocket::errorString()可以提供更具体的信息。 |
QDtls::QDtlsError::RemoteClosedConnectionError | 4 | 收到了TLS关闭警报消息。 |
QDtls::QDtlsError::PeerVerificationError | 5 | 在TLS握手过程中无法验证对等方的身份。 |
QDtls::QDtlsError::TlsInitializationError | 6 | 在初始化底层TLS后端时出现错误。 |
QDtls::QDtlsError::TlsFatalError | 7 | 在TLS握手过程中发生了致命错误,除了对等方验证错误或TLS初始化错误之外。 |
QDtls::QDtlsError::TlsNonFatalError | 8 | 加密或解密数据包失败,非致命的,意味着QDtls在出现此错误后可以继续工作。 |
© 2024 The Qt Company Ltd。此处包含的文档贡献的版权属于其各自的所有者。此处提供的文档根据自由软件基金会发布的GNU自由文档许可协议版本1.3的条款进行许可。Qt及其相应标志是芬兰The Qt Company Ltd和/或其他国家的商标。所有其他商标均为其各自所有者的财产。