2015-09-03 18 views
0

我想將comodo Positive SSL多站點證書加載到Java的HttpsServer中。我沒有從代碼中得到任何錯誤,但是當我嘗試訪問瀏覽器中的URL時,它告訴我存在SSL錯誤。 Chrome和FireFox都不提供任何其他信息。這個證書在Apache中工作正常。在Java HttpsServer中使用Positive SSL多站點證書時遇到問題

以下是我正在使用的代碼。我已經做得相當詳細了。有什麼事情脫穎而出嗎?我已將私鑰轉換爲pkcs8進行導入。我正在加載的證書和軟件包是PEM編碼的。

serverHttps = HttpsServer.create(new InetSocketAddress(ports[port_selector]), 0); 
SSLContext sslContext = SSLContext.getInstance("TLS"); 

String alias = "alias"; 

// Load Certificates 
InputStream stream = MyClass.class.getResourceAsStream("/certs/mycert.crt"); 
CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
X509Certificate cert = (X509Certificate)cf.generateCertificate(stream); 
stream.close(); 

stream = MyClass.class.getResourceAsStream("/certs/bundle.crt"); 
cf = CertificateFactory.getInstance("X.509"); 
Collection bundle = cf.generateCertificates(stream); 
stream.close(); 

// Build cert chain 
java.security.cert.Certificate[] chain = new Certificate[bundle.size()+1]; 
Iterator i = bundle.iterator(); 
int pos = 0; 
while (i.hasNext()) { 
    chain[pos] = (Certificate)i.next(); 
    pos++; 
} 
chain[chain.length-1] = cert; 

// Load private key 
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); 
stream = MyClass.class.getResourceAsStream("/certs/pkcs8_my_key"); 
PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(IOUtils.toByteArray(stream)); 
RSAPrivateKey privKey = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8); 
stream.close(); 
stream = null; 

KeyStore ks = KeyStore.getInstance("JKS"); 
char[] ksPassword = "mypass".toCharArray(); 

ks.load(null, ksPassword); 
ks.setKeyEntry(alias, privKey, ksPassword, chain); 

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
kmf.init(ks, ksPassword); 

TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 
tmf.init(ks); 

sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 

// serverHttps.setHttpsConfigurator(new HttpsConfigurator(sslContext)); 
serverHttps.setHttpsConfigurator (new HttpsConfigurator(sslContext) 
{ 
    @Override 
    public void configure (HttpsParameters params) 
    { 
     try 
     { 
      // initialise the SSL context 
      SSLContext c = SSLContext.getDefault(); 
      SSLEngine engine = c.createSSLEngine(); 
      params.setNeedClientAuth (false); 
      params.setCipherSuites (engine.getEnabledCipherSuites()); 
      params.setProtocols (engine.getEnabledProtocols()); 

      // get the default parameters 
      SSLParameters defaultSSLParameters = c.getDefaultSSLParameters(); 
      params.setSSLParameters (defaultSSLParameters); 
     } 
     catch (Exception ex) 
     { 
      System.out.println("Failed to configure HTTPS server: "+ex.getMessage()); 
      System.exit(100); 
     } 
    } 
}); 

回答

1

您的服務器證書必須在密鑰庫條目中爲chain[0]

其餘證書應該是向上順序即根最後的 - 當你使用keytool這使他們的順序 - 因爲JSSE服務器密鑰庫中的順序將它們發送和SSL/TLS協議說,他們應該是向上發送。然而,根據我的經驗(大多數?),只要服務器證書是第一個,瀏覽器/客戶端就會容忍鏈條的其他部分無序。

PS:我認爲你的configure覆蓋的一切都是不必要的。您沒有做任何事情來使SSLContext的參數與默認參數不同,並且默認上下文的SSLParameters是(並覆蓋)您剛纔單獨設置的CipherSuites和Protocols。但我不能輕易測試。

+0

這是問題所在。所有我改變的是設置'chain [0] = cert;'在遍歷bundle並將其插入鏈中之前。現在就像魅力一樣。關於覆蓋你也是對的,默認的配置函數對我的用例工作正常。 –