2012-06-20 48 views
29

我想發出https請求。Android版本的密鑰庫版本不正確

我用BouncyCastle的生成這樣的密鑰庫:

keytool -importcert -trustcacerts -alias ludevCA -file lu_dev_cert.crt -keypass mypass -keystore keystore.bks -storepass mypass -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk15on-146.jar 

而且密鑰列表命令返回正確的值。

但是當我做:

KeyStore ks = KeyStore.getInstance("BKS"); 
InputStream in = getResources().openRawResource(R.raw.keystore); 
ks.load(in, "mypass".toCharArray()); 

我有一個錯誤:

wrong version of keystore 

我試圖用bouncycast的幾個版本,但結果是一樣的。我也試圖定義keysize 1024,但沒有任何改變。

任何想法?

+0

不要忘記使用SHA-256,SHA引起-1沒有與Android 23+更多的使用,並且是默認...... – Cukic0d

回答

30

有它Android: Trusting SSL certificates

-storetype BKS 
    -provider org.bouncycastle.jce.provider.BouncyCastleProvider 
    -providerpath /path/to/bouncycastle.jar 

一看,創建密鑰庫時使用此版本:版本1.46found here

可能它可以幫助...

+1

這正是我所做的事情(我再次執行教程),但結果仍然相同。 – JuSchz

+1

@julesanchez:你必須使用bcprov-jdk16-146.jar。最新v147會導致上述問題 –

+1

我可以確認它的工作原理! –

4

最後我用一個圖形編輯器(KeyStore Explorer)在Windows下運行。

也許錯誤是在Java/Mac版的問題

2

解決方案引起的就在這裏,能夠去除版本prolem

創建BKS文件爲Android客戶端所需

軟件安裝細節打造BKS文件:

下載鏈接,從密鑰存儲Explorer軟件http://keystore-explorer.sourceforge.net/

http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html下載UnlimitedJCEPolicyJDK7

提取zip並將US_export_policy和local_policy複製到C:/ programes文件/ java/jre7/lib/security文件夾中。

安裝Keystore Explorer軟件。

步驟生成BKS文件:(需要CA文件,證書文件,密鑰文件和.P12 i.e.PKCS文件(如果可用)

1)使用密鑰庫使用CA軟件.crt文件創建信任文件。

步驟:

開放式軟件
轉到文件 - >新建 - >從嚮導 選擇.BKS導入CA證書文件轉到工具 - >導入受信任的證書 - >選擇CA .crt文件 - > entert密碼 - >(如果證書是自簽名,它會拋出一個異常)強制導入文件。

4.保存擴展名爲.bks的文件。

2)創建密鑰庫使用軟件中使用.P12文件密鑰文件

步驟

開放式軟件 轉到文件 - >新建 - >從嚮導中選擇.BKS

導入> P12文件轉到工具 - >導入密鑰對 - >從嚮導中選擇PKCS#12 - >輸入文件和眉毛文件的描述密碼 - >輸入alise名稱(如果想更改其他可以保持原樣) - >輸入新密碼

用.bks擴展名保存文件nsion。

3)使用,如果.P12是使用密鑰存儲軟件

步驟

開放式軟件

轉到文件 - >新建 - >選擇.BKS從嚮導 導入不可用文件創建密鑰文件> p12文件轉到工具 - >導入密鑰對 - >從嚮導選擇OpenSSL - >未選中的文件密碼,眉毛.key和.crt(證書文件不是CA)文件 - >輸入alise名稱(如果想更改其他可以保留照原樣) - >輸入新密碼

用.bks擴展名保存文件。

複製res/raw文件夾中的兩個文件(兩個BKS文件都是強制的)。

代碼:

