使用Java编写SSL检查器

使用Java编写SSL检查器,java,ssl,x509,Java,Ssl,X509,有人知道关于用Java编写SSL检查器的好教程、网站和/或书籍吗?我正在尝试做什么可以在这里找到:。 我不是在尝试创建自签名证书或使用密钥库。我希望能够访问任何站点,确定是否存在有效的SSL证书,确定证书上的主机名是否与输入的名称匹配,并确定此证书何时过期。我在谷歌上搜索过这个主题,但“如何使用Java创建SSL购物者”并没有给我带来任何结果,我的其他搜索只给我提供了如何创建自签名证书的链接。任何帮助都将不胜感激。您可以做的是在e.g 您应该初始化SSL上下文,并覆盖TrustManagers,

有人知道关于用Java编写SSL检查器的好教程、网站和/或书籍吗?我正在尝试做什么可以在这里找到:。
我不是在尝试创建自签名证书或使用密钥库。我希望能够访问任何站点,确定是否存在有效的SSL证书,确定证书上的主机名是否与输入的名称匹配,并确定此证书何时过期。我在谷歌上搜索过这个主题,但“如何使用Java创建SSL购物者”并没有给我带来任何结果,我的其他搜索只给我提供了如何创建自签名证书的链接。任何帮助都将不胜感激。

您可以做的是在e.g
您应该初始化SSL上下文,并覆盖
TrustManagers
,以执行所需的任何检查

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

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

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

要首先获取服务器证书以便手动执行验证,不管它是否有效,最简单的方法是在禁用任何证书验证后通过
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);
(旁注:对于正在寻找内部使用测试证书的方法的人,我建议您构建自己的测试CA,而不是禁用检查,以防这些虚拟检查错误地遗留在生产代码中,并且因为这使测试更加真实。)

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

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

X509Certificate[] peerCertificates = (X509Certificate[]) socket
        .getSession().getPeerCertificates();
如果要根据默认信任锚(默认的受信任CA证书)进行验证,请基于默认值构建
X509TrustManager
(这实际上是上面禁用的
passthroughTrustManager
):

现在,检查证书当前是否及时有效,是否根据受信任的锚进行了验证,以及它是否具有正确的扩展

所有这些都利用了

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

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


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

X509Certificate serverCert = peerCertificates[0];
有许多关于日期和各种扩展的方法。例如:

Date expirationDate = serverCert.getNotAfter();
主机名验证应遵循(或至少遵循)。简言之,检查您要连接的主机名是否是Subject Alternative Names(SAN)DNS条目之一。如果做不到这一点,请回头检查主机名是否在证书的CN RDN中(为此,需要将主题DN拆分为RDN)。你也可能对这一点感兴趣

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

关于Security.SE的这个问题也应该引起关注:


尝试执行此操作时,我会得到不可转换的类型:X509Certificate[]peerCertificates=(X509Certificate[])socket.getSession().getPeerCertificates();我甚至尝试了Oracles网站上的一个例子,使用上面的方法,不断得到“不可转换的类型”,不管我看到了什么,我使用的是import javax.security.cert.X509Certificate;而不是导入java.security.cert.X509Certificate;
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.
}
X509Certificate serverCert = peerCertificates[0];
Date expirationDate = serverCert.getNotAfter();