14.4.3. Självsignerade certifikat#
Ett självsignerat certifikat är det snabbaste sättet att få TLS att fungera mellan två enheter du kontrollerar: båda ändarna litar på ett enda certifikat som du genererar själv. Det täcker varje driftsättning där du konfigurerar båda sidorna av anslutningen – en offentlig Certificate Authority kommer in i bilden först när tredjepartsklienter måste ansluta utan att bli tillsagda att lita på ett anpassat certifikat.
14.4.3.1. Skapa ett självsignerat certifikat#
Kör OpenSSL på din utvecklingsmaskin. subjectAltName (SAN) är vad moderna TLS-klienter kontrollerar under värdnamnsverifieringen, så sätt det till de värdnamn och/eller IP-adresser som klienterna kommer att använda för att nå kameran (CN ensamt är föråldrat och ignoreras av många klienter). Ersätt DNS:openmv / IP:192.168.1.50 med adressen som dina klienter faktiskt ansluter till.
ECDSA P-256 – rekommenderas:
# 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 – starkare, större/långsammare:
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 – maximal kompatibilitet:
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"
Observera
Ett klient-certifikat (som används för ömsesidig autentisering, nedan) skapas med exakt samma kommandon – det finns inget klientspecifikt med själva certifikatet. Generera bara ett andra, oberoende nyckel-/certifikatpar under andra namn (t.ex. client.key / client.crt) och använd det på klienten som visas i mTLS-exemplet. subjectAltName spelar bara roll för den sida vars värdnamn motparten verifierar (klienten kontrollerar serverns namn; ingenting kontrollerar klientens), så det kan utelämnas för ett certifikat enbart för klienter. -subj / CN är på samma sätt bara en etikett på ett klientcertifikat – serversidan här kontrollerar bara att certifikatet kedjar till en betrodd CA, den matchar aldrig namnet – så sätt det till vad som än identifierar den klienten (t.ex. /CN=sensor-01). Behåll något -subj-värde oavsett, så att OpenSSL kan generera certifikatet icke-interaktivt.
Certifikatets livslängd ställs in med -days; certifikat går ut och måste regenereras och driftsättas på nytt innan dess.
14.4.3.2. Konvertera till DER#
Konvertera både certifikatet och den privata nyckeln till DER innan du kopierar dem till kameran:
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. Kopiera filer till kameran#
Kopiera DER-filerna till kamerans filsystem – till exempel genom att dra dem till OpenMV Cam:ens USB-enhet, eller med mpremote cp server.der : och mpremote cp server.key.der :. På den verifierande sidan, kopiera även CA-/motpartscertifikatet i DER-form.
DER-filerna behöver inte finnas på det skrivbara filsystemet. MicroPython kan även montera en skrivskyddad ROMFS-avbildning på /rom, och certifikat som placerats där laddas precis som vilken annan fil som helst – t.ex. ctx.load_cert_chain("/rom/server.der", "/rom/server.key.der"). En ROMFS-avbildning förbereds på din utvecklingsmaskin och är skrivskyddad vid körning, så certifikatet kan inte ändras på enheten – användbart för att låsa ner en produktionsenhet. Observera att en privat nyckel som lagras i ROMFS fortfarande är läsbar av kod som körs på kameran; ROMFS skyddar mot modifiering, inte extrahering. Ett ROMFS-residerande certifikat kan endast bytas ut genom att bygga om och flasha om avbildningen.
14.4.3.4. Använda certifikatet#
En fullständig klient som ställer klockan, öppnar en socket, verifierar en självsignerad server och utbyter data:
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()
En fullständig server som presenterar sitt certifikat och sin nyckel:
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()
För ömsesidig autentisering (mTLS) kräver och verifierar servern dessutom ett klientcertifikat, och klienten presenterar ett eget:
# 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")
Se dokumentationen för modulen ssl för det fullständiga API:et.
Observera
Allt på den här sidan gäller oförändrat för DTLS (TLS över UDP). Nycklarna, certifikaten, DER-formatet, förtroendemodellen, utgångsfrågorna och anropen load_cert_chain / load_verify_locations är identiska; bara transporten skiljer sig – du omsluter en socket.SOCK_DGRAM-socket och väljer ssl.PROTOCOL_DTLS_CLIENT / ssl.PROTOCOL_DTLS_SERVER istället för TLS-protokollkonstanterna. Den enda extra komplikationen är en anti-spoofing-cookie på serversidan – den första anslutningen från en ny klient förväntas misslyckas och klienten gör helt enkelt ett nytt försök; se DTLS-stöd för detaljer.