簡體   English   中英

使用 C# 與 Diffie Hellman 密鑰交換和 Aes 進行客戶端/服務器通信

[英]Client/server communication with Diffie Hellman Key Exchange and Aes with C#

我需要兩個程序來相互通信,通信應該用 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();
        }
    }
}

到目前為止,我修復了很多問題,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();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM