J'essaie de me connecter à une boîte IIS6 exécutant un certificat SSL godaddy 256 bits, et j'obtiens le message d'erreur suivant:
Java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
J'essayais de déterminer ce qui pouvait être la cause de cela, mais je dessinais des blancs en ce moment.
Voici comment je me connecte:
HttpsURLConnection conn;
conn = (HttpsURLConnection) (new URL(mURL)).openConnection();
conn.setConnectTimeout(20000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.connect();
String tempString = toString(conn.getInputStream());
La solution de @Chrispix est dangereuse! Faire confiance à tous les certificats permet à quiconque de faire l'attaque d'un homme au milieu! Envoyez n'importe quel certificat au client et il l'acceptera!
Ajoutez vos certificats à un gestionnaire de confiance personnalisé comme décrit dans cet article: Faire confiance à tous les certificats utilisant HttpClient via HTTPS
Bien qu’il soit un peu plus complexe d’établir une connexion sécurisée avec un certificat personnalisé, il vous apportera la sécurité de chiffrement SSL recherchée sans le danger d’une attaque de type homme au milieu!
Contrairement à la réponse acceptée, vous n'avez pas besoin d'un gestionnaire de confiance personnalisé, vous devez réparer votre serveur configuration!
Je rencontre le même problème lors de la connexion à un serveur Apache avec un certificat dynadot/alphassl mal installé. Je me connecte à l'aide de HttpsUrlConnection (Java/Android), qui lançait -
javax.net.ssl.SSLHandshakeException:
Java.security.cert.CertPathValidatorException:
Trust anchor for certification path not found.
Le problème réel est une mauvaise configuration du serveur - testez-le avec http://www.digicert.com/help/ ou similaire, et il vous indiquera même la solution:
"Le certificat n'est pas signé par une autorité de confiance (vérification par rapport au magasin racine de Mozilla). Si vous avez acheté le certificat auprès d'une autorité de confiance, , il vous suffit probablement de l'installer. un ou plusieurs certificats intermédiaires . Contactez votre fournisseur de certificats pour obtenir de l'aide pour cette opération sur votre plate-forme de serveur. "
Vous pouvez également vérifier le certificat avec openssl:
openssl s_client -debug -connect www.thedomaintocheck.com:443
Vous verrez probablement:
Verify return code: 21 (unable to verify the first certificate)
et plus tôt dans la sortie:
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 OU = Domain Control Validated, CN = www.thedomaintocheck.com
verify error:num=21:unable to verify the first certificate`
La chaîne de certificats ne contiendra qu'un seul élément (votre certificat):
Certificate chain
0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
i:/O=AlphaSSL/CN=AlphaSSL CA - G2
... mais les autorités de signature doivent, dans une chaîne, faire référence à des autorités de confiance approuvées par Android (Verisign, GlobalSign, etc.):
Certificate chain
0 s:/OU=Domain Control Validated/CN=www.thedomaintocheck.com
i:/O=AlphaSSL/CN=AlphaSSL CA - G2
1 s:/O=AlphaSSL/CN=AlphaSSL CA - G2
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
2 s:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
i:/C=BE/O=GlobalSign nv-sa/OU=Root CA/CN=GlobalSign Root CA
Les instructions (et les certificats intermédiaires) pour la configuration de votre serveur sont généralement fournies par l'autorité qui a délivré votre certificat, par exemple: http://www.alphassl.com/support/install-root-certificate.html =
Après avoir installé les certificats intermédiaires fournis par mon émetteur de certificats, je n'ai plus d'erreur lors de la connexion à l'aide de HttpsUrlConnection.
Vous pouvez faire confiance à un certificat particulier au moment de l'exécution.
Il suffit de le télécharger depuis le serveur, de mettre des actifs et de le charger comme ceci avec ssl-utils-Android :
OkHttpClient client = new OkHttpClient();
SSLContext sslContext = SslUtils.getSslContextForCertificateFile(context, "BPClass2RootCA-sha2.cer");
client.setSslSocketFactory(sslContext.getSocketFactory());
Dans l'exemple ci-dessus, j'ai utilisé OkHttpClient
mais SSLContext
peut être utilisé avec n'importe quel client Java.
Si vous avez des questions, n'hésitez pas à les poser. Je suis l'auteur de cette petite bibliothèque.
Mise à jour basée sur la dernière documentation Android (mars 2017):
Lorsque vous obtenez ce type d'erreur:
javax.net.ssl.SSLHandshakeException: Java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.Java:374)
at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.Java:209)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.Java:478)
at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.Java:433)
at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.Java:290)
at libcore.net.http.HttpEngine.sendRequest(HttpEngine.Java:240)
at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.Java:282)
at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.Java:177)
at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.Java:271)
le problème pourrait être l'un des suivants:
La solution consiste à apprendre à HttpsURLConnection
à faire confiance à un ensemble spécifique d'AC. Comment? Veuillez vérifier https://developer.Android.com/training/articles/security-ssl.html#CommonProblems
Les autres utilisateurs de AsyncHTTPClient
de la bibliothèque com.loopj.Android:android-async-http
doivent vérifier Configurez AsyncHttpClient pour utiliser HTTPS .
Répondre à très vieux poste. Mais peut-être que cela aidera certains débutants et si aucune de ces solutions ne fonctionne.
Explication: Je sais que personne ne veut une explication merde; plutôt la solution. Mais dans une ligne, vous essayez d'accéder à un service de votre ordinateur local vers un ordinateur distant qui ne fait pas confiance à votre ordinateur. Votre demande doit gagner la confiance du serveur distant.
Solution: La solution suivante suppose que vous remplissez les conditions suivantes.
Pas:
Vous avez besoin d’un fichier d’extension .keystore pour inscrire votre application. Si vous ne savez pas comment créer un fichier .keystore; Ensuite, suivez la section suivante Créer un fichier .keystore ou passez à la section suivante Sign Apk File
Créer un fichier .keystore
Ouvrez Android Studio. Cliquez sur le menu supérieur Construction> Générer un APK signé. Dans la fenêtre suivante, cliquez sur le bouton Créer nouveau .... Dans la nouvelle fenêtre, veuillez saisir les données dans tous les champs. Rappelez-vous que le champ de deux mots de passe que je recommande devrait avoir le même mot de passe; n'utilisez pas de mot de passe différent; et souvenez-vous également du chemin de sauvegarde situé en haut du champ chemin du magasin de clés:. Après avoir saisi tout le champ, cliquez sur le bouton OK.
Sign Apk File
Vous devez maintenant créer une application signée avec le fichier .keystore que vous venez de créer. Suivez ces étapes
Choose existing...
Key store password
et Key password
. Entrez également le pseudonymebuild.gradle
, vous devez sélectionner Build Types
et Flavors
.Build Types
, choisissez release
dans le menu déroulant.Pour Flavors
cependant, cela dépendra de vos paramètres dans le fichier build.gradle
. Choisissez staging
dans ce champ. J'ai utilisé les paramètres suivants dans le build.gradle
, vous pouvez utiliser la même chose que le mien, mais assurez-vous de changer la applicationId
pour le nom de votre paquet
productFlavors {
staging {
applicationId "com.yourapplication.package"
manifestPlaceholders = [icon: "@drawable/ic_launcher"]
buildConfigField "boolean", "CATALYST_DEBUG", "true"
buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "true"
}
production {
buildConfigField "boolean", "CATALYST_DEBUG", "false"
buildConfigField "boolean", "ALLOW_INVALID_CERTIFICATE", "false"
}
}
Cliquez sur les deux cases Signature Versions
du bas, puis sur le bouton Finish
.
Presque là:
Tout le travail est fait, maintenant le mouvement de la vérité. Pour pouvoir accéder au serveur de stockage intermédiaire sauvegardé par un proxy, vous devez définir certains paramètres dans vos appareils Android en cours de test.
Configuration du proxy sur un périphérique Android:
Modify network
Advanced options
si vous ne pouvez pas voir le champ Proxy Hostname
Proxy Hostname
, entrez l'adresse IP de l'hôte ou le nom que vous souhaitez connecter. Un serveur de transfert type sera nommé stg.api.mygoodcompany.com
9502
Save
Un dernier arrêt:
Rappelez-vous que nous avons généré le fichier apk signé dans la section Sign APK APK. Il est maintenant temps d'installer ce fichier APK.
adb install
name of the apk file
adb command not found
. Entrez le chemin complet en tant que C:\Users\shah\AppData\Local\Android\sdk\platform-tools\adb.exe
install
name of the apk file
J'espère que le problème pourra être résolu. Si non s'il vous plaît laissez-moi un commentaire.
Salam!
Le message d'erreur que je recevais était similaire, mais la raison en était que le certificat auto-signé avait expiré . Lorsque le client openssl a été tenté, il m'a donné la raison qui avait été oubliée lorsque je vérifiais la boîte de dialogue du certificat de Firefox.
Donc, en général, si le certificat est présent dans le magasin de clés et que sa valeur est "VALID", cette erreur disparaîtra.
J'ai eu le même problème lors de la connexion d'un client Android au serveur Kurento . Le serveur Kurento utilisait des certificats jks. errors . Mais si vous utilisez fullchain.pem au lieu de cert.pem - tout va bien.
J'ai eu le même problème ce que j'ai trouvé était que le fichier de certificat .crt i fourni manquant un certificat intermédiaire. J'ai donc demandé à tous les fichiers .crt de mon administrateur serveur, puis je les ai concaténés dans l'ordre inverse.
Ex ..__ 1. Root.crt 2. Inter.crt 3. myCrt.crt
dans Windows i exécuté copier Inter.crt + Root.crt newCertificate.crt
(Ici j'ai ignoré myCrt.crt)
Ensuite, j'ai fourni le fichier newCertificate.crt dans le code via inputstream . Travail effectué.
Je sais que vous n'avez pas besoin de faire confiance à tous les certificats, mais dans mon cas, j'avais des problèmes avec certains environnements de débogage dans lesquels nous avions des certificats auto-signés et j'avais besoin d'une solution fictive.
Tout ce que je devais faire était de changer l'initialisation de sslContext
mySSLContext.init(null, trustAllCerts, null);
où trustAllCerts
a été créé comme ceci:
private final TrustManager[] trustAllCerts= new TrustManager[] { new X509TrustManager() {
public Java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new Java.security.cert.X509Certificate[]{};
}
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
} };
J'espère que cela vous sera utile.
L'erreur d'ancrage de confiance peut se produire pour de nombreuses raisons. Pour moi, c'était simplement que j'essayais d'accéder à https://example.com/
au lieu de https://www.example.com/
.
Donc, vous voudrez peut-être vérifier vos URL avant de commencer à créer votre propre gestionnaire de confiance (comme je l'ai fait).
Si vous utilisez retrofit, vous devez personnaliser votre OkHttpClient.
retrofit = new Retrofit.Builder() .baseUrl(ApplicationData.FINAL_URL) .client(getUnsafeOkHttpClient().build()) .addConverterFactory(GsonConverterFactory.create()) .build();
Le code complet est comme ci-dessous.
public class RestAdapter {
private static Retrofit retrofit = null;
private static ApiInterface apiInterface;
public static OkHttpClient.Builder getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(Java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(Java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public Java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new Java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new Java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return builder;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static ApiInterface getApiClient() {
if (apiInterface == null) {
try {
retrofit = new Retrofit.Builder()
.baseUrl(ApplicationData.FINAL_URL)
.client(getUnsafeOkHttpClient().build())
.addConverterFactory(GsonConverterFactory.create())
.build();
} catch (Exception e) {
e.printStackTrace();
}
apiInterface = retrofit.create(ApiInterface.class);
}
return apiInterface;
}
}
Sur les téléphones en pain d'épice, j'obtiens toujours l'erreur: Trust Anchor not found for Android SSL Connection
, même si je dois installer mon certificat.
Voici le code que j'utilise (en langage Scala):
object Security {
private def createCtxSsl(ctx: Context) = {
val cer = {
val is = ctx.getAssets.open("mycertificate.crt")
try
CertificateFactory.getInstance("X.509").generateCertificate(is)
finally
is.close()
}
val key = KeyStore.getInstance(KeyStore.getDefaultType)
key.load(null, null)
key.setCertificateEntry("ca", cer)
val tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm)
tmf.init(key)
val c = SSLContext.getInstance("TLS")
c.init(null, tmf.getTrustManagers, null)
c
}
def prepare(url: HttpURLConnection)(implicit ctx: Context) {
url match {
case https: HttpsURLConnection ⇒
val cSsl = ctxSsl match {
case None ⇒
val res = createCtxSsl(ctx)
ctxSsl = Some(res)
res
case Some(c) ⇒ c
}
https.setSSLSocketFactory(cSsl.getSocketFactory)
case _ ⇒
}
}
def noSecurity(url: HttpURLConnection) {
url match {
case https: HttpsURLConnection ⇒
https.setHostnameVerifier(new HostnameVerifier {
override def verify(hostname: String, session: SSLSession) = true
})
case _ ⇒
}
}
}
et voici le code de connexion:
def connect(securize: HttpURLConnection ⇒ Unit) {
val conn = url.openConnection().asInstanceOf[HttpURLConnection]
securize(conn)
conn.connect();
....
}
try {
connect(Security.prepare)
} catch {
case ex: SSLHandshakeException /*if ex.getMessage != null && ex.getMessage.contains("Trust anchor for certification path not found")*/ ⇒
connect(Security.noSecurity)
}
Fondamentalement, j'ai configuré pour faire confiance à mon certificat personnalisé. Si cela échoue, alors je désactive la sécurité. Ce n'est pas la meilleure option, mais le seul choix que je connaisse avec les téléphones anciens et bogués.
Cet exemple de code peut être facilement traduit en Java.
Dans mon cas, cela se produisait après la mise à jour vers Android 8.0. Le certificat auto-signé par Android était censé utiliser l’algorithme de signature SHA1withRSA. Le passage à un nouveau certificat utilisant l’algorithme de signature SHA256withRSA a résolu le problème.