1

我一直在寻找这个几个星期,似乎无法在任何地方找到答案。我正在尝试为Android进行以下操作。此代码来自我编写的C#应用​​程序,但将其移植到Android。 Web端点需要将证书附加到相互验证请求以进行Web服务调用。Android和客户端证书

 string certThumbprint = "E1313F6A2D770783868755D016CE748F6A9B0028"; 
     X509Store certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
     try 
     { 
      certStore.Open(OpenFlags.ReadOnly); 
     } 
     catch (Exception e) 
     { 
      if (e is CryptographicException) 
      { 
       Console.WriteLine("Error: The store is unreadable."); 
      } 
      else if (e is SecurityException) 
      { 
       Console.WriteLine("Error: You don't have the required permission."); 
      } 
      else if (e is ArgumentException) 
      { 
       Console.WriteLine("Error: Invalid values in the store."); 
      } 
      else 
      { 
       throw; 
      } 
     } 
     X509Certificate2Collection certCollection = certStore.Certificates.Find(X509FindType.FindByThumbprint, certThumbprint, false); 
     certStore.Close(); 
     if (0 == certCollection.Count) 
     { 
      throw new Exception("Error: No certificate found containing thumbprint " + certThumbprint); 
     } 
     X509Certificate2 certificate = certCollection[0]; 
     return certificate; 

我再这样做(请求是HttpWebRequest的):

request.ClientCertificates.Add(cert); 

但是当我移动到Android我得到的一个“文件未找到”错误此作品在C#精getInputStream()调用。这是我的Android代码:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); 

     StrictMode.setThreadPolicy(policy); 
     CertificateFactory cf = CertificateFactory.getInstance("X.509"); 

     InputStream caInput = new BufferedInputStream(new FileInputStream("/sdcard/Certificate.pfx")); 
     KeyHelper kh = new KeyHelper(); 
     Certificate ca = kh.GetKey("Password"); 
     String keyStoreType = KeyStore.getDefaultType(); 
     keyStore = KeyStore.getInstance(keyStoreType); 
     keyStore.load(null, null); 
     keyStore.setCertificateEntry("ca", ca); 
     KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
     kmf.init(keyStore, "Password".toCharArray()); 
     SSLContext context = SSLContext.getInstance("TLS"); 
     context.init(kmf.getKeyManagers(),null,new SecureRandom()); 
     HttpsURLConnection urlConnection = 
       (HttpsURLConnection)url.openConnection(); 
     urlConnection.setRequestProperty("x-ms-version",AZURE_REST_VERSION); 
     urlConnection.setDoInput(true); 
     urlConnection.setDoOutput(true); 
     urlConnection.setRequestMethod("GET"); 
     urlConnection.setSSLSocketFactory(context.getSocketFactory()); 
     urlConnection.connect(); 

     InputStream in = new BufferedInputStream(urlConnection.getInputStream()); //<-----Blows up here 

    } catch (KeyStoreException e) { 
     throw new KeyStoreException("Keystore Exception",e); 
    } catch (NoSuchAlgorithmException e) { 
     throw new NoSuchAlgorithmException("Algorithm exception",e); 
    } catch (KeyManagementException e) { 
     throw new KeyManagementException("Key Exception", e); 
    } 

我试图把仿真器和终点之间的提琴手和它回来了200.我想这是因为我的证书是在我的开发机器上我的本地私人商店。有什么想法吗?

回答

2

好的。我找到了这个答案。问题在于自签名证书只有存在于android TrustStore中才能使用。但是,在应用程序启动后,默认的TrustStore是只读的,因此很难对其进行修改。我设置了自己的自定义信任存储,但是根证书不是它的一部分,所以向任何https发出呼叫都会失败。该解决方案从这个博客帖子就来了:

http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html

长话短说,建立包含自签名证书的自定义信任库,然后从默认的信任存储中导出的所有证书,并将其导入自定义信任存储。然后使用该信任存储设置您的SSL上下文(也需要使用自定义密钥存储,因为客户端证书也需要附加到请求中)。我相信,如果我不允许自签名证书,这将不是什么大问题,因为客户端证书的根证书将存在于默认的TrustStore中(或者至少我希望这样做)。

0

而且你永远不应该硬编码路径:

InputStream caInput = new BufferedInputStream(new FileInputStream("/sdcard/Certificate.pfx")); 

而是使用:

Environment.getExternalStorageDirectory() 

看看这个:http://developer.android.com/training/basics/data-storage/files.html

也为证书 在此请看:Using a self-signed certificate to create a secure client-server connection in android

+0

虽然heplful这不是一个实际的解决方案,你必须将密钥库添加到android项目本身。这样做的目的就在于,尽管我已经有了一个证书 - 最终用户可能会将其上传到应用程序,但我需要生成密钥库并将证书填入其中。实现此代码后,我现在正在收到SSLPeerUnverifiedError“无对等证书”错误。自签名证书存在于客户端和服务器端。所以搜索仍在继续。 – AnthonyBCodes