[英]SSL Socket between .Net and Java with client authentication
我正在嘗試在.NET和Java之間創建一個SSL套接字服務器/客戶端。 在這種情況下,我的SSL套接字服務器將在.net中運行,客戶端在Linux下以Java運行。 我的問題是握手期間連接失敗,特別是當服務器從客戶端請求證書時,客戶端無法發送回來的東西,連接失敗。
在.net中我使用sslStream建立連接,在Java上我使用的是標准的SSLSocket。 下面是一些代碼片段,但這是我到目前為止的內容:
在服務器端(Windows),我在MMC下的Personal / Certificates文件夾中有一個私有證書。 我在“受信任的人/證書”中擁有來自客戶的公共證書。 兩個證書都是由同一個CA頒發的。 兩個證書的證書鏈都有多個級別,但兩者都相同。 鏈中的根級證書也安裝在受信任的證書頒發機構/證書文件夾中。
在客戶端(Linux),我有一個密鑰庫,其中包含與服務器上安裝的公共證書匹配的私有證書。 我有一個信任存儲,它包含來自服務器的公共證書,與服務器的私有證書匹配。
在服務器端(.net)我使用的是一個執行異步讀取的Socket,然后它被包裝到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中,我設置了適當的varialbes以指向信任和密鑰存儲區及其密碼。
現在,遵循標准SSL握手,這是發生的事情:
就是這樣,客戶端不會將有效證書發送回服務器。 我對此有一些疑問:
有沒有人經歷過這樣的事情? 關於服務器發送的CA列表(Windows),.net如何確定要發送給客戶端的內容? 有沒有辦法修改該列表? 我是否需要發送用於在CA列表中簽署證書的鏈中的所有權限? 或根夠了嗎?
我在代碼的兩邊都遺漏了什么嗎?
任何幫助將不勝感激。 在
以下兩個語句在客戶端是無用的(盡管它們不應該受到傷害):
socket.setNeedClientAuth(true);
socket.setWantClientAuth(true);
您看到證書請求消息和客戶端證書消息的事實表明服務器配置正確。
在客戶端證書消息中缺少證書的最可能原因是密鑰庫(在客戶端)可能未正確配置。 您可能對此答案感興趣,以確保正確配置了客戶端密鑰庫。 更具體地說,您需要確保將客戶端證書的私鑰導入到與證書鏈相同的別名中(並且它是鏈回到證書請求消息中公布的CA)。
(關於你的其余問題,我不確定在C#中使用SslStream
時如何修改服務器發送的CA列表。 這個早期的問題似乎表明沒有解決方案,盡管.Net的新版本可能有地址自問這個問題以來的問題。通過查看SslStream
API文檔和相關類,我找不到任何可以做到的事情,但這並不意味着它不存在。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.