使用Java编写SSL检查器

W3B*_*T4R 6 java ssl x509

有没有人知道有关用Java编写SSL检查器的任何好的教程,网站和书籍?我正在尝试做的事情可以在这里找到:http://www.sslshopper.com/ssl-checker.html.我不是要创建自签名证书或使用密钥库.我希望能够到任何站点确定是否存在有效的SSL证书,确定证书上的主机名是否与输入的命名匹配,并确定此证书何时到期.我已经搜索了这个主题,但"如何使用Java创建SSL购物者"并没有让我任何东西,而我的其他搜索只给我带来了如何创建自签名证书的链接.任何帮助将不胜感激.

Bru*_*uno 5

要首先获取服务器证书以便手动进行验证,无论其是否有效,最简单的方法是在SSLSocket禁用任何证书验证后通过连接。

创建一个SSLContext允许任何东西通过的:

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);
Run Code Online (Sandbox Code Playgroud)

(旁注:对于寻找在内部使用测试证书的方法的人,我建议构建自己的测试 CA 而不是禁用检查,以防万一这些虚拟检查错误地留在生产代码中,而且还因为它使得测试更真实。)

创建一个套接字,连接并显式启动握手(因为您实际上并不打算读取它):

SSLSocketFactory ssf = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) ssf.createSocket(
        "the.host.name", 443);
socket.startHandshake();
Run Code Online (Sandbox Code Playgroud)

获取对等证书链。第一项是实际的服务器证书。

X509Certificate[] peerCertificates = (X509Certificate[]) socket
        .getSession().getPeerCertificates();
Run Code Online (Sandbox Code Playgroud)

如果您想根据默认信任锚点(默认受信任的 CA 证书)进行验证,请X509TrustManager根据默认值构建一个(这实际上是passthroughTrustManager上面禁用的内容):

// 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];
Run Code Online (Sandbox Code Playgroud)

现在,检查证书当前是否及时有效、是否针对受信任的锚进行了验证以及是否根据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.
}
Run Code Online (Sandbox Code Playgroud)

以上所有内容都使用了JSSE API

或者,如果您想深入了解 PKIX 的详细信息,可以使用Java Certification Path API(JSSE 使用)。

(如果您只想从有效证书开始,只需SSLContext sslContext = SSLContext.getDefault()在开始时使用,创建套接字并进行握手。)

要直接获取服务器证书,可以使用以下命令:

X509Certificate serverCert = peerCertificates[0];
Run Code Online (Sandbox Code Playgroud)

X509Certificate有许多关于日期和各种扩展的方法。例如:

Date expirationDate = serverCert.getNotAfter();
Run Code Online (Sandbox Code Playgroud)

主机名验证应遵循RFC 6125(或至少RFC 2818)。简而言之,检查您要连接的主机名是否是主题备用名称 (SAN) DNS 条目之一。如果失败,请重新检查主机名是否在您证书的 CN RDN 中(为此,您需要将主题 DN 拆分为 RDN)。您可能也对此讨论感兴趣(关于使用 IP 地址的具体情况)

这完全取决于您想要进行多少“手动”验证。除了 API 文档之外,还有许多规范需要阅读(至少 RFC 5280/RFC 3280 和 RFC 6125/RFC 2818)。

Security.SE 上的这个问题也应该引起人们的兴趣:


Cra*_*lus 1

您可以做的是在Apache 的 HttpClient之上实现您自己的检查器。
您应该初始化 SSL 上下文并覆盖TrustManagers以执行您想要的任何检查。

主机名验证可以由库自动完成。

例如,如果主机名与证书信息不匹配,以下将配置 SSL 套接字处理以引发异常:

SSLSocketFactory sf = new SSLSocketFactory(
    SSLContext.getInstance("TLS"),
    SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
Run Code Online (Sandbox Code Playgroud)