2012-03-06 119 views
5

我的目標是在Java服務器和用C#編寫的客戶端之間進行安全通信。Java和C#應用程序之間的SSL通信

Java服務器代碼:

System.setProperty("javax.net.ssl.keyStore","cert/mySrvKeystore"); 
    System.setProperty("javax.net.ssl.keyStorePassword","myPassword"); 

    SSLServerSocketFactory sslserversocketfactory = 
      (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); 
    SSLServerSocket sslserversocket = = (SSLServerSocket) sslserversocketfactory.createServerSocket(2389); 

    while(true) { 
    System.err.println("server w8 new connection"); 
    try { 

      SSLSocket sslsocket = (SSLSocket) sslserversocket.accept(); 
      //sslsocket.startHandshake(); 

      in = sslsocket.getInputStream(); 
      out = sslsocket.getOutputStream(); 
      out.flush(); 

      String response = new String(receiveMessage()); 
      while (response != "end") { 
       System.out.println("Server recv="+response); 
       response = new String(receiveMessage()); 
       sendMessage(("echo="+response).getBytes()); 
      } 
     } catch (Exception exception) { 
      exception.printStackTrace(); 
     } 
    } 

和客戶端用C#:

 client = new TcpClient() { SendTimeout = 5000, ReceiveTimeout = 5000 }; 
     IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(host), port); 

     client.Connect(serverEndPoint); 
     client.NoDelay = true; 
     Console.WriteLine("Client connected."); 

     // Create an SSL stream that will close the client's stream. 
     SslStream sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate, null); 
     // The server name must match the name on the server certificate. 
     try 
     { 
      sslStream.AuthenticateAsClient("someName"); 
     } 
     catch (AuthenticationException error) 
     { 
      Console.WriteLine("Exception: {0}", error.Message); 
      if (error.InnerException != null) 
      { 
       Console.WriteLine("Inner exception: {0}", error.InnerException.Message); 
      } 
      Console.WriteLine("Authentication failed - closing the connection."); 
      client.Close(); 
      return; 
     } 

     ASCIIEncoding ascii = new ASCIIEncoding(); 
     SendData(ascii.GetBytes("Hello World"));  

public static bool ValidateServerCertificate(
      object sender, 
      X509Certificate certificate, 
      X509Chain chain, 
      SslPolicyErrors sslPolicyErrors) 
    { 
     if (sslPolicyErrors == SslPolicyErrors.None) 
      return true; 

     Console.WriteLine("Certificate error: {0}", sslPolicyErrors); 

     // Do not allow this client to communicate with unauthenticated servers. 
     return false; 
    } 

,我也得到了以下錯誤:在C#中

A first chance exception of type "System.Security.Authentication.AuthenticationException" occurred in System.dll 
Certificate error: RemoteCertificateChainErrors 
Exception: The remote certificate is invalid according to the validation procedure. 
Authentication failed - closing the connection. 

我知道這個問題可能是因爲我使用不同類型的證書,但我不知道如何在java中使用X509Certificate製作標準sslServerSocket。有人能幫助我,舉個好例子,或者一些建議,我怎麼能達到我的目標?

P.S.我正在尋找bouncycastle庫,使它具有java和c#實現,但我想使用標準庫和語言的內置功能。

+2

啊,[記憶](http://stackoverflow.com/questions/719556/c-sharp-client-connecting-to-a-java-server-over-ssl)。 (我的第一個問題之一) – 2012-03-06 20:12:31

+0

這是有點類似StackOverflow上的另一個問題,但我不能發表評論問題:[x509創建沒有BouncyCastle的證書](http://stackoverflow.com/questions/1615871/created-an-x509-certificate-in-java-without-bouncycastle)這裏是在頁面上找到的鏈接,它描述瞭如何做到這一點:[在Java中創建x509證書](http://bfo.com/博客/ 2011/03/08/odds_and_ends_creating_a_new_x_509_certificate.html) – ry8806 2012-03-06 16:40:22

+0

謝謝,這真的幫助我生成X509證書,但我現在如何將它捆綁到java中的SSLServerSocket? – savionok 2012-03-06 17:10:14

回答

2

在你的例子中,它看起來並不像你需要以編程方式生成證書和私鑰。您可以生成你的服務器密鑰庫與keytool證書:

keytool -genkey -alias myalias -keystore mykeystore.jks -dname "CN=www.example.com" 

或者更好的,與SAN擴展也一樣,如果你使用的是Java 7的keytool

keytool -genkey -alias myalias -keystore mykeystore.jks -dname "CN=www.example.com" -ext san=dns:www.example.com 

這裏,www.example.com是主機客戶看到的名字。您可以在主題DN(dname)中添加其他內容,但請確保CN是主機名。

一旦它的產生,使用導出自簽名證書:

keytool -export myservercert.crt -alias myalias -keystore mykeystore.jks 

然後,您應該能夠導入它作爲從C#使用Windows證書存儲區中受信任的證書。

+0

爲什麼你需要以編程方式生成證書私鑰?誰會信任它? – EJP 2012-03-07 01:14:03

+0

@EJP同意了,這不是很有用。如果你寫一個「MITM代理」(如Fiddler或[Squid的SslBump](http://wiki.squid-cache.org/Features/SslBump)),你可以將代理的CA證書導入瀏覽器,爲請求的主機即時生成新的證書。 – Bruno 2012-03-07 10:45:00

+0

謝謝!導出jks到crt,並在OS中導入這個crt作爲可信證書解決了我的問題! – savionok 2012-03-07 11:54:56

相關問題