[英]Android - validating self-signed certificates in addition to normal SSL certificates
我有一個通過SSL調用Web服務的Android應用程序。 在生產中,我們將擁有由受信任的CA簽名的普通SSL證書。 但是,我們需要能夠支持自簽名證書(由我們自己的CA簽名)。
我已經成功實施了接受自簽名證書的建議解決方案,但由於中間人攻擊的風險,這不起作用。 然后,我創建了一個信任管理器,用於驗證證書鏈實際上是由我們的CA簽署的。
問題是我必須繞過正常的SSL驗證 - 應用程序現在只會對安裝了我們自簽名證書的服務器說話。
我有點迷茫,我已經廣泛搜索但找不到任何東西。 我希望找到一種以編程方式將我們的CA添加到設備上的信任存儲的方法,因為這將是處理問題的最不具侵入性的方式。
我想要實現的目標:1。對普通SSL證書的完全標准支持。 2.對我們自己的CA簽署的自簽名證書的額外支持。
有什么建議?
你沒有發布任何代碼,所以我不能確定你實際做了什么。 但是,我假設您只使用自定義X509TrustManager
子類設置SSLContext
。 這很好,但你可以做的是讓你的自定義信任管理器實現也鏈接到內置的信任管理器。 您可以在設置信任經理時執行此操作; 這樣的事情應該有效:
private List<X509TrustManager> trustManagers = new ArrayList<X509TrustManager>();
public MyCustomTrustManager() {
TrustManagerFactory tmFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmFactory.init((KeyStore)null);
for (TrustManager tm : tmFactory.getTrustManagers()) {
if (tm instanceof X509TrustManager)
trustManagers.add((X509TrustManager)tm);
}
}
所以現在您的自定義信任管理器有一個包含所有內置信任管理器的列表。 在你的checkServerTrusted()
重寫中,你需要遍歷內置的信任管理器並通過checkServerTrusted()
調用每個信任管理器上的checkServerTrusted()
來檢查每個信任管理器。 如果他們都不信任證書,您可以應用自己的證書檢查。 如果通過,您可以正常返回。 如果沒有,只需拋出CertificateException
,否則就這樣做。
編輯:添加以下關於主機名驗證等操作。
您還可以驗證證書中的主機名是否與預期的一致。 您需要在自定義信任管理器的構造函數中傳入有效的主機名,並將其存儲在類中。 您的checkServerTrusted()
方法將傳遞一個X509Certificate
數組。 許多“連鎖店”只包含一個證書,但其他人會有幾個,具體取決於cA如何簽署您的證書。 無論哪種方式,數組中的第一個證書應該是您要比較的“您的”證書。
在使用信任管理器檢查基本證書有效性之后,您將需要執行以下操作:
Principal subjectDN = chain[0].getSubjectDN();
String subjectCN = parseDN(subjectDN.getName(), "CN");
if (this.allowedCN.equals(subjectCN)) {
// certificate is good
}
parseDN()
的實現由您自己決定。 subjectDN.getName()
將返回以逗號分隔的鍵值對列表(由=
分隔),例如C=US,ST=California,L=Mountain View,O=Google Inc,CN=www.google.com
。 您希望CN(“公共名稱”)值用於主機名比較。 請注意,如果您有通配符證書,它將被列為類似*.example.com
,因此在這種情況下您需要做的不僅僅是簡單的等號匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.