【问题标题】:Client/server communication with Diffie Hellman Key Exchange and Aes with C#使用 Diffie Hellman 密钥交换和使用 C# 的 Aes 进行客户端/服务器通信
【发布时间】:2020-02-03 22:12:09
【问题描述】:

我需要两个程序与另一个程序通信,通信应该用 aes 加密,我需要用 diffie hellman 密钥交换来做。我有 DiffieHellman 类来生成密钥,并使用加密、解密方法和两个名为 alice 和 bob 的控制台应用程序,当我运行应用程序时会抛出许多异常。这是我第一次使用密码学和套接字,所以我不明白它们是如何工作的,有人能告诉我我做错了什么,我该如何解决?

public class DiffieHellman
{
        private Aes aes = null;
        private ECDiffieHellmanCng diffieHellman = null;
        private readonly byte[] publicKey;

    public DiffieHellman()
    {
        this.aes = new AesCryptoServiceProvider();

        this.diffieHellman = new ECDiffieHellmanCng
        {
            KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash,
            HashAlgorithm = CngAlgorithm.Sha256
        };

        // This is the public key we will send to the other party
        this.publicKey = this.diffieHellman.PublicKey.ToByteArray();
    }

    public byte[] PublicKey
    {
        get
        {
            return this.publicKey;
        }
    }

    public byte[] IV
    {
        get
        {
            return this.aes.IV;
        }
    }

    public byte[] Encrypt(byte[] publicKey, string secretMessage)
    {
        byte[] encryptedMessage;
        var key = CngKey.Import(publicKey, CngKeyBlobFormat.EccPublicBlob);
        var derivedKey = this.diffieHellman.DeriveKeyMaterial(key); // "Common secret"

        this.aes.Key = derivedKey;

        using (var cipherText = new MemoryStream())
        {
            using (var encryptor = this.aes.CreateEncryptor())
            {
                using (var cryptoStream = new CryptoStream(cipherText, encryptor, CryptoStreamMode.Write))
                {
                    byte[] ciphertextMessage = Encoding.UTF8.GetBytes(secretMessage);
                    cryptoStream.Write(ciphertextMessage, 0, ciphertextMessage.Length);
                }
            }

            encryptedMessage = cipherText.ToArray();
        }

        return encryptedMessage;
    }

    public string Decrypt(byte[] publicKey, byte[] encryptedMessage, byte[] iv)
    {
        string decryptedMessage;
        var key = CngKey.Import(publicKey, CngKeyBlobFormat.EccPublicBlob);
        var derivedKey = this.diffieHellman.DeriveKeyMaterial(key);

        this.aes.Key = derivedKey;
        this.aes.IV = iv;

        using (var plainText = new MemoryStream())
        {
            using (var decryptor = this.aes.CreateDecryptor())
            {
                using (var cryptoStream = new CryptoStream(plainText, decryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(encryptedMessage, 0, encryptedMessage.Length);
                }
            }

            decryptedMessage = Encoding.UTF8.GetString(plainText.ToArray());
        }

        return decryptedMessage;
    }
}  


  class Alice
  {
      static void Main(string[] args)
      {

        DiffieHellman dhke = new DiffieHellman();

        while (true)
        {
            TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 13000);
            server.Start();

            Socket s = server.AcceptSocket();

            byte[] encryptedText = new byte[1024];
            int k = s.Receive(encryptedText);
            Console.Write("Friend: ");

            byte[] bobPublicKey = new byte[1024];
            s.Receive(bobPublicKey);

            Console.WriteLine(dhke.Decrypt(bobPublicKey,encryptedText,dhke.IV));

            Console.WriteLine();

            ASCIIEncoding asen = new ASCIIEncoding();
            string message = Console.ReadLine();

            s.Send(dhke.Encrypt(dhke.PublicKey,message));

            s.Close();
            server.Stop();
        }
    }
}


