有一个在我们的系统中的一些代码自动生成自签名证书到密钥存储,然后使用码头。 如果给定主机的关键已经存在,那么什么都不会发生,但如果它不存在,我们生成一个新的密钥,就像这样:
public void generateKey(String commonName) {
X500Name x500Name = new X500Name("CN=" + commonName);
CertAndKeyGen keyPair = new CertAndKeyGen("DSA", "SHA1withDSA");
keyPair.generate(1024);
PrivateKey privateKey = keyPair.getPrivateKey();
X509Certificate certificate = keyPair.getSelfCertificate(x500Name, 20*365*24*60*60);
Certificate[] chain = { certificate };
keyStore.setEntry(commonName, privateKey, "secret".toCharArray(), chain);
}
这一切只要有密钥存储器中的唯一一个密钥和证书工作正常。 一旦你有多个按键,奇怪的事情,当你试图连接发生:
java.io.IOException: HTTPS hostname wrong: should be <127.0.0.1>
这是一个相当神秘的错误,但我终于写它连接到服务器,并声称该证书上的CN的主机名匹配一个单元测试,以追查。 我发现很有意思 - 码头似乎任意选择呈现给客户端的证书,但以一致的方式。
例如:
- 如果“CN =本地主机”和“CN = cheese.mydomain”是在密钥存储,它总是选择“CN = cheese.mydomain”。
- 如果 “CN = 127.0.0.1” 和 “CN = cheese.mydomain” 是在密钥存储,它总是选择 “CN = cheese.mydomain”。
- 如果 “CN = 192.168.222.100”(cheese.mydomain)和 “CN = cheese.mydomain” 是在密钥存储,它总是选择 “CN = 192.168.222.100”。
我写了一些代码,它通过在商店中的证书循环到打印出来,发现它没有始终如一地选择第一个证书或任何琐碎的那样。
那么究竟它用什么样的标准? 起初我还以为是本地主机特殊但随后的第三个例子我彻底难倒了。
我认为这是某种由的KeyManagerFactory,这是SunX509在我的情况决定。