14.4.3. Önaláírt tanúsítványok

Az önaláírt tanúsítvány a leggyorsabb módja annak, hogy a TLS működjön két olyan eszköz között, amelyeket te irányítasz: mindkét vég egyetlen, általad generált tanúsítványban bízik. Lefed minden olyan telepítést, ahol a kapcsolat mindkét oldalát te konfigurálod – egy nyilvános hitelesítésszolgáltató (Certificate Authority) csak akkor kerül a képbe, amikor harmadik féltől származó klienseknek anélkül kell csatlakozniuk, hogy megmondanád nekik, bízzanak meg egy egyedi tanúsítványban.

14.4.3.1. Önaláírt tanúsítvány létrehozása

Futtasd az OpenSSL-t a fejlesztői gépeden. A subjectAltName (SAN) az, amit a modern TLS-kliensek a gazdagépnév-ellenőrzés során ellenőriznek, ezért állítsd be azokra a gazdagépnevekre és/vagy IP-címekre, amelyeken a kliensek elérik a kamerát (a CN önmagában elavult, és sok kliens figyelmen kívül hagyja). Cseréld le a DNS:openmv / IP:192.168.1.50 értékeket arra a címre, amelyhez a klienseid valójában csatlakoznak.

ECDSA P-256 – ajánlott:

# Generate a P-256 private key.
openssl ecparam -name prime256v1 -genkey -noout -out server.key

# Self-signed certificate valid for one year, with a SAN.
openssl req -new -x509 -key server.key -out server.crt -days 365 \
    -subj "/CN=openmv" -addext "subjectAltName=DNS:openmv,IP:192.168.1.50"

ECDSA P-384 – erősebb, nagyobb/lassabb:

openssl ecparam -name secp384r1 -genkey -noout -out server.key

openssl req -new -x509 -key server.key -out server.crt -days 365 \
    -subj "/CN=openmv" -addext "subjectAltName=DNS:openmv,IP:192.168.1.50"

RSA-2048 – maximális kompatibilitás:

openssl req -new -x509 -newkey rsa:2048 -nodes -keyout server.key \
    -out server.crt -days 365 -subj "/CN=openmv" \
    -addext "subjectAltName=DNS:openmv,IP:192.168.1.50"

Megjegyzés

Egy klienstanúsítványt (a kölcsönös hitelesítéshez használt, lásd alább) pontosan ugyanezekkel a parancsokkal hoznak létre – magában a tanúsítványban nincs semmi kliens-specifikus. Csak generálj egy második, független kulcs/tanúsítvány párt eltérő nevekkel (pl. client.key / client.crt), és használd a kliensen az mTLS-példában bemutatott módon. A subjectAltName csak annak az oldalnak számít, amelynek a gazdagépnevét a partner ellenőrzi (a kliens ellenőrzi a kiszolgáló nevét; a kliensét semmi sem ellenőrzi), így egy csak kliensként használt tanúsítványnál elhagyható. A -subj / CN hasonlóképpen csak egy címke egy klienstanúsítványon – az itteni kiszolgáló oldal csak azt ellenőrzi, hogy a tanúsítvány egy megbízható CA-hoz láncolódik-e, a nevet soha nem veti össze –, így állítsd arra, ami az adott klienst azonosítja (pl. /CN=sensor-01). Mindenképpen adj meg valamilyen -subj értéket, hogy az OpenSSL interaktív beavatkozás nélkül tudja generálni a tanúsítványt.

A tanúsítvány élettartamát a -days kapcsoló állítja be; a tanúsítványok lejárnak, és azelőtt újra kell generálni és újra kell telepíteni őket.

14.4.3.2. Átalakítás DER formátumra

Alakítsd át mind a tanúsítványt, mind a privát kulcsot DER formátumra, mielőtt a kamerára másolnád őket:

openssl x509 -in server.crt -outform DER -out server.der
openssl pkey -in server.key -outform DER -out server.key.der

14.4.3.3. Fájlok másolása a kamerára

Másold a DER-fájlokat a kamera fájlrendszerére – például úgy, hogy ráhúzod őket az OpenMV Cam USB-meghajtójára, vagy az mpremote cp server.der : és mpremote cp server.key.der : parancsokkal. Az ellenőrző oldalon másold át a CA / partner tanúsítványt is DER formátumban.

A DER-fájloknak nem kell feltétlenül az írható fájlrendszeren lakniuk. A MicroPython egy csak olvasható ROMFS-képet is fel tud csatolni a /rom útvonalon, és az ott elhelyezett tanúsítványok pontosan úgy töltődnek be, mint bármely más fájl – pl. ctx.load_cert_chain("/rom/server.der", "/rom/server.key.der"). A ROMFS-kép a fejlesztői gépeden készül, és futásidőben csak olvasható, így a tanúsítvány nem módosítható az eszközön – ami hasznos egy gyártási egység lezárásához. Vedd figyelembe, hogy a ROMFS-ben tárolt privát kulcsot a kamerán futó kód továbbra is ki tudja olvasni; a ROMFS a módosítás, nem a kinyerés ellen véd. Egy ROMFS-ben lakó tanúsítvány csak a kép újraépítésével és újraflashelésével cserélhető le.

14.4.3.4. A tanúsítvány használata

Egy teljes kliens, amely beállítja az órát, megnyit egy socketet, ellenőriz egy önaláírt kiszolgálót, és adatot cserél:

import socket
import ssl
import ntptime

ntptime.settime()                 # correct clock for the validity check

# Open a plain TCP connection.
addr = socket.getaddrinfo("openmv", 8443)[0][-1]
sock = socket.socket()
sock.connect(addr)

# Wrap it for TLS, trusting the server's self-signed certificate.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="server.der")
ssock = ctx.wrap_socket(sock, server_hostname="openmv")

ssock.write(b"hello\n")
print(ssock.read())
ssock.close()

Egy teljes kiszolgáló, amely bemutatja a tanúsítványát és a kulcsát:

import socket
import ssl
import ntptime

ntptime.settime()                 # correct clock for the validity check

ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("server.der", "server.key.der")

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)

while True:
    client, addr = sock.accept()
    sclient = ctx.wrap_socket(client, server_side=True)
    sclient.write(b"hello\n")
    print(sclient.read())
    sclient.close()

A kölcsönös hitelesítéshez (mTLS) a kiszolgáló ezenfelül megköveteli és ellenőrzi a kliens tanúsítványát, a kliens pedig bemutatja a sajátját:

# Server side: also demand and verify a client certificate.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain("server.der", "server.key.der")
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="client.der")

# Client side: present a certificate of our own.
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.load_cert_chain("client.der", "client.key.der")
ctx.verify_mode = ssl.CERT_REQUIRED
ctx.load_verify_locations(cafile="server.der")

A teljes API-hoz lásd az ssl modul dokumentációját.

Megjegyzés

Az ezen az oldalon szereplő minden változatlanul érvényes a DTLS-re (TLS UDP felett) is. A kulcsok, a tanúsítványok, a DER-formátum, a bizalmi modell, a lejárati szempontok, valamint a load_cert_chain / load_verify_locations hívások azonosak; csak a szállítóréteg tér el – egy socket.SOCK_DGRAM socketet csomagolsz be, és a TLS protokollkonstansok helyett az ssl.PROTOCOL_DTLS_CLIENT / ssl.PROTOCOL_DTLS_SERVER értéket választod. Az egyetlen plusz csavar egy kiszolgáló-oldali, hamisítás elleni süti – egy új klienstől érkező első kapcsolat várhatóan meghiúsul, és a kliens egyszerűen újrapróbálkozik; a részletekért lásd: DTLS támogatás.