Comment les noms de serveurs de certificates SSL sont-ils résolus / Puis-je append des noms alternatifs avec keytool?

Celles-ci peuvent être formulées sous forme de questions distinctes pour plus de clarté, mais elles sont toutes liées au même problème.

Comment les noms de serveurs de certificates SSL sont-ils résolus?

Pourquoi les navigateurs semblent-ils utiliser le champ CN du certificate, mais le mécanisme de Java semble ne regarder que les “noms de substitution des objects” uniquement?

Est-il possible d’append des noms alternatifs à un certificate SSL en utilisant keytool? Sinon, est-ce que openSSL est une bonne option?

Juste un peu d’arrière-plan: j’ai besoin d’un serveur principal pour communiquer avec plusieurs serveurs en utilisant HTTPS. Evidemment, nous ne voulons pas acheter de certificates SSL pour chaque serveur (il pourrait y en avoir beaucoup), donc je veux utiliser des certificates auto-signés (j’ai utilisé keytool pour les générer). Après avoir ajouté les certificates approuvés dans le système d’exploitation, les navigateurs (IE et Chrome) acceptent volontiers la connexion comme fiable. Cependant, même après avoir ajouté les certificates aux Java cacerts, Java n’acceptera toujours pas la connexion de la manière la plus fiable et émettra l’exception suivante:

Causée par: java.security.cert.CertificateException: aucun autre nom de sujet présent sur sun.security.util.HostnameChecker.matchIP (HostnameChecker.java:142) sur sun.security.util.HostnameChecker.match (HostnameChecker.java:75) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity (X509T rustManagerImpl.java:264) à l’adresse com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted (X509TrustManagerImpl.java:250). sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate (Clien tHandshaker.java:1185) … 14 de plus

J’ai trouvé que je pouvais faire confiance à Java au certificate implémentant mon propre HostNameVerifier, que j’ai copié ici: com.sun.jbi.internal.security.https.DefaultHostnameVerifier juste pour tester (au fait, le nom d’hôte est passé en argument au HostnameVerifier est correct, donc je pense qu’il aurait dû être accepté).

J’ai utilisé le champ de certificate CN comme nom d’hôte (généralement l’adresse IP).

Quelqu’un peut-il s’il vous plaît me dire si je fais quelque chose de mal et me diriger dans la bonne direction?

La façon dont la vérification du nom d’hôte doit être effectuée est définie dans la RFC 6125 , qui est assez récente et généralise la pratique à tous les protocoles, et remplace la RFC 2818 , qui était spécifique à HTTPS. (Je ne suis même pas sûr que Java 7 utilise la RFC 6125, qui pourrait être trop récente pour cela.)

De la RFC 2818 (section 3.1) :

Si une extension subjectAltName de type dNSName est présente, elle DOIT être utilisée comme identité. Sinon, le champ (le plus spécifique) Common Name du champ Subject du certificate DOIT être utilisé. Bien que l’utilisation du nom commun soit une pratique existante, elle est obsolète et les autorités de certificateion sont encouragées à utiliser le nom dNSName à la place.

[…]

Dans certains cas, l’URI est spécifié en tant qu’adresse IP plutôt que nom d’hôte. Dans ce cas, l’iPAddress subjectAltName doit être présent dans le certificate et doit correspondre exactement à l’adresse IP de l’URI.

Essentiellement, le problème spécifique que vous rencontrez vient du fait que vous utilisez des adresses IP dans votre CN et non un nom d’hôte. Certains navigateurs peuvent fonctionner car tous les outils ne suivent pas ssortingctement cette spécification, en particulier parce que “plus spécifique” dans la RFC 2818 n’est pas clairement défini (voir les discussions dans la RFC 6215).

Si vous utilisez keytool , à partir de Java 7, keytool a la possibilité d’inclure un nom de sujet alternatif (voir le tableau dans la documentation de -ext ): vous pouvez utiliser -ext san=dns:www.example.com ou -ext san=ip:10.0.0.1 .

MODIFIER:

Vous pouvez demander un SAN dans OpenSSL en modifiant openssl.cnf (il sélectionnera la copie dans le répertoire actuel si vous ne souhaitez pas modifier la configuration globale, pour autant que je m’en souvienne, ou vous pouvez choisir un emplacement explicite à l’aide de OPENSSL_CONF variable d’environnement).

Définissez les options suivantes (recherchez les sections appropriées entre crochets):

 [req] req_extensions = v3_req [ v3_req ] subjectAltName=IP:10.0.0.1 # or subjectAltName=DNS:www.example.com 

Il y a aussi un bon truc pour utiliser une variable d’environnement pour cela (plutôt que de la fixer dans un fichier de configuration) ici: http://www.crsr.net/Notes/SSL.html