我試圖在.NET和Java之間創建一個SSL套接字服務器/客戶端。在這種情況下,我的SSL套接字服務器將以.net運行,並且客戶端在Linux下以Java運行。我的問題是在握手期間連接失敗,特別是當服務器從客戶端請求證書時,客戶端無法發回某些內容並且連接失敗。使用客戶端身份驗證的.Net和Java之間的SSL Socket
在.net我使用sslStream建立連接,並在Java上使用標準的SSLSocket。一些代碼片段在下面,但這是我迄今爲止:
在服務器端(Windows),我在MMC下的個人/證書文件夾中有私人證書。我有可信人員/證書中的客戶的公共證書。這兩個證書都是由同一個CA頒發的。兩個證書的證書鏈都有多個級別,但兩者都是相同的。鏈中的根級證書也安裝在受信任的證書頒發機構/證書文件夾中。
在客戶端(Linux)上,我有一個密鑰存儲庫,其中包含與服務器上安裝的公用證書匹配的專用證書。我有一個信任存儲庫,其中包含來自服務器的公共證書,與服務器的私人證書相匹配。
在服務器端(.NET)我使用的是插座,做一個異步讀取,然後它被包裹成一個SSLStream,代碼片段是這樣的:
NetworkStream ns = new NetworkStream(socket, false);
SslStream ssl = new SslStream(ns, true);
ssl.AuthenticateAsServer(serverCertificate, true, SslProtocols.Default, true);
客戶端代碼是相當很多標準代碼:
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
InetAddress addr = InetAddress.getByName(servername);
SSLSocket socket = (SSLSocket) factory.createSocket(addr,port);
socket.setUseClientMode(true);
socket.setNeedClientAuth(true);
socket.setWantClientAuth(true);
socket.startHandshake();
os = new DataOutputStream(socket.getOutputStream());
is = new DataInputStream(socket.getInputStream());
byte[] outBuf = new byte[50];
os.write("SEND SOMETHING".getBytes("UTF-8"));
is.read(outBuf);
在java中,我已經設置了適當的變量來指向信任和密鑰存儲與他們的密碼。現在
,按照標準SSL握手,這是發生了什麼:
- 客戶問候
- 服務器問候
- 服務器發送公證書
- 客戶端上的信任存儲的一個公證書相匹配
- 服務器發送證書請求
- 隨着證書請求服務器sen ds列出有效的CA,在此列表上僅發送我的根CA(在其他衆所周知的CA的長列表中)。
- 客戶端證書爲空。
- 服務器從客戶端收到空證書,從而關閉連接。
而就是這樣,客戶端不會將有效的證書發送回服務器。我有這方面的一些問題:
有沒有人經歷過這樣的事情? 關於服務器發送的CA列表(Windows),.net如何確定要發送給客戶端的內容?有沒有辦法修改該列表? 我是否需要發送用於在該CA列表中籤署我的證書的鏈中的所有權限?或者是一個足夠的根?
我是否在代碼的任何一側缺少某些東西?
任何幫助將不勝感激。 在
問題出在客戶端的證書上。證書不包含完整鏈,因此,當服務器發送包括僅有根CA的有效CA列表時,客戶端無法在存儲中找到匹配的證書。我們將全鏈式證書重新導入密鑰存儲區,所有事情都開始正常工作。 – 2012-03-17 12:07:29
那麼你是如何得到它在JAVA端的工作?任何信息將不勝感激。謝謝 – 2015-02-19 15:04:09
@ Mr.Noob抱歉,對此回覆有很長很長的延遲。在Java方面,這是同樣的問題。證書需要具有完整的CA鏈,因爲驗證是針對鏈進行的。 – 2015-12-03 17:30:57