Sur cette page

QDtls Class

Cette classe assure le chiffrement des sockets UDP. Plus d'informations...

En-tête : #include <QDtls>
CMake : find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake : QT += network
Héritages : QObject

Types publics

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

Fonctions publiques

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)

Signaux

void handshakeTimeout()
void pskRequired(QSslPreSharedKeyAuthenticator *authenticator)
enum class QDtlsError { NoError, InvalidInputParameters, InvalidOperation, UnderlyingSocketError, RemoteClosedConnectionError, …, TlsNonFatalError }

Description détaillée

La classe QDtls peut être utilisée pour établir une connexion sécurisée avec un pair du réseau en utilisant le protocole User Datagram Protocol (UDP). La connexion DTLS sur un protocole UDP essentiellement sans connexion signifie que les deux homologues doivent d'abord réussir une poignée de main TLS en appelant doHandshake(). Une fois la poignée de main terminée, des datagrammes chiffrés peuvent être envoyés à l'homologue en utilisant writeDatagramEncrypted(). Les datagrammes cryptés provenant de l'homologue peuvent être décryptés à l'aide de decryptDatagram().

QDtls est conçu pour fonctionner avec QUdpSocket. Étant donné que QUdpSocket peut recevoir des datagrammes provenant de différents pairs, une application doit mettre en œuvre le démultiplexage, en transmettant les datagrammes provenant de différents pairs à leurs instances correspondantes de QDtls. Une association entre un pair du réseau et son objet QDtls peut être établie en utilisant l'adresse et le numéro de port du pair. Avant de commencer une poignée de main, l'application doit définir l'adresse et le numéro de port de l'homologue à l'aide de setPeer().

QDtls ne lit pas les datagrammes de QUdpSocket, l'application doit le faire, par exemple, dans une fente attachée au signal QUdpSocket::readyRead(). Ces datagrammes doivent ensuite être traités par QDtls.

Remarque : QDtls n'est pas propriétaire de l'objet QUdpSocket.

Normalement, plusieurs datagrammes doivent être reçus et envoyés par les deux pairs pendant la phase de poignée de main. Lors de la lecture des datagrammes, le serveur et le client doivent transmettre ces datagrammes à doHandshake() jusqu'à ce qu'une erreur soit détectée ou que handshakeState() renvoie 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.
    }
}

Pour un serveur, le premier appel à doHandshake() nécessite un datagramme non vide contenant un message ClientHello. Si le serveur déploie également QDtlsClientVerifier, le premier message ClientHello devrait être celui qui a été vérifié par QDtlsClientVerifier.

Si l'identité de l'homologue ne peut pas être validée au cours de la poignée de main, l'application doit examiner les erreurs renvoyées par peerVerificationErrors(), puis soit ignorer les erreurs en appelant ignoreVerificationErrors(), soit interrompre la poignée de main en appelant abortHandshake(). Si les erreurs ont été ignorées, la poignée de main peut être reprise en appelant resumeHandshake().

Une fois la poignée de main terminée, les datagrammes peuvent être envoyés et reçus de l'homologue du réseau en toute sécurité :

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

Une connexion DTLS peut être fermée en utilisant shutdown().

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

Attention : Il est recommandé d'appeler shutdown() avant de détruire l'objet QDtls du client si vous prévoyez de réutiliser le même numéro de port pour vous connecter au serveur ultérieurement. Sinon, le serveur peut laisser tomber les messages ClientHello entrants, voir RFC 6347, section 4.2.8 pour plus de détails et des conseils d'implémentation.

Si le serveur n'utilise pas QDtlsClientVerifier, il doit configurer ses objets QDtls pour désactiver la procédure de vérification des cookies :

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

Un serveur qui utilise la vérification des cookies avec des paramètres de générateur autres que ceux par défaut doit définir les mêmes paramètres pour son objet QDtls avant de commencer la poignée de main.

Note : Le protocole DTLS laisse à l'application le soin de découvrir l'unité de transmission maximale du chemin (PMTU). L'application peut fournir à QDtls le MTU en utilisant setMtuHint(). Ce conseil n'affecte que la phase de poignée de main, puisque seuls les messages de poignée de main peuvent être fragmentés et réassemblés par le DTLS. Tous les autres messages envoyés par l'application doivent tenir dans un seul datagramme.

Remarque : les en-têtes spécifiques au DTLS ajoutent une certaine surcharge aux données de l'application, ce qui réduit encore la taille possible du message.

Attention : Un serveur configuré pour répondre avec HelloVerifyRequest abandonnera tous les messages ClientHello fragmentés, sans jamais commencer une poignée de main.

