Écriture d'un vérificateur SSL à l'aide de Java


Quelqu'un connaît-il de bons tutoriels, sites et ou livres sur l'écriture d'un vérificateur SSL en Java? J'essaie de faire ce qui peut être trouvé ici: http://www.sslshopper.com/ssl-checker.html . Je n'essaie pas de créer un certificat auto-signé ou d'utiliser un magasin de clés. Je veux pouvoir aller sur n'importe quel site déterminer si un certificat SSL valide existe, déterminer si le nom d'hôte sur le certificat correspond au nom entré et déterminer quand ce certificat expirera. J'ai googlé ce sujet, mais "Comment créer un client SSL en utilisant Java " ne m'a rien donné et mes autres recherches ne m'ont apporté que des liens sur la façon de créer un certificat auto-signé. Toute aide serait grandement appréciée.

Author: W3B5T4R, 2011-12-17

2 answers

Pour obtenir le certificat du serveur en premier lieu afin de faire la vérification manuellement, peu importe qu'il soit valide ou non, le plus simple est de se connecter via un SSLSocket après avoir désactivé toute vérification de certificat.

Créez un SSLContext qui laisse passer n'importe quoi:

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);

(Note latérale: pour les personnes à la recherche d'un moyen d'utiliser les certificats de test en interne, je recommanderais de créer votre propre autorité de certification de test plutôt que de désactiver les vérifications, juste au cas où ces vérifications factices seraient laissé dans le code de production par erreur, et aussi parce que cela rend les tests plus réalistes.)

Créez un socket, connectez-vous et démarrez explicitement la poignée de main (puisque vous n'allez pas vraiment le lire):

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

Obtenez la chaîne de certificats de pair. Le premier élément est le certificat de serveur.

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

Si vous voulez valider par rapport aux ancres de confiance par défaut (les certificats d'autorité de certification de confiance par défaut), créez un X509TrustManager basé sur les valeurs par défaut (c'est effectivement ce que le passthroughTrustManager ci-dessus désactivé):

// 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];

Maintenant, vérifiez si le certificat est actuellement valide dans le temps, s'il est vérifié par rapport à une ancre de confiance et s'il a les bonnes extensions selon 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.
}

Tout ce qui précède utilise l'API JSSE.

Alternativement, si vous souhaitez approfondir les détails de PKIX, vous pouvez utiliser l'API Java Certification Path (qui est utilisée par JSSE).

(Si vous vous voulez de toute façon des certificats valides pour commencer, utilisez simplement SSLContext sslContext = SSLContext.getDefault() au début, créez le socket et effectuez la poignée de main.)

Pour obtenir le certificat de serveur directement, vous pouvez utiliser ceci:

X509Certificate serverCert = peerCertificates[0];

X509Certificate a un certain nombre de méthodes concernant les dates et les différentes extensions. Par exemple:

Date expirationDate = serverCert.getNotAfter();

La vérification du nom d'hôte doit suivre RFC 6125 (ou au moins RFC 2818). En bref, vérifiez si le nom d'hôte auquel vous aviez l'intention de vous connecter est l'un des Objet Noms alternatifs (SAN) entrée DNS. À défaut, revenez vérifier si le nom d'hôte est dans le RDN CN de votre certificat (pour cela, vous devez diviser le DN sujet en RDN). Vous pouvez également être intéressé par cette discussion (sur le cas spécifique de l'utilisation des adresses IP).

Tout dépend de la vérification "manuelle" que vous souhaitez effectuer. Il y a un certain nombre de spécifications à lire (RFC 5280/RFC 3280 et RFC 6125/RFC 2818 au moins), en plus de l'API documentation.

Cette question sur Security.SE devrait également être intéressant:

 3
Author: Bruno, 2017-05-23 12:25:22

Ce que vous pouvez faire est d'implémenter votre propre vérificateur au-dessus de par exemple HttpClient d'Apache
Vous devez initialiser un contexte SSL et remplacer le TrustManagers pour effectuer toutes les vérifications souhaitées.

La vérification du nom d'hôte peut être effectuée automatiquement par la bibliothèque.

Par exemple, ce qui suit configurera la gestion du socket SSL pour lever une exception si le nom d'hôte ne correspond pas aux informations du certificat:

SSLSocketFactory sf = new SSLSocketFactory(
    SSLContext.getInstance("TLS"),
    SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
 1
Author: Cratylus, 2011-12-17 15:47:38