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.