Les exemples de serveur DTLS et de client DTLS illustrent la manière d'utiliser QDtls dans les applications.

Voir également QUdpSocket, QDtlsClientVerifier, HandshakeState, QDtlsError, et QSslConfiguration.

Documentation sur les types de membres

[alias] QDtls::GeneratorParameters

enum QDtls::HandshakeState

Décrit l'état actuel du handshake DTLS.

Cette énumération décrit l'état actuel du handshake DTLS pour une connexion QDtls.

ConstanteValeurDescription
QDtls::HandshakeNotStarted0Rien n'a encore été fait.
QDtls::HandshakeInProgress1La prise de contact a été initiée et aucune erreur n'a été trouvée jusqu'à présent.
QDtls::PeerVerificationFailed2L'identité de l'homologue ne peut être établie.
QDtls::HandshakeComplete3L'échange s'est déroulé avec succès et une connexion cryptée a été établie.

Voir également QDtls::doHandshake() et QDtls::handshakeState().

Documentation des fonctions membres

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

Crée un objet QDtls, parent est passé au constructeur QObject. mode est QSslSocket::SslServerMode pour une connexion DTLS côté serveur ou QSslSocket::SslClientMode pour un client.

Voir également sslMode() et QSslSocket::SslMode.

[virtual noexcept] QDtls::~QDtls()

Détruit l'objet QDtls.

bool QDtls::abortHandshake(QUdpSocket *socket)

Abandonne la poignée de main en cours. Retourne vrai si une poignée de main était en cours sur socket; sinon, met en place une erreur appropriée et retourne faux.

Voir aussi doHandshake() et resumeHandshake().

QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const

Renvoie l'algorithme de hachage et le secret actuels, soit ceux par défaut, soit ceux précédemment définis par un appel à setCookieGeneratorParameters().

L'algorithme de hachage par défaut est QCryptographicHash::Sha256 si Qt XML a été configuré pour le supporter, QCryptographicHash::Sha1 sinon. Le secret par défaut est obtenu à partir du générateur de nombres pseudo-aléatoires cryptographiquement fort spécifique au backend.

Voir aussi QDtlsClientVerifier et setCookieGeneratorParameters().

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

Décrypte dgram et renvoie son contenu en texte clair. La poignée de main doit être terminée avant que les datagrammes puissent être décryptés. Selon le type de message TLS, la connexion peut écrire dans socket, qui doit être un pointeur valide.

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

Démarre ou poursuit une poignée de main DTLS. socket doit être un pointeur valide. Lors du démarrage d'une poignée de main DTLS côté serveur, dgram doit contenir le message ClientHello initial lu à partir de QUdpSocket. Cette fonction renvoie true si aucune erreur n'a été trouvée. L'état de la poignée de main peut être testé à l'aide de handshakeState(). Le retour de false signifie qu'une erreur s'est produite, utilisez dtlsError() pour obtenir des informations plus détaillées.

Remarque : si l'identité de l'homologue ne peut être établie, l'erreur est renvoyée à QDtlsError::PeerVerificationError. Si vous souhaitez ignorer les erreurs de vérification et continuer à vous connecter, vous devez appeler ignoreVerificationErrors(), puis resumeHandshake(). Si les erreurs ne peuvent pas être ignorées, vous devez appeler abortHandshake().

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

Voir aussi handshakeState(), dtlsError(), ignoreVerificationErrors(), resumeHandshake() et abortHandshake().

QSslConfiguration QDtls::dtlsConfiguration() const

Renvoie soit la configuration DTLS par défaut, soit la configuration définie par un appel antérieur à setDtlsConfiguration().

Voir aussi setDtlsConfiguration() et QSslConfiguration::defaultDtlsConfiguration().

QDtlsError QDtls::dtlsError() const

Renvoie la dernière erreur rencontrée par la connexion ou QDtlsError::NoError.

Voir aussi dtlsErrorString() et QDtlsError.

QString QDtls::dtlsErrorString() const

Renvoie une description textuelle de la dernière erreur rencontrée par la connexion ou une chaîne vide.

Voir aussi dtlsError().

bool QDtls::handleTimeout(QUdpSocket *socket)

Si un dépassement de délai se produit au cours de la poignée de main, le signal handshakeTimeout() est émis. L'application doit appeler handleTimeout() pour retransmettre les messages de la poignée de main ; handleTimeout() renvoie true si un dépassement de délai s'est produit, false dans le cas contraire. socket doit être un pointeur valide.

Voir également handshakeTimeout().

QDtls::HandshakeState QDtls::handshakeState() const

Renvoie l'état actuel de la poignée de main pour cette QDtls.

Voir aussi doHandshake() et QDtls::HandshakeState.

[signal] void QDtls::handshakeTimeout()

La perte de paquets peut entraîner des dépassements de délai pendant la phase d'échange. Dans ce cas, QDtls émet un signal handshakeTimeout(). Appelez handleTimeout() pour retransmettre les messages de prise de contact :

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

void DtlsClient::handleTimeout()
{
    clientDtls.handleTimeout(&clientSocket);
}

Voir aussi handleTimeout().

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

Cette méthode indique à QDtls d'ignorer uniquement les erreurs indiquées dans errorsToIgnore.

Si, par exemple, vous souhaitez vous connecter à un serveur qui utilise un certificat auto-signé, examinez l'extrait suivant :

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

Vous pouvez également appeler cette fonction après que doHandshake() a rencontré l'erreur QDtlsError::PeerVerificationError, puis reprendre la poignée de main en appelant resumeHandshake().

Les appels ultérieurs à cette fonction remplaceront la liste des erreurs transmises lors des appels précédents. Vous pouvez effacer la liste des erreurs que vous souhaitez ignorer en appelant cette fonction avec une liste vide.

Voir aussi doHandshake(), resumeHandshake() et QSslError.

bool QDtls::isConnectionEncrypted() const

Renvoie true si la poignée de main DTLS s'est terminée avec succès.

Voir aussi doHandshake() et handshakeState().

quint16 QDtls::mtuHint() const

Renvoie la valeur précédemment définie par setMtuHint(). La valeur par défaut est 0.

Voir aussi setMtuHint().

QHostAddress QDtls::peerAddress() const

Renvoie l'adresse de l'homologue, définie par setPeer(), ou QHostAddress::Null.

Voir aussi setPeer().

quint16 QDtls::peerPort() const

Renvoie le numéro de port de l'homologue, défini par setPeer(), ou 0.

Voir aussi setPeer().

QList<QSslError> QDtls::peerVerificationErrors() const

Renvoie les erreurs trouvées lors de l'établissement de l'identité de l'homologue.

Si vous voulez continuer à vous connecter malgré les erreurs qui se sont produites, vous devez appeler ignoreVerificationErrors().

QString QDtls::peerVerificationName() const

Renvoie le nom d'hôte défini par setPeer() ou setPeerVerificationName(). La valeur par défaut est une chaîne vide.

Voir aussi setPeerVerificationName() et setPeer().

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

QDtls émet ce signal lorsqu'il négocie une suite de chiffrement PSK, et une authentification PSK est donc nécessaire.

Lors de l'utilisation de la PSK, le client doit envoyer au serveur une identité valide et une clé prépartagée valide, afin que la poignée de main TLS puisse se poursuivre. Les applications peuvent fournir ces informations dans un slot connecté à ce signal, en remplissant l'objet authenticator en fonction de leurs besoins.

Remarque : le fait d'ignorer ce signal ou de ne pas fournir les informations d'identification requises entraîne l'échec de la poignée de main et, par conséquent, l'interruption de la connexion.

Remarque : l'objet authenticator appartient à QDtls et ne doit pas être supprimé par l'application.

Voir aussi QSslPreSharedKeyAuthenticator.

bool QDtls::resumeHandshake(QUdpSocket *socket)

Si les erreurs de vérification de l'homologue ont été ignorées pendant la poignée de main, resumeHandshake() reprend et termine la poignée de main et renvoie true. socket doit être un pointeur valide. Retourne false si la poignée de main n'a pas pu être reprise.

Voir aussi doHandshake(), abortHandshake(), peerVerificationErrors() et ignoreVerificationErrors().

QSslCipher QDtls::sessionCipher() const

Renvoie le code cryptographique cipher utilisé par cette connexion, ou un code nul si la connexion n'est pas cryptée. Le système de chiffrement de la session est sélectionné lors de la phase d'échange de données. Il est utilisé pour chiffrer et déchiffrer les données.

QSslConfiguration fournit des fonctions permettant de définir la liste ordonnée de chiffrements à partir de laquelle la phase de poignée de main sélectionnera finalement le chiffrement de la session. Cette liste ordonnée doit être en place avant le début de la phase de poignée de main.

Voir aussi QSslConfiguration, setDtlsConfiguration(), et dtlsConfiguration().

QSsl::SslProtocol QDtls::sessionProtocol() const

