android-security - responde - porque mi celular no abre las aplicaciones android
Cómo solucionar la implementación insegura de X509TrustManager en la aplicación de Android (4)
Google me ha informado que tengo una implementación no segura de la interfaz X509TrustManager en mi aplicación de Android y necesito cambiar mi código de la siguiente manera:
Para manejar adecuadamente la validación de certificados SSL, cambie su código en el método checkServerTrusted de su interfaz X509TrustManager personalizada para generar CertificateException o IllegalArgumentException cuando el certificado presentado por el servidor no cumpla con sus expectativas. Para preguntas técnicas, puede publicar en Stack Overflow y usar las etiquetas "android-security" y "TrustManager".
¿Cómo se puede modificar el siguiente código para solucionar el problema anterior?
public EasySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
mContext.init(null, new TrustManager[] { tm }, null);
}
He resuelto esto usando el siguiente código:
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
try {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("Certificate not valid or trusted.");
}
}
Me he encontrado con este problema. Si tu código es así:
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
aceptará todos los certificados y es una mala idea, por lo que Google le enviará un correo. También podemos hacer un cambio para aceptar el certificado autofirmado. Lo resolví, aquí está mi pregunta y mi solución.
Si encuentra esto en la biblioteca externa que está usando, verifique si la causa es la biblioteca de appache.
Para mí, la biblioteca de apache provocó el error: estaba usando una clase en desuso - MultipartEntity . Esta clase usa SSLContextBuilder que usa TrustManagerDelegate . TrustManagerDelegate implementa X509TrustManager, lo que provoca un error de "implementación insegura de TrustManager" al cargar la aplicación en Google Play Store.
La solución es: en lugar de MultipartEntity clase MultipartEntity obsoleta, use MultipartEntityBuilder .
Por ejemplo :
MultipartEntity httpMultipart = new MultipartEntity();
String contentType = httpMultipart.getContentType().getValue();
Será reemplazado por:
MultipartEntityBuilder httpMultipart = new MultipartEntityBuilder();
String contentType = httpMultipart.build().getContentType().getValue();
Si está usando HttpClient
, la solución de share es muy buena, pero si está usando HttpsUrlConnection
, este código es muy bueno para eso:
import android.util.Log;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* TrustManager that accepts all certificates and hosts.
* Useful when you want to use HTTPS but you have self-signed certificates.
* Works with HttpsUrlConnection.
* Use at your own risk and only for development.
*
* @author gotev (Aleksandar Gotev)
*/
public class AllCertificatesAndHostsTruster implements TrustManager, X509TrustManager {
@Override
public final void checkClientTrusted(final X509Certificate[] xcs, final String string)
throws CertificateException {
}
@Override
public final void checkServerTrusted(final X509Certificate[] xcs, final String string)
throws CertificateException {
}
@Override
public final X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
/**
* Gets an {@link SSLContext} which trusts all certificates.
* @return {@link SSLContext}
*/
public static SSLContext getSSLContext() {
final TrustManager[] trustAllCerts =
new TrustManager[] {new AllCertificatesAndHostsTruster()};
try {
final SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustAllCerts, new SecureRandom());
return context;
} catch (Exception exc) {
Log.e("CertHostTruster", "Unable to initialize the Trust Manager to trust all the "
+ "SSL certificates and HTTPS hosts.", exc);
return null;
}
}
/**
* Creates an hostname verifier which accepts all hosts.
* @return {@link HostnameVerifier}
*/
public static HostnameVerifier getAllHostnamesVerifier() {
return new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
}
/**
* Call this method once before all your network calls
* to accept all the self-signed certificates in HTTPS connections.
*/
public static void apply() {
final TrustManager[] trustAllCerts =
new TrustManager[] {new AllCertificatesAndHostsTruster()};
try {
final SSLContext context = SSLContext.getInstance("SSL");
context.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (Exception exc) {
Log.e("CertHostTruster", "Unable to initialize the Trust Manager to trust all the "
+ "SSL certificates and HTTPS hosts.", exc);
}
}
}
Fuente: https://gist.github.com/gotev/6784c1303793c6ee9e56
Luego, para usar certificados autofirmados, simplemente invoque:
AllCertificatesAndHostsTruster.apply();
Antes de cualquier llamada a la red.