ssl — SSL/TLS-moduuli

Tämä moduuli tarjoaa pääsyn Transport Layer Security -salaukseen (aiemmin ja yleisesti tunnettu nimellä ”Secure Sockets Layer”) sekä vertaisosapuolen todennustoimintoihin verkkoyhteyksissä (sockets), sekä asiakas- että palvelinpuolella.

Vihje

Oletko uusi TLS:n parissa kameralla? Aloita opetusohjelmasta TLS-varmenteiden kanssa työskentely. Se käy läpi avaintyyppien valinnan, varmenteiden luomisen ja muuntamisen kameran vaatimaan DER-muotoon, niiden siirtämisen laitteelle sekä palvelinten ja asiakkaiden varmentamisen – täydellisten toimivien esimerkkien kera.

Muista

MicroPython ei toteuta ssl.SSLError-poikkeusta. SSL/TLS-virheet nostetaan sen sijaan OSError-poikkeuksina.

Esimerkit

TLS-asiakas, joka varmentaa palvelimen varmenteen tiedostojärjestelmään tallennettua CA-varmennetta (DER-muodossa) vasten:

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

Nopeaa, turvatonta yhteyttä varten (ei varmenteen vahvistusta) voidaan sen sijaan käyttää ssl.wrap_socket() -apufunktiota:

ssock = ssl.wrap_socket(sock, server_hostname="example.com")

TLS-palvelin, joka esittää oman varmenteensa ja yksityisen avaimensa (DER-muoto):

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

Funktiot

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

Kääri annettu sock ja palauta uusi käärityn yhteyden objekti. Tämän funktion toteutus luo ensin SSLContext-objektin ja kutsuu sitten SSLContext.wrap_socket() -metodia kyseiselle kontekstiobjektille. Argumentit sock, server_side ja server_hostname välitetään muuttumattomina metodikutsulle. Argumentti do_handshake välitetään argumenttina do_handshake_on_connect. Jäljelle jäävillä argumenteilla on seuraava käyttäytyminen:

  • cert_reqs määrittää, onko vertaisosapuolen (palvelimen tai asiakkaan) esitettävä kelvollinen varmenne. Huomaa, että ssl.CERT_NONE ja ssl.CERT_OPTIONAL eivät vahvista mitään varmennetta; vain ssl.CERT_REQUIRED tekee niin.

  • cadata on bytes-objekti, joka sisältää CA-varmenneketjun (DER-muodossa), joka vahvistaa vertaisosapuolen varmenteen. Tällä hetkellä tuetaan vain yhtä DER-koodattua varmennetta.

Luokat

class ssl.SSLContext(protocol: int, /)

Luo uusi SSLContext-instanssi. protocol-argumentin on oltava jokin PROTOCOL_*-vakioista.

load_cert_chain(certfile: str | bytes, keyfile: str | bytes) None

Lataa yksityinen avain ja vastaava varmenne. certfile on merkkijono, joka sisältää varmenteen tiedostopolun. keyfile on merkkijono, joka sisältää yksityisen avaimen tiedostopolun.

Ero CPythoniin

MicroPython-laajennus: certfile ja keyfile voivat olla merkkijonojen sijaan bytes-objekteja, jolloin ne tulkitaan varsinaiseksi varmenne-/avaintiedoksi.

load_verify_locations(cafile: str | None = None, cadata: bytes | None = None) None

Lataa CA-varmenneketju, joka vahvistaa vertaisosapuolen varmenteen. cafile on CA-varmenteiden tiedostopolku. cadata on bytes-objekti, joka sisältää CA-varmenteet. Vain toinen näistä argumenteista tulisi antaa.

get_ciphers() List[str]

Hae luettelo käytössä olevista salausmenetelmistä, palautettuna merkkijonojen luettelona.

set_ciphers(ciphers: List[str]) None

Aseta käytettävissä olevat salausmenetelmät tällä kontekstilla luoduille yhteyksille. ciphers tulisi olla luettelo merkkijonoista IANA cipher suite -muodossa .

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

Ottaa stream-tyyppisen sock-objektin (yleensä SOCK_STREAM-tyyppinen socket.socket-instanssi) ja palauttaa ssl.SSLSocket-instanssin, joka käärii alla olevan tietovirran. Palautetulla objektilla on tavanomaiset stream-rajapinnan metodit kuten read(), write() jne.

  • server_side valitsee, onko käärityn yhteyden objekti palvelin- vai asiakaspuolella. Palvelinpuolen SSL-yhteyden objekti tulisi luoda tavallisesta yhteysobjektista, jonka accept() palauttaa ei-SSL-kuuntelevasta palvelinyhteydestä.

  • do_handshake_on_connect määrittää, tehdäänkö kättely osana wrap_socket-kutsua vai lykätäänkö se tehtäväksi osana ensimmäisiä luku- tai kirjoitusoperaatioita. Estäville (blocking) yhteyksille kättelyn tekeminen välittömästi on tavanomaista. Estämättömille (non-blocking) yhteyksille (eli kun wrap_socket-funktiolle välitetty sock on estämättömässä tilassa) kättely tulisi yleensä lykätä, koska muuten wrap_socket estyy, kunnes kättely valmistuu.

  • server_hostname on tarkoitettu asiakaskäyttöön ja asettaa isäntänimen, jota verrataan vastaanotettuun palvelimen varmenteeseen. Se asettaa myös nimen Server Name Indication (SNI) -toiminnolle, jolloin palvelin voi esittää oikean varmenteen.

  • client_id on MicroPython-kohtainen laajennusargumentti, jota käytetään vain DTLS-palvelinta toteutettaessa. Katso lisätiedot kohdasta DTLS-tuki.

