temz 2023-03-19 13:57 采纳率: 100%
浏览 111
已结题

C# 客户端 与 java 服务端做SSL通信报错

C# 客户端 与 java 服务端做SSL通信
java报错:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: no cipher suites in common

C#报错 :

System.Security.Authentication.AuthenticationException

java的server.jks是用的keytool生成的
C#的client.pfx也是用keytool生成并用keytool转换为pfx文件的
哪个牛人给看看怎么弄,似乎是加密的问题

java代码

 import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.security.KeyStore;
    import java.security.Security;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLServerSocketFactory;
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.TrustManagerFactory;
    import com.google.gson.Gson;
     
    public class Server {
        public static void main(String[] args) throws Exception {
            // Set up key manager to do server authentication
            char[] passphrase = "123456".toCharArray();
            KeyStore ks = KeyStore.getInstance("JKS");
            ks.load(Server.class.getResourceAsStream("e:/server.jks"), passphrase);
     
            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
            kmf.init(ks, passphrase);
     
            // Set up trust manager to do client authentication
            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
            tmf.init(ks);
     
            // Set up SSL context
            SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
            SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
     
            // Start server
            ServerSocket serverSocket = sslServerSocketFactory.createServerSocket(8080);
     
            System.out.println("Server started on port 8080");
            
           // Gson gson = new Gson();
           // String s = gson.toJson(ob);
            while (true) {
                // Accept client connections
                SSLSocket socket = (SSLSocket) serverSocket.accept();
                InetAddress address =socket.getInetAddress();
                
                System.out.println("Client connected: " + address.getHostAddress());
     
                BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
     
                // Receive message from client
                String message = reader.readLine();
                System.out.println("Message received: " + message);
     
                // Send message back to client
                writer.println("Message received: " + message);
                writer.flush();
     
                socket.close();
                System.out.println("Client disconnected: " + socket.getInetAddress());
            }
        }
    }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace sslsocket1
{
    internal class SSLClient
    {
        public static void Main(string[] args)
        {
            int port = 8080;

            // 创建 SSL 证书集合
            X509CertificateCollection certCollection = new X509CertificateCollection();
            certCollection.Add(new X509Certificate2("E:\\client.pfx", "123456"));

            // 创建 SSL 流
            TcpClient client = new TcpClient("localhost", port);
            SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

            try 
            {
                // 客户端认证
                sslStream.AuthenticateAsClient("localhost", certCollection, SslProtocols.Tls12, false);
                Console.WriteLine("客户端已连接服务器");
            }
            catch (AuthenticationException e) 
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                client.Close();
                return;

            }

           

            // 向服务器发送消息
            string message = "你好,服务器!";
            byte[] messageBytes = Encoding.UTF8.GetBytes(message);
            sslStream.Write(messageBytes);
            sslStream.Flush();

            Console.WriteLine("已向服务器发送消息:" + message);

            // 接收服务器的响应消息
            byte[] buffer = new byte[2048];
            int bytesRead;

            while ((bytesRead = sslStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                Console.WriteLine("接收到服务器的响应消息:" + response);
            }
            
            // 关闭 SSL 流和客户端 socket
            sslStream.Close();
            client.Close();
        }

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

            Console.WriteLine("SSL 证书验证失败:" + sslPolicyErrors);
            return false;
        }

    }
}


  • 写回答

7条回答 默认 最新

  • dahe0825 2023-03-19 16:31
    关注

    参考GPT和自己的思路,这个错误提示说明在 SSL 握手阶段,服务端和客户端无法协商出一组共同的加密算法。这个问题可能是由于以下原因导致的:

    1.服务端和客户端协议版本不兼容。可以尝试使用更高或更低版本的 TLS/SSL 协议,看看是否能够解决问题。例如,尝试使用 TLSv1.0,TLSv1.1 或 TLSv1.3 协议。

    2.服务端和客户端支持的加密算法不同。可以在服务端和客户端的 SSL/TLS 配置中检查并确保它们支持相同的加密算法。例如,在服务端配置中添加支持客户端需要的加密算法。

    3.证书不匹配。可以检查证书链是否正确并确保证书是有效的。

    针对你的代码,你可以尝试在 Java 服务端代码中明确指定使用 TLSv1.2 协议,并且指定一组加密算法,例如:

    String[] enabledCipherSuites = { "TLS_RSA_WITH_AES_128_CBC_SHA256" };
    sslContext.getServerSocketFactory().setEnabledCipherSuites(enabledCipherSuites);
    SSLServerSocket sslServerSocket = (SSLServerSocket)sslServerSocketFactory.createServerSocket(8080);
    sslServerSocket.setEnabledCipherSuites(enabledCipherSuites);
    

    同时,在 C# 客户端代码中,也需要指定相同的加密算法,例如:

    SslProtocols enabledProtocols = SslProtocols.Tls12;
    string targetHost = "localhost";
    SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
    sslStream.AuthenticateAsClient(targetHost, null, enabledProtocols, false);
    sslStream.CipherAlgorithm = CipherAlgorithmType.Aes128;
    sslStream.HashAlgorithm = HashAlgorithmType.Sha256;
    

    这样做应该能够解决你遇到的问题。如果问题仍然存在,请尝试检查证书链是否正确,并确保证书是有效的。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月27日
  • 已采纳回答 3月24日
  • 创建了问题 3月19日

悬赏问题

  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题