2015-10-06 76 views
2

我明白這是不是很困難,但非常不幸,我卡在這裏,並從昨天開始打架,我遵循這個Mutual Authentication in Android教程,放置一個密鑰庫在資源和嘗試連接到我的服務器通過SSL,但得到以下異常安卓到服務器通信使用SSL與Bouncy城​​堡

java.lang.RuntimeException: org.spongycastle.jcajce.provider.asymmetric.x509.CertificateFactory$ExCertificateException

我已經把我的sslapptruststore.pfx文件res/raw/sslapptruststore.pfx 下,並使用這段代碼

try { 

          KeyStore clientCert = KeyStore.getInstance("PKCS12"); 
            clientCert.load(getResources().openRawResource(R.raw.sslapptruststore), "123456".toCharArray());// this line causes exception 

          HttpClient httpClient = null; 
          HttpParams httpParams = new BasicHttpParams(); 
          SSLSocketFactory sslSocketFactory = new SSLSocketFactory(clientCert, null, null); 
          SchemeRegistry registry = new SchemeRegistry(); 
          registry.register(new Scheme("https", sslSocketFactory, 8443)); 
          httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(httpParams, registry), httpParams); 


          HttpPost httpPost = new HttpPost(
            "https://192.168.1.113:8443/CertProvider"); 
          httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); 
          List<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(2); 
          nameValuePair.add(new BasicNameValuePair("csr", csr.toString())); 

          // Url Encoding the POST parameters 
           httpPost.setEntity(new UrlEncodedFormEntity(nameValuePair)); 

          // Making HTTP Request 
          // HttpResponse response = null; 
          ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
          String response = ""; 
          response = httpClient.execute(httpPost, responseHandler); 
           } catch (Exception e) { 
            Log.e("", e.getMessage()); 
           } 

我也搜索過,但其他人正在使用.bks

任何幫助表示讚賞。

回答

1

我已經添加下面的類來解決這個問題

import org.apache.http.conn.ssl.SSLSocketFactory; 

import java.io.IOException; 
import java.io.InputStream; 
import java.net.Socket; 
import java.security.KeyManagementException; 
import java.security.KeyStore; 
import java.security.KeyStoreException; 
import java.security.NoSuchAlgorithmException; 
import java.security.UnrecoverableKeyException; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 
import java.util.ArrayList; 
import java.util.Arrays; 

import javax.net.ssl.KeyManager; 
import javax.net.ssl.KeyManagerFactory; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.TrustManagerFactory; 
import javax.net.ssl.X509TrustManager; 

/** 
* Allows you to trust certificates from additional KeyStores in addition to 
* the default KeyStore 
*/ 
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory{ 
    protected SSLContext sslContext = SSLContext.getInstance("TLSv1"); 

    public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { 
     super(null, null, null, null, null, null); 
     KeyManagerFactory keyManagerFactory = KeyManagerFactory 
       .getInstance(KeyManagerFactory.getDefaultAlgorithm());; 
     keyManagerFactory.init(keyStore, "123456".toCharArray()); 
     sslContext.init(keyManagerFactory.getKeyManagers(), new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null); 
    } 

    @Override 
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { 
     return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 
    } 

    @Override 
    public Socket createSocket() throws IOException { 
     return sslContext.getSocketFactory().createSocket(); 
    } 



    /** 
    * Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager 
    */ 
    public static class AdditionalKeyStoresTrustManager implements X509TrustManager { 

     protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>(); 


     protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) { 
      final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>(); 

      try { 
       // The default Trustmanager with default keystore 
       final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
       original.init((KeyStore) null); 
       factories.add(original); 

       for(KeyStore keyStore : additionalkeyStores) { 
        final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
        additionalCerts.init(keyStore); 
        factories.add(additionalCerts); 
       } 

      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 



      /* 
      * Iterate over the returned trustmanagers, and hold on 
      * to any that are X509TrustManagers 
      */ 
      for (TrustManagerFactory tmf : factories) 
       for(TrustManager tm : tmf.getTrustManagers()) 
        if (tm instanceof X509TrustManager) 
         x509TrustManagers.add((X509TrustManager)tm); 


      if(x509TrustManagers.size()==0) 
       throw new RuntimeException("Couldn't find any X509TrustManagers"); 

     } 

     /* 
     * Delegate to the default trust manager. 
     */ 
     public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0); 
      defaultX509TrustManager.checkClientTrusted(chain, authType); 
     } 

     /* 
     * Loop over the trustmanagers until we find one that accepts our server 
     */ 
     public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      for(X509TrustManager tm : x509TrustManagers) { 
       try { 
        tm.checkServerTrusted(chain,authType); 
        return; 
       } catch(CertificateException e) { 
        // ignore 
       } 
      } 
      throw new CertificateException(); 
     } 

     public X509Certificate[] getAcceptedIssuers() { 
      final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>(); 
      for(X509TrustManager tm : x509TrustManagers) 
       list.addAll(Arrays.asList(tm.getAcceptedIssuers())); 
      return list.toArray(new X509Certificate[list.size()]); 
     } 
    } 

} 
+0