Renvoie la version du protocole DTLS utilisée par cette connexion, ou UnknownProtocol si la connexion n'est pas encore cryptée. Le protocole de la connexion est sélectionné lors de la phase d'échange.

setDtlsConfiguration() peut définir la version préférée avant le début de la poignée de main.

Voir aussi setDtlsConfiguration(), QSslConfiguration, QSslConfiguration::defaultDtlsConfiguration(), et QSslConfiguration::setProtocol().

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

Définit l'algorithme de hachage cryptographique et le secret à partir de params. Cette fonction n'est nécessaire que pour une connexion côté serveur QDtls. Retourne true en cas de succès.

Remarque : cette fonction doit être appelée avant le début de la poignée de main.

Voir aussi cookieGeneratorParameters(), doHandshake(), QDtlsClientVerifier, et QDtlsClientVerifier::cookieGeneratorParameters().

bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)

Définit la configuration TLS de la connexion à partir de configuration et renvoie true en cas de succès.

Remarque : cette fonction doit être appelée avant le début de la poignée de main.

Voir aussi dtlsConfiguration() et doHandshake().

void QDtls::setMtuHint(quint16 mtuHint)

mtuHint est l'unité de transmission maximale (MTU), découverte ou devinée par l'application. L'application n'est pas tenue de définir cette valeur.

Voir également mtuHint() et QAbstractSocket::PathMtuSocketOption.

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

Définit l'adresse de l'homologue, port, et le nom d'hôte et renvoie true en cas de succès. address ne doit pas être null, multicast ou broadcast. verificationName est le nom d'hôte utilisé pour la validation du certificat.

Voir aussi peerAddress(), peerPort() et peerVerificationName().

bool QDtls::setPeerVerificationName(const QString &name)

Définit l'hôte name qui sera utilisé pour la validation du certificat et renvoie true en cas de succès.

Remarque : cette fonction doit être appelée avant le début de la poignée de main.

Voir aussi peerVerificationName() et setPeer().

bool QDtls::shutdown(QUdpSocket *socket)

Envoie un message d'alerte d'arrêt crypté et ferme la connexion DTLS. L'état de la poignée de main passe à QDtls::HandshakeNotStarted. socket doit être un pointeur valide. Cette fonction renvoie true en cas de succès.

Voir aussi doHandshake().

QSslSocket::SslMode QDtls::sslMode() const

Retourne QSslSocket::SslServerMode pour une connexion côté serveur et QSslSocket::SslClientMode pour un client.

Voir aussi QDtls() et QSslSocket::SslMode.

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

Chiffre dgram et écrit les données chiffrées dans socket. Retourne le nombre d'octets écrits, ou -1 en cas d'erreur. La poignée de main doit être terminée avant d'écrire des données cryptées. socket doit être un pointeur valide.

Voir également doHandshake(), handshakeState(), isConnectionEncrypted() et dtlsError().

Non-membres apparentés

enum class QDtlsError

Décrit les erreurs qui peuvent être trouvées par QDtls et QDtlsClientVerifier.

Cette énumération décrit les erreurs générales et spécifiques à TLS qui peuvent être rencontrées par les objets des classes QDtlsClientVerifier et QDtls.

ConstanteValeurDescription de l'erreur
QDtls::QDtlsError::NoError0Aucune erreur ne s'est produite, la dernière opération a réussi.
QDtls::QDtlsError::InvalidInputParameters1Les paramètres d'entrée fournis par un appelant n'étaient pas valides.
QDtls::QDtlsError::InvalidOperation2Une opération a été tentée dans un état qui ne la permettait pas.
QDtls::QDtlsError::UnderlyingSocketError3QUdpSocket::writeDatagram() a échoué, QUdpSocket::error() et QUdpSocket::errorString() peuvent fournir des informations plus spécifiques.
QDtls::QDtlsError::RemoteClosedConnectionError4Un message d'alerte d'arrêt de TLS a été reçu.
QDtls::QDtlsError::PeerVerificationError5L'identité de l'homologue n'a pas pu être vérifiée au cours de l'échange TLS.
QDtls::QDtlsError::TlsInitializationError6Une erreur s'est produite lors de l'initialisation d'un backend TLS sous-jacent.
QDtls::QDtlsError::TlsFatalError7Une erreur fatale s'est produite au cours de l'échange TLS, autre qu'une erreur de vérification de l'homologue ou une erreur d'initialisation TLS.
QDtls::QDtlsError::TlsNonFatalError8Échec du chiffrement ou du déchiffrement d'un datagramme, non fatal, ce qui signifie que QDtls peut continuer à fonctionner après cette erreur.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.