QDtls 类

此类为 UDP (用户数据报协议) 套接字提供加密。 更多...

头: #include <QDtls>
CMake: find_package(Qt6 COMPONENTS Network REQUIRED)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network
Since: Qt 5.12
继承: QObject

公共类型

  GeneratorParameters
enum HandshakeState { HandshakeNotStarted, HandshakeInProgress, PeerVerificationFailed, HandshakeComplete }

公共函数

  QDtls (QSslSocket::SslMode mode , QObject * parent = nullptr)
virtual ~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 & params )
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 handshakeTimeout ()
void pskRequired (QSslPreSharedKeyAuthenticator * authenticator )
enum class QDtlsError { NoError, InvalidInputParameters, InvalidOperation, UnderlyingSocketError, RemoteClosedConnectionError, …, TlsNonFatalError }

详细描述

The QDtls class can be used to establish a secure connection with a network peer using User Datagram Protocol (UDP). DTLS connection over essentially connectionless UDP means that two peers first have to successfully complete a TLS handshake by calling doHandshake (). After the handshake has completed, encrypted datagrams can be sent to the peer using writeDatagramEncrypted (). Encrypted datagrams coming from the peer can be decrypted by decryptDatagram ().

QDtls is designed to work with QUdpSocket 。由于 QUdpSocket can receive datagrams coming from different peers, an application must implement demultiplexing, forwarding datagrams coming from different peers to their corresponding instances of QDtls. An association between a network peer and its QDtls object can be established using the peer's address and port number. Before starting a handshake, the application must set the peer's address and port number using setPeer ().

QDtls does not read datagrams from QUdpSocket , this is expected to be done by the application, for example, in a slot attached to the QUdpSocket::readyRead () signal. Then, these datagrams must be processed by QDtls.

注意: QDtls does not 拥有所有权对于 QUdpSocket 对象。

Normally, several datagrams are to be received and sent by both peers during the handshake phase. Upon reading datagrams, server and client must pass these datagrams to doHandshake () until some error is found or 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.
    }
}
					

For a server, the first call to doHandshake () requires a non-empty datagram containing a ClientHello message. If the server also deploys QDtlsClientVerifier , the first ClientHello message is expected to be the one verified by QDtlsClientVerifier .

In case the peer's identity cannot be validated during the handshake, the application must inspect errors returned by peerVerificationErrors () and then either ignore errors by calling ignoreVerificationErrors () or abort the handshake by calling abortHandshake (). If errors were ignored, the handshake can be resumed by calling resumeHandshake ().

After the handshake has been completed, datagrams can be sent to and received from the network peer securely:

// 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);
					

A DTLS connection may be closed using shutdown ().

DtlsClient::~DtlsClient()
{
    clientDtls.shutdown(&clientSocket);
}
					

警告: It's recommended to call shutdown () before destroying the client's QDtls object if you are planning to re-use the same port number to connect to the server later. Otherwise, the server may drop incoming ClientHello messages, see RFC 6347, section 4.2.8 for more details and implementation hints.

If the server does not use QDtlsClientVerifier , it must configure its QDtls objects to disable the cookie verification procedure:

auto config = QSslConfiguration::defaultDtlsConfiguration();
config.setDtlsCookieVerificationEnabled(false);
// Some other customization ...
dtlsConnection.setDtlsConfiguration(config);
					

A server that uses cookie verification with non-default generator parameters must set the same parameters for its QDtls object before starting the handshake.

注意: The DTLS protocol leaves Path Maximum Transmission Unit (PMTU) discovery to the application. The application may provide QDtls with the MTU using setMtuHint (). This hint affects only the handshake phase, since only handshake messages can be fragmented and reassembled by the DTLS. All other messages sent by the application must fit into a single datagram.

注意: DTLS-specific headers add some overhead to application data further reducing the possible message size.

警告: A server configured to reply with HelloVerifyRequest will drop all fragmented ClientHello messages, never starting a handshake.

DTLS 服务器 and DTLS 客户端 examples illustrate how to use QDtls in applications.

另请参阅 QUdpSocket , QDtlsClientVerifier , HandshakeState , QDtlsError ,和 QSslConfiguration .

成员类型文档编制

[alias] QDtls:: GeneratorParameters

