2011-12-17 16 views
6

¿Alguien sabe de algún buen tutorial, sitio o libro sobre cómo escribir un comprobador SSL en Java? Estoy tratando de hacer lo que se puede encontrar aquí: http://www.sslshopper.com/ssl-checker.html. No estoy tratando de crear un certificado autofirmado o usar un almacén de claves. Quiero poder ir a cualquier sitio para determinar si existe un Certificado SSL válido, determinar si el nombre de host en el Certificado coincide con el nombre ingresado, y determinar cuándo caducará este Certificado. He buscado este tema en Google, pero "Cómo crear un comprador SSL utilizando Java" no me ha dado nada y mis otras búsquedas solo me trajeron enlaces sobre cómo crear un certificado autofirmado. Cualquier ayuda sería muy apreciada.Escribiendo un Comprobador SSL usando Java

Respuesta

1

Lo que puede hacer es poner en práctica su propia ficha en la parte superior de por ejemplo Apache's HttpClient
Debe inicializar un contexto SSL y anular el TrustManagers que comprobar nada que desee.

La biblioteca puede realizar automáticamente la verificación del nombre de host.

E.g. lo siguiente será configurar el manejo de socket SSL para lanzar una excepción si el nombre de host no coincide con los datos del certificado:

SSLSocketFactory sf = new SSLSocketFactory(
    SSLContext.getInstance("TLS"), 
    SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); 
3

Para obtener el certificado de servidor en el primer lugar con el fin de hacer la verificación manual, independientemente de si se trata de válido o no, lo más fácil es conectarse a través de un SSLSocket después de haber desactivado cualquier verificación de certificado.

Crear una SSLContext que deja nada a través de:

SSLContext sslContext = SSLContext.getInstance("TLS"); 
X509TrustManager passthroughTrustManager = new X509TrustManager() { 
    @Override 
    public void checkClientTrusted(X509Certificate[] chain, 
      String authType) throws CertificateException { 
    } 

    @Override 
    public void checkServerTrusted(X509Certificate[] chain, 
      String authType) throws CertificateException { 
    } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
     return null; 
    } 
}; 
sslContext.init(null, new TrustManager[] { passthroughTrustManager }, 
     null); 

(Nota al margen: para personas que buscan una manera de utilizar los certificados de prueba internamente, me gustaría recomendar la construcción de su propia prueba de CA en lugar de deshabilitar comprobaciones, justo en caso de que esas verificaciones se dejen en el código de producción por error, y también porque hace que las pruebas sean más realistas.)

Cree un socket, conéctese e inicie el handshake explícitamente (ya que realmente no va a leer el formulario it):

SSLSocketFactory ssf = sslContext.getSocketFactory(); 
SSLSocket socket = (SSLSocket) ssf.createSocket(
     "the.host.name", 443); 
socket.startHandshake(); 

Obtiene la cadena de certificados de pares. El primer elemento es el certificado del servidor real.

X509Certificate[] peerCertificates = (X509Certificate[]) socket 
     .getSession().getPeerCertificates(); 

Si desea validar contra las anclas de confianza predeterminado (el valor por defecto de confianza certificados CA), construir un X509TrustManager basado en los valores por defecto (esto es efectivamente lo que el passthroughTrustManager por encima de personas con discapacidad):

// By default on Oracle JRE, algorithm is PKIX 
TrustManagerFactory tmf = TrustManagerFactory 
     .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
// 'null' will initialise the tmf with the default CA certs installed 
// with the JRE. 
tmf.init((KeyStore) null); 
X509TrustManager tm = (X509TrustManager) tmf.getTrustManagers()[0]; 

Ahora, verifique si el certificado es actualmente válido en el tiempo, si se verifica contra un ancla confiable y si tiene las extensiones correctas de acuerdo con RFC 3280.

try { 
    // Assuming RSA key here. 
    tm.checkServerTrusted(peerCertificates, "RSA"); 
} catch (CertificateException e) { 
    // Here you may check which subclass of CertificateException to know what the error is. 
} 

Todo lo anterior hace uso de JSSE API.

Como alternativa, si desea profundizar en los detalles de PKIX, puede utilizar el Java Certification Path API (que es utilizado por JSSE).

(Si solo desea certificados válidos para empezar, simplemente use SSLContext sslContext = SSLContext.getDefault() al comienzo, cree el socket y realice el intercambio de contactos.)

Para obtener el certificado de servidor directamente, puede utilizar esto:

X509Certificate serverCert = peerCertificates[0]; 

X509Certificate tiene una serie de métodos en relación con las fechas y diversas extensiones. Por ejemplo:

Date expirationDate = serverCert.getNotAfter(); 

La verificación nombre de host debe seguir RFC 6125 (o al menos RFC 2818). En resumen, verifique si el nombre de host al que desea conectarse es una de las entradas de DNS de los Nombres Alternativos del Sujeto (SAN). De lo contrario, vuelva a comprobar si el nombre de host está en el CN ​​RDN de su certificado (para esto, debe dividir el DN del asunto en RDN). También te puede interesar this discussion (on the specific case of using IP addresses).

Todo depende de la cantidad de verificación "manual" que desee realizar. Hay una serie de especificaciones para leer (RFC 5280/RFC 3280 y RFC 6125/RFC 2818 al menos), además de la documentación de API.

Esta pregunta sobre Security.SE también debe ser de interés:

+0

consigo tipos no convertibles cuando se trata de hacer esto: X509Certificate [] = peerCertificates (X509Certificate [ ]) socket.getSession(). getPeerCertificates(); – W3B5T4R

+0

Incluso probé un ejemplo del sitio de Oracles usando lo anterior y sigo obteniendo los "tipos inconvertibles" – W3B5T4R

+0

No importa que vea, estaba usando import javax.security.cert.X509Certificate; en lugar de importar java.security.cert.X509Certificate; – W3B5T4R