78 votes

Générer un certificat auto-signé avec openssl qui fonctionne dans Chrome 58

À partir de Chrome 58, il n'accepte plus les certificats auto-signés qui dépendent du Common Name : https://productforums.google.com/forum/#!topic/chrome/zVo3M8CgKzQ;context-place=topicsearchin/chrome/category$3ACanary%7Csort:relevance%7Cspell:false

Il exige désormais l'utilisation de Subject Alt Name. J'ai suivi précédemment ce guide sur la génération d'un certificat auto-signé : https://devcenter.heroku.com/articles/ssl-certificate-self qui fonctionnait bien car j'avais besoin des fichiers server.crt et server.key pour ce que je faisais. Maintenant, je dois générer de nouveaux certificats qui incluent le SAN cependant toutes mes tentatives jusqu'à présent n'ont pas fonctionné avec Chrome 58.

Voici ce que j'ai fait :

J'ai suivi les étapes de l'article Heroku mentionné ci-dessus pour générer la clé. J'ai ensuite rédigé un nouveau fichier de configuration OpenSSL :

[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions      = san
extensions          = san
[ req_distinguished_name ]
countryName         = US
stateOrProvinceName = Massachusetts
localityName        = Boston
organizationName    = MyCompany
[ san ]
subjectAltName      = DNS:dev.mycompany.com

Puis j'ai généré le server.crt avec la commande suivante :

openssl req \
-new \
-key server.key \
-out server.csr \
-config config.cnf \
-sha256 \
-days 3650

Je suis sur un Mac, donc j'ai ouvert le fichier server.crt avec Keychain, l'ai ajouté à mes Certificats Système. Je l'ai ensuite défini en tant que Toujours faire confiance.

À l'exception du fichier de configuration pour définir la valeur SAN, ce sont des étapes similaires à celles que j'ai utilisées dans les versions précédentes de Chrome pour générer et faire confiance au certificat auto-signé.

Cependant, après cela, je reçois toujours l'erreur ERR_CERT_COMMON_NAME_INVALID dans Chrome 58.

0 votes

77voto

Robert Kubrick Points 1379

Ma solution :

openssl req \
    -newkey rsa:2048 \
    -x509 \
    -nodes \
    -keyout server.key \
    -new \
    -out server.crt \
    -subj /CN=dev.mycompany.com \
    -reqexts SAN \
    -extensions SAN \
    -config <(cat /System/Library/OpenSSL/openssl.cnf \
        <(printf '[SAN]\nsubjectAltName=DNS:dev.mycompany.com')) \
    -sha256 \
    -days 3650

Statut : Fonctionne pour moi

2 votes

Excellent usage of subshell. Je pense que vous pouvez le simplifier un peu: -config <(cat /System/Library/OpenSSL/openssl.cnf ; printf '[SAN]\nsubjectAltName=DNS:dev.mycompany.com')

1 votes

Je ne reçois plus l'erreur de nom alternatif de sujet, mais maintenant j'obtiens une erreur sur le nom commun, et définir le certificat téléchargé comme "toujours faire confiance" ne fonctionne pas. Des idées ? @bcardarella

3 votes

Avec la mise à jour vers Chrome 59, le certificat affiche une erreur comme ceci : Il y a des problèmes avec la chaîne de certificats du site (net::ERR_CERT_COMMON_NAME_INVALID).

23voto

Philippe Sabourin Points 4957

Voici une solution qui fonctionne pour moi :

Créer la clé et le certificat du CA

# openssl genrsa -out server_rootCA.key 2048
# openssl req -x509 -new -nodes -key server_rootCA.key -sha256 -days 3650 -out server_rootCA.pem

Créer server_rootCA.csr.cnf

# server_rootCA.csr.cnf
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=DE
ST=Berlin
L=NeuKoelln
O=Weisestrasse
OU=local_RootCA
emailAddress=ikke@server.berlin
CN = server.berlin

Créer le fichier de configuration v3.ext

# v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = server.berlin

Créer la clé du serveur

# openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <( cat server_rootCA.csr.cnf )

Créer le certificat du serveur

# openssl x509 -req -in server.csr -CA server_rootCA.pem -CAkey server_rootCA.key -CAcreateserial -out server.crt -days 3650 -sha256 -extfile v3.ext

Ajouter le certificat et la clé au fichier du site Apache2, section HTTPS (port 443)

SSLCertificateFile    /etc/apache2/ssl/server.crt
SSLCertificateKeyFile    /etc/apache2/ssl/server.key

Copier server_rootCA.pem du serveur vers votre machine..

# scp you@server.berlin:~/server_rootCA.pem .

.. et l'ajouter au navigateur Chromium

Chromium -> Paramètres -> (Avancés) Gérer les certificats -> Importer -> 'server_rootCA.pem'

VOUS AVEZ TERMINÉ !

P.S. Au lieu de créer une paire de certificat CA & serveur fonctionnelle (selon les instructions ci-dessus), vous pourriez simplement désactiver les en-têtes HSTS dans la configuration de votre serveur HTTP. Cela empêchera Chromium de forcer HTTPS et permettra aux utilisateurs de cliquer sur "Avancé, accéder à your.url (non sécurisé)" sans avoir à obtenir et installer votre certificat CA personnalisé (server_rootCA.pem). En d'autres termes, le fait de devoir désactiver HSTS permettra à votre site d'être consulté publiquement via HTTP et/ou une connexion HTTPS non sécurisée (attention !).

Pour Apache2, ajoutez ce qui suit au fichier du site, section HTTP (port 80)

Header unset Strict-Transport-Security
Header always set Strict-Transport-Security "max-age=0;includeSubDomains"

Testé sur Debian/Apache2.4 + Debian/Chromium 59

https://ram.k0a1a.net/self-signed_https_cert_after_chrome_58

1 votes

Aller à la route d'une autorité CA racine qui signe ensuite les certificats individuels est la seule façon dont j'ai pu obtenir que Chrome s'authentifie pleinement; a aussi l'avantage que je n'avais besoin que de faire installer un seul certificat. Merci

10 votes

Quelqu'un peut-il s'il vous plaît m'expliquer pourquoi tout le monde dans cette région semble utiliser des bashismes comme -config <( cat server_rootCA.csr.cnf ) au lieu de simplement -config server_rootCA.csr.cnf?

0 votes

Pouvez-vous s'il vous plaît mettre à jour votre réponse concernant les en-têtes Apache qui peuvent contourner le problème (cela ne me dérange pas, car il s'agit de sites locaux pour le développement uniquement et j'aimerais une solution générique sans avoir à générer de nouveaux certificats à chaque fois). Pouvez-vous indiquer où à l'intérieur d'une définition de virtual host ils doivent être placés. J'ai essayé plusieurs alternatives et je ne peux toujours pas accéder aux sites via HTTPS. Merci

19voto

STWilson Points 299

Sous Windows, enregistrez ce script dans votre dossier SSL sous le nom makeCERT.bat. Il créera ces fichiers : example.cnf, example.crt, example.key

 @echo off

REM DANS VOTRE DOSSIER SSL, ENREGISTREZ CE FICHIER SOUS LE NOM : makeCERT.bat
REM À LA LIGNE DE COMMANDE DANS VOTRE DOSSIER SSL, EXÉCUTEZ : makecert
REM IL CRÉERA CES FICHIERS : example.cnf, example.crt, example.key
REM IMPORTER LE FICHIER .crt DANS LES Autorités de Certification Racine de Confiance de CHROME
REM N'OUBLIEZ PAS DE REDEMMARRER APACHE OU NGINX APRÈS AVOIR CONFIGURÉ CES FICHIERS

REM VEUILLEZ METTRE À JOUR LES VARIABLES SUIVANTES EN FONCTION DE VOS BESOINS.
SET HOSTNAME=exemple
SET DOT=com
SET COUNTRY=US
SET STATE=KS
SET CITY=Olathe
SET ORGANIZATION=IT
SET ORGANIZATION_UNIT=Département IT
SET EMAIL=webmaster@%HOSTNAME%.%DOT%

(
echo [req]
echo default_bits = 2048
echo prompt = no
echo default_md = sha256
echo x509_extensions = v3_req
echo distinguished_name = dn
echo:
echo [dn]
echo C = %COUNTRY%
echo ST = %STATE%
echo L = %CITY%
echo O = %ORGANIZATION%
echo OU = %ORGANIZATION_UNIT%
echo emailAddress = %EMAIL%
echo CN = %HOSTNAME%.%DOT%
echo:
echo [v3_req]
echo subjectAltName = @alt_names
echo:
echo [alt_names]
echo DNS.1 = *.%HOSTNAME%.%DOT%
echo DNS.2 = %HOSTNAME%.%DOT%
)>%HOSTNAME%.cnf

openssl req -new -x509 -newkey rsa:2048 -sha256 -nodes -keyout %HOSTNAME%.key -days 3560 -out %HOSTNAME%.crt -config %HOSTNAME%.cnf

19voto

pavon Points 343

Il y a plusieurs bonnes réponses qui donnent des exemples de comment faire fonctionner cela, mais aucune qui n'explique où les choses ont mal tourné dans votre tentative. OpenSSL peut être assez déroutant parfois, il vaut donc la peine de marcher à travers.

Tout d'abord, en passant, OpenSSL ignore par défaut toutes les valeurs de noms distingués que vous fournissez dans la configuration. Si vous souhaitez les utiliser, vous devez ajouter prompt = no à votre configuration. De plus, la commande telle que écrite génère uniquement une demande de certificat et non un certificat lui-même, donc la commande -days ne sert à rien.

Si vous générez votre demande de certificat en utilisant la commande que vous avez donnée et inspectez le résultat, le Subject Alt Name est présent :

$ openssl req -new -key server.key -out server.csr -config config.cnf -sha256
$ openssl req -text -noout -in server.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name:
                DNS:dev.mycompany.com
    Signature Algorithm: sha256WithRSAEncryption
         ...

Mais si vous générez le certificat en utilisant la commande dans le lien heroku et inspectez le résultat, le Subject Alt Name est manquant :

$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
$ openssl x509 -text -noout -in server.crt
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            89:fd:75:26:43:08:04:61
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Validity
            Not Before: Jan 21 04:27:21 2018 GMT
            Not After : Jan 21 04:27:21 2019 GMT
        Subject: C = US, ST = Massachusetts, L = Boston, O = MyCompany
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    ...
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
         ...

La raison en est qu'OpenSSL, par défaut, ne copie pas les extensions de la demande dans le certificat. Normalement, le certificat serait créé/signé par une CA en fonction d'une demande d'un client, et certaines extensions pourraient accorder au certificat plus de pouvoir que la CA n'avait l'intention, si elle devait faire aveuglément confiance aux extensions définies dans la demande.

Il existe des moyens de dire à OpenSSL de copier les extensions, mais à mon avis il est plus laborieux que de simplement fournir les extensions dans un fichier de configuration lors de la génération du certificat.

Si vous essayez d'utiliser votre fichier de configuration existant, cela ne fonctionnera pas car la section de niveau supérieur est marquée [req] donc ces paramètres s'appliquent uniquement à la commande req et non à la commande x509. Il n'est pas nécessaire d'avoir un marqueur de section de niveau supérieur, vous pouvez juste supprimer cette première ligne, et alors cela fonctionnera très bien pour générer des demandes ou des certificats.

$ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt -extfile config.cnf

Alternativement, vous pouvez utiliser l'argument -x509 pour la commande req pour générer un certificat auto-signé en une seule commande, au lieu de d'abord créer une demande puis un certificat. Dans ce cas, il n'est pas nécessaire de supprimer la ligne de section [req], car cette section est lue et utilisée par la commande req.

$ openssl req -x509 -sha256 -days 365 -key server.key -out server.crt -config config.cnf

Pour récapituler, voici le fichier de configuration modifié utilisé dans les commandes ci-dessus :

default_bits        = 2048
distinguished_name  = dn
x509_extensions     = san
req_extensions      = san
extensions          = san
prompt              = no
[ dn ]
countryName         = US
stateOrProvinceName = Massachusetts
localityName        = Boston
organizationName    = MyCompany
[ san ]
subjectAltName      = DNS:dev.mycompany.com

3 votes

C'est la seule explication qui m'a aidé à comprendre pourquoi le certificat est sorti sans un SAN (dans mon cas, j'avais besoin d'inclure x509_extensions dans le fichier de configuration)

8voto

JPvRiel Points 181

Script Bash avec configuration intégrée

En tant que script shell qui devrait fonctionner sur différentes plateformes avec bash. Suppose que HOSTNAME est défini pour l'environnement shell ou fournir un nom d'hôte de votre choix, par exemple self_signed_cert.sh test

set -e

if [ -z "$1" ]; then
  hostname="$HOSTNAME"
else
  hostname="$1"
fi

local_openssl_config="
[ req ]
prompt = no
distinguished_name = req_distinguished_name
x509_extensions = san_self_signed
[ req_distinguished_name ]
CN=$hostname
[ san_self_signed ]
subjectAltName = DNS:$hostname, DNS:localhost, IP:127.0.0.1, IP:::1
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = CA:true
keyUsage = nonRepudiation, digitalSignature, keyEncipherment, dataEncipherment, keyCertSign, cRLSign
extendedKeyUsage = serverAuth, clientAuth, timeStamping
"

openssl req \
  -newkey rsa:2048 -nodes \
  -keyout "$hostname.key.pem" \
  -x509 -sha256 -days 3650 \
  -config <(echo "$local_openssl_config") \
  -out "$hostname.cert.pem"
openssl x509 -noout -text -in "$hostname.cert.pem"

Le code ci-dessus injecte plus ou moins les informations minimales du fichier de configuration dont openssl a besoin.

Remarque, inclut l'extra DNS:localhost comme un SAN pour permettre un test via localhost plus facilement. Supprimez cette partie supplémentaire du script si vous ne la voulez pas.

Crédit

La réponse de bcardarella est excellente (je ne peux pas commenter/voter en raison d'un manque de réputation). Cependant, la réponse utilise un emplacement de fichier de configuration openssl existant qui est spécifique à la plateforme... d'où :

Fonctionne pour moi

Évidemment, il suffirait simplement de trouver le fichier de configuration openssl pour votre propre plateforme et substituer le bon emplacement.

Test

Pour une manière de tester, importez test.cert.pem dans les autorités de chrome à chrome://settings/certificates, et :

openssl s_server -key test.key.pem -cert test.cert.pem -accept 20443 -www &
openssl_pid=$!
google-chrome "https://localhost:20443"
google-chrome "https://127.0.0.1:20443"
google-chrome "https://[::1]:20443"

Et après le test

kill $openssl_pid

2 votes

Dans certains cas, le nom d'hôte est une adresse IP. Le Chrome actuel (v80) rejettera les certificats qui ont SAN avec une adresse IP étiquetée en tant que DNS, il devra être défini comme IP:123.123.123.123 (ou quelle que soit l'adresse IP).

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X