gpt4 book ai didi

java - 为什么 IE 仅拒绝 127.0.0.1 的自签名本地主机证书,而 Chrome 接受它?

转载 作者:搜寻专家 更新时间:2023-10-31 20:02:15 24 4
gpt4 key购买 nike

我们的 Java 7 应用程序需要在本地主机上监听 HTTPS 请求。它必须接受 https://localhost:8112https://127.0.0.1:8112 上的连接。

为此,我们以编程方式构建了一个自动签名的 X509v3 证书,并将此证书安装在 Windows-ROOT keystore 中,如下所示:

KeyStore.TrustedCertificateEntry trustedCert = ...;
KeyStore ks = KeyStore.getInstance("Windows-ROOT");
ks.load(null, null);
ks.setEntry("xxxx_localhost", trustedCert, null);

这使得证书在两种情况下(localhost 和 127.0.0.1)都被 Chrome 36 接受,但是 IE 11 在访问 127.0.0.1 时不认为该证书有效,而在访问 本地主机:

Test ok with Chrome (top), KO with IE (bottom)

为什么?证书构建如下,使用 sun.security.x509 包裹:

KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair kp = generator.generateKeyPair();

X509Certificate cert = generateCertificate("CN=localhost, OU=XXX, O=XXX", kp,
1825, "SHA256withRSA", "ip:127.0.0.1,dns:localhost,uri:https://127.0.0.1:8112");

/**
* Create a self-signed X.509 Certificate.
* @param dn the X.509 Distinguished Name
* @param pair the KeyPair
* @param days how many days from now the Certificate is valid for
* @param algorithm the signing algorithm, eg "SHA256withRSA"
* @param san SubjectAlternativeName extension (optional)
*/
private static X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm, String san)
throws GeneralSecurityException, IOException {
PrivateKey privkey = pair.getPrivate();
X509CertInfo info = new X509CertInfo();
Date from = new Date();
Date to = new Date(from.getTime() + days * 86400000l);
CertificateValidity interval = new CertificateValidity(from, to);
BigInteger sn = new BigInteger(64, new SecureRandom());
X500Name owner = new X500Name(dn);

info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(sn));
info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(owner));
info.set(X509CertInfo.ISSUER, new CertificateIssuerName(owner));
info.set(X509CertInfo.KEY, new CertificateX509Key(pair.getPublic()));
info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3));
AlgorithmId algo = new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);
info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algo));

CertificateExtensions ext = new CertificateExtensions();
// Critical: Not CA, max path len 0
ext.set(BasicConstraintsExtension.NAME, new BasicConstraintsExtension(true, false, 0));
// Critical: only allow TLS ("serverAuth" = 1.3.6.1.5.5.7.3.1)
ext.set(ExtendedKeyUsageExtension.NAME, new ExtendedKeyUsageExtension(true,
new Vector<ObjectIdentifier>(Arrays.asList(new ObjectIdentifier("1.3.6.1.5.5.7.3.1")))));

if (san != null) {
int colonpos;
String[] ps = san.split(",");
GeneralNames gnames = new GeneralNames();
for(String item: ps) {
colonpos = item.indexOf(':');
if (colonpos < 0) {
throw new IllegalArgumentException("Illegal item " + item + " in " + san);
}
String t = item.substring(0, colonpos);
String v = item.substring(colonpos+1);
gnames.add(createGeneralName(t, v));
}
// Non critical
ext.set(SubjectAlternativeNameExtension.NAME, new SubjectAlternativeNameExtension(false, gnames));
}

info.set(X509CertInfo.EXTENSIONS, ext);

// Sign the cert to identify the algorithm that's used.
X509CertImpl cert = new X509CertImpl(info);
cert.sign(privkey, algorithm);

// Update the algorithm, and resign.
algo = (AlgorithmId)cert.get(X509CertImpl.SIG_ALG);
info.set(CertificateAlgorithmId.NAME + "." + CertificateAlgorithmId.ALGORITHM, algo);
cert = new X509CertImpl(info);
cert.sign(privkey, algorithm);
return cert;
}

关注this tutorial在CAPI2 Diagnostics上,我发现了IE报错:

<CertVerifyCertificateChainPolicy>
<Policy type="CERT_CHAIN_POLICY_SSL" constant="4" />
<Certificate fileRef="XXX.cer" subjectName="127.0.0.1" />
<CertificateChain chainRef="{XXX}" />
<Flags value="0" />
<SSLAdditionalPolicyInfo authType="server" serverName="127.0.0.1">
<IgnoreFlags value="0" />
</SSLAdditionalPolicyInfo>
<Status chainIndex="0" elementIndex="0" />
<EventAuxInfo ProcessName="iexplore.exe" />
<CorrelationAuxInfo TaskId="{XXX}" SeqNumber="4" />
<Result value="800B010F">The certificate's CN name does not match the passed value.</Result>
</CertVerifyCertificateChainPolicy>

关于 CertVerifyCertificateChainPolicy 的文档和 CERT_CHAIN_POLICY_STATUS对我帮助不大:看起来 IE 期望 CN 等于服务器名称,但我试图将我的 CN 更改为 CN=127.0.0.1 但没有成功(相同的行为)。

最佳答案

IE 不支持主题备用名称 (SAN) 中的 IP 地址值,仅支持 DNS 条目。

这是一个 known limitation根据微软的说法,这不会被修复:

We do not support using the IP choice in the Subject Alternative name to match the server name. You can work around this by adding the IP address as a string for a DNS name choice. At this time we do not plan on fixing this issue.

所以正确的处理方式是添加一个包含IP地址的DNS条目:

"dns:127.0.0.1"

不幸的是,由于 Java bug 8016345,这不可能使用 keytool 或以编程方式使用 sun.security.x509 类.

然而,您可以自己修复此错误,只需复制最新版本的 DNSName.java并删除此检查:

//DNSName components must begin with a letter A-Z or a-z
if (alpha.indexOf(name.charAt(startIndex)) < 0)
throw new IOException("DNSName components must begin with a letter");

关于java - 为什么 IE 仅拒绝 127.0.0.1 的自签名本地主机证书,而 Chrome 接受它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24971552/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com