2014-06-29 28 views
1

我試圖爲Android應用程序實現客戶端證書通信,目前爲止沒有取得太大的成功 - 並且似乎這個功能如果可能的話非常困難。我正在執行的完整流程在my previous question中描述。客戶端證書不能從Android工作 - 如何調試?

我跟着那裏的代碼和代碼從this blog post,描述相同的情況,或多或少,沒有結果。

什麼不工作:打開Android客戶端和服務器之間的SSL連接(HttpsURLConnection)導致服務器返回一個403 status code
AFAIK,這是因爲服務器沒有得到或不信任它得到的客戶端證書,我不知道如何調試它。

什麼工作:

  • 創建PKCS#10的請求,將其發送到CA,並得到一個簽名的PKCS#7(P7B
  • 存儲接收P7B與KeyStore中的私鑰,並將其導出到PKCS#12(P12
  • Most annonying)picking從設備上安裝它,在Windows上安裝它,聯繫服務器並獲得一致(200 HTTP-OK)響應。

我已經改變了:從代碼樣本中我得到了(從herehere),我不得不改變一些事情。我使用HttpsURLConnection而不是OkHttpClient作爲@Than在那裏使用(但它應該沒有關係),我無法提供證書作爲Rich Freedman做的(他證書,我通過PKCS# 10和#7),所以我創建了一個可以信任服務器證書的CustomTrustManager,爲此我使用SpongyCastle(v1.5.0.0,如果它很重要,設置爲提供者插入爲0),也不會堅持證書,但都是在內存中完成的。

問題是下一步該做什麼:

  • 我如何才能知道什麼樣的服務器要求(客戶端證書明智的)?
  • 如何判斷哪些客戶端證書(如果有)正在發送到服務器?
  • 如何在一般情況下調試此場景? (如Fiddler這樣的代理對底層SSL沒用)

謝謝!

回答

4

這不是一個好的答案,但是這裏有太多的帖子來發表評論。

進行日誌記錄,調試,你可以創建自己的X509KeyManager它使用從KeyManagerFactory獲得正常的密鑰管理器:

@DebugLog註釋來源於由Jake沃頓商學院創建雨果庫。它打印函數參數和它返回的內容。你可以使用正常的Log.d或任何你想要的。

例如:

class MyKeyManager implements X509KeyManager { 

    private final X509KeyManager keyManager; 

    MyKeyManager(X509KeyManager keyManager) { 
     this.keyManager = keyManager; 
    } 

    @DebugLog 
    @Override 
    public String chooseClientAlias(String[] strings, Principal[] principals, Socket socket) { 
     return this.keyManager.chooseClientAlias(strings, principals, socket); 
    } 

    @DebugLog 
    @Override 
    public String chooseServerAlias(String s, Principal[] principals, Socket socket) { 
     return keyManager.chooseServerAlias(s, principals, socket); 
    } 

    @DebugLog 
    @Override 
    public X509Certificate[] getCertificateChain(String s) { 
     return keyManager.getCertificateChain(s); 
    } 

    @DebugLog 
    @Override 
    public String[] getClientAliases(String s, Principal[] principals) { 
     return keyManager.getClientAliases(s, principals); 
    } 

    @DebugLog 
    @Override 
    public String[] getServerAliases(String s, Principal[] principals) { 
     return keyManager.getServerAliases(s, principals); 
    } 

    @DebugLog 
    @Override 
    public PrivateKey getPrivateKey(String s) { 
     return keyManager.getPrivateKey(s); 
    } 
} 

並用它來初始化SSLContext

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
kmf.init(keyStore, password); 

final X509KeyManager origKm = (X509KeyManager) kmf.getKeyManagers()[0]; 
X509KeyManager km = new MyKeyManager(origKm); 

SSLContext sslCtx = SSLContext.getInstance("TLS"); 
sslCtx.init(new KeyManager[]{km}, tmf.getTrustManagers(), null); 

你會看到被稱爲哪種方法,有什麼論據(從serwer證書獲得)以及證書和私鑰你的keymanager返回。