2011-12-09 57 views
54

爲了清楚起見,這些可能被視爲單獨的問題,但它們都與相同的問題有關。如何解析SSL證書服務器名稱/我可以使用keytool添加替代名稱嗎?

如何解決SSL證書服務器名稱?

爲什麼瀏覽器似乎使用證書的CN字段,但Java的機制似乎只看「主題替代名稱」?

是否可以使用keytool向SSL證書添加替代名稱? 如果沒有,是使用openSSL而不是一個好的選擇?

只是一點點背景:我需要一個主服務器來與使用HTTPS的多個服務器進行通信。顯然,我們不想爲每臺服務器購買SSL證書(可能有很多),所以我想使用自簽名證書(我一直在使用keytool來生成它們)。在操作系統中添加可信的證書後,瀏覽器(IE和Chrome)很高興地將連接接受爲可信。然而,即使添加了證書與Java的cacerts中之後,Java的仍然不會爲信任接受連接,並拋出以下異常:

產生的原因:java.security.cert.CertificateException:沒有主題備用名稱 本 at sun.security.util.HostnameChecker.matchIP(HostnameChecker.java:142) at sun.security.util.HostnameChecker.match(HostnameChecker.java:75) at com.sun.net.ssl.internal.ssl。 X509TrustManagerImpl.checkIdentity(X509T rustManagerImpl.java:264) at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted( X509TrustManagerImpl.java:250) 在com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(CLIEN tHandshaker.java:1185) ...... 14多個

我發現我可以信任的Java實現的證書我自己的HostNameVerifier,我從這裏複製:com.sun.jbi.internal.security.https.DefaultHostnameVerifier只是爲了測試(順便說一下,作爲HostnameVerifier的參數傳遞的主機名是正確的,所以我認爲它應該被接受)。

我一直在使用證書字段CN作爲主機名(通常是IP地址)。

有人可以告訴我,如果我做錯了什麼,並指出我在正確的方向嗎?

+1

鏈接已損壞。 – axiopisty

+1

選擇您的替代方案:http://grepcode.com/search?query=DefaultHostnameVerifier&n= – Renato

回答

82

如何主機名驗證應做在RFC 6125定義,這是相當最近的和可以推廣的做法,所有的協議,並取代RFC 2818,這是專門針對HTTPS。 (我甚至不能確定Java 7的採用RFC 6125,這可能是太新了這一點)。

RFC 2818 (Section 3.1)

如果類型DNSNAME的subjectAltName擴展存在, 使用必須作爲身份。否則,務必使用證書的主題字段中的(最具體的)通用名稱 字段。雖然 使用通用名稱是現有的慣例,但它已被棄用,並鼓勵證書頒發機構改爲使用dNSName。

[...]

在一些情況下,URI被指定爲IP地址,而不是一個 主機名。在這種情況下,iPAddress subjectAltName必須在證書中出現 ,並且必須與URI中的IP完全匹配。

實質上,您遇到的具體問題來自您在CN中使用IP地址而不是主機名。某些瀏覽器可能會工作,因爲並非所有工具都嚴格遵循此規範,特別是因爲RFC 2818中的「最具體」沒有明確定義(請參閱RFC 6215中的討論)。

如果您使用keytoolas of Java 7, keytool有一個選項包括主題備用名稱(見表格文檔中爲-ext):你可以使用-ext san=dns:www.example.com-ext san=ip:10.0.0.1

編輯:

您可以通過改變openssl.cnf(它會挑副本在當前目錄下,如果你不想要編輯的全局配置,據我記得在請求OpenSSL創建SAN,或者您可以使用OPENSSL_CONF環境變量選擇明確的位置)。

設置以下選項(找到括號內的適當部分在前):

[req] 
req_extensions = v3_req 

[ v3_req ] 
subjectAltName=IP:10.0.0.1 
# or subjectAltName=DNS:www.example.com 

還有一個好的技巧使用環境變量本(而在比它在配置文件中固定)在這裏: http://www.crsr.net/Notes/SSL.html

+0

這正是我需要知道的......但是,看起來Java 6沒有這個-ext選項。我將嘗試將我的虛擬機更改爲Java 7並對其進行測試。 – Renato

+2

請注意,您可以在另一臺計算機上使用來自Java 7的keytool,並稍後複製密鑰庫(不必運行Java 7)。另外,我已經編輯了我的答案,用OpenSSL來做。這就是說,從長遠來看,使用主機名而不是IP地址可能會更靈活(無論如何,使用SAN是一個好主意)。 – Bruno

+0

-ext選項在Java6中不起作用!我將切換到Java 7,並看看我是否可以使用keytool來做...非常感謝您的答案..(PS。將在我測試後接受答案) – Renato

相關問題