如何解析SSL证书服务器名称/我可以使用keytool添加备用名称吗? [英] How are SSL certificate server names resolved/Can I add alternative names using keytool?

查看:469
本文介绍了如何解析SSL证书服务器名称/我可以使用keytool添加备用名称吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为清楚起见,这些可能是单独的问题,但它们都与同一问题有关。

These may be phrased as separate questions for clarity, but they are all related to the same issue.

如何解析SSL证书服务器名称?

How are SSL certificate server names resolved?

为什么浏览器似乎使用证书的CN字段,但Java的机制似乎只看主题替代名称?

Why do browsers seem to use the CN field of the certificate, but Java's mechanism seem to only look at "subject alternative names" only?

是否可以使用keytool为SSL证书添加备用名称?
如果没有,是使用openSSL而不是一个好的选择吗?

Is it possible to add alternative names to a SSL certificate using keytool? If not, is using openSSL instead a good option??

只是一点背景:我需要一个主服务器使用HTTPS与多个服务器通信。显然,我们不想为每个服务器购买SSL证书(可能有很多),所以我想使用自签名证书(我一直使用keytool来生成它们)。在操作系统中添加证书后,浏览器(IE和Chrome)很乐意接受该连接为可信任的。但是,即使将证书添加到Java的cacerts之后,Java仍然不会接受该连接为受信任并抛出以下异常:

Just a little background: I need to get a main server to communicate with several servers using HTTPS. Obviously, we don't want to buy SSL certificates for every server (there could be many), so I want to use self-signed certificates (I have been using keytool to generate them). After I add the certificates as trusted in the OS, the browsers (IE and Chrome) happily accept the connection as trusted. However, even after adding the certificates to Java's cacerts, Java still won't accept the connection as trusted and throws the following Exception:


by:java.security.cert.CertificateException:没有主题替代名称
在sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:142)
at sun.security.util .HostnameChecker.match(HostnameChecker.java:75)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity(X509T
rustManagerImpl.java:264)
at com。 sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(
X509TrustManagerImpl.java:250)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien
tHandshaker.java:1185)
... 14更多

Caused by: java.security.cert.CertificateException: No subject alternative names present at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:142) at sun.security.util.HostnameChecker.match(HostnameChecker.java:75) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkIdentity(X509T rustManagerImpl.java:264) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted( X509TrustManagerImpl.java:250) at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien tHandshaker.java:1185) ... 14 more

我发现我可以让Java信任实施我的证书拥有HostNameVerifier,我从这里复制: com.sun.jbi.internal.security.https.DefaultHostnameVerifier 只是为了测试(顺便说一句,主机名传递为HostnameVerifier的参数是正确的,所以我认为应该已经接受了。)

I found that I can make Java trust the certificate implementing my own HostNameVerifier, which I copied from here: com.sun.jbi.internal.security.https.DefaultHostnameVerifier just to test (by the way, the hostname passed as an argument to the HostnameVerifier is correct, so I think it should have been accepted).

我一直使用证书字段CN作为主机名(通常是IP地址) 。

I have been using the certificate field CN as the hostname (usually the IP address).

任何人都可以告诉我,如果我做错了什么并指出我正确的方向?

Can anybody please tell me if I am doing something wrong and point me in the right direction?

推荐答案

如何进行主机名验证在 RFC 6125 ,这是非常新的,并将这种做法推广到所有协议,并取代了 RFC 2818 ,特定于HTTPS。 (我甚至不确定Java 7是否使用RFC 6125,这可能是最新的。)

How host name verification should be done is defined in RFC 6125, which is quite recent and generalises the practice to all protocols, and replaces RFC 2818, which was specific to HTTPS. (I'm not even sure Java 7 uses RFC 6125, which might be too recent for this.)

来自 RFC 2818(第3.1节)


如果subjectAltName扩展名为类型dNSName存在,必须使用
作为标识。否则,必须使用证书的Subject字段中的(最具体的)Common Name
字段。虽然
使用公共名称是现有做法,但不推荐使用它,并且鼓励
证书颁发机构使用dNSName。

If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead.

[。 ..]

在某些情况下,URI被指定为IP地址而不是
主机名。在这种情况下,iPAddress subjectAltName必须在证书中出现
,并且必须与URI中的IP完全匹配。

In some cases, the URI is specified as an IP address rather than a hostname. In this case, the iPAddress subjectAltName must be present in the certificate and must exactly match the IP in the URI.

基本上,您遇到的具体问题来自于您在CN中使用IP地址而不是主机名。有些浏览器可能会工作,因为并非所有工具都严格遵循此规范,特别是因为RFC 2818中的最具体并未明确定义(请参阅RFC 6215中的讨论)。

Essentially, the specific problem you have comes from the fact that you're using IP addresses in your CN and not a host name. Some browsers might work because not all tools follow this specification strictly, in particular because "most specific" in RFC 2818 isn't clearly defined (see discussions in RFC 6215).

如果您使用 keytool ,则从Java 7开始, keytool 可以选择包含主题备用名称(请参阅文档中的表格 - ext ):您可以使用 -ext san = dns:www.example.com -ext san = ip: 10.0.0.1

If you're using keytool, as of Java 7, keytool has an option to include a Subject Alternative Name (see the table in the documentation for -ext): you could use -ext san=dns:www.example.com or -ext san=ip:10.0.0.1.

编辑:

您可以通过更改 openssl.cnf 在OpenSSL中请求SAN(如果您不想编辑全局配置,它将在当前目录中选择副本,至我记得,或者您可以使用 OPENSSL_CONF 环境变量选择显式位置。

You can request a SAN in OpenSSL by changing openssl.cnf (it will pick the copy in the current directory if you don't want to edit the global configuration, as far as I remember, or you can choose an explicit location using the OPENSSL_CONF environment variable).

设置以下选项(找到合适的部分在括号内首先):

Set the following options (find the appropriate sections within brackets first):

[req]
req_extensions = v3_req

[ v3_req ]
subjectAltName=IP:10.0.0.1
# or subjectAltName=DNS:www.example.com

这里有一个很好的技巧来使用环境变量(而不是在配置文件中修复它): http://www.crsr.net/Notes/SSL.html

There's also a nice trick to use an environment variable for this (rather in than fixing it in a configuration file) here: http://www.crsr.net/Notes/SSL.html

这篇关于如何解析SSL证书服务器名称/我可以使用keytool添加备用名称吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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