为清楚起见,这些可能被表述为单独的问题,但它们都与同一问题有关.
SSL证书服务器名称是如何解析的?
为什么浏览器似乎使用证书的CN字段,但Java的机制似乎只关注"主题替代名称"?
是否可以使用keytool为SSL证书添加备用名称?如果没有,是使用openSSL而不是一个好的选择?
只是一点背景:我需要让主服务器使用HTTPS与多个服务器通信.显然,我们不想为每个服务器购买SSL证书(可能有很多),所以我想使用自签名证书(我一直使用keytool来生成它们).在操作系统中添加证书后,浏览器(IE和Chrome)很乐意接受该连接为可信任的.但是,即使将证书添加到Java的cacerts之后,Java仍然不会将该连接接受为受信任,并抛出以下异常:
引起:java.security.cert.CertificateException:在sun.security.util.HostnameChecker.match(HostnameChecker.java:75)的sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:142)中没有主题备用名称. 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更多
我发现我可以让Java信任实现我自己的HostNameVerifier的证书,我从这里复制了:com.sun.jbi.internal.security.https.DefaultHostnameVerifier只是为了测试(顺便说一句,主机名作为参数传递给HostnameVerifier是正确的,所以我认为应该已经接受了).
我一直使用证书字段CN作为主机名(通常是IP地址).
任何人都可以告诉我,如果我做错了什么,并指出我正确的方向?
我有一个用Java编写的内部HTTP服务器; 完整的源代码供我使用.HTTP服务器可以配置任意数量的网站,每个网站都有一个单独的监听套接字创建:
skt=SSLServerSocketFactory.getDefault().createServerSocket(prt,bcklog,adr);
Run Code Online (Sandbox Code Playgroud)
使用使用Java keytool创建的标准密钥库,我不能在我的生活中找出如何获得与不同侦听套接字关联的不同证书,以便每个配置的网站都拥有自己的证书.
我现在正处于这种状态,因此一些代码示例将非常受欢迎.但是我很欣赏JSSE如何在这方面联系起来的任何好的概述(我已经搜索了Sun的JSSE doco,直到我的大脑疼痛(字面意思;虽然它可能与咖啡因戒断一样多)).
编辑
有没有简单的方法来使用别名将密钥存储区中的服务器证书与侦听套接字相关联?以便:
我得到的印象(今天下午早些时候)我可以编写一个简单的KeyManager,只chooseServerAlias(...)返回非null,这是我想要的别名的名字 - 任何人对这一推理线有什么想法?
解
我使用的解决方案是根据slyvarking的回答构建的,它创建了一个临时密钥库,并使用从单个外部密钥库中提取的所需密钥/证书填充它.对于任何感兴趣的人(svrctfals是我的"服务器证书别名"值),代码如下:
SSLServerSocketFactory ssf; // server socket factory
SSLServerSocket skt; // server socket
// LOAD EXTERNAL KEY STORE
KeyStore mstkst;
try {
String kstfil=GlobalSettings.getString("javax.net.ssl.keyStore" ,System.getProperty("javax.net.ssl.keyStore" ,""));
String ksttyp=GlobalSettings.getString("javax.net.ssl.keyStoreType" ,System.getProperty("javax.net.ssl.keyStoreType" ,"jks"));
char[] kstpwd=GlobalSettings.getString("javax.net.ssl.keyStorePassword",System.getProperty("javax.net.ssl.keyStorePassword","")).toCharArray();
mstkst=KeyStore.getInstance(ksttyp);
mstkst.load(new FileInputStream(kstfil),kstpwd);
}
catch(java.security.GeneralSecurityException thr) {
throw new IOException("Cannot load keystore ("+thr+")");
}
// CREATE EPHEMERAL KEYSTORE FOR THIS SOCKET USING DESIRED CERTIFICATE
try {
SSLContext ctx=SSLContext.getInstance("TLS"); …Run Code Online (Sandbox Code Playgroud)