java - significa - ssl pinning android
Problemas con https(sin certificado de pares) en Android (3)
El método de solicitud
POST
es apropiado para la URL/
. Eso es todo lo que sabemos.
El ejemplo 1 no funciona porque parece que no tiene permiso para enviar solicitudes POST
a esa página. Tratar:
/* ... */
HttpGet httpGet = new HttpGet(url);
HttpResponse response = httpClient.execute(httpGet);
/* ... */
El ejemplo 2 no funciona porque no acepta el certificado del sitio web como un certificado aceptado, por lo que también debería ser así:
/* ... */
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
/* ... */
Problema
Quiero enviar una solicitud https al sitio https://10.2.20.20/fido/EzPay/login.php mi propio servidor y obtener respuesta de él y guardarlo, por ejemplo, en una cadena. He encontrado algunos códigos de ejemplo en Internet e intento probarlos para mi problema, pero no son útiles. A continuación presento algunas partes de los códigos que he probado.
Ejemplo de código:
Intento este código, pero siempre obtengo la misma excepción "Sin certificado" ¿Por qué?
try
{
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
DefaultHttpClient client = new DefaultHttpClient();
SchemeRegistry registry = new SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register(new Scheme("https", socketFactory, 443));
SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());
// Set verifier
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
// Example send http request
final String url = "https://10.2.20.20/fido/EzPay/login.php";
HttpPost httpPost = new HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
Log.i(DownloadImageTask.class.getName(), line);
}
}
catch(IOException ex)
{
Log.e(DownloadImageTask.class.getName(), ex.getMessage());
}
Excepción.
03-02 16: 58: 25.234: W / System.err (1868): javax.net.ssl.SSLPeerUnverifiedException: Sin certificado entre pares 03-02 16: 58: 25.238: W / System.err (1868): en org. apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates (SSLSessionImpl.java:137) 03-02 16: 58: 25.238: W / System.err (1868): en org.apache.http.conn.ssl.AbstractVerifier .verify (AbstractVerifier.java:93) 03-02 16: 58: 25.238: W / System.err (1868): en org.apache.http.conn.ssl.SSLSocketFactory.createSocket (SSLSocketFactory.java:381) 03- 02 16: 58: 25.238: W / System.err (1868): en org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection (DefaultClientConnectionOperator.java:165) 03-02 16: 58: 25.250: W / System. err (1868): en org.apache.http.impl.conn.AbstractPoolEntry.open (AbstractPoolEntry.java:164) 03-02 16: 58: 25.250: W / System.err (1868): en org.apache.http .impl.conn.AbstractPooledConnAdapter.open (AbstractPooledConnAdapter.java:119) 03-02 16: 58: 25.250: W / System.err (1868): en org.apache.http.impl.client.DefaultRequestDirector.execut e (DefaultRequestDirector.java:360) 03-02 16: 58: 25.250: W / System.err (1868): en org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:555) 03-02 16: 58: 25.250: W / System.err (1868): en org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:487) 03-02 16: 58: 25.250: W / System.err (1868): en org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:465) 03-02 16: 58: 25.250: W / System.err (1868): at com.https.test. DownloadImageTask.doInBackground (Https_testActivity.java:78) 03-02 16: 58: 25.250: W / System.err (1868): at com.https.test.DownloadImageTask.doInBackground (Https_testActivity.java:1) 03-02 16: 58: 25.250: W / System.err (1868): en android.os.AsyncTask $ 2.call (AsyncTask.java:264) 03-02 16: 58: 25.253: W / System.err (1868): en java. util.concurrent.FutureTask $ Sync.innerRun (FutureTask.java:305) 03-02 16: 58: 25.253: W / System.err (1868): at java.util.concurrent.FutureTask.run (FutureTask.java:137 ) 03-02 16: 58: 25.253: W / System.err (1868): en y roid.os.AsyncTask $ SerialExecutor $ 1.run (AsyncTask.java:208) 03-02 16: 58: 25.257: W / System.err (1868): at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java: 1076) 03-02 16: 58: 25.257: W / System.err (1868): en java.util.concurrent.ThreadPoolExecutor $ Worker.run (ThreadPoolExecutor.java:569) 03-02 16: 58: 25.257: W / System.err (1868): en java.lang.Thread.run (Thread.java:856)
Pregunta
Lo que estoy haciendo mal y cómo puedo resolver este problema. ¿Por qué obtengo la excepción " Sin certificado de igual "?
Gracias.
Editado
Configuración del servidor Windows.
<VirtualHost *:443>
ServerName 10.2.20.20
Alias /fido/EzPay/ "d:/fido/EzPay/"
Alias /fido/EzPay "d:/fido/EzPay/"
<Directory "d:/fido/EzPay/">
Options Indexes FollowSymLinks MultiViews
AllowOverride all
Order allow,deny
Allow from all
</Directory>
# These are the actual SSL directives needed to get it all working!
SSLEngine on
SSLCertificateFile C:/wamp/bin/apache/apache2.2.17/conf/ssl/fidoserver.crt
SSLCertificateKeyFile C:/wamp/bin/apache/apache2.2.17/conf/ssl/fidoserver.pem
</VirtualHost>
¿Has intentado abrir la página con un navegador? Si no está abriendo su configuración es incorrecto.
Tenga en cuenta que si utiliza un certificado autofirmado, puede tener algunos problemas de conexión. Algunas versiones del núcleo de Android (anteriores a 2.6.32.9) no les gustan los certificados autocantados.
Finalmente he resuelto el problema https. Mientras luchaba el problema principal estaba en el servidor, concretamente en el certificado. Android solo admite el certificado "BKS" y esa es la razón por la que no podemos obtener una respuesta del servidor. Para resolver este problema, he leído más de 30 artículos y, finalmente, he encontrado una solución.
Los pasos que hice para resolver este problema se pueden ver a continuación:
Lo primero que hice fue generar el archivo .bks keystore de nuestro certificado fidoserver.crt, para hacer eso he leído este artículo y hago lo siguiente:
- Abrir cmd
- Vaya a la carpeta JDK "cd X: / Programs / Java / Jdk6 / bin"
- Llamada siguiente comando:
keytool -import -alias tomcat -file X: //KeyStore/fidoserver.crt -keypass password - keystore X: //KeyStore/keystore.bks -storetype BKS -storepass 222222 -providerCproveedorprovidencia X: //KeyStore/bcprov-jdk16-146.jar
Antes de ejecutar este comando, descargué el archivo .jar de Bouncy Castle y lo puse en la carpeta con certificados. Después de hacer esto, todos los pasos obtengo el archivo keystore.bks, que es el archivo de certificado correcto para la aplicación de Android. Puse este archivo en la carpeta Androids mnc / sdcard. En el código java, he escrito el siguiente código para leer el archivo keystore.bbk
KeyStore trustStore = KeyStore.getInstance( "BKS" /*KeyStore.getDefaultType()*/ );
FileInputStream instream = new FileInputStream(new File("/mnt/sdcard/keystore.bks"));
try {
trustStore.load(instream, "222222".toCharArray());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try { instream.close(); } catch (Exception ignore) {}
}
// Create socket factory with given keystore.
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", socketFactory, 443);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
HttpGet httpget = new HttpGet("https://10.2.20.20/fido/EzPay/login.php");
System.out.println("executing request " + httpget.getRequestLine());
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
// Print html.
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
Todo esto permite que m cargue nuestro certificado con la contraseña 222222 dada (la contraseña que damos cuando creamos un almacén de claves con keytool).
Después de esto, todas mis aplicaciones de prueba comienzan a funcionar correctamente. Ahora puedo enviar la solicitud a https y obtener respuesta de ella. He probado la aplicación con el servidor FIDO, todo funciona muy bien! Creo que el lunes haré algunos cambios en la aplicación EzPay y comenzará a trabajar con conexiones https.