class QDtls#

此类为UDP套接字提供加密。 更多

Inheritance diagram of PySide6.QtNetwork.QDtls

概述#

方法#

信号#

注意

本文档可能包含从 C++ 自动翻译到 Python 的片段。我们始终欢迎对片段翻译的贡献。如果您发现翻译有问题,您也可以通过在 https:/bugreports.qt.io/projects/PYSIDE 上创建工单来通知我们。

详细描述#

警告

本节包含从 C++ 自动翻译到 Python 的片段,可能包含错误。

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:
clientSocket = QUdpSocket()
clientDtls = QDtls()
clientDtls.setPeer(address, port, peerName)
clientDtls.doHandshake(clientSocket)
# A server accepting an incoming connection; address, port, clientHello are
# read by QUdpSocket::readDatagram():
clientHello = QByteArray(serverSocket.pendingDatagramSize(), Qt.Uninitialized)
address = QHostAddress()
port = {}
serverSocket.readDatagram(clientHello.data(), clientHello.size(), address, port)
serverDtls = QDtls()
serverDtls.setPeer(address, port)
serverDtls.doHandshake(serverSocket, clientHello)
# Handshake completion, both for server and client:
def continueHandshake(self, datagram):

    if dtls.doHandshake(udpSocket, datagram):
        # Check handshake status:
        if dtls.handshakeStatus() == QDlts.HandshakeComplete:
            # Secure DTLS connection is now established.

    else:
        # Error handling.

对于服务器,对 doHandshake() 的首次调用需要一个包含客户端问候信息的非空数据报。如果服务器也部署了 QDtlsClientVerifier,则期望第一个客户端问候信息是由 QDtlsClientVerifier 验证的。

如果对方在握手过程中无法验证其身份,应用程序必须检查 peerVerificationErrors() 返回的错误,然后通过调用 ignoreVerificationErrors() 忽略错误或通过调用 abortHandshake() 中断握手。如果忽略错误,可以通过调用 resumeHandshake() 重新启动握手。

握手完成后,可以安全地与网络对等方发送和接收数据报。

# Sending an encrypted datagram:
dtlsConnection.writeDatagramEncrypted(clientSocket, "Hello DTLS server!")
# Decryption:
encryptedMessage = QByteArray(dgramSize)
socket.readDatagram(encryptedMessage.data(), dgramSize)
plainText = dtlsConnection.decryptDatagram(socket, encryptedMessage)

可以使用 shutdown() 关闭 DTLS 连接。

DtlsClient.~DtlsClient()

    clientDtls.shutdown(clientSocket)

警告

建议在销毁客户端的 QDtls 对象之前调用 shutdown(),如果您计划稍后使用相同的端口号连接到服务器。否则,服务器可能会丢弃进入的 ClientHello 消息,请参阅 RFC 6347,第 4.2.8 节以获取更多详细信息和建议的实现线索。

如果服务器没有使用 QDtlsClientVerifier,则 必须 配置其 QDtls 对象以禁用cookie验证过程。

config = QSslConfiguration.defaultDtlsConfiguration()
config.setDtlsCookieVerificationEnabled(False)
# Some other customization ...
dtlsConnection.setDtlsConfiguration(config)

使用非默认生成器参数进行cookie验证的服务器 必须 在握手之前将相同的参数设置为其 QDtls 对象。

注意

DTLS协议将路径最大传输单元(PMTU)发现留给了应用程序。应用程序可以使用 setMtuHint() 将 MTU 提供给 QDtls。此提示仅影响握手阶段,因为只有握手消息可以被DTLS分片和重新组装。所有其他由应用程序发送的消息都必须适合单个数据包。

注意

DTLS特定的头部为应用程序数据添加了一些开销,进一步减少了可能的消息大小。

警告

配置为回复 HelloVerifyRequest 的服务器将丢弃所有分片的 ClientHello 消息,永远不会启动握手。

DTLS服务器DTLS客户端 示例说明了如何在应用程序中使用 QDtls

class HandshakeState#

描述了DTLS握手的当前状态。

此枚举描述了QDtls 连接的当前握手状态。

常量

描述

