使用Java编写SSL检查器 [英] Writing a SSL Checker using Java

查看:128
本文介绍了使用Java编写SSL检查器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Does anyone know of any good tutorials, sites, and or books on writing a SSL checker in Java? I'm trying to do what can be found here: http://www.sslshopper.com/ssl-checker.html . I'm not trying to create a self signed cert or use a a keystore. I want to be able to go out to any site determine if a valid SSL Certificate exists, determine if the hostname on the Cert matches the named entered, and determine when this Cert will expire. I have googled this topic but "How to create a SSL shopper using Java" hasn't yielded me anything and my other searches only brought me links on how to create a self-signed Cert. Any help would be greatly appreciated.

推荐答案

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

To get the server certificate in the first place in order to do the verification manually, irrespectively of whether it's valid or not, the easiest is to connect via an SSLSocket after having disabled any certificate verification.

创建一个 SSLContext ,它允许任何操作:

Create an SSLContext that lets anything through:

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而不是禁用检查,以防错误地在生产代码中遗留这些虚拟检查,并且因为它使测试更加真实。)

(Side note: for people looking for a way to use test certificates internally, I'd recommend building your own test CA rather than disabling checks, just in case those dummy checks are left over in production code by mistake, and also because it makes the tests more realistic.)

创建一个套接字,显式连接并启动握手(因为你真的不会从中读取它):

Create a socket, connect and start the handshake explicitly (since you're not really going to read form it):

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

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

Get the peer certificates chain. The first item is the actual server certificate.

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

如果要针对默认信任锚(默认的可信CA证书)进行验证,请构建 X509TrustManager 基于默认值(这实际上是 passthroughTrustManager 以上禁用):

If you want to validate against the default trust anchors (the default trusted CA certificates), build a X509TrustManager based on the default values (this is effectively what the passthroughTrustManager above disabled):

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

现在,检查证书当前是否有效,是否针对可信锚点进行验证以及是否根据 RFC 3280 ,它具有正确的扩展名。

Now, check whether the certificate is currently valid in time, whether it's verified against a trusted anchor and whether it has the right extensions according to 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.
}

以上所有都使用了 JSSE API

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

Alternatively, if you want to dig deeper into the details of PKIX, you can use the Java Certification Path API (which is used by JSSE).

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

(If you only want valid certificates anyway to start with, just use SSLContext sslContext = SSLContext.getDefault() at the start, create the socket and do the handshake.)

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

To get the server certificate directly, you can use this:

X509Certificate serverCert = peerCertificates[0];

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

X509Certificate has a number of methods regarding dates and various extensions. For example:

Date expirationDate = serverCert.getNotAfter();

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

The hostname verification should follow RFC 6125 (or at least RFC 2818). In short, check whether the hostname you intended to connect to is one of the Subject Alternative Names (SAN) DNS entry. Failing that, fall back on checking whether the hostname is in the CN RDN of your certificate (for this, you need to split the Subject DN into RDNs). You may also be interested in this discussion (on the specific case of using IP addresses).

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

It all depends on how much "manual" verification you want to make. There are a number of specifications to read (RFC 5280/RFC 3280 and RFC 6125/RFC 2818 at least), in addition to the API documentations.

关于安全性的这个问题.SE也应该是有意义的:

This question on Security.SE should also be of interest:

  • What data should I validate when validating X.509 certificates using Java?
  • How are possible uses for X.509 (SSL) certificates denoted?

这篇关于使用Java编写SSL检查器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