14.4.3. Certificats auto-signés#
Un certificat auto-signé est le moyen le plus rapide de faire fonctionner TLS entre deux appareils que vous contrôlez : les deux extrémités font confiance à un seul certificat que vous générez vous-même. Il couvre tous les déploiements où vous configurez les deux côtés de la connexion – une autorité de certification publique n’entre en jeu que lorsque des clients tiers doivent se connecter sans qu’on leur ait demandé de faire confiance à un certificat personnalisé.
14.4.3.1. Créer un certificat auto-signé#
Exécutez OpenSSL sur votre machine de développement. Le subjectAltName (SAN) est ce que les clients TLS modernes vérifient lors de la validation du nom d’hôte ; définissez-le donc avec le ou les noms d’hôte et/ou la ou les adresses IP que les clients utiliseront pour atteindre la caméra (le CN seul est obsolète et ignoré par de nombreux clients). Remplacez DNS:openmv / IP:192.168.1.50 par l’adresse à laquelle vos clients se connectent réellement.
ECDSA P-256 – recommandé:
# 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 – plus robuste, plus volumineux/plus lent:
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 – compatibilité maximale:
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"
Note
Un certificat client (utilisé pour l’authentification mutuelle, ci-dessous) se crée avec exactement ces mêmes commandes – il n’y a rien de spécifique au client dans le certificat lui-même. Générez simplement une seconde paire clé/certificat indépendante sous des noms différents (par exemple client.key / client.crt) et utilisez-la sur le client comme indiqué dans l’exemple mTLS. Le subjectAltName n’a d’importance que pour le côté dont le pair vérifie le nom d’hôte (le client vérifie le nom du serveur ; rien ne vérifie celui du client), il peut donc être omis pour un certificat purement client. Le -subj / CN n’est de même qu’une étiquette sur un certificat client – le côté serveur ici vérifie uniquement que le certificat remonte à une CA de confiance, il ne fait jamais correspondre le nom – définissez-le donc avec ce qui identifie ce client (par exemple /CN=sensor-01). Conservez tout de même une valeur -subj, afin qu’OpenSSL puisse générer le certificat de façon non interactive.
La durée de vie du certificat est définie par -days ; les certificats expirent et doivent être régénérés et redéployés avant cette échéance.
14.4.3.2. Conversion en DER#
Convertissez à la fois le certificat et la clé privée en DER avant de les copier sur la caméra:
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. Copier les fichiers sur la caméra#
Copiez les fichiers DER dans le système de fichiers de la caméra – par exemple en les faisant glisser sur le lecteur USB de l’OpenMV Cam, ou avec mpremote cp server.der : et mpremote cp server.key.der :. Du côté qui effectue la vérification, copiez également le certificat de la CA / du pair au format DER.
Les fichiers DER n’ont pas à résider sur le système de fichiers accessible en écriture. MicroPython peut aussi monter une image ROMFS en lecture seule sur /rom, et les certificats qui y sont placés sont chargés exactement comme n’importe quel autre fichier – par exemple ctx.load_cert_chain("/rom/server.der", "/rom/server.key.der"). Une image ROMFS est préparée sur votre machine de développement et est en lecture seule à l’exécution, de sorte que le certificat ne peut pas être modifié sur l’appareil – utile pour verrouiller une unité de production. Notez qu’une clé privée stockée dans ROMFS reste lisible par le code s’exécutant sur la caméra ; ROMFS protège contre la modification, pas contre l”extraction. Un certificat résidant dans ROMFS ne peut être remplacé qu’en reconstruisant et en reprogrammant l’image.
14.4.3.4. Utiliser le certificat#
Un client complet qui règle l’horloge, ouvre une socket, vérifie un serveur auto-signé et échange des données:
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()
Un serveur complet présentant son certificat et sa clé:
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()
Pour l”authentification mutuelle (mTLS), le serveur exige et vérifie en plus un certificat client, et le client en présente un qui lui est propre:
# 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")
Consultez la documentation du module ssl pour l’API complète.
Note
Tout ce qui figure sur cette page s’applique sans modification à DTLS (TLS sur UDP). Les clés, les certificats, le format DER, le modèle de confiance, les considérations d’expiration ainsi que les appels load_cert_chain / load_verify_locations sont identiques ; seul le transport diffère – vous encapsulez une socket socket.SOCK_DGRAM et sélectionnez ssl.PROTOCOL_DTLS_CLIENT / ssl.PROTOCOL_DTLS_SERVER au lieu des constantes de protocole TLS. La seule subtilité supplémentaire est un cookie anti-usurpation côté serveur – la première connexion d’un nouveau client est censée échouer et le client réessaie simplement ; voir Prise en charge DTLS pour les détails.