[since 5.12] enum QDtls:: HandshakeState

描述 DTLS 握手的当前状态。

This enum describes the current state of DTLS handshake for a QDtls 连接。

常量 描述
QDtls::HandshakeNotStarted 0 什么都没做。
QDtls::HandshakeInProgress 1 握手被初启,且到目前为止没有发现错误。
QDtls::PeerVerificationFailed 2 无法建立对等方身份。
QDtls::HandshakeComplete 3 握手成功完成并建立加密连接。

该枚举在 Qt 5.12 引入或被修改。

另请参阅 QDtls::doHandshake () 和 QDtls::handshakeState ().

成员函数文档编制

QDtls:: QDtls ( QSslSocket::SslMode mode , QObject * parent = nullptr)

创建 QDtls 对象, parent 被传递给 QObject 构造函数。 mode is QSslSocket::SslServerMode for a server-side DTLS connection or QSslSocket::SslClientMode for a client.

另请参阅 sslMode () 和 QSslSocket::SslMode .

[signal] void QDtls:: handshakeTimeout ()

Packet loss can result in timeouts during the handshake phase. In this case QDtls emits a handshakeTimeout() signal. Call handleTimeout () to retransmit the handshake messages:

DtlsClient::DtlsClient()
{
    // Some initialization code here ...
    connect(&clientDtls, &QDtls::handshakeTimeout, this, &DtlsClient::handleTimeout);
}
void DtlsClient::handleTimeout()
{
    clientDtls.handleTimeout(&clientSocket);
}
					

另请参阅 handleTimeout ().

[signal] void QDtls:: pskRequired ( QSslPreSharedKeyAuthenticator * authenticator )

QDtls 发射此信号当它协商 PSK (预共享密钥) 密码套件时,因此接着需要 PSK 身份验证。

When using PSK, the client must send to the server a valid identity and a valid pre shared key, in order for the TLS handshake to continue. Applications can provide this information in a slot connected to this signal, by filling in the passed authenticator 对象根据需要。

注意: 忽略此信号或未能提供要求证书,将导致握手失败,因此连接将被中止。

注意: authenticator object is owned by QDtls and must not be deleted by the application.

另请参阅 QSslPreSharedKeyAuthenticator .

[虚拟] QDtls:: ~QDtls ()

销毁 QDtls 对象。

bool QDtls:: abortHandshake ( QUdpSocket * socket )

Aborts the ongoing handshake. Returns true if one was on-going on socket ; otherwise, sets a suitable error and returns false.

另请参阅 doHandshake () 和 resumeHandshake ().

QDtls::GeneratorParameters QDtls:: cookieGeneratorParameters () const

Returns the current hash algorithm and secret, either default ones or previously set by a call to setCookieGeneratorParameters ().

The default hash algorithm is QCryptographicHash::Sha256 if Qt was configured to support it, QCryptographicHash::Sha1 otherwise. The default secret is obtained from the backend-specific cryptographically strong pseudorandom number generator.

另请参阅 setCookieGeneratorParameters (), QDtlsClientVerifier , and cookieGeneratorParameters().

QByteArray QDtls:: decryptDatagram ( QUdpSocket * socket , const QByteArray & dgram )

Decrypts dgram and returns its contents as plain text. The handshake must be completed before datagrams can be decrypted. Depending on the type of the TLS message the connection may write into socket , which must be a valid pointer.

bool QDtls:: doHandshake ( QUdpSocket * socket , const QByteArray & dgram = {})

Starts or continues a DTLS handshake. socket must be a valid pointer. When starting a server-side DTLS handshake, dgram must contain the initial ClientHello message read from QUdpSocket 。此函数返回 true if no error was found. Handshake state can be tested using handshakeState (). false return means some error occurred, use dtlsError () for more detailed information.

注意: If the identity of the peer can't be established, the error is set to QDtlsError::PeerVerificationError . If you want to ignore verification errors and continue connecting, you must call ignoreVerificationErrors () and then resumeHandshake (). If the errors cannot be ignored, you must call abortHandshake ().

if (!dtls.doHandshake(&socket, dgram)) {
    if (dtls.dtlsError() == QDtlsError::PeerVerificationError)
        dtls.abortAfterError(&socket);
}
					