class Bob
{
    static void Main(string[] args)
    {

        DiffieHellman dhke = new DiffieHellman();

        while (true)
        {
            TcpClient tcpClient = new TcpClient();

            tcpClient.Connect("127.0.0.1", 13000);

            String message = Console.ReadLine();
            Stream clientStream = tcpClient.GetStream();

            ASCIIEncoding asen = new ASCIIEncoding();
            byte[] messageBuffer = new byte[1024];
            messageBuffer = dhke.Encrypt(dhke.PublicKey, message);

            clientStream.Write(messageBuffer, 0, messageBuffer.Length);
            clientStream.Write(dhke.PublicKey, 0, dhke.PublicKey.Length);

            byte[] encryptedText = new byte[1024];
            int k = clientStream.Read(encryptedText, 0, encryptedText.Length);

            Console.Write("Friend: ");
            byte[] alicePublicKey = new byte[1024];
            clientStream.Read(alicePublicKey, 0, alicePublicKey.Length);

            Console.WriteLine(dhke.Decrypt(alicePublicKey,encryptedText,dhke.IV));

            Console.WriteLine();
            tcpClient.Close();
        }
    }
}

【问题讨论】:

  • 您是否考虑过使用 SSLStream 并设置密码?
  • @RowanSmith 这是我大学的作业,我必须使用 diffie hellman 作为密钥和任何对称算法进行加密和解密
  • 你遇到了什么异常?它们对你意味着什么?您已经尝试过哪些更改,但无法开始工作?
  • @bartonjs 我发布了一个我修复到现在的答案,我没有任何异常只是一个逻辑问题

标签: c# sockets aes diffie-hellman


【解决方案1】:

到目前为止我修复了很多东西,diffie hellman 密钥交换很好,并且使用 aes 加密/解密,我仍然有一个错误,当我发送文本并在其他程序中解密它时,它会显示一些其他加密字符带有解密的文本。 IV 长度为 16 字节,我将消息长度设置为 32 字节,当我发送小于或等于 16 个字符的文本时,它搞砸了,当我发送大于 16 个字符的文本时,它工作正常。

class DiffieHellman
{
    private Aes aes = null;
    private ECDiffieHellmanCng diffieHellman = null;
    private readonly byte[] publicKey;

    public DiffieHellman()
    {
        this.aes = new AesCryptoServiceProvider();

        this.diffieHellman = new ECDiffieHellmanCng
        {
            KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash,
            HashAlgorithm = CngAlgorithm.Sha256
        };

        // This is the public key we will send to the other party
        this.publicKey = this.diffieHellman.PublicKey.ToByteArray();
    }

    public byte[] PublicKey
    {
        get
        {
            return this.publicKey;
        }
    }

    public byte[] IV
    {
        get
        {
            return this.aes.IV;
        }
    }

    public byte[] Encrypt(byte[] publicKey, string secretMessage)
    {
        byte[] encryptedMessage;
        var key = CngKey.Import(publicKey, CngKeyBlobFormat.EccPublicBlob);
        var derivedKey = this.diffieHellman.DeriveKeyMaterial(key); // "Common secret"

        this.aes.Key = derivedKey;
        this.aes.Padding = PaddingMode.Zeros;

        using (var cipherText = new MemoryStream())
        {
            using (var encryptor = this.aes.CreateEncryptor())
            {
                using (var cryptoStream = new CryptoStream(cipherText, encryptor, CryptoStreamMode.Write))
                {
                    byte[] ciphertextMessage = Encoding.UTF8.GetBytes(secretMessage);
                    cryptoStream.Write(ciphertextMessage, 0, ciphertextMessage.Length);
                }
            }

            encryptedMessage = cipherText.ToArray();
        }

        return encryptedMessage;
    }

