Certificados autofirmados Java

Iniciado por alzehimer_cerebral, 8 Febrero 2011, 20:56 PM

0 Miembros y 1 Visitante están viendo este tema.

alzehimer_cerebral

Hola foro,

llevo bastante tiempo intentando programar una conexion Https con certificados autofirmados..  Haber si alguien me puede aclarar un par de dudas para rematar las clases.

Los clientes que utilizan las clases que posteo a continuacion tiene el certificado autofirmado añadido al cacerts (key store por defecto de la maquina virtual Java donde se encuentran los certificados de confianza).

De momento estoy intentando conectar a dicho un servidor mediante Https para descargar archivos xml. La duda que tengo es si la interfaz X509TrustManager permite realizar conexiones con certificados autofirmados que han sido autofirmados (Lo pregunto porque he leido en algunos sitios que no se puede, pero me surje la duda de que tal vez si se añaden al cacerts si lo permite).

Si se diera el caso de que dicha interfaz no permite las conexiones con certificados autofirmados entonces que interfaz debo utilizar???

Os dejo las clases que estoy implementando por si os sirven de ayuda:

Código (java) [Seleccionar]

public class Https {




    public static void main(String args[]) throws MalformedURLException, NoSuchAlgorithmException, Exception {

       //System.setProperty("javax.net.ssl.trustStore","tomcatKeystore");
       //System.setProperty("javax.net.ssl.keyStore", "/usr/jdk1.5.0_11/jre/lib/security/cacerts");
       //System.setProperty("javax.net.ssl.keyStorePassword","changeit");
       
       // java -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=123456 MyApp

       //System.setProperty("javax.net.ssl.trustStore","C:\\Archivos de Programa\\Java\\jre1.6.0_07\\lib\\security\\cacerts");
       //System.setProperty("javax.net.ssl.trustStorePassword","changeit"");

       //Para aceptar certificados que no estan en el keystore del cliente
       SSLContext sc = SSLContext.getInstance("TLS");
       sc.init(null, new TrustManager[] { new SimpleTrustManager1() }, null);
       SSLSocketFactory ssf = sc.getSocketFactory();

       System.out.println("Antes URL");
       URL url = new URL("https://loquesea.es");
       HttpsURLConnection urlConection = (HttpsURLConnection) url.openConnection();
       
       urlConection.setSSLSocketFactory(ssf);


       urlConection.setHostnameVerifier(new SimpleHostnameVerifier());
       
       //urlConection.connect();

       
       System.out.println("Antes INPUTSTREAM");
       InputStream is = urlConection.getInputStream();
       System.out.println("Despues INPUTSTREAM");


       System.out.println("Antes leer fichero");
       File fichero = new File("pruebas_ssl.xml");
       FileOutputStream fos = new FileOutputStream(fichero);
       byte[] bytes = new byte[1024];
       int leidos;
       while ((leidos = is.read(bytes)) != -1){
           fos.write(bytes, 0, leidos);
       }
       fos.close();
       is.close();


    }

}




public class SimpleTrustManager1 implements X509TrustManager   {

   private Set<X509Certificate> certs = new HashSet<X509Certificate>();


   public SimpleTrustManager1() throws Exception {
       System.out.println("Entra en constructor SimpleTrustManager1()");
       //Falta Cargar los certificados del Keystore en el atributo certs
       KeyStore ks = KeyStore.getInstance("JKS");
       String cacerts = "C:\\Archivos de Programa\\Java\\jre1.6.0_07\\lib\\security\\cacerts";
       FileInputStream stream = new FileInputStream(new File(cacerts));
       ks.load(stream, "changeit".toCharArray());
       stream.close();

       //Comprobamos si cacerts se ha cargado correctamente en el KeyStore



       // KeyStore.TrustedCertificateEntry certificateEntry = (KeyStore.TrustedCertificateEntry)ks.getCertificateAlias("alias_certificado");

       //certs.addAll();

  }

  public void checkClientTrusted(X509Certificate[] chain, String authType)
     throws CertificateException {
  }

  public X509Certificate[] getAcceptedIssuers() {
       System.out.println("Entra en getAcceptedIssuers");
    return certs.toArray(new X509Certificate[certs.size()]);
  }