另请参阅 handshakeState (), dtlsError (), ignoreVerificationErrors (), resumeHandshake (),和 abortHandshake ().

QSslConfiguration QDtls:: dtlsConfiguration () const

Returns either the default DTLS configuration or the configuration set by an earlier call to setDtlsConfiguration ().

另请参阅 setDtlsConfiguration () 和 QSslConfiguration::defaultDtlsConfiguration ().

QDtlsError QDtls:: dtlsError () const

Returns the last error encountered by the connection or QDtlsError::NoError .

另请参阅 dtlsErrorString () 和 QDtlsError .

QString QDtls:: dtlsErrorString () const

Returns a textual description for the last error encountered by the connection or empty string.

另请参阅 dtlsError ().

bool QDtls:: handleTimeout ( QUdpSocket * socket )

If a timeout occurs during the handshake, the handshakeTimeout () signal is emitted. The application must call handleTimeout() to retransmit handshake messages; handleTimeout() returns true if a timeout has occurred, false otherwise. socket must be a valid pointer.

另请参阅 handshakeTimeout ().

QDtls::HandshakeState QDtls:: handshakeState () const

返回当前握手状态为此 QDtls .

另请参阅 doHandshake () 和 QDtls::HandshakeState .

void QDtls:: ignoreVerificationErrors (const QList < QSslError > & errorsToIgnore )

此方法告诉 QDtls 仅忽略的错误给出于 errorsToIgnore .

If, for instance, you want to connect to a server that uses a self-signed certificate, consider the following snippet:

QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem"));
QSslError error(QSslError::SelfSignedCertificate, cert.at(0));
QList<QSslError> expectedSslErrors;
expectedSslErrors.append(error);
QDtls dtls;
dtls.ignoreVerificationErrors(expectedSslErrors);
dtls.doHandshake(udpSocket);
					

You can also call this function after doHandshake () encountered the QDtlsError::PeerVerificationError error, and then resume the handshake by calling resumeHandshake ().

Later calls to this function will replace the list of errors that were passed in previous calls. You can clear the list of errors you want to ignore by calling this function with an empty list.

另请参阅 doHandshake (), resumeHandshake (),和 QSslError .

bool QDtls:: isConnectionEncrypted () const

返回 true if DTLS handshake completed successfully.

另请参阅 doHandshake () 和 handshakeState ().

quint16 QDtls:: mtuHint () const

Returns the value previously set by setMtuHint (). The default value is 0.

另请参阅 setMtuHint ().

QHostAddress QDtls:: peerAddress () const

Returns the peer's address, set by setPeer (),或 QHostAddress::Null .

另请参阅 setPeer ().

quint16 QDtls:: peerPort () const

Returns the peer's port number, set by setPeer (), or 0.

另请参阅 setPeer ().

QList < QSslError > QDtls:: peerVerificationErrors () const

Returns errors found while establishing the identity of the peer.

If you want to continue connecting despite the errors that have occurred, you must call ignoreVerificationErrors ().

QString QDtls:: peerVerificationName () const

Returns the host name set by setPeer () 或 setPeerVerificationName (). The default value is an empty string.

另请参阅 setPeerVerificationName () 和 setPeer ().

bool QDtls:: resumeHandshake ( QUdpSocket * socket )

If peer verification errors were ignored during the handshake, resumeHandshake() resumes and completes the handshake and returns true . socket must be a valid pointer. Returns false if the handshake could not be resumed.

另请参阅 doHandshake (), abortHandshake (), peerVerificationErrors (),和 ignoreVerificationErrors ().

QSslCipher QDtls:: sessionCipher () const

Returns the cryptographic cipher used by this connection, or a null cipher if the connection isn't encrypted. The cipher for the session is selected during the handshake phase. The cipher is used to encrypt and decrypt data.

QSslConfiguration provides functions for setting the ordered list of ciphers from which the handshake phase will eventually select the session cipher. This ordered list must be in place before the handshake phase begins.

另请参阅 QSslConfiguration , setDtlsConfiguration (),和 dtlsConfiguration ().

QSsl::SslProtocol QDtls:: sessionProtocol () const

