---
pubDate = 2025-01-25T16:09:04
tags = ['https', 'web', 'nginx', 'linux', 'cryptographie']
lang = "fr"
type = "note"
[author]
name = "ache"
email = "ache@ache.one"
[[alt_lang]]
lang = "en"
url = "/notes/create_self-signed_certificate_from_a_self-signed_CA"
---
# Obtenir un certificat auto-signé à partir de sa propre autorité de certification

Dans ce poste de blog, nous allons créer un certificat TLS autosigné, l'installer sur un serveur nginx et sur les systèmes clients.
## Objectifs de TLS
:::attention
Généralement, vous ne souhaitez pas avoir un certificat autosigné.
Si vous souhaitez obtenir un certificat valide sur internet, alors vous avez besoin qu'il soit validé par une autorité de certification.
Dans ce cas, [Let's Encrypt](https://letsencrypt.org/fr/) peut très certainement vous délivrer le certificat dont vous avez besoin.
:::
L'authentification TLS sert à **attester que le** serveur que vous souhaitez contacter (par son **nom de domaine**) **correspond bien au serveur** ayant autorité sur ce nom de domaine.
Cela peut paraître abstrait comme ça, mais il peut y avoir plusieurs raisons qui font que le nom de domaine ne redirige pas vers le bon serveur.
- Un DNS menteur
- Un routeur compromis vous redirige vers le mauvais serveur
- Une erreur de configuration (coté client ou serveur)
- ...
Ensuite, TLS se chargera du chiffrement qui assurera la confidentialité et l'intégrité.
TLS est un protocole utilisé comme surcouche à pleins d'autres protocoles (FTP, IMAP, SMTP, ..., et même DNS !) afin de leur rajouter une sécurité.
## Chaîne de certification (ou chaîne de confiance)
Nous n'avons pas la liste des certificats émis sur nos ordinateurs.
Ça serait trop compliqué à gérer, trop lourd, difficile à mettre à jour et au final peu fiable.[^ct-logs]
[^ct-logs]:
C'est le rôle cependant des _Certification Transparency (CT) logs_ qui assurent que tout comportement suspect (au niveau de l'émission de certificat) puisse être détecté.
Plus d'info à .
Au contraire, on a une seulement une liste relative faible de certificats de confiance sur nos ordinateurs (149 chez moi).
Ce sont les certificats d'autorité, ou racines.
Ces certificats vont déléguer leur rôle de vérificateur d'identité à d'autres.
Ces autorités intermédiaires ont alors pour rôle de s'assurer que la demande de certification émane bien du bon serveur et d'émettre un certificat signé (et de courte durée, c'est-à-dire quelques jours, au plus quelques mois).
Dans notre cas, nous allons nous passez l'étape du certificat intermédiaire puisque nous n'allons jamais déléguer notre autorité.
:::info
Les certificats installés sur votre ordinateur sont sélectionnés par votre système d'exploitation (par exemple [celle de Windows](https://ccadb.my.salesforce-sites.com/microsoft/IncludedCACertificateReportForMSFT)).
Souvent, celui-ci délègue votre confiance à un organisme de sélection de certificats comme [Mozilla](https://wiki.mozilla.org/CA/Included_Certificates).
:::
### Sous Arch Linux
Arch Linux utilise [p11-kit](https://github.com/p11-glue/p11-kit) pour gérer les certificats.
Tout comme sur les systèmes Ubuntu et Debian, la liste des certificats est disponible au format PEM dans le dossier `/etc/ssl/certs`.
OpenSSL est l'outil de référence en matière de TLS.
Vous pouvez l'utiliser pour afficher un certificat comme ceci.
```shell
$ openssl x509 -noout -text -in $certificat
```
Dans le cas d'un site web, on peut interroger le certificat d'un site web avec la commande suivante.
```shell
$ openssl s_client -connect ache.one:443 -verify_return_error /dev/null
Connecting to 2001:41d0:601:1100::11dc
depth=2 C=US, O=Internet Security Research Group, CN=ISRG Root X1
verify return:1
depth=1 C=US, O=Let's Encrypt, CN=R10
verify return:1
depth=0 CN=ache.one
verify return:1
DONE
```
On peut ajouter :
- `-showcerts` pour afficher le certificat serveur
- `-servername` pour mettre en place le SNI
- `-starttls` avec `smtp`, `ldap`, `pop3`, `xmpp`... pour vérifier l'installation TLS sur un serveur avec un protocole compatible StartTLS.
- On peut également extraire le certificat dans un fichier :
```shell
$ openssl s_client -connect ache.one:443 -servername ache.one < /dev/null | \
openssl x509 -outform PEM > ache_one.cert
```
- Vérifier les dates de validité du certificat :
```shell
$ openssl x509 -in ache_one.cert -noout -dates # Pour un certificat que l'on possède localement
notBefore=Wen 16 15:27:33 2025 GMT
notAfter=Wen 30 15:27:33 2025 GMT
$ openssl s_client -servername ache.one -connect ache.one:443 2>/dev/null /dev/null 2>/dev/null
for cert in $(find -name "*.cert"); do
if openssl x509 -checkend 345600 -noout -in ${cert} > /dev/null; then
echo -e "✔️ $(basename ${cert}) will expire in more than 4 days"
else
echo -e "❌ $(basename ${cert}) will expire soon !"
if [ $(basename "$cert") = $(basename "$LOCAL_CA_CERT") ]; then
echo -e "\t⛔ I don't renew local CA certificate"
continue
fi
NEW_CSR=$(echo ${cert} | sed 's/.cert/.csr/')
CERT_KEY=$(echo ${cert} | sed 's/.cert/.key/')
CERT_CONFIG=$(echo ${cert} | sed 's/.cert/.conf/')
echo "Renewing ${cert}"
echo "Creating new CSR ($NEW_CSR)"
echo ${cert}
echo ${CERT_KEY}
echo ${CERT_CONFIG}
# Sign the new signing request
if openssl req -new -key "${CERT_KEY}" -out "${NEW_CSR}" -config "${CERT_CONFIG}"; then
echo "👍 CSR created"
else
echo "❌ Failled to create signing request!"
continue
fi
echo "Renewing certificate"
openssl x509 -req -CA "${LOCAL_CA_CERT}" -CAkey "${LOCAL_CA_KEY}" -in "${NEW_CSR}" -out "${cert}" -days 10 -CAcreateserial -extensions v3_ext -extfile "${CERT_CONFIG}" -sha256
if [ $? -eq 0 ]; then
HAS_RENEW_CERT="yes"
echo "✔️ Certificate renew"
else
echo "❌ Failled to renew certificate!"
fi
fi
done
echo -e "\nNo more certificate to check"
if [ -n "$HAS_RENEW_CERT" ]; then
echo "🔃 Reload nginx configuration (and update certificates)"
nginx -s reload
fi
popd >/dev/null 2>/dev/null
```
::::