  public void checkServerTrusted(X509Certificate[] chain, String authType)
     throws CertificateException {
       Boolean trusted =false;
       //try {

           System.out.println("chain.length="+chain.length);
           System.out.println("authType:" + authType);

           for (int i = 0; i < chain.length; i++) {
               System.out.println("Entra en checkServerTrusted" + i);
               X509Certificate aux = chain[i];
               Principal prueba=aux.getIssuerDN();
               System.out.println(prueba.getName());

               if (certs.contains(chain[i])) {
                   System.out.println("certs.contains(chain[i])");
                   trusted=true;
                   return;
               }
           }

           if(!trusted){

               int x = JOptionPane.showConfirmDialog(null, "El servidor " + chain[0].getIssuerDN() + " no se puede verificar. " + "¿Desde realizar la conexión de todas formas?", "TITULO", JOptionPane.YES_NO_OPTION);
               if (x == JOptionPane.OK_OPTION) {
               //throw new CertificateException("La clave no está en el trustore");
               certs.add(chain[0]);
               trusted=true;
               System.out.println("Despues certs.add(chain[0]); ");
               }

               else{

               }
               /**System.out.println("El servidor " + chain[0].getIssuerDN() + " no se puede verificar. " + "¿Desde realizar la conexión de todas formas?");
               //Scanner s = new Scanner(System.in).useDelimiter("\r\n");
               BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
               String linea = br.readLine();
               System.out.println("Despues Scanner");
               //String opcion = s.next();
               System.out.println("opcion:" + linea);
               if (!linea.equalsIgnoreCase("si")) {
                   throw new CertificateException("La clave no está en el trustore");
               }

               * */
               /**
           } catch (IOException ex) {
               Logger.getLogger(SimpleTrustManager1.class.getName()).log(Level.SEVERE, null, ex);
           }**/
   
      }
  }


}



public class SimpleHostnameVerifier implements HostnameVerifier {

   @Override
 public boolean verify(String hostname, SSLSession session) {
    System.out.println("Host: "+hostname);
    try {
       X509Certificate cert = (X509Certificate)session.getPeerCertificates()[0];
       System.out.println("DN:"+cert.getIssuerDN());
    } catch (SSLPeerUnverifiedException e) {
       e.printStackTrace();
    }
    return true;
 }


}


Cada clase se encuentra en un fichero por lo cual no se pueden compartir variables.

Cualquier aclaracion para encaminarme sera mas que agradecida.

Gracias de antemano.

Salu2.

alzehimer_cerebral
Servicios Informaticos Valencia - www.ag-solutions.es
Mi blog - www.alvarogarciasolano.com

alzehimer_cerebral

#1
He avanzado un poco en la materia de los certificados..  Y apuedo confirmar que si se pueden utilizar certificados autofirmados con X09TrustManager, tambien se como cargar el contenido de cacerts y buscar si se encuentra un cierto certificado.  La cuestion es que me interesa que si un certificado autofirmado no se encuentra en cacerts que se le pregunte al usuario si desea aceptarlo o no..

Lo he implementado dentro de la interfaz X509TrustManager en el metodo checkServerTrusted(X509Certificate[] chain, String authType).

El metodo quedaria asi:

Código (java) [Seleccionar]


public void checkServerTrusted(X509Certificate[] chain, String authType)
     throws CertificateException {
       Boolean trusted =false;
       //try {

           System.out.println("chain.length="+chain.length);
           System.out.println("authType:" + authType);

           X509Certificate aux= null;

           for (int i = 0; i < chain.length; i++) {
               System.out.println("Entra en checkServerTrusted" + i);
               aux = chain[i];
               Principal prueba=aux.getIssuerDN();
               System.out.println("IssuerDN:" + prueba.getName());

               if (certs.contains(chain[i])) {
                   System.out.println("certs.contains(chain[i])");
                   trusted=true;
                   return;
               }
           }

           if(!trusted){

               int x = JOptionPane.showConfirmDialog(null, "El servidor " + chain[0].getIssuerDN() + " no se puede verificar. " + "¿Desde realizar la conexión de todas formas?", "TITULO", JOptionPane.YES_NO_OPTION);
               if (x == JOptionPane.OK_OPTION) {
               //throw new CertificateException("La clave no está en el trustore");
               certs.add(aux);
               trusted=true;
               System.out.println("Despues certs.add(chain[0]); ");
               }

               else{
                   System.out.println("No se quiere confiar en el certificado y por lo tanto no se debe proceder con la descarga del fichero");

               }
               /**System.out.println("El servidor " + chain[0].getIssuerDN() + " no se puede verificar. " + "¿Desde realizar la conexión de todas formas?");
               //Scanner s = new Scanner(System.in).useDelimiter("\r\n");
               BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
               String linea = br.readLine();
               System.out.println("Despues Scanner");
               //String opcion = s.next();
               System.out.println("opcion:" + linea);
               if (!linea.equalsIgnoreCase("si")) {
                   throw new CertificateException("La clave no está en el trustore");
               }

               * */
               /**
           } catch (IOException ex) {
               Logger.getLogger(SimpleTrustManager1.class.getName()).log(Level.SEVERE, null, ex);
           }**/
   
      }
  }


}



Mi duda es la siguiente: tengo la clase Https (la del post anterior) en la cual dependiendo de la accion del usuario de aceptar o no el certificado se debe proceder con la descarga...

La verdad que no se como hacer para desde el main saber si el usuario acepta o deniega el certificado.  Deberia usar una variable global??

Comentarme cosas please...

Salu2.

alzehimer_cerebral
Servicios Informaticos Valencia - www.ag-solutions.es
Mi blog - www.alvarogarciasolano.com

novanoticia

hola,
he puesto un ejemplo en c# de como pasar un certificado de un almacen a otro y instalarlo en en servidor IIS:
este es el enlace:
http://foro.elhacker.net/criptografia/certificados_digitales_autofirmados-t316228.0.html;msg1696344#msg1696344