2012-02-15 107 views
49

我試圖連接到一個安全的web服務。爲什麼在SSL握手期間java不發送客戶端證書?

即使我的密鑰存儲庫和信任庫已正確設置,我仍遇到握手失敗。

經過幾天的沮喪,無盡的谷歌搜索,並詢問身邊的每一個人,我發現唯一的問題是java握手期間選擇不發送客戶端證書到服務器。

具體做法是:

  1. 服務器請求客戶端證書(CN =根CA) - 即「給我,由根CA簽署的證書」
  2. 的Java看着密鑰庫,只發現我的客戶證書由「SubCA」簽名,而「SubCA」則由「RootCA」簽發。它沒有費心去查看信任庫......嗯好吧我猜
  3. 很遺憾,當我試圖將「SubCA」證書添加到密鑰庫時,根本沒有任何幫助。我沒有檢查證書是否加載到密鑰庫中。他們這樣做,但KeyManager忽略除客戶端之外的所有證書。
  4. 所有上述導致了Java的決定它不具有滿足服務器的請求的任何證書,併發送什麼... tadaaa握手失敗:-(

我的問題的事實:

  1. 是否有可能將「SubCA」證書以「破壞證書鏈」或其他方式添加到密鑰庫中,以便KeyManager僅加載客戶端證書並忽略其餘部分?(Chrome和openssl管理圖形那麼爲什麼不能java? - 請注意,「SubCA」證書總是作爲受信任的權威機構單獨列出,以適應Chrome應用程序在握手過程中將其與客戶端證書一起正確包裝)
  2. 這是服務器端的正式「配置問題」嗎?服務器是第三方。我希望服務器請求由「SubCA」權威機構簽署的證書,因爲這是他們提供給我們的。我懷疑,這在Chrome和openssl中起作用的事實是因爲它們「不那麼嚴格」,而java只是「靠本書」而失敗。

我的確設法解決了這個問題,但我對此並不滿意,所以如果有人能爲我澄清這一點,我會很高興。

+2

值得向@Bruno的回答添加一個基本原因是存在一個私鑰但沒有相應的證書(即具有相同的別名),所以當被證書請求消息詢問時,Java不能發送一個證書。其他原因可能包括沒有指定服務器簽發的證書,或沒有與服務器指定的密碼匹配的證書。 – EJP 2014-02-05 05:41:55

+0

我們解決了這個問題,只是匹配服務器指定的密碼。謝謝你們所有這些信息,這非常有用。 – 2016-05-20 20:19:01

回答

76

您可能已將中間CA證書導入密鑰庫,而無需將其與您擁有客戶端證書及其私鑰的條目相關聯。你應該能夠看到這個使用keytool -v -list -keystore store.jks。如果每個別名條目只有一個證書,則它們不在一起。

您需要將您的證書及其鏈一起導入到具有您的私鑰的密鑰庫別名中。

要找出哪個密鑰庫別名具有私鑰,請使用keytool -list -keystore store.jks(我假設此處爲JKS存儲類型)。這會告訴你是這樣的:

Your keystore contains 1 entry 

myalias, Feb 15, 2012, PrivateKeyEntry, 
Certificate fingerprint (MD5): xxxxxxxx 

這裏,別名是myalias。如果除此之外還使用-v,則應該看到Alias Name: myalias

如果你沒有它已經分開,從密鑰庫導出客戶端證書:

keytool -exportcert -rfc -file clientcert.pem -keystore store.jks -alias myalias 

這應該給你一個PEM文件。

使用文本編輯器(或cat),使用該客戶端證書和中間CA證書(如果需要,可能還有根CA證書本身)準備文件(我們稱之爲bundle.pem),以便客戶端證書是在開始時,其發行人證書就在其中。

這應該是這樣的:

-----BEGIN CERTIFICATE----- 
MIICajCCAdOgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJVSzEa 
.... 
-----END CERTIFICATE----- 
-----BEGIN CERTIFICATE----- 
MIICkjCCAfugAwIBAgIJAKm5bDEMxZd7MA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNV 
.... 
-----END CERTIFICATE----- 

現在,進口這種捆綁到一起地瞭解自己的私鑰別名:

keytool -importcert -keystore store.jks -alias myalias -file bundle.pem 
+1

超過一百萬布魯諾 - 做了這項工作。我認爲這可能有更多的文件記錄。我只花了好幾天的時間來弄清楚到底發生了什麼。 Java的提示實際上並不存在。 – 2012-02-16 08:00:13

+1

我也需要將證書和私鑰合併到導入中,但我以* .pem證書文件(以「----- BEGIN CERTIFICATE -----」開頭)和* .key開頭私鑰(「----- BEGIN RSA PRIVATE KEY -----」)。我嘗試連接它們,然後導入,但我得到:keytool錯誤:java.lang.Exception:輸入不是一個X.509證書。任何想法,我要去錯了嗎?我閱讀http://stackoverflow.com/questions/5297867/ssl-tomcat-certificate-error/11984173#11984173可能需要轉換爲密鑰類型pkcs12。有任何想法嗎?我卡住了!謝謝。 – 2012-12-18 21:25:57

+0

感謝布魯諾,你已經救了我的一天! – Gaucho 2014-07-03 07:45:37

5

此處作爲插件,您可以使用%> openssl s_client -connect host.example.com:443並查看轉儲並檢查所有主要證書是否對客戶端有效。您正在輸出的底部尋找這個。 驗證返回碼:0(OK)

如果添加-showcerts將傾倒,將其與主機證書,這是你加載到您的鑰匙串什麼一起發送鑰匙串中的所有信息。

+0

哪個命令你使用'-showcerts'? – 2017-01-03 19:39:07

+0

@JerylCook'openssl s_client -showcerts -connect host.example.com:443' – Sky 2018-01-19 17:50:08