static final String ENABLED_CIPHERS[] = { 
    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", 
    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", 
    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", 
    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", 
    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", 
    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", 
    "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", 
    "TLS_ECDHE_RSA_WITH_RC4_128_SHA", 
    "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", 
    "TLS_RSA_WITH_AES_256_CBC_SHA", 
    "TLS_RSA_WITH_AES_128_CBC_SHA", 
    "SSL_RSA_WITH_3DES_EDE_CBC_SHA", 
    "SSL_RSA_WITH_RC4_128_SHA", 
    "SSL_RSA_WITH_RC4_128_MD5", 
}; 
// put this in a place where it can be reused 
static final String ENABLED_PROTOCOLS[] = { 
     "TLSv1.2", "TLSv1.1", "TLSv1" 
    }; 

    private void sslCon() 
    { 
     try { 
          // setup truststore to provide trust for the server certificate 
       // load truststore certificate 
      InputStream trustStoresIs = getResources().openRawResource(R.raw.client_ca); 
      String trustStoreType = KeyStore.getDefaultType(); 
      KeyStore trustStore = KeyStore.getInstance(trustStoreType); 
      trustStore.load(trustStoresIs, "spsoft_123".toCharArray()); 
      //keyStore.setCertificateEntry("ca", ca); 

      // initialize trust manager factory with the read truststore 
      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
      tmf.init(trustStore); 

      // setup client certificate 
      // load client certificate 
      InputStream keyStoreStream = getResources().openRawResource(R.raw.client_cert_key); 
      KeyStore keyStore = null; 
      keyStore = KeyStore.getInstance("BKS"); 
      keyStore.load(keyStoreStream, "your password".toCharArray()); 

      KeyManagerFactory keyManagerFactory = null; 
      keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
      keyManagerFactory.init(keyStore, "your password".toCharArray()); 

      // Create an SSLContext that uses our TrustManager 
      SSLContext context = SSLContext.getInstance("SSL"); 
      context.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null); 

      SSLSocketFactory sslsocketfactory = (SSLSocketFactory)context.getSocketFactory(); 
      InetAddress serverAddr = InetAddress.getByName("192.168.11.104"); 
      sslSocket = (SSLSocket) sslsocketfactory.createSocket(serverAddr, 5212); 
      //String[] ciphers = sslSocket.getEnabledCipherSuites(); 
      sslSocket.setEnabledCipherSuites(ENABLED_CIPHERS); 
      // put this right before setEnabledCipherSuites()! 
      //sslSocket.setEnabledProtocols(ENABLED_PROTOCOLS); 
      //InputStream inputStream = sslSocket.getInputStream(); 
      OutputStream out = sslSocket.getOutputStream(); 

      Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_SHORT).show(); 
      sslSocket.close(); 


     } catch (KeyManagementException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (CertificateException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (KeyStoreException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (NoSuchAlgorithmException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (UnrecoverableKeyException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

} 
+0

例..... – Cukic0d

24

無需再次做好每一件事!

您需要更改密鑰庫的類型,從BKS​​到BKS-v1(BKS-v1是BKS的舊版本)。因爲說here

還有另一種解決方案BKS版本發生變化,這是非常非常簡單:

  1. 使用Portecle:

  2. 您可以使用密鑰庫資源管理器

,新文件將與BKS-V1進行編碼,並不會顯示再次錯誤....

注: Android能與型動物BKS版本:例如,API 15將需要BKS-1違背API 23需要BKS,所以你可能需要把兩個文件在您的應用程序。

注2:您可以使用此代碼:

int bks_version; 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 
    bks_version = R.raw.publickey; //The BKS file 
} else { 
    bks_version = R.raw.publickey_v1; //The BKS (v-1) file 
} 
KeyStore ks = KeyStore.getInstance("BKS"); 
InputStream in = getResources().openRawResource(bks_version); 
ks.load(in, "mypass".toCharArray()); 
+0

似乎解決我有一個4.0.4設備的問題,但設備4.1 .1/2仍然存在相同問題 – Fonix

+1

不知道爲什麼,但是當我試圖用Portecle改變它時,它只是不斷讓我改變密鑰庫,因爲它說unrecoverablekeyexception。但後來我用Windows和Keystore Explorer試用了它,並從那裏改變了keystore類型,它像一個魅力一樣工作。 +1 – Simon

+1

4.1.1/2的解決方法:'''if(Build.VERSION.SDK_INT> = Build.VERSION_CODES.JELLY_BEAN_MR1){...}''' – L3K0V

0

我張貼這個答案用於轉變.pkcs12-file來keystore.bks

提供CMDLINE版本是什麼需要:

下載

如果你不知道如何生成.PKCS12-文件看看這些網站:

對於此示例我使用jetty.pkcs12源。 命令生成:keystore.bks /usr/local/share/java/portecle-1.9/是我已經安裝了下載Portecle工具(.ZIP)路徑

keytool -importkeystore -srckeystore jetty.pkcs12 \ 
-srcstoretype PKCS12 -deststoretype BKS -providerpath \ 
/usr/local/share/java/portecle-1.9/bcprov.jar -provider \ 
org.bouncycastle.jce.provider.BouncyCastleProvider-destkeystore \ 
keystore.bks 

現在你可以使用Android的下BKS-密鑰庫

多虧了上一個帖子,我能夠找到一個解決方案,並提供該CMD。希望它能幫助別人!