Returns the DTLS protocol version used by this connection, or UnknownProtocol if the connection isn't encrypted yet. The protocol for the connection is selected during the handshake phase.

setDtlsConfiguration () can set the preferred version before the handshake starts.

另请参阅 setDtlsConfiguration (), QSslConfiguration , QSslConfiguration::defaultDtlsConfiguration (),和 QSslConfiguration::setProtocol ().

bool QDtls:: setCookieGeneratorParameters (const QDtls::GeneratorParameters & params )

Sets the cryptographic hash algorithm and the secret from params . This function is only needed for a server-side QDtls connection. Returns true 若成功。

注意: This function must be called before the handshake starts.

另请参阅 cookieGeneratorParameters (), doHandshake (), QDtlsClientVerifier ,和 QDtlsClientVerifier::cookieGeneratorParameters ().

bool QDtls:: setDtlsConfiguration (const QSslConfiguration & configuration )

Sets the connection's TLS configuration from configuration 并返回 true 若成功。

注意: This function must be called before the handshake starts.

另请参阅 dtlsConfiguration () 和 doHandshake ().

void QDtls:: setMtuHint ( quint16 mtuHint )

mtuHint is the maximum transmission unit (MTU), either discovered or guessed by the application. The application is not required to set this value.

另请参阅 mtuHint () 和 QAbstractSocket::PathMtuSocketOption .

bool QDtls:: setPeer (const QHostAddress & address , quint16 port , const QString & verificationName = {})

Sets the peer's address, port , and host name and returns true 若成功。 address must not be null, multicast, or broadcast. verificationName is the host name used for the certificate validation.

另请参阅 peerAddress (), peerPort (),和 peerVerificationName ().

bool QDtls:: setPeerVerificationName (const QString & name )

Sets the host name that will be used for the certificate validation and returns true 若成功。

注意: This function must be called before the handshake starts.

另请参阅 peerVerificationName () 和 setPeer ().

bool QDtls:: shutdown ( QUdpSocket * socket )

Sends an encrypted shutdown alert message and closes the DTLS connection. Handshake state changes to QDtls::HandshakeNotStarted . socket must be a valid pointer. This function returns true 当成功时。

另请参阅 doHandshake ().

QSslSocket::SslMode QDtls:: sslMode () const

返回 QSslSocket::SslServerMode for a server-side connection and QSslSocket::SslClientMode for a client.

另请参阅 QDtls () 和 QSslSocket::SslMode .

qint64 QDtls:: writeDatagramEncrypted ( QUdpSocket * socket , const QByteArray & dgram )

Encrypts dgram and writes the encrypted data into socket . Returns the number of bytes written, or -1 in case of error. The handshake must be completed before writing encrypted data. socket must be a valid pointer.

另请参阅 doHandshake (), handshakeState (), isConnectionEncrypted (),和 dtlsError ().

相关非成员

[since 5.12] enum class QDtlsError

Describes errors that can be found by QDtls and QDtlsClientVerifier .

This enum describes general and TLS-specific errors that can be encountered by objects of the classes QDtlsClientVerifier and QDtls .

常量 描述
QDtls::QDtlsError::NoError 0 No error occurred, the last operation was successful.
QDtls::QDtlsError::InvalidInputParameters 1 Input parameters provided by a caller were invalid.
QDtls::QDtlsError::InvalidOperation 2 An operation was attempted in a state that did not permit it.
QDtls::QDtlsError::UnderlyingSocketError 3 QUdpSocket::writeDatagram () failed, QUdpSocket::error () 和 QUdpSocket::errorString () can provide more specific information.
QDtls::QDtlsError::RemoteClosedConnectionError 4 TLS shutdown alert message was received.
QDtls::QDtlsError::PeerVerificationError 5 Peer's identity could not be verified during the TLS handshake.
QDtls::QDtlsError::TlsInitializationError 6 An error occurred while initializing an underlying TLS backend.
QDtls::QDtlsError::TlsFatalError 7 A fatal error occurred during TLS handshake, other than peer verification error or TLS initialization error.
QDtls::QDtlsError::TlsNonFatalError 8 A failure to encrypt or decrypt a datagram, non-fatal, meaning QDtls can continue working after this error.

该枚举在 Qt 5.12 引入或被修改。