2014-07-26 44 views
5

我們的Java 7應用程序需要監聽本地主機上的HTTPS請求。它必須接受https://localhost:8112https://127.0.0.1:8112上的連接。爲什麼IE只接受127.0.0.1的自簽名本地主機證書,當Chrome接受它時?

要做到這一點,我們編程內置自動簽名採用X509v3證書,我們已經安裝在的Windows-ROOT密鑰存儲這個證書,如下所示:

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

這使得Chrome所接受證書36在兩種情況下(本地主機和127.0.0.1),但IE 11訪問127.0.0.1當同時訪問時localhost確實不能識別該證書是有效的:

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

爲什麼?該證書是建立如下,BasicConstraints執行extendedKeyUsage主題替代擴展,通過使用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; 
} 

通過以下對CAPI2診斷this tutorial,我發現通過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> 

CertVerifyCertificateChainPolicyCERT_CHAIN_POLICY_STATUS文檔沒有幫助我很多:它看起來像IE前將CN等同於服務器名稱,但我試圖將我的CN更改爲CN=127.0.0.1而沒有成功(相同的行爲)。

+0

「CN = localhost」 - 可能不是。這被IETF和更重要的[CA /瀏覽器論壇](https://cabforum.org/baseline-requirements-documents/)所棄用。參見第9.2節。CA/B基線要求2:*「棄用(不鼓勵,但不禁止)」*。使CN像「XXX IT」一樣友好(個人而言,我不使用合法名稱)。由於SAN包含'localhost'和'127.0.0.1',因此SAN看起來不錯。請參閱CA/B基準要求的第9.2.1節。 – jww

+0

我不認爲應將最終實體證書(服務器或用戶證書)置於* Trusted Root *存儲(其實際稱爲*受信任根證書頒發機構*存儲)。聽起來很奇怪,他們可以用來簽署其他證書。相反,他們進入*個人 - >證書*)。 – jww

+0

您確定您的標題中沒有交換IE和Chrome嗎?這看起來像一個Chrome屏幕截圖給我(拒絕證書的那個)。可以肯定的是,您是否檢查過您的證書是否具有* iPAddress *類型的127.0.0.1的SAN條目? (你可以導出它,並用'openssl x509 -text ...'查看。) – Bruno

回答

5

IE不支持主題備用名稱(SAN)中的IP地址值,僅支持DNS條目。

這是一個known limitation不會被固定,根據微軟:

我們不使用IP選擇在主題備用名稱相匹配的服務器名支持。您可以通過添加IP地址作爲DNS名稱選擇的字符串來解決此問題。目前我們不打算解決這個問題。

所以來處理它正確的方法是加入一個包含IP地址的DNS條目:

"dns:127.0.0.1" 

不幸的是,使用密鑰工具或編程方式,因爲Java bug 8016345sun.security.x509類,這是不可能的。

然而,可以自行修復這個bug,只是通過複製的最新版本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"); 
+0

也許你可以嘗試使用BouncyCastle或[OpenSSL(用「DNS」替換「IP」)](http://stackoverflow.com/a/8444863/372643)。 (使用'sun。*'的私有API通常不是一個好主意,但這取決於你自己。) – Bruno

+0

謝謝,但是我們試圖將COTS的使用降到最低。只要它支持Oracle JRE和OpenJDK/IcedTea版本,我們就可以使用這個軟件包。 – vip

+0

我猜你可以發佈一個「本地主機」證書及其已經生成的私鑰,而不是嘗試將證書生成集成到應用程序中。當然,一般來說,私人密鑰資料不應該共享,但在這種情況下,在所有用戶之間共享一個證書和私鑰到「127.0.0.1」可能不會帶來重大風險,因爲它們也必須共享無論如何,同一臺機器。 – Bruno

-1

爲什麼不只是發出一個HTTP 301重定向當用戶使用127.0.0.1發送他們到本地主機呢?

+0

**初始請求/響應交換成功執行後,重定向僅工作**。如果證書對於初始請求無效,您將不會收到任何回覆。 – Bruno

相關問題