Varoitus

Oletuksena varmennetta ei vahvisteta (ssl.CERT_NONE). Turvallista yhteyttä varten sinun on varmennettava vertaisosapuolen varmenne asettamalla cert_reqs / SSLContext.verify_mode arvoon ssl.CERT_REQUIRED; muutoin yhteys on altis välistävetohyökkäyksille (man-in-the-middle).

CPythonin wrap_socket palauttaa SSLSocket-objektin, jolla on yhteyksille tyypilliset metodit, kuten send, recv jne. MicroPythonin wrap_socket palauttaa objektin, joka muistuttaa enemmän CPythonin SSLObject-objektia, jolla ei ole näitä socket-metodeja.

verify_mode

Aseta tai hae vertaisosapuolen varmenteiden vahvistuksen käyttäytyminen. On oltava jokin CERT_*-vakioista.

Muista

ssl.CERT_REQUIRED edellyttää, että laitteen päivämäärä/aika on asetettu oikein, esim. käyttäen mpremote rtc --set tai ntptime, ja server_hostname on määritettävä asiakaspuolella.

DTLS-tuki

Ero CPythoniin

Tämä on MicroPython-laajennus.

Tämä moduuli tukee DTLS:ää asiakas- ja palvelintilassa PROTOCOL_DTLS_CLIENT- ja PROTOCOL_DTLS_SERVER-vakioiden kautta, joita voidaan käyttää SSLContext-luokan protocol-argumenttina.

Tässä tapauksessa alla olevan yhteyden odotetaan käyttäytyvän datagram-yhteytenä (eli kuten yhteys, joka avataan socket.socket-kutsulla, jossa socket.AF_INET on af ja socket.SOCK_DGRAM on type).

DTLS-palvelintuki

MicroPythonin DTLS-palvelintuki on konfiguroitu ”Hello Verify” -toiminnolla, kuten DTLS 1.2 edellyttää. Tämä on läpinäkyvää DTLS-asiakkaille, mutta DTLS-palvelinta MicroPythonissa toteutettaessa on huomioitava seuraavat seikat:

  • Palvelimen tulisi välittää lisäargumentti client_id kutsuessaan SSLContext.wrap_socket(). Tämän tunnisteen on oltava bytes-objekti (tai vastaava), joka sisältää siirtokohtaisen tunnisteen asiakkaalle.

    Yksinkertaisin lähestymistapa on muuntaa socket.recv_from()-kutsun palauttama (client_ip, client_port)-monikko tavujonoksi, eli:

    _, 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())
    
  • Ensimmäisellä kerralla, kun asiakas yhdistää, palvelimen wrap_socket-kutsu epäonnistuu OSError-virheellä ”Hello Verify Required”. Tämä johtuu siitä, että asiakas ei vielä tunne DTLS:n ”Hello Verify” -evästettä. Jos sama asiakas yhdistää toisen kerran, wrap_socket onnistuu.

  • ”Hello Verify” -toiminnon DTLS-evästeet liittyvät SSLContext-objektiin, joten samaa SSLContext-objektia tulisi käyttää saman asiakkaan myöhemmän yhteyden käärimiseen. Evästetoteutus sisältää aikakatkaisun ja käyttää vakiomäärän muistia riippumatta siitä, kuinka monta asiakasta yhdistää, joten samaa SSLContext-objektia voi käyttää uudelleen koko palvelimen elinkaaren ajan.

Vakiot

ssl.PROTOCOL_TLS_CLIENT: int

Tuettu arvo protocol-parametrille, valitsee TLS-asiakastilan.

ssl.PROTOCOL_TLS_SERVER: int

Tuettu arvo protocol-parametrille, valitsee TLS-palvelintilan.

ssl.PROTOCOL_DTLS_CLIENT: int

Tuettu arvo protocol-parametrille, valitsee DTLS-asiakastilan.

ssl.PROTOCOL_DTLS_SERVER: int

Tuettu arvo protocol-parametrille, valitsee DTLS-palvelintilan.

ssl.CERT_NONE: int

Tuettu arvo cert_reqs-parametrille ja SSLContext.verify_mode -attribuutille. Vertaisosapuolen varmennetta ei vahvisteta.

ssl.CERT_OPTIONAL: int

Tuettu arvo cert_reqs-parametrille ja SSLContext.verify_mode -attribuutille. Varmenteen vahvistus on valinnainen. Huomaa, että OpenMV Cam -laitteella tämä toimii kuten ssl.CERT_NONE.

ssl.CERT_REQUIRED: int

Tuettu arvo cert_reqs-parametrille ja SSLContext.verify_mode -attribuutille. Vertaisosapuolelta vaaditaan kelvollinen varmenne.