ssl — SSL/TLS modul¶
Ovaj modul omogućuje pristup mehanizmima za šifriranje i provjeru identiteta na razini Transport Layer Security (ranije i šire poznato kao “Secure Sockets Layer”) za mrežne socket-e, kako na strani klijenta tako i na strani poslužitelja.
Savjet
Nov si u radu s TLS-om na kameri? Započni s vodičem Rad s TLS certifikatima. On vodi kroz odabir vrsta ključeva, stvaranje i pretvaranje certifikata u DER format koji kamera zahtijeva, prijenos na uređaj te provjeru poslužitelja i klijenata – s potpunim radnim primjerima.
Napomena
MicroPython ne implementira ssl.SSLError. Pogreške SSL/TLS-a umjesto toga se dižu kao OSError.
Primjeri¶
TLS klijent koji provjerava certifikat poslužitelja u odnosu na CA certifikat (u DER formatu) pohranjen na datotečnom sustavu:
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()
Za brzu, nesigurnu vezu (bez provjere certifikata) umjesto toga može se upotrijebiti praktična funkcija ssl.wrap_socket()
ssock = ssl.wrap_socket(sock, server_hostname="example.com")
TLS poslužitelj koji predstavlja vlastiti certifikat i privatni ključ (DER format):
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()
Funkcije¶
- 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¶
Omata zadani sock i vraća novi omotani socket objekt. Implementacija ove funkcije najprije stvara
SSLContext, a zatim na tom kontekstnom objektu poziva metoduSSLContext.wrap_socket(). Argumenti sock, server_side i server_hostname nepromijenjeni se prosljeđuju u poziv metode. Argument do_handshake prosljeđuje se kao do_handshake_on_connect. Preostali argumenti imaju sljedeće ponašanje:cert_reqs određuje mora li druga strana (poslužitelj ili klijent) predočiti valjani certifikat. Imajte na umu da
ssl.CERT_NONEissl.CERT_OPTIONALne provjeravaju nijedan certifikat; to čini samossl.CERT_REQUIRED.cadata je bytes objekt koji sadrži lanac CA certifikata (u DER formatu) koji će provjeriti certifikat druge strane. Trenutačno je podržan samo jedan DER-kodirani certifikat.
Klase¶
- class ssl.SSLContext(protocol: int, /)¶
Stvara novu instancu SSLContext. Argument protocol mora biti jedna od konstanti
PROTOCOL_*.- load_cert_chain(certfile: str | bytes, keyfile: str | bytes) None¶
Učitava privatni ključ i odgovarajući certifikat. certfile je niz znakova s putanjom datoteke certifikata. keyfile je niz znakova s putanjom datoteke privatnog ključa.
Razlika u odnosu na CPython
MicroPython proširenje: certfile i keyfile mogu biti bytes objekti umjesto nizova znakova, u kojem se slučaju tumače kao stvarni podaci certifikata/ključa.
- load_verify_locations(cafile: str | None = None, cadata: bytes | None = None) None¶
Učitava lanac CA certifikata koji će provjeriti certifikat druge strane. cafile je putanja datoteke CA certifikata. cadata je bytes objekt koji sadrži CA certifikate. Treba navesti samo jedan od ovih argumenata.
- set_ciphers(ciphers: List[str]) None¶
Postavlja dostupne šifre za socket-e stvorene s ovim kontekstom. ciphers treba biti popis nizova znakova u IANA formatu šifrarnih kompleta .
- 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¶
Prima stream sock (obično instancu socket.socket tipa
SOCK_STREAM) i vraća instancu ssl.SSLSocket koja omata temeljni tok. Vraćeni objekt ima uobičajene metode sučelja stream poputread(),write()itd.server_side odabire je li omotani socket na strani poslužitelja ili klijenta. SSL socket na strani poslužitelja treba stvoriti iz normalnog socket-a vraćenog iz
accept()na ne-SSL slušajućem poslužiteljskom socket-u.do_handshake_on_connect određuje izvodi li se rukovanje (handshake) kao dio
wrap_socketili se odgađa kako bi se izvelo u sklopu početnog čitanja ili pisanja. Za blokirajuće socket-e standardno je rukovanje izvesti odmah. Za neblokirajuće socket-e (tj. kada je sock proslijeđen uwrap_socketu neblokirajućem načinu rada) rukovanje treba općenito odgoditi jer u protivnomwrap_socketblokira dok se ne dovrši.server_hostname služi za uporabu kao klijent i postavlja ime poslužitelja koje se provjerava u odnosu na primljeni certifikat poslužitelja. Također postavlja ime za Server Name Indication (SNI), omogućujući poslužitelju da predoči ispravan certifikat.
client_id je argument proširenja specifičan za MicroPython koji se koristi samo pri implementaciji DTLS poslužitelja. Pojedinosti potražite u Podrška za DTLS.
Upozorenje
Prema zadanim postavkama ne provodi se provjera certifikata (
ssl.CERT_NONE). Za sigurnu vezu morate provjeriti certifikat druge strane postavljanjem cert_reqs /SSLContext.verify_modenassl.CERT_REQUIRED; u protivnom je veza ranjiva na napade tipa man-in-the-middle.CPython-ov
wrap_socketvraća objektSSLSocketkoji ima metode tipične za socket-e, kao što susend,recvitd. MicroPython-ovwrap_socketvraća objekt sličniji CPython-ovomSSLObjectkoji nema te socket metode.
- verify_mode¶
Postavlja ili dohvaća ponašanje za provjeru certifikata druge strane. Mora biti jedna od konstanti
CERT_*.Napomena
ssl.CERT_REQUIREDzahtijeva da su datum/vrijeme uređaja ispravno postavljeni, npr. pomoću mpremote rtc --set ilintptime, aserver_hostnamemora biti naveden kada se radi na strani klijenta.
Podrška za DTLS¶
Razlika u odnosu na CPython
Ovo je MicroPython proširenje.
Ovaj modul podržava DTLS u klijentskom i poslužiteljskom načinu rada putem konstanti PROTOCOL_DTLS_CLIENT i PROTOCOL_DTLS_SERVER koje se mogu upotrijebiti kao argument protocol u SSLContext.
U tom se slučaju očekuje da se temeljni socket ponaša kao datagramski socket (tj. poput socket-a otvorenog s socket.socket uz socket.AF_INET kao af i socket.SOCK_DGRAM kao type).
Podrška za DTLS poslužitelj¶
MicroPython-ova podrška za DTLS poslužitelj konfigurirana je s „Hello Verify” kako to zahtijeva DTLS 1.2. To je prozirno za DTLS klijente, ali postoje važna razmatranja pri implementaciji DTLS poslužitelja u MicroPython-u:
Poslužitelj treba proslijediti dodatni argument client_id pri pozivu
SSLContext.wrap_socket(). Taj ID mora bitibytesobjekt (ili sličan) s identifikatorom specifičnim za prijenos koji predstavlja klijenta.Najjednostavniji je pristup pretvoriti torku
(client_ip, client_port)koju vraćasocket.recv_from()u niz bajtova, 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())
Prvi put kada se klijent poveže, poslužiteljev poziv funkciji
wrap_socketneuspjet će s pogreškomOSError„Hello Verify Required”. To je zato što DTLS „Hello Verify” kolačić klijentu još nije poznat. Ako se isti klijent poveže drugi put,wrap_socketće uspjeti.DTLS kolačići za „Hello Verify” povezani su s objektom
SSLContext, pa za omatanje sljedeće veze od istog klijenta treba upotrijebiti isti objektSSLContext. Implementacija kolačića uključuje istek vremena i ima konstantnu uporabu memorije bez obzira na to koliko se klijenata poveže, pa je u redu ponovno koristiti isti objektSSLContexttijekom cijelog životnog vijeka poslužitelja.
Konstante¶
- ssl.PROTOCOL_TLS_CLIENT: int¶
Podržana vrijednost za parametar protocol, koja odabire TLS klijentski način rada.
- ssl.PROTOCOL_TLS_SERVER: int¶
Podržana vrijednost za parametar protocol, koja odabire TLS poslužiteljski način rada.
- ssl.PROTOCOL_DTLS_CLIENT: int¶
Podržana vrijednost za parametar protocol, koja odabire DTLS klijentski način rada.
- ssl.PROTOCOL_DTLS_SERVER: int¶
Podržana vrijednost za parametar protocol, koja odabire DTLS poslužiteljski način rada.
- ssl.CERT_NONE: int¶
Podržana vrijednost za parametar cert_reqs i atribut
SSLContext.verify_mode. Ne provodi se provjera certifikata druge strane.
- ssl.CERT_OPTIONAL: int¶
Podržana vrijednost za parametar cert_reqs i atribut
SSLContext.verify_mode. Provjera certifikata je neobavezna. Imajte na umu da se na OpenMV Cam ovo ponaša kaossl.CERT_NONE.
- ssl.CERT_REQUIRED: int¶
Podržana vrijednost za parametar cert_reqs i atribut
SSLContext.verify_mode. Od druge strane zahtijeva se valjani certifikat.