ssl — modul SSL/TLS¶
Tento modul poskytuje přístup k šifrování Transport Layer Security (dříve a obecně známému jako „Secure Sockets Layer“) a k mechanismům ověřování protistrany pro síťové sockety, a to jak na straně klienta, tak na straně serveru.
Tip
Začínáte s TLS na kameře? Začněte tutoriálem Práce s TLS certifikáty. Provede vás výběrem typů klíčů, vytvořením a převodem certifikátů do formátu DER, který kamera vyžaduje, jejich přenosem do zařízení a ověřováním serverů i klientů – včetně kompletních funkčních příkladů.
Poznámka
MicroPython neimplementuje ssl.SSLError. Chyby SSL/TLS jsou místo toho vyvolávány jako OSError.
Příklady¶
TLS klient, ověřující certifikát serveru proti certifikátu CA (ve formátu DER) uloženému v souborovém systému:
import socket
import ssl
import ntptime
# CERT_REQUIRED checks the certificate's validity dates, so the clock
# must be set (see the certificates tutorial linked above).
ntptime.settime()
# Open a plain TCP connection.
addr = socket.getaddrinfo("example.com", 443)[0][-1]
sock = socket.socket()
sock.connect(addr)
# Wrap it for TLS and require a valid certificate.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="ca.der")
ssock = ctx.wrap_socket(sock, server_hostname="example.com")
ssock.write(b"GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
print(ssock.read())
ssock.close()
Pro rychlé, nezabezpečené připojení (bez ověřování certifikátu) lze místo toho použít pomocnou funkci ssl.wrap_socket()
ssock = ssl.wrap_socket(sock, server_hostname="example.com")
TLS server, předkládající svůj vlastní certifikát a soukromý klíč (formát DER):
import socket
import ssl
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(socket.getaddrinfo("0.0.0.0", 8443)[0][-1])
sock.listen(1)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("server.der", "server.key")
while True:
client, addr = sock.accept()
sclient = ctx.wrap_socket(client, server_side=True)
sclient.write(b"hello\n")
sclient.close()
Funkce¶
- ssl.wrap_socket(sock: Any, server_side: bool = False, key: bytes | None = None, cert: bytes | None = None, cert_reqs: int = CERT_NONE, cadata: bytes | None = None, server_hostname: str | None = None, do_handshake: bool = True) Any¶
Obalí daný sock a vrátí nový objekt obaleného socketu. Implementace této funkce nejprve vytvoří
SSLContexta poté nad tímto kontextovým objektem zavolá metoduSSLContext.wrap_socket(). Argumenty sock, server_side a server_hostname jsou beze změny předány volání metody. Argument do_handshake je předán jako do_handshake_on_connect. Zbývající argumenty mají následující chování:cert_reqs určuje, zda protistrana (server nebo klient) musí předložit platný certifikát. Vezměte na vědomí, že
ssl.CERT_NONEassl.CERT_OPTIONALneověřují žádný certifikát; činí tak pouzessl.CERT_REQUIRED.cadata je objekt typu bytes obsahující řetězec certifikátů CA (ve formátu DER), který bude ověřovat certifikát protistrany. Aktuálně je podporován pouze jediný certifikát zakódovaný v DER.
Třídy¶
- class ssl.SSLContext(protocol: int, /)¶
Vytvoří novou instanci SSLContext. Argument protocol musí být jednou z konstant
PROTOCOL_*.- load_cert_chain(certfile: str | bytes, keyfile: str | bytes) None¶
Načte soukromý klíč a odpovídající certifikát. certfile je řetězec s cestou k souboru certifikátu. keyfile je řetězec s cestou k souboru soukromého klíče.
Rozdíl oproti CPythonu
Rozšíření MicroPythonu: certfile a keyfile mohou být místo řetězců objekty typu bytes, v takovém případě jsou interpretovány jako vlastní data certifikátu/klíče.
- load_verify_locations(cafile: str | None = None, cadata: bytes | None = None) None¶
Načte řetězec certifikátů CA, který bude ověřovat certifikát protistrany. cafile je cesta k souboru certifikátů CA. cadata je objekt typu bytes obsahující certifikáty CA. Měl by být uveden pouze jeden z těchto argumentů.
- set_ciphers(ciphers: List[str]) None¶
Nastaví dostupné šifry pro sockety vytvořené s tímto kontextem. ciphers by měl být seznam řetězců ve formátu sad šifer IANA .
- wrap_socket(sock: Any, *, server_side: bool = False, do_handshake_on_connect: bool = True, server_hostname: str | None = None, client_id: bytes | None = None) Any¶
Přijímá stream sock (obvykle instanci socket.socket typu
SOCK_STREAM) a vrací instanci ssl.SSLSocket, která obaluje podkladový stream. Vrácený objekt má obvyklé metody rozhraní stream, jakoread(),write()atd.server_side vybírá, zda je obalený socket na straně serveru, nebo klienta. SSL socket na straně serveru by měl být vytvořen z běžného socketu vráceného metodou
accept()na naslouchajícím serverovém socketu bez SSL.do_handshake_on_connect určuje, zda se handshake provede jako součást
wrap_socket, nebo zda se jeho provedení odloží na první čtení či zápisy. Pro blokující sockety je standardem provést handshake okamžitě. Pro neblokující sockety (tj. když je sock předaný dowrap_socketv neblokujícím režimu) by měl být handshake obvykle odložen, protože jinakwrap_socketblokuje, dokud se nedokončí.server_hostname slouží pro použití na straně klienta a nastavuje název hostitele, který se má kontrolovat proti přijatému certifikátu serveru. Nastavuje také název pro Server Name Indication (SNI), což serveru umožňuje předložit správný certifikát.
client_id je argument specifický pro MicroPython, používaný pouze při implementaci DTLS serveru. Podrobnosti viz Podpora DTLS.
Varování
Ve výchozím nastavení není prováděno žádné ověřování certifikátu (
ssl.CERT_NONE). Pro zabezpečené připojení musíte ověřit certifikát protistrany nastavením cert_reqs /SSLContext.verify_modenassl.CERT_REQUIRED; jinak je připojení zranitelné vůči útokům typu man-in-the-middle.wrap_socketv CPythonu vrací objektSSLSocket, který má metody typické pro sockety, jakosend,recvatd.wrap_socketv MicroPythonu vrací objekt podobnější objektuSSLObjectz CPythonu, který tyto metody socketu nemá.
- verify_mode¶
Nastaví nebo získá chování ověřování certifikátů protistrany. Musí být jednou z konstant
CERT_*.Poznámka
ssl.CERT_REQUIREDvyžaduje, aby bylo na zařízení správně nastaveno datum/čas, např. pomocí mpremote rtc --set nebontptime, a na straně klienta musí být uvedenserver_hostname.
Podpora DTLS¶
Rozdíl oproti CPythonu
Toto je rozšíření MicroPythonu.
Tento modul podporuje DTLS v klientském i serverovém režimu prostřednictvím konstant PROTOCOL_DTLS_CLIENT a PROTOCOL_DTLS_SERVER, které lze použít jako argument protocol třídy SSLContext.
V tomto případě se očekává, že se podkladový socket chová jako datagramový socket (tj. jako socket otevřený pomocí socket.socket s socket.AF_INET jako af a socket.SOCK_DGRAM jako type).
Podpora DTLS serveru¶
Podpora DTLS serveru v MicroPythonu je nakonfigurována s „Hello Verify“, jak vyžaduje DTLS 1.2. To je pro DTLS klienty transparentní, ale při implementaci DTLS serveru v MicroPythonu je třeba vzít v úvahu několik souvislostí:
Server by měl při volání
SSLContext.wrap_socket()předat dodatečný argument client_id. Tímto ID musí být objekt typubytes(nebo podobný) s identifikátorem specifickým pro daný transport, který reprezentuje klienta.Nejjednodušší přístup je převést na bajtový řetězec n-tici
(client_ip, client_port)vrácenou zsocket.recv_from(), tj.:_, client_addr = sock.recvfrom(1, socket.MSG_PEEK) sock.connect(client_addr) # Connect back to the client sock = ssl_ctx.wrap_socket(sock, server_side=True, client_id=repr(client_addr).encode())
Při prvním připojení klienta volání
wrap_socketna serveru selže s chybouOSError„Hello Verify Required“. Je to proto, že DTLS cookie „Hello Verify“ klient zatím nezná. Pokud se tentýž klient připojí podruhé,wrap_socketuspěje.DTLS cookies pro „Hello Verify“ jsou asociovány s objektem
SSLContext, takže k obalení následného připojení od téhož klienta by měl být použit tentýž objektSSLContext. Implementace cookies zahrnuje časový limit a má konstantní spotřebu paměti bez ohledu na to, kolik klientů se připojí, takže je v pořádku používat tentýž objektSSLContextpo celou dobu životnosti serveru.
Konstanty¶
- ssl.PROTOCOL_TLS_CLIENT: int¶
Podporovaná hodnota parametru protocol, vybírající klientský režim TLS.
- ssl.PROTOCOL_TLS_SERVER: int¶
Podporovaná hodnota parametru protocol, vybírající serverový režim TLS.
- ssl.PROTOCOL_DTLS_CLIENT: int¶
Podporovaná hodnota parametru protocol, vybírající klientský režim DTLS.
- ssl.PROTOCOL_DTLS_SERVER: int¶
Podporovaná hodnota parametru protocol, vybírající serverový režim DTLS.
- ssl.CERT_NONE: int¶
Podporovaná hodnota parametru cert_reqs a atributu
SSLContext.verify_mode. U protistrany se neprovádí žádné ověřování certifikátu.
- ssl.CERT_OPTIONAL: int¶
Podporovaná hodnota parametru cert_reqs a atributu
SSLContext.verify_mode. Ověření certifikátu je volitelné. Vezměte na vědomí, že na OpenMV Cam se chová jakossl.CERT_NONE.
- ssl.CERT_REQUIRED: int¶
Podporovaná hodnota parametru cert_reqs a atributu
SSLContext.verify_mode. Od protistrany je vyžadován platný certifikát.