QDtls.HandshakeNotStarted

还没有做任何事情。

QDtls.HandshakeInProgress

已经启动了握手,且迄今为止没有错误。

QDtls.PeerVerificationFailed

无法建立对等方的身份。

QDtls.HandshakeComplete

握手成功完成,并建立了加密连接。

__init__(mode[, parent=None])#
参数:

创建一个 QDtls 对象,将 parent 传递给 QObject 构造函数。《mode》对于服务器端的 DTLS 连接是 SslServerMode,对于客户端是 SslClientMode

另请参阅

sslMode() SslMode

abortHandshake(socket)#
参数:

socket - QUdpSocket

返回类型:

布尔值

取消正在进行的手动握手。如果 socket 中有一个正在进行的手动过程,则返回 true;否则,设置适当的错误并返回 false。

decryptDatagram(socket, dgram)#
参数:
返回类型:

QByteArray

解密 dgram 并将其内容作为纯文本返回。在解密数据报文之前必须完成手动过程。根据 TLS 消息的类型,连接可能会写入 socket,该 socket 必须是有效的指针。

doHandshake(socket[, dgram={}])#
参数:
返回类型:

布尔值

警告

本节包含从 C++ 自动翻译到 Python 的片段,可能包含错误。

开始或继续 DTLS 握手。参数 socket 需要是一个有效的指针。当开始服务器端 DTLS 握手时,参数 dgram 必须包含从 QUdpSocket 读取的初始 ClientHello 消息。该函数在没有发现错误的情况下返回 true。可以使用 handshakeState() 检测握手状态。false 的返回表示出现了一些错误,可以使用 dtlsError() 获取更详细的信息。

注意

如果无法确定对等方的身份,错误将被设置为 PeerVerificationError。如果想要忽略验证错误并继续连接,必须调用 ignoreVerificationErrors() 然后 resumeHandshake()。如果错误无法忽略,必须调用 abortHandshake()

if not dtls.doHandshake(socket, dgram):
    if dtls.dtlsError() == QDtlsError.PeerVerificationError:
        dtls.abortAfterError(socket)
dtlsConfiguration()#
返回类型:

QSslConfiguration

返回默认 DTLS 配置或通过先前调用 setDtlsConfiguration() 设置的配置。

dtlsError()#
返回类型:

QDtlsError

返回连接遇到的上一个错误或 NoError

另请参阅

dtlsErrorString() QDtlsError

dtlsErrorString()#
返回类型:

str

返回连接遇到的上一个错误的文本描述或空字符串。

另请参阅

dtlsError()

handleTimeout(socket)#
参数:

socket - QUdpSocket

返回类型:

布尔值

如果在握手期间发生超时,将发出 handshakeTimeout() 信号。应用程序必须调用 handleTimeout() 以重新发送握手消息;当发生超时时,handleTimeout() 返回 true,否则返回 false。socket 必须是一个有效的指针。

另请参阅

handshakeTimeout()

handshakeState()#
返回类型:

HandshakeState

返回此 QDtls 的当前握手状态。

handshakeTimeout()#

警告

本节包含从 C++ 自动翻译到 Python 的片段,可能包含错误。

数据包丢失可能导致握手阶段的超时。在这种情况下,QDtls 将发出 handshakeTimeout() 信号。调用 handleTimeout() 以重新发送握手消息

def __init__(self):

    # Some initialization code here ...
    clientDtls.handshakeTimeout.connect(self.handleTimeout)

def handleTimeout(self):

    clientDtls.handleTimeout(clientSocket)

另请参阅

handleTimeout()

ignoreVerificationErrors(errorsToIgnore)#
参数:

errorsToIgnore – .QSslError 列表

警告

本节包含从 C++ 自动翻译到 Python 的片段,可能包含错误。

此方法告诉 QDtls 仅忽略在 errorsToIgnore 中给出的错误。

例如,如果要连接到使用自签名证书的服务器,请考虑以下代码片段

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

您还可以在 doHandshake() 遇到 PeerVerificationError 错误后调用此函数,然后通过调用 resumeHandshake() 恢复握手。

