Je développe une application Java qui interroge une API REST sur un serveur distant via HTTP. Pour des raisons de sécurité, cette communication doit être commutée sur HTTPS.
Maintenant que Let's Encrypt a commencé sa version bêta publique, j'aimerais savoir si Java fonctionne actuellement (ou s'il est confirmé qu'il fonctionnera à l'avenir) avec leurs certificats par défaut.
Let's Encrypt a obtenu sa signature croisée intermédiaire par IdenTrust , ce qui devrait être une bonne nouvelle. Cependant, je ne trouve aucun de ces deux dans la sortie de cette commande:
keytool -keystore "..\lib\security\cacerts" -storepass changeit -list
Je sais que des autorités de certification de confiance peuvent être ajoutées manuellement sur chaque machine, mais comme mon application doit être téléchargeable gratuitement et exécutable sans autre configuration, je recherche des solutions qui fonctionnent «hors de la boîte». Avez-vous de bonnes nouvelles pour moi?
Réponses:
[ Mise à jour du 08/06/2016 : selon https://bugs.openjdk.java.net/browse/JDK-8154757, l'autorité de certification IdenTrust sera incluse dans Oracle Java 8u101.]
[ Mise à jour du 05/08/2016 : Java 8u101 a été publié et inclut effectivement IdenTrust CA: notes de version ]
Oui. Le certificat Let's Encrypt n'est qu'un certificat de clé publique ordinaire. Java le prend en charge (selon la compatibilité des certificats Let's Encrypt , pour Java 7> = 7u111 et Java 8> = 8u101).
Non / cela dépend de la JVM. Le truststore d'Oracle JDK / JRE jusqu'à 8u66 ne contient ni l'AC Let's Encrypt spécifiquement, ni l'AC IdenTrust qui l'a signé de manière croisée.
new URL("https://letsencrypt.org/").openConnection().connect();
par exemple, il en résultejavax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException
.Vous pouvez toutefois fournir votre propre validateur / définir un fichier de clés personnalisé contenant l'autorité de certification racine requise ou importer le certificat dans le magasin de clés de confiance JVM.
https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/10 aborde également le sujet.
Voici un exemple de code qui montre comment ajouter un certificat au truststore par défaut au moment de l'exécution. Vous aurez juste besoin d'ajouter le certificat (exporté depuis Firefox en tant que .der et mis dans classpath)
Basé sur Comment puis-je obtenir une liste de certificats racine de confiance en Java? et http://developer.android.com/training/articles/security-ssl.html#UnknownCa
la source
isrgrootx1.der
etlets-encrypt-x1-cross-signed.der
, mais aucun d'eux ne semble être le bon.https://helloworld.letsencrypt.org
par exemple sur et inspectez la chaîne de certificats dans le navigateur (en cliquant sur l'icône verte). Pour celui-ci, vous avez besoin soit du certificat spécifique au site, soit le certificat intermédiaire X1 (signé par IdenTrust) ou le certificat DSTRootCAX3. LeISRG Root X1
ne fonctionne pas pour le site helloworld car il n'est pas dans la chaîne, c'est la chaîne alternative. J'utiliserais le DSTRoot, simplement exporté via un navigateur car je ne l'ai vu nulle part en téléchargement.javax.net.ssl.trustStore
propriété système, mais -1 pour ensuite définir la valeur par défaut de la JVMSSLContext
. Il serait préférable d'en créer un nouveauSSLSocketFactory
et de l'utiliser ensuite pour diverses connexions (par exempleHttpUrlConnection
) plutôt que de remplacer la configuration SSL à l'échelle de la VM. (Je me rends compte que ce changement n'est efficace que pour la JVM en cours d'exécution et ne persiste pas ou n'affecte pas les autres programmes. Je pense simplement que c'est une meilleure pratique de programmation d'être explicite sur l'endroit où votre configuration s'applique.)Je sais que l'OP a demandé une solution sans modifications de configuration locale, mais au cas où vous voudriez ajouter la chaîne de confiance au keystore de manière permanente:
source: https://community.letsencrypt.org/t/will-the-cross-root-cover-trust-by-the-default-list-in-the-jdk-jre/134/13
la source
Réponse détaillée pour ceux d'entre nous souhaitant apporter des modifications de configuration locales qui incluent la sauvegarde du fichier de configuration:
1. Testez si cela fonctionne avant les changements
Si vous n'avez pas encore de programme de test, vous pouvez utiliser mon programme java SSLPing ping qui teste la négociation TLS (fonctionnera avec n'importe quel port SSL / TLS, pas seulement HTTPS). J'utiliserai le SSLPing.jar prédéfini, mais lire le code et le construire vous-même est une tâche rapide et facile:
Comme ma version Java est antérieure à 1.8.0_101 (non publiée au moment de la rédaction de cet article), un certificat Let's Encrypt ne sera pas vérifié par défaut. Voyons à quoi ressemble l'échec avant d'appliquer le correctif:
2. Importez le certificat
Je suis sous Mac OS X avec le jeu de variables d'environnement JAVA_HOME. Les commandes ultérieures supposeront que cette variable est définie pour l'installation java que vous modifiez:
Faites une sauvegarde du fichier cacerts que nous allons modifier afin que vous puissiez annuler toute modification sans réinstaller le JDK:
Téléchargez le certificat de signature que nous devons importer:
Effectuez l'importation:
3. Vérifiez qu'il fonctionne après les modifications
Vérifiez que Java est maintenant bien connecté au port SSL:
la source
Pour le JDK qui ne prend pas encore en charge les certificats Let's Encrypt, vous pouvez les ajouter au JDK en
cacerts
suivant ce processus (grâce à cela ).Téléchargez tous les certificats sur https://letsencrypt.org/certificates/ (choisissez le format der ) et ajoutez-les un par un avec ce type de commande (exemple pour
letsencryptauthorityx1.der
):la source