Cela ressemble à une question standard, mais je n'ai trouvé aucune direction claire nulle part.
J'ai du code java essayant de me connecter à un serveur avec un certificat probablement auto-signé (ou expiré). Le code signale l'erreur suivante:
[HttpMethodDirector] I/O exception (javax.net.ssl.SSLHandshakeException) caught
when processing request: sun.security.validator.ValidatorException: PKIX path
building failed: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
Si je comprends bien, je dois utiliser keytool et dire à java que c'est OK pour autoriser cette connexion.
Toutes les instructions pour résoudre ce problème supposent que je suis parfaitement compétent avec keytool, comme
générer une clé privée pour le serveur et l'importer dans le magasin de clés
Y a-t-il quelqu'un qui pourrait publier des instructions détaillées?
J'utilise unix, donc le script bash serait le meilleur.
Je ne sais pas si c'est important, mais le code est exécuté dans jboss.
Réponses:
Vous avez essentiellement deux options ici: ajoutez le certificat auto-signé à votre magasin de clés de confiance JVM ou configurez votre client pour
Option 1
Exportez le certificat à partir de votre navigateur et importez-le dans votre magasin de confiance JVM (pour établir une chaîne de confiance):
Option 2
Désactiver la validation du certificat:
Notez que je ne recommande pas du tout l'option n ° 2 . La désactivation du gestionnaire de confiance annule certaines parties de SSL et vous rend vulnérable aux attaques de l'homme au milieu. Préférez l'option n ° 1 ou, mieux encore, demandez au serveur d'utiliser un "vrai" certificat signé par une autorité de certification bien connue.
la source
J'ai pourchassé ce problème à un fournisseur de certificats qui ne fait pas partie des hôtes de confiance JVM par défaut
JDK 8u74
. Le fournisseur est www.identrust.com , mais ce n'était pas le domaine auquel j'essayais de me connecter. Ce domaine avait obtenu son certificat de ce fournisseur. Voir Est-ce que la couverture cross root est approuvée par la liste par défaut dans le JDK / JRE? - lisez quelques entrées. Voir également Quels navigateurs et systèmes d'exploitation prennent en charge Let's Encrypt .Donc, afin de me connecter au domaine qui m'intéressait, qui avait un certificat émis par,
identrust.com
j'ai fait les étapes suivantes. Fondamentalement, je devais obtenir le identrust.com (DST Root CA X3
certificat ) pour être approuvé par la JVM. J'ai pu le faire en utilisant Apache HttpComponents 4.5 comme ceci:1: Obtenez le certificat d'indettrust dans les instructions de téléchargement de la chaîne de certificats . Cliquez sur le lien DST Root CA X3 .
2: enregistrez la chaîne dans un fichier nommé "DST Root CA X3.pem". Assurez-vous d'ajouter les lignes "----- BEGIN CERTIFICATE -----" et "----- END CERTIFICATE -----" dans le fichier au début et à la fin.
3: Créez un fichier de clés Java, cacerts.jks avec la commande suivante:
4: Copiez le fichier de clés cacerts.jks résultant dans le répertoire des ressources de votre application java / (maven).
5: Utilisez le code suivant pour charger ce fichier et le joindre à Apache 4.5 HttpClient. Cela résoudra le problème pour tous les domaines pour lesquels des certificats émis par
indetrust.com
util oracle incluent le certificat dans le magasin de clés par défaut JRE.Lorsque le projet est généré, le fichier cacerts.jks sera copié dans le chemin de classe et chargé à partir de là. Je n'ai pas, à ce stade, testé contre d'autres sites SSL, mais si le code ci-dessus "chaînes" dans ce certificat alors ils fonctionneront aussi, mais encore une fois, je ne sais pas.
Référence: contexte SSL personnalisé et comment puis-je accepter un certificat auto-signé avec une connexion Java HttpsURLConnection?
la source
Apache HttpClient 4.5 prend en charge l'acceptation de certificats auto-signés:
Cela crée une fabrique de sockets SSL qui utilisera le
TrustSelfSignedStrategy
, l'enregistre auprès d'un gestionnaire de connexions personnalisé puis effectue un HTTP GET à l'aide de ce gestionnaire de connexions.Je suis d'accord avec ceux qui chantent "ne faites pas cela en production", mais il existe des cas d'utilisation pour accepter des certificats auto-signés en dehors de la production; nous les utilisons dans des tests d'intégration automatisés, de sorte que nous utilisons SSL (comme en production) même lorsqu'ils ne fonctionnent pas sur le matériel de production.
la source
Plutôt que de définir la fabrique de socket par défaut (laquelle IMO est une mauvaise chose) - cela affectera simplement la connexion actuelle plutôt que chaque connexion SSL que vous essayez d'ouvrir:
la source
checkServerTrusted
n'implémente pas la logique nécessaire pour réellement approuver le certificat et vous assurer que les certificats non approuvés sont rejetés. Cela pourrait faire une bonne lecture: Le code le plus dangereux du monde: valider les certificats SSL dans un logiciel non navigateur .getAcceptedIssuers()
méthode n'est pas conforme à la spécification, et cette «solution» reste radicalement précaire.Il existe une meilleure alternative à l'approbation de tous les certificats: créez un
TrustStore
qui approuve spécifiquement un certificat donné et utilisez-le pour créer un àSSLContext
partir duquel obtenir leSSLSocketFactory
pour définir sur leHttpsURLConnection
. Voici le code complet:Vous pouvez également charger le
KeyStore
directement à partir d'un fichier ou récupérer le certificat X.509 à partir de n'importe quelle source fiable.Notez qu'avec ce code, les certificats
cacerts
ne seront pas utilisés. Ce particulierHttpsURLConnection
ne fera confiance qu'à ce certificat spécifique.la source
Faites confiance à tous les certificats SSL: - Vous pouvez contourner SSL si vous souhaitez tester sur le serveur de test. Mais n'utilisez pas ce code pour la production.
}
Veuillez appeler cette fonction dans la fonction onCreate () dans Activity ou dans votre classe d'application.
Cela peut être utilisé pour Volley dans Android.
la source
La réponse acceptée est correcte, mais je voudrais ajouter quelque chose à cela car j'utilisais IntelliJ sur Mac et je ne pouvais pas le faire fonctionner en utilisant la
JAVA_HOME
variable path.Il s'avère que Java Home était différent lors de l'exécution de l'application à partir d'IntelliJ.
Pour savoir exactement où il se trouve, vous pouvez simplement faire
System.getProperty("java.home")
comme c'est là que les certificats de confiance sont lus.la source
S'ils utilisent un certificat auto-signé, c'est à eux de prendre les mesures nécessaires pour rendre leur serveur utilisable. Plus précisément, cela signifie vous fournir leur certificat hors ligne de manière fiable. Alors, faites-les faire ça. Vous importez ensuite cela dans votre fichier de clés certifiées à l'aide de l'outil de clés comme décrit dans le Guide de référence JSSE. Ne pensez même pas au TrustManager non sécurisé publié ici.
EDIT Pour le bénéfice des dix - sept (!) Downvoters, et de nombreux commentateurs ci-dessous, qui n'ont clairement pas réellement lu ce que j'ai écrit ici, ce n'est pas une jérémiade contre les certificats auto-signés. Il n'y a rien de mal avec les certificats auto-signés lorsqu'ils sont correctement mis en œuvre. Mais, la bonne façon de les implémenter est de faire livrer le certificat en toute sécurité via un processus hors ligne, plutôt que via le canal non authentifié qu'ils vont être utilisés pour s'authentifier. C'est sûrement évident? C'est certainement évident pour chaque organisation soucieuse de la sécurité pour laquelle j'ai déjà travaillé, des banques avec des milliers de succursales à mes propres entreprises. La «solution» de base de code côté client de la confiance tousles certificats, y compris les certificats auto-signés signés par absolument n'importe qui, ou tout organisme arbitral s'établissant en tant qu'AC, ne sont ipso facto pas sécurisés. C'est juste jouer à la sécurité. C'est inutile. Vous avez une conversation privée, inviolable, à l'épreuve des réponses et à l'épreuve des injections avec ... quelqu'un. N'importe qui. Un homme au milieu. Un imitateur. N'importe qui. Vous pouvez tout aussi bien utiliser du texte en clair.
la source
Ce n'est pas une solution au problème complet mais Oracle a une bonne documentation détaillée sur la façon d'utiliser cet outil clé. Cela explique comment
https://docs.oracle.com/cd/E54932_01/doc.705/e54936/cssg_create_ssl_cert.htm#CSVSG178
la source
Au lieu d'utiliser keytool comme suggéré par le commentaire du haut, sur RHEL, vous pouvez utiliser update-ca-trust à partir des versions plus récentes de RHEL 6. Vous devrez avoir le certificat au format pem. ensuite
Modifiez /etc/pki/ca-trust/source/cert.p11-kit et remplacez "catégorie de certificat: autre entrée" par "catégorie de certificat: autorité". (Ou utilisez sed pour le faire dans un script.)
Quelques mises en garde:
update-ca-trust enable
. Cela remplacera / etc / pki / java / cacerts par un lien symbolique pointant vers / etc / pki / ca-trust / extract / java / cacerts. (Donc, vous voudrez peut-être sauvegarder l'ancien en premier.)la source
J'ai eu le problème que je passais une URL dans une bibliothèque qui appelait
url.openConnection();
j'ai adapté la réponse de jon-daniel,En utilisant cette classe, il est possible de créer une nouvelle URL avec:
Cela a l'avantage d'être localisé et de ne pas remplacer la valeur par défaut
URL.openConnection
.la source