后续调用此函数将替换先前调用传入的错误列表。您可以通过调用此函数并传入空列表来清除您想要忽略的错误列表。

isConnectionEncrypted()#
返回类型:

布尔值

如果 DTLS 握手成功完成,则返回 true

mtuHint()#
返回类型:

整型

返回由 setMtuHint() 设置的值。默认值为 0。

另请参阅

setMtuHint()

peerAddress()#
返回类型:

QHostAddress

返回对等方的地址,由 setPeer() 设置,或 Null

另请参阅

setPeer()

peerPort()#
返回类型:

整型

返回对等方的端口编号,由 setPeer() 设置,或 0。

另请参阅

setPeer()

peerVerificationErrors()#
返回类型:

QSslError 列表

在建立对等方身份时找到的错误。

如果您想要继续连接,尽管已发生错误,您必须调用 ignoreVerificationErrors()

peerVerificationName()#
返回类型:

str

返回由 setPeer()setPeerVerificationName() 设置的域名。默认值为空字符串。

pskRequired(authenticator)#
参数:

认证器QSslPreSharedKeyAuthenticator

QDtls 在协商 PSK 密码组时会发出此信号,因此需要进行 PSK 验证。

使用 PSK 时,客户端必须向服务器发送一个有效的身份和一个有效的预共享密钥,以便 TLS 握手可以继续进行。应用程序可以通过连接到该信号的槽来提供这些信息,根据需求填充传递的 authenticator 对象。

注意

忽略此信号或无法提供所需的凭据,会导致握手失败,从而中断连接。

注意

authenticator 对象属于 QDtls,应用程序不得删除。

resumeHandshake(socket)#
参数:

socket - QUdpSocket

返回类型:

布尔值

如果在握手过程中忽略了 Peer 验证错误,则 resumeHandshake() 会恢复并完成握手并返回 truesocket 必须是一个有效的指针。如果不能恢复握手,则返回 false

sessionCipher()#
返回类型:

QSslCipher

返回此连接使用的加密算法 cipher,如果没有加密,则返回空加密算法。会话密码在握手阶段被选中。密码用于加密和解密数据。

QSslConfiguration 提供了设置在握手阶段将从中选择会话密码的密码顺序列表的函数。在握手阶段开始之前,必须设置这个顺序列表。

sessionProtocol()#
返回类型:

SslProtocol

返回此连接使用的DTLS协议版本,如果连接尚未加密,则返回UnknownProtocol。连接的协议在握手阶段选择。

setDtlsConfiguration()可以在握手开始之前设置首选版本。

setDtlsConfiguration(configuration)#
参数:

configurationQSslConfiguration

返回类型:

布尔值

设置连接的TLS配置为configuration,如果成功则返回true

注意

此函数必须在握手开始之前调用。

setMtuHint(mtuHint)#
参数:

mtuHint – int

mtuHint是最大传输单元(MTU),可以是应用程序发现或猜测的。应用程序无需设置此值。

setPeer(address, port[, verificationName={}])#
参数:
  • addressQHostAddress

  • port – int

  • verificationName – str

返回类型:

布尔值

设置对等方的地址、端口号和主机名,并在成功时返回true。地址address不能为null、多播或广播。 verificationName是用于证书验证的主机名。

setPeerVerificationName(name)#
参数:

name – 字符串

返回类型:

布尔值

设置用于证书验证的主机name并在成功时返回true

注意

此函数必须在握手开始之前调用。

shutdown(socket)#
参数:

socket - QUdpSocket

返回类型:

布尔值

发送加密的关闭警告消息并关闭DTLS连接。握手状态变为HandshakeNotStartedsocket必须是一个有效的指针。此函数成功时返回true

另请参阅

doHandshake()

sslMode()#
返回类型:

SSL模式

对于服务器端连接返回SslServerMode,对于客户端则返回SslClientMode

另请参阅

QDtls() SslMode

writeDatagramEncrypted(socket, dgram)#
参数:
返回类型:

整型

加密dgram并将加密数据写入到socket。返回写入的字节数,或者在出错时返回-1。在写入加密数据之前必须完成握手。 socket必须是一个有效的指针。