    public string Decrypt(byte[] publicKey, byte[] encryptedMessage, byte[] iv)
    {
        string decryptedMessage;
        var key = CngKey.Import(publicKey, CngKeyBlobFormat.EccPublicBlob);
        var derivedKey = this.diffieHellman.DeriveKeyMaterial(key);

        this.aes.Key = derivedKey;
        this.aes.IV = iv;
        this.aes.Padding = PaddingMode.Zeros;

        using (var plainText = new MemoryStream())
        {
            using (var decryptor = this.aes.CreateDecryptor())
            {
                using (var cryptoStream = new CryptoStream(plainText, decryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(encryptedMessage, 0, encryptedMessage.Length);
                }
            }

            decryptedMessage = Encoding.UTF8.GetString(plainText.ToArray());
        }

        return decryptedMessage;
    }
}

class Alice
{
    static void Main(string[] args)
    {

        while (true)
        {
            DiffieHellman dhke = new DiffieHellman();
            ASCIIEncoding asen = new ASCIIEncoding();
            TcpListener server = new TcpListener(IPAddress.Parse("127.0.0.1"), 13000);
            server.Start();

            Socket s = server.AcceptSocket();

            byte[] bobPublicKey = new byte[140];
            byte[] bobIV = new byte[16];

            s.Send(dhke.PublicKey);

            s.Receive(bobPublicKey);

            s.Receive(bobIV);

            byte[] acceptedMessage = new byte[32];

            s.Receive(acceptedMessage);

            System.Threading.Thread.Sleep(1000);
            Console.WriteLine("Mesazhi qe vjen i enkriptuar " + asen.GetString(acceptedMessage));
            Console.WriteLine();
            string decryptedMessage = dhke.Decrypt(bobPublicKey, acceptedMessage, bobIV);
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write("Friend: ");
            Console.WriteLine(decryptedMessage);
            Console.WriteLine();
            Console.ForegroundColor = ConsoleColor.Red;

            string mesazhi = Console.ReadLine();
            byte[] encryptedMessage = dhke.Encrypt(bobPublicKey, mesazhi);
            Console.ResetColor();
            Console.WriteLine();
            Console.WriteLine("Mesazhi qe dergohet i enkriptuar " + asen.GetString(encryptedMessage));
            Console.WriteLine();

            s.Send(encryptedMessage);

            s.Send(dhke.IV);

            s.Close();
            server.Stop();
        }
    }
}

class Bob
{
    static void Main(string[] args)
    {
        while (true)
        {
            DiffieHellman dhke = new DiffieHellman();
            ASCIIEncoding asen = new ASCIIEncoding();
            TcpClient tcpClient = new TcpClient();
            tcpClient.Connect("127.0.0.1", 13000);
            Stream stream = tcpClient.GetStream();
            byte[] alicePublicKey = new byte[140];

            stream.Read(alicePublicKey, 0, alicePublicKey.Length);

            stream.Write(dhke.PublicKey, 0, dhke.PublicKey.Length);

            stream.Write(dhke.IV, 0, dhke.IV.Length);

            Console.ForegroundColor = ConsoleColor.Red;
            String message = Console.ReadLine();  //Shkruaj mesazhin
            byte[] encryptedMessage = dhke.Encrypt(alicePublicKey, message);
            Console.ResetColor();
            Console.WriteLine();
            Console.WriteLine("Mesazhi qe dergohet i enkriptuar " + asen.GetString(encryptedMessage));
            Console.WriteLine();

            stream.Write(encryptedMessage, 0, encryptedMessage.Length);

            byte[] acceptedMessage = new byte[32];

            byte[] aliceIV = new byte[16];

            stream.Read(acceptedMessage, 0, acceptedMessage.Length);
            stream.Read(aliceIV, 0, aliceIV.Length);

            Console.WriteLine("Mesazhi qe vjen i enkriptuar " + asen.GetString(acceptedMessage));
            Console.WriteLine();
            string decryptedMessage = dhke.Decrypt(alicePublicKey, acceptedMessage, aliceIV);
            Console.ForegroundColor = ConsoleColor.Green;
            System.Threading.Thread.Sleep(1000);
            Console.Write("Friend: ");
            Console.WriteLine(decryptedMessage);
            Console.WriteLine();
            tcpClient.Close();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 2014-09-22
    • 1970-01-01
    • 2018-06-10
    相关资源
    最近更新 更多