--- pubDate = 2025-01-25T16:09:04 tags = ['https', 'web', 'nginx', 'linux', 'cryptography'] lang = "en" type = "note" [author] name = "ache" email = "ache@ache.one" [[alt_lang]] lang = "fr" url = "/notes/créer-un-certificat-auto-signé-depuis-un-CA-auto-signé" --- # Obtaining a self-signed SSL certificate from our own Certificate Authority ![Illustration of a self-signed certificate](res/certificat-signed-alt.svg) In this blog post, we will create a self-signed TLS certificate, install it on an nginx server and on client systems. ## Objectives of the TLS Protocol :::attention Generally, you do not want a self-signed certificate. If you want to obtain a valid certificate on the internet, then you need it to be verified by a trusted Certificate Authority (CA). In this case, [Let's Encrypt](https://letsencrypt.org/fr/) can certainly provide the certificate you need. ::: TLS authentication is used to **verify that** the server you want to connect to (by its **domain name**) **is indeed the server** that has authority over that domain name. This may seem abstract, but there are several reasons why a domain name may not redirect to the correct server. - A lying DNS - A compromised router redirects you to the wrong server - A configuration error (on either the client or the server side) - ... Subsequently, TLS will handle encryption that ensures confidentiality and integrity. TLS is a protocol used as an overlay on many other protocols (FTP, IMAP, SMTP, ..., and even DNS!) to add security to them. ## Certificate Chain (or Chain of Trust) We do not have a list of certificates issued on our computers. It would be too complicated to manage, heavy, difficult to update and ultimately unreliable.[^ct-logs] [^ct-logs]: The role of _Certificate Transparency (CT) logs_ is to ensure that any suspicious behavior (at the level of certificate issuance) can be detected. For more information, see . Schema of the Certificate Chain On the contrary, we have only a relatively small list of certificates of trust on our computers (149 in my case). These are the root certificates. These certificates will delegate their role of identity verifier to others. These intermediate authorities then have the role of ensuring that the request for certification comes from the correct server and issuing a signed certificate (and of short duration, i.e., several days at most, up to a few months). In our case, we will pass the intermediate certificate step as we will never delegate our authority. :::info The certificates installed on your computer are selected by your operating system (for example, [that of Windows](https://ccadb.my.salesforce-sites.com/microsoft/IncludedCACertificateReportForMSFT)). Often, this delegates your trust to a certificate selection organization such as [Mozilla](https://wiki.mozilla.org/CA/Included_Certificates). ::: ### Under Arch Linux Arch Linux uses [p11-kit](https://github.com/p11-glue/p11-kit) to manage certificates. Just like on Ubuntu and Debian systems, the list of certificates is available in the PEM format in the `/etc/ssl/certs` directory. OpenSSL is the reference tool for TLS. You can use it to display a certificate as follows: ```shell $ openssl x509 -noout -text -in $certificat ``` In the case of a website, you can query the certificate of a website with the following command: ` ```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 ``` One can add : - `-showcerts` to print the server certificat - `-servername` to set a SNI field - `-starttls` with `smtp`, `ldap`, `pop3`, `xmpp`... to verify that a TLS setup is compatible with StartTLS. - - We can also extract the certificate into a file as follows: ```shell $ openssl s_client -connect ache.one:443 -servername ache.one < /dev/null | \ openssl x509 -outform PEM > ache_one.cert ``` - To verify dates of a certificate : ```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 ``` ::::