Spec-Zone.ru › Qt 6.0

Класс QDtls

Этот класс предоставляет шифрование для UDP-сокет. Подробнее...

Заголовок: #include <QDtls>
CMake: find_package(Qt6 COMPONENTS Network REQUIRED) target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network
С момента: Qt 5.12
Наследует: QObject
  • Список всех членов, включая унаследованные члены

Открытые типы

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

Связанные нечлены

Перечисление QDtlsError { NoError, InvalidInputParameters, InvalidOperation, UnderlyingSocketError, RemoteClosedConnectionError, …, TlsNonFatalError }

Подробное описание

Класс QDtls может использоваться для установления защищённого соединения с узлом сети, использующим протокол пользователя Datagram (UDP). DTLS-соединение по фактически бессоединительному UDP означает, что два узла сначала должны успешно завершить 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);

DTLS-соединение может быть закрыто с помощью shutdown().

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

Предупреждение: Рекомендуется вызвать shutdown() перед уничтожением объекта QDtls клиента, если вы планируете повторно использовать тот же номер порта для подключения к серверу позже. В противном случае сервер может отбросить поступающие сообщения ClientHello, см. RFC 6347, раздел 4.2.8 для получения дополнительной информации и советов по реализации.

Если сервер не использует QDtlsClientVerifier, он обязан настроить свои объекты QDtls для отключения процедуры проверки куки:

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

Сервер, использующий проверку cookie с параметрами генератора, отличными от стандартных, обязан установить те же параметры для своего объекта QDtls перед началом рукопожатия.

Примечание: Протокол DTLS перекладывает обнаружение максимального размера передаваемого блока пути (PMTU) на приложение. Приложение может предоставить QDtls размер MTU с помощью setMtuHint(). Этот подсказка влияет только на фазу рукопожатия, поскольку только сообщения рукопожатия могут быть фрагментированы и повторно собраны DTLS. Все остальные сообщения, отправленные приложением, должны помещаться в один датаграмму.

Примечание: DTLS-специфичные заголовки добавляют некоторую избыточность к данным приложения, еще больше уменьшая возможный размер сообщения.

Предупреждение: Сервер, настроенный на ответ с HelloVerifyRequest, отклонит все фрагментированные сообщения ClientHello, никогда не начав рукопожатие.

Примеры сервера DTLS и клиента DTLS демонстрируют, как использовать QDtls в приложениях.

См. также QUdpSocket, QDtlsClientVerifier, HandshakeState, QDtlsError и QSslConfiguration.

Документация по типам членов

[alias] QDtls::GeneratorParameters

[since 5.12] enum QDtls::HandshakeState

Описывает текущее состояние рукопожатия DTLS.

Этот перечисление описывает текущее состояние рукопожатия DTLS для соединения 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 равен QSslSocket::SslServerMode для соединения DTLS на стороне сервера или QSslSocket::SslClientMode для соединения DTLS на стороне клиента.

См. также sslMode() и QSslSocket::SslMode.

[signal] 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().

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

QDtls генерирует этот сигнал, когда он согласовывает криптографический набор PSK, и поэтому требуется аутентификация PSK.

При использовании PSK клиент должен отправить серверу действительную информацию об идентичности и действительный предварительно согласованный ключ, чтобы TLS-рукопожатие продолжилось. Приложения могут предоставить эту информацию в слоте, подключённом к этому сигналу, заполнив переданный объект authenticator в соответствии со своими потребностями.

Примечание: Игнорирование этого сигнала или невозможность предоставить требуемые учетные данные приведут к сбою рукопожатия, а следовательно, к прерыванию соединения.

Примечание: Объект authenticator принадлежит QDtls и не должен удаляться приложением.

См. также QSslPreSharedKeyAuthenticator.

[virtual] QDtls::~QDtls()

Уничтожает объект QDtls.

bool QDtls::abortHandshake(QUdpSocket *socket)

Прерывает текущее рукопожатие. Возвращает true, если оно происходило на socket; в противном случае устанавливает подходящую ошибку и возвращает 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 должен быть валидным указателем. При инициализации рукопожатия на стороне сервера, dgram должен содержать первоначальное сообщение ClientHello, прочитанное из QUdpSocket. Эта функция возвращает 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::ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore)

Этот метод сообщает QDtls игнорировать только ошибки, указанные в errorsToIgnore.

Если, например, вы хотите подключиться к серверу, использующему самоподписанный сертификат, рассмотрите следующий фрагмент:

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

Также можно вызвать эту функцию после того, как функция doHandshake() столкнулась с ошибкой QDtlsError::PeerVerificationError, и затем возобновить рукопожатие, вызвав resumeHandshake().

Позже вызовы этой функции заменят список ошибок, переданных в предыдущих вызовах. Вы можете очистить список ошибок, которые вы хотите игнорировать, вызвав эту функцию со пустым списком.

См. также doHandshake(), resumeHandshake() и QSslError.

bool QDtls::isConnectionEncrypted() const

Возвращает true если рукопожатие DTLS завершилось успешно.

См. также 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().

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 &params)

Устанавливает криптографический алгоритм хэширования и секрет из params. Эта функция необходима только для серверного соединения QDtls. Возвращает true при успешном выполнении.

Примечание: эту функцию необходимо вызвать перед началом рукопожатия.

См. также cookieGeneratorParameters(), doHandshake(), QDtlsClientVerifier и QDtlsClientVerifier::cookieGeneratorParameters().

bool QDtls::setDtlsConfiguration(const QSslConfiguration &configuration)

Устанавливает конфигурацию TLS соединения из configuration и возвращает 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)

Устанавливает имя хоста 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().

Связанные нечлены

[since 5.12] перечисление QDtlsError

Описывает ошибки, которые могут быть обнаружены QDtls и QDtlsClientVerifier.

Это перечисление описывает общие и специфичные для TLS ошибки, которые могут возникнуть у объектов классов QDtlsClientVerifier и QDtls.

Константа Значение Описание
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 может продолжить работу после этой ошибки.

Это перечисление было введено или изменено в Qt 5.12.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.0/qdtls.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API