ssl — SSL/TLS modul¶
Ez a modul hozzáférést biztosít a Transport Layer Security (korábban és széles körben „Secure Sockets Layer” néven ismert) titkosítási és partnerhitelesítési szolgáltatásokhoz a hálózati socketek számára, mind a kliens, mind a szerver oldalon.
Javaslat
Most ismerkedsz a TLS-sel a kamerán? Kezdd a TLS tanúsítványok kezelése oktatóanyaggal. Ez végigvezet a kulcstípusok kiválasztásán, a tanúsítványok létrehozásán és a kamera által megkövetelt DER formátumra való átalakításán, az eszközre juttatásukon, valamint a szerverek és kliensek ellenőrzésén – teljes, működő példákkal.
Megjegyzés
A MicroPython nem valósítja meg az ssl.SSLError kivételt. Az SSL/TLS hibák helyette OSError formájában keletkeznek.
Példák¶
TLS kliens, amely a szerver tanúsítványát egy fájlrendszeren tárolt (DER formátumú) CA-tanúsítvánnyal ellenőrzi:
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()
Gyors, nem biztonságos kapcsolathoz (tanúsítvány-ellenőrzés nélkül) helyette a ssl.wrap_socket() kényelmi függvény használható:
ssock = ssl.wrap_socket(sock, server_hostname="example.com")
TLS szerver, amely saját tanúsítványát és privát kulcsát (DER formátum) mutatja be:
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()
Függvények¶
- 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¶
Csomagolja be a megadott sock objektumot, és adjon vissza egy új, becsomagolt socket objektumot. A függvény megvalósítása először létrehoz egy
SSLContextobjektumot, majd meghívja annakSSLContext.wrap_socket()metódusát. A sock, server_side és server_hostname argumentumok változatlanul kerülnek átadásra a metódushívásnak. A do_handshake argumentum do_handshake_on_connect néven kerül átadásra. A fennmaradó argumentumok az alábbi módon viselkednek:A cert_reqs határozza meg, hogy a partnernek (szervernek vagy kliensnek) érvényes tanúsítványt kell-e bemutatnia. Vedd figyelembe, hogy az
ssl.CERT_NONEés azssl.CERT_OPTIONALnem ellenőriz egyetlen tanúsítványt sem; csak azssl.CERT_REQUIREDteszi ezt.A cadata egy bytes objektum, amely a partner tanúsítványát ellenőrző CA-tanúsítványláncot (DER formátumban) tartalmazza. Jelenleg csak egyetlen DER-kódolású tanúsítvány támogatott.
Osztályok¶
- class ssl.SSLContext(protocol: int, /)¶
Új SSLContext példányt hoz létre. A protocol argumentumnak a
PROTOCOL_*konstansok egyikének kell lennie.- load_cert_chain(certfile: str | bytes, keyfile: str | bytes) None¶
Betölt egy privát kulcsot és a hozzá tartozó tanúsítványt. A certfile egy karakterlánc, amely a tanúsítvány fájl elérési útját adja meg. A keyfile egy karakterlánc, amely a privát kulcs fájl elérési útját adja meg.
Eltérés a CPython-tól
MicroPython kiterjesztés: a certfile és a keyfile karakterláncok helyett bytes objektumok is lehetnek, ebben az esetben magát a tanúsítvány-/kulcsadatot jelentik.
- load_verify_locations(cafile: str | None = None, cadata: bytes | None = None) None¶
Betölti a partner tanúsítványát ellenőrző CA-tanúsítványláncot. A cafile a CA-tanúsítványok fájl elérési útja. A cadata egy bytes objektum, amely a CA-tanúsítványokat tartalmazza. Ezek közül csak az egyik argumentumot szabad megadni.
- get_ciphers() List[str]¶
Lekéri az engedélyezett titkosítók listáját, karakterláncok listájaként visszaadva.
- set_ciphers(ciphers: List[str]) None¶
Beállítja az ezzel a kontextussal létrehozott socketekhez elérhető titkosítókat. A ciphers karakterláncok listája kell legyen az IANA cipher suite formátumban .
- 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¶
Átvesz egy stream sock objektumot (általában egy
SOCK_STREAMtípusú socket.socket példányt), és visszaad egy ssl.SSLSocket példányt, amely becsomagolja az alatta lévő streamet. A visszaadott objektum rendelkezik a szokásos stream interfész metódusokkal, mint aread(),write()stb.A server_side azt választja ki, hogy a becsomagolt socket a szerver vagy a kliens oldalon van-e. A szerver oldali SSL socketet egy nem SSL figyelő szerver socket
accept()hívásából visszakapott normál socketből kell létrehozni.A do_handshake_on_connect határozza meg, hogy a kézfogás a
wrap_socketrészeként történik-e, vagy elhalasztódik az első olvasások vagy írások részeként. Blokkoló socketeknél a kézfogás azonnali elvégzése a szokásos. Nem blokkoló socketeknél (azaz amikor awrap_sockethívásnak átadott sock nem blokkoló módban van) a kézfogást általában el kell halasztani, mert egyébként awrap_socketblokkol, amíg az be nem fejeződik.A server_hostname kliensként való használatra szolgál, és beállítja a kapott szervertanúsítvánnyal szemben ellenőrizendő gazdagépnevet. Beállítja a Server Name Indication (SNI) nevét is, lehetővé téve, hogy a szerver a megfelelő tanúsítványt mutassa be.
A client_id egy MicroPython-specifikus kiterjesztés-argumentum, amelyet csak DTLS szerver megvalósításakor használnak. A részletekért lásd: DTLS támogatás.
Figyelem
Alapértelmezetten nem történik tanúsítvány-ellenőrzés (
ssl.CERT_NONE). Biztonságos kapcsolathoz ellenőrizned kell a partner tanúsítványát úgy, hogy a cert_reqs /SSLContext.verify_modeértékétssl.CERT_REQUIREDértékre állítod; egyébként a kapcsolat sebezhető a közbeékelődéses (man-in-the-middle) támadásokkal szemben.A CPython
wrap_socketfüggvénye egySSLSocketobjektumot ad vissza, amely a socketekre jellemző metódusokkal rendelkezik, mint asend,recvstb. A MicroPythonwrap_socketfüggvénye egy olyan objektumot ad vissza, amely jobban hasonlít a CPythonSSLObjectobjektumára, és nem rendelkezik ezekkel a socket metódusokkal.
- verify_mode¶
Beállítja vagy lekéri a partnertanúsítványok ellenőrzésének viselkedését. A
CERT_*konstansok egyikének kell lennie.Megjegyzés
Az
ssl.CERT_REQUIREDmegköveteli, hogy az eszköz dátuma/ideje megfelelően be legyen állítva, pl. a mpremote rtc --set vagy azntptimesegítségével, és a kliens oldalon meg kell adni aserver_hostnameértékét.
DTLS támogatás¶
Eltérés a CPython-tól
Ez egy MicroPython kiterjesztés.
Ez a modul támogatja a DTLS-t kliens és szerver módban a PROTOCOL_DTLS_CLIENT és PROTOCOL_DTLS_SERVER konstansokon keresztül, amelyek az SSLContext protocol argumentumaként használhatók.
Ebben az esetben az alatta lévő socketnek datagram socketként kell viselkednie (azaz úgy, mint a socket.socket függvénnyel megnyitott socket, ahol az af a socket.AF_INET és a type a socket.SOCK_DGRAM).
DTLS szerver támogatás¶
A MicroPython DTLS szerver támogatása „Hello Verify” mechanizmussal van konfigurálva, ahogyan azt a DTLS 1.2 megköveteli. Ez a DTLS kliensek számára átlátszó, de a MicroPython-ban való DTLS szerver megvalósításakor vannak releváns megfontolások:
A szervernek egy további client_id argumentumot kell átadnia a
SSLContext.wrap_socket()hívásakor. Ez az azonosító egybytesobjektum (vagy hasonló) kell legyen, amely egy átvitel-specifikus, a klienst reprezentáló azonosítót tartalmaz.A legegyszerűbb megközelítés az, ha a
socket.recv_from()által visszaadott(client_ip, client_port)tuple-t bájtfüzérré alakítjuk, azaz:_, 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())
Amikor egy kliens először csatlakozik, a szerver
wrap_sockethívása egyOSError„Hello Verify Required” hibával hiúsul meg. Ez azért van, mert a DTLS „Hello Verify” sütit a kliens még nem ismeri. Ha ugyanaz a kliens másodszor is csatlakozik, akkor awrap_socketsikeres lesz.A „Hello Verify” DTLS sütik az
SSLContextobjektumhoz vannak társítva, ezért ugyanazt azSSLContextobjektumot kell használni az ugyanattól a klienstől érkező későbbi kapcsolat becsomagolásához. A süti megvalósítása tartalmaz egy időtúllépést, és állandó memóriahasználatú, függetlenül attól, hány kliens csatlakozik, így rendben van ugyanazt azSSLContextobjektumot újrahasználni a szerver teljes élettartama alatt.
Konstansok¶
- ssl.PROTOCOL_TLS_CLIENT: int¶
A protocol paraméter támogatott értéke, amely TLS kliens módot választ ki.
- ssl.PROTOCOL_TLS_SERVER: int¶
A protocol paraméter támogatott értéke, amely TLS szerver módot választ ki.
- ssl.PROTOCOL_DTLS_CLIENT: int¶
A protocol paraméter támogatott értéke, amely DTLS kliens módot választ ki.
- ssl.PROTOCOL_DTLS_SERVER: int¶
A protocol paraméter támogatott értéke, amely DTLS szerver módot választ ki.
- ssl.CERT_NONE: int¶
A cert_reqs paraméter és a
SSLContext.verify_modeattribútum támogatott értéke. Nem történik tanúsítvány-ellenőrzés a partneren.
- ssl.CERT_OPTIONAL: int¶
A cert_reqs paraméter és a
SSLContext.verify_modeattribútum támogatott értéke. A tanúsítvány-ellenőrzés opcionális. Vedd figyelembe, hogy az OpenMV Cam eszközön ez úgy viselkedik, mint assl.CERT_NONE.
- ssl.CERT_REQUIRED: int¶
A cert_reqs paraméter és a
SSLContext.verify_modeattribútum támogatott értéke. Érvényes tanúsítvány szükséges a partnertől.