我有同樣的問題。我的代碼在CertificateFactory cf = CertificateFactory.getInstance(「X.509」,「BC」)行中給出錯誤。我如何使用這個類來避免錯誤?謝謝 – Hilal

+0

@Hilal分享你的錯誤跟蹤,大致我可以建議你檢查你的提供者列表,可能是BC提供者不在列表中 – SSH

+0

我不能粘貼整個錯誤,因爲stackoverflow不允許:)另外我怎樣才能檢查提供者列表?這裏是錯誤; com.android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory $ ExCertificateException 09-20 12:48:02.042 20236-20350/com.example.hilalinan.cert W/System.err:at com。 android.org.bouncycastle.jcajce.provider.asymmetric.x509.CertificateFactory.engineGenerateCertificate(CertificateFactory.java:220) 09-20 12:48:02.042 20236-20350/com.example.hilalinan.cert W/System.err: – Hilal

3

我已經回答了一些問題看起來像你的問題如下所示:

Read in PKCS12/P12 Client Cert file for Android App

Android volley self signed HTTPS trust anchor for certification path not found

你會發現

private SSLSocketFactory getSSLSocketFactory_KeyStore(String keyStoreType, int keystoreResId, String keyPassword) 
      throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException { 

     InputStream caInput = getResources().openRawResource(keystoreResId); 

     // creating a KeyStore containing trusted CAs 

     if (keyStoreType == null || keyStoreType.length() == 0) { 
      keyStoreType = KeyStore.getDefaultType(); 
     } 
     KeyStore keyStore = KeyStore.getInstance(keyStoreType); 

     keyStore.load(caInput, keyPassword.toCharArray()); 

     // creating a TrustManager that trusts the CAs in the KeyStore 

     String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
     TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
     tmf.init(keyStore); 

     TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers()); 

     SSLContext sslContext = SSLContext.getInstance("TLS"); 
     sslContext.init(null, wrappedTrustManagers, null); 

     return sslContext.getSocketFactory(); 
    } 

getSSLSocketFactory_Certificate.cert文件。如果使用的密鑰存儲文件

SSLSocketFactory sslSocketFactory = getSSLSocketFactory_KeyStore("PKCS12", R.raw.androidpkcs12, "123456789"); 

如果使用證書文件:

SSLSocketFactory sslSocketFactory = getSSLSocketFactory_Certificate("PKCS12", R.raw.androidpkcs12_cert); 

如上第一個鏈接,在你的項目,你可以調用兩種方法之一

P/S:如果這些方法在非活動類別內,爲避免NPE,您必須將Context從您的活動傳遞到該cl屁股(如上面的第一個鏈接)。

希望這會有所幫助!

+0

如果不能正常工作,請告訴我。然後,如果可能的話,提供給我你的.pfx文件,以便我可以檢查我的項目:) – BNK

+0

是肯定,,, thnx – SSH

+0

previuosly我只把簽名證書放在密鑰庫中,但我試着用一個完整的密鑰庫鏈,它工作和至少能夠加載密鑰庫,但現在得到這個異常<< javax.net.ssl.SSLPeerUnverifiedException:沒有同行證書>> – SSH