我的任務是實現可以在同一端口上處理SSL和非SSL消息的自定義/獨立Java Web服務器。使用自簽名證書和SSLEngine(JSSE)的SSL握手
我已經實現了一個NIO服務器,它的工作非常好,適用於非SSL請求。我有一段SSL時間,可以真正使用一些指導。
這是我迄今爲止所做的。
爲了區分SSL和非SSL消息,我檢查入站請求的第一個字節以查看它是否爲SSL/TLS消息。例如:
byte a = read(buf);
if (totalBytesRead==1 && (a>19 && a<25)){
parseTLS(buf);
}
在parseTLS()方法我實例類似這樣的SSLEngine:
java.security.KeyStore ks = java.security.KeyStore.getInstance("JKS");
java.security.KeyStore ts = java.security.KeyStore.getInstance("JKS");
ks.load(new java.io.FileInputStream(keyStoreFile), passphrase);
ts.load(new java.io.FileInputStream(trustStoreFile), passphrase);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passphrase);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLEngine serverEngine = sslc.createSSLEngine();
serverEngine.setUseClientMode(false);
serverEngine.setEnableSessionCreation(true);
serverEngine.setWantClientAuth(true);
一旦SSLEngine的被實例化,我過程,使用所述解包/渦卷方法使用代碼直出所述入站數據官方JSSE Samples的:
log("----");
serverResult = serverEngine.unwrap(inNetData, inAppData);
log("server unwrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
log("----");
serverResult = serverEngine.wrap(outAppData, outNetData);
log("server wrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
握手的第一部分似乎工作就好了。客戶端發送握手消息和服務器與4條記錄的消息進行響應:
handshake (22)
- server_hello (2)
- certificate (11)
- server_key_exchange (12)
- certificate_request (13)
- server_hello_done (14)
接下來,客戶端將消息發送具有三個部分:
handshake (22)
- certificate (11)
- client_key_exchange (16)
change_cipher_spec (20)
- client_hello (1)
handshake (22)
*** Encrypted Message ****
所述的SSLEngine解開該客戶機請求,並解析記錄但是wrap方法產生0字節,握手狀態爲OK/NEED_UNWRAP。換句話說,我沒有什麼可以送回客戶端,而握手就會停下來。
這是我卡住的地方。
在調試器中,我可以看到SSLEngine,特別是ServerHandshaker沒有找到任何對等證書。當我查看來自客戶端的長度爲0字節的證書記錄時,這很明顯。但爲什麼?
我只能假設HelloServer響應有問題,但我似乎無法將它放在手指上。服務器似乎在發送有效的證書,但客戶端沒有發送任何迴應。我的密鑰庫有問題嗎?或者它是信任商店?或者它與我實例化SSLEngine的方式有什麼關係?我很難過。
夫婦其它點:
- 的密鑰庫和信任在SNIPPIT以上使用下述教程中創建的代碼中引用: http://www.techbrainwave.com/?p=953
- 我使用的Firefox 10和IE 9作爲客戶端,以測試服務器。兩個Web客戶端的結果相同。
- 我正在使用附帶的Sun/Oracle JDK 6和Java安全套接字擴展(JSSE)。
我期待着您可能有的任何指導,但請不要告訴我我堅果或使用Netty或Grizzly或其他現有解決方案。目前它不是一種選擇。我只是想明白我做錯了什麼。
在此先感謝!
只是一個愚蠢的問題:你有沒有產生並安裝客戶端證書,例如Firefox通過HTTPS連接到Web服務器時? – Robert 2012-03-07 16:26:40
是的。 FF促使我接受/拒絕證書。我點擊「我接受技術風險」,我可以在工具 - >選項 - >高級 - >加密 - >查看證書 - >服務器下看到證書。事實上,沒有這個,FF不會發送第二個握手消息。 – Peter 2012-03-07 17:01:51
這不是我問的問題。我正在要求客戶證書。 SSL客戶端身份驗證是可選的,主要用於企業環境中,通常與芯片卡結合使用。如果客戶端沒有安裝證書(Firefox部分「您的證書」),則不會發送證書。 – Robert 2012-03-07 20:10:58