2009-02-11 81 views
17

我有一個pkcs12文件。我需要使用它來使用https協議連接到網頁。我碰到一些代碼,其中,以連接到安全的網頁我需要設置下面的系統屬性:如何使用pkcs12文件在Java中使用SSL連接到安全網站?

System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
System.setProperty("javax.net.ssl.keyStoreType", "pkcs12"); 
System.setProperty("javax.net.ssl.keyStore", "new_cert.p12"); 
System.setProperty("javax.net.ssl.keyStorePassword", "newpass"); 

我有P12(PKCS12)的文件。我需要的只是一個信任庫文件。

我提取的證書中使用:

openssl.exe pkcs12 -in c:/mykey.p12 -out c:/cert.txt -nokeys -clcerts 

現在轉換的證書PEM文件爲DER

openssl.exe x509 -in c:/cert.txt -outform DER -out c:/CAcert.der 

現在添加DER文件密鑰庫查閱

keytool -import -file C:/Cacert.der -keystore mytruststore 

我有信任庫,但是當我使用它時,出現以下錯誤

Exception in thread "main" java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: com.sun.net.ssl.internal.ssl.DefaultSSLContextImpl) 

更新: 刪除某些屬性和唯一設置 「的trustStore」 後, 「trustStorePassword」 和 「trustStoreType」 屬性,我得到了以下異常

java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty 

請幫助。

+0

如果您可以發佈更多的堆棧跟蹤(來自堆棧幀的信息,而不僅僅是異常消息),我會查看它。 – erickson 2009-02-12 15:38:13

+0

要檢查的另一件事是您的信任存儲位置正確指定;如果指定了javax.net.ssl.trustStore但不存在,則會立即創建一個空的信任庫。你的新錯誤信息使得它聽起來像這可能發生。 – erickson 2009-02-12 15:52:46

回答

18

對於任何人遇到了類似的情況,我能夠解決這個問題上面如下:

  1. 重新生成PKCS12文件如下:

    openssl pkcs12 -in oldpkcs.p12 -out keys -passout pass:tmp 
    openssl pkcs12 -in keys -export -out new.p12 -passin pass:tmp -passout pass:newpasswd 
    
  2. 導入從服務器上下載CA證書導入一個TrustStore(您自己的,或者$JAVA_HOME/jre/lib/security/cacerts中的java密鑰庫,密碼:changeit)。

  3. 設置以下系統屬性:

    System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
    System.setProperty("javax.net.ssl.keyStoreType", "pkcs12"); 
    System.setProperty("javax.net.ssl.keyStore", "new.p12"); 
    System.setProperty("javax.net.ssl.keyStorePassword", "newpasswd"); 
    
  4. 測試烏爾網址。

禮貌@http://forums.sun.com/thread.jspa?threadID=5296333

4

看來您正在從PKCS#12密鑰存儲中提取證書並創建一個新的Java密鑰存儲(類型爲「JKS」)。您不必嚴格地提供信任庫密碼(儘管使用它可以測試根證書的完整性)。

因此,請嘗試僅使用的程序以下SSL屬性集。您的問題中顯示的列表超出規定範圍,可能會導致問題。

System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 

此外,使用PKCS#12文件直接作爲信任存儲應該工作,只要CA證書被檢測爲「受信任」條目。但在這種情況下,您必須將javax.net.ssl.trustStoreType屬性指定爲"PKCS12"

請僅嘗試使用這些屬性。如果你得到同樣的錯誤,我懷疑你的問題不是關鍵商店。如果問題仍然存在,請在問題中發佈更多堆棧跟蹤以縮小問題範圍。


新的錯誤「的trustAnchors參數必須是非空的,」可能是由於設置javax.net.ssl.trustStore屬性不存在的文件;如果文件無法打開,則會創建一個空的密鑰存儲區,這會導致此錯誤。

+0

我只設置了你指定的屬性,現在我得到下面的異常: 「InvalidAlogrithmException:trustAnchors參數必須是非空的」 – user27221 2009-02-12 06:46:29

+0

我只想感謝這個答案,因爲我不知道「使用PKCS#12文件直接作爲信任商店應該工作「,這解決了我自己的問題 – fabien7474 2016-09-21 10:33:53

4

這是隻使用P12文件它不optimazed但它的工作的例子。 由我由OpenSSL生成的pkcs12文件。 示例如何加載P12文件,並從它建立信任區... 它輸出從P12文件證書,並添加良好的證書到信任庫

KeyStore ks=KeyStore.getInstance("pkcs12"); 
ks.load(new FileInputStream("client_t_c1.p12"),"c1".toCharArray()); 

KeyStore jks=KeyStore.getInstance("JKS"); 
jks.load(null); 

for (Enumeration<String>t=ks.aliases();t.hasMoreElements();) 
{ 
    String alias = t.nextElement(); 
    System.out.println("@:" + alias); 
    if (ks.isKeyEntry(alias)){ 
     Certificate[] a = ks.getCertificateChain(alias); 
     for (int i=0;i<a.length;i++) 
     { 
      X509Certificate x509 = (X509Certificate)a[i]; 
      System.out.println(x509.getSubjectDN().toString()); 
      if (i>0) 
       jks.setCertificateEntry(x509.getSubjectDN().toString(), x509); 
      System.out.println(ks.getCertificateAlias(x509)); 
      System.out.println("ok"); 
     } 
    } 
} 

System.out.println("init Stores..."); 

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

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

SSLContext ctx = SSLContext.getInstance("TLS"); 
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
0

我知道,這篇文章可能已經過時,但我仍想請smithsv糾正他的源代碼,它包含很多錯誤,我設法糾正他們中的大多數,但仍然不知道x509可能是什麼樣的對象。下面是我認爲應該的源代碼:

import java.io.FileInputStream; 
import java.security.KeyStore; 
import java.security.cert.Certificate; 
import java.util.Enumeration; 

import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManagerFactory; 

public class Connection2 { 
    public void connect() { 
     /* 
     * This is an example to use ONLY p12 file it's not optimazed but it 
     * work. The pkcs12 file where generated by OpenSSL by me. Example how 
     * to load p12 file and build Trust zone from it... It outputs 
     * certificates from p12 file and add good certs to TrustStore 
     */ 
     KeyStore ks = KeyStore.getInstance("pkcs12"); 
     ks.load(new FileInputStream(cert.pfx), "passwrd".toCharArray()); 

     KeyStore jks = KeyStore.getInstance("JKS"); 
     jks.load(null); 

     for(Enumeration t = ks.aliases(); t.hasMoreElements();) { 
      String alias = (String)t.nextElement(); 
      System.out.println("@:" + alias); 
      if(ks.isKeyEntry(alias)) { 
       Certificate[] a = ks.getCertificateChain(alias); 
       for(int i = 0; i == 0;) 
        jks.setCertificateEntry(x509Cert.getSubjectDN().toString(), x509); 

       System.out.println(ks.getCertificateAlias(x509)); 
       System.out.println("ok"); 
      } 
     } 

     System.out.println("init Stores..."); 

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

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

     SSLContext ctx = SSLContext.getInstance("TLS"); 
     ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 
    } 
} 
1

此示例顯示瞭如何在現有套接字的頂部對SSL進行分層,從PKCS#12 fil獲取客戶端證書即當你需要通過代理連接到上游服務器,並且你想自己處理完整的協議時,這是適當的。

本質,但是,一旦你有SSL環境,您可以將其應用到HttpsURLConnection的,等等,等等

KeyStore ks = KeyStore.getInstance("PKCS12"); 
InputStream is = ...; 
char[] ksp = storePassword.toCharArray(); 
ks.load(is, ksp); 
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
char[] kp = keyPassword.toCharArray(); 
kmf.init(ks, kp); 
sslContext = SSLContext.getInstance("SSLv3"); 
sslContext.init(kmf.getKeyManagers(), null, null); 
SSLSocketFactory factory = sslContext.getSocketFactory(); 
SSLSocket sslsocket = (SSLSocket) factory.createSocket(socket, socket 
    .getInetAddress().getHostName(), socket.getPort(), true); 
sslsocket.setUseClientMode(true); 
sslsocket.setSoTimeout(soTimeout); 
sslsocket.startHandshake(); 
5

因爲50pts門限的我不能發表評論,但我不認爲https://stackoverflow.com/a/537344/1341220中提供的答案是正確的。 什麼你實際上描述的是你如何插入服務器證書到系統默認的信任:

$JAVA_HOME/jre/lib/security/cacerts, password: changeit) 

這工作,的確是,但它意味着你真的不指定信任存儲您的本地項目,而是接受證書通常在您的系統中。

實際上,你永遠不會使用您在此處定義了自己的信任:

System.setProperty("javax.net.ssl.trustStore", "myTrustStore"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
0
URL url = new URL("https://test.domain:443"); 
String keyStore = "server.p12" 
String keyStorePassword = "changeit";  
String keyPassword = "changeit";  
String KeyStoreType= "PKCS12";  
String KeyManagerAlgorithm = "SunX509";  
String SSLVersion = "SSLv3";  
public HttpURLConnection getHttpsURLConnection(URL url, String keystore, 
    String keyStorePass,String keyPassword, String KeyStoreType 
    ,String KeyManagerAlgorithm, String SSLVersion) 
    throws NoSuchAlgorithmException, KeyStoreException, 
     CertificateException, FileNotFoundException, IOException, 
     UnrecoverableKeyException, KeyManagementException { 
    System.setProperty("javax.net.debug","ssl,handshake,record"); 

    SSLContext sslcontext = SSLContext.getInstance(SSLVersion); 
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerAlgorithm); 
    KeyStore ks = KeyStore.getInstance(KeyStoreType); 
    ks.load(new FileInputStream(keystore), keyStorePass.toCharArray()); 
    kmf.init(ks, keyPassword.toCharArray()); 

    TrustManagerFactory tmf = TrustManagerFactory 
      .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
    tmf.init(ks); 
    TrustManager[] tm = tmf.getTrustManagers(); 

    sslcontext.init(kmf.getKeyManagers(), tm, null); 
    SSLSocketFactory sslSocketFactory = sslcontext.getSocketFactory(); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory); 
    HttpsURLConnection httpsURLConnection = (HttpsURLConnection)uRL.openConnection(); 

    return httpsURLConnection; 
} 
1

下面的步驟將幫助你整理出你的問題。

步驟: developer_identity.cer < =從蘋果下載 mykey。P12 < =你的私鑰

命令遵循:

openssl x509 -in developer_identity.cer -inform DER -out developer_identity.pem -outform PEM 

    openssl pkcs12 -nocerts -in mykey.p12 -out mykey.pem 

    openssl pkcs12 -export -inkey mykey.pem -in developer_identity.pem -out iphone_dev.p12 

我們需要最終P12是iphone_dev.p12文件和密碼。

使用此文件作爲您的p12然後嘗試。這確實是解決方案。:)