为什么我能够使用AES 256Bit解密来解密修改的加密数据

时间:2014-03-14 06:04:43

标签: c# .net encryption cryptography aes

我创建了一个简单的加密和解密程序。我在这个程序中使用AESManaged类。密钥和IV使用Rfc2898DeriveBytes从预定义密码派生。

我测试了我的程序,如下所述:

  1. 将示例文本输入我的程序并捕获加密文本。
  2. 在程序中输入相同的加密文本,经过验证的解密文本与原始文本相同。
  3. 修改了来自步骤2的加密文本中的“=”之前的字母(进入下一个字母)并使用相同的密钥广告IV解密。我收到了原始文本。
  4. 在第3步,我期待程序出错,但它解密了错误的文本。

    有人可以帮助我了解我的程序出了什么问题,以及如何阻止我的程序解密错误的数据。

    这是我的程序输出:

    Please put in input message
    Some Text
    Encrypted text is "xJzgOiMzimNOY6UsB+TNw9gUmcpdiZxQq70FxwbmkCc="
    Please put in encrypted text to decrypt
    xJzgOiMzimNOY6UsB+TNw9gUmcpdiZxQq70FxwbmkCc=
    Decrypted text is "Some Text"
    Please put in encrypted text to decrypt  <<here I have modified "c=" to "d=">>
    xJzgOiMzimNOY6UsB+TNw9gUmcpdiZxQq70FxwbmkCd=
    Decrypted text is "Some Text"
    Enter "Exit" to exit!
    

    AesExample.cs:

    using System;
    using System.IO;
    using System.Security.Cryptography;
    using System.Text;
    
    namespace Aes_Example
    {
        class AesExample
        {
            public static void Main()
            {
                string action, plainText, encryptedText, decryptedText;
    
                Begin:
                Console.WriteLine("Please put in input message");
                plainText = Console.ReadLine();
    
                encryptedText = Encrypt(plainText);
                Console.WriteLine("Encrypted text is \"{0}\"", encryptedText);
    
                Console.WriteLine("Please put in encrypted text to decrypt");
                encryptedText = Console.ReadLine();
    
                decryptedText = Decrypt(encryptedText);
                Console.WriteLine("Decrypted text is \"{0}\"", decryptedText);
    
                Console.WriteLine("Please put in encrypted text to decrypt");
                encryptedText = Console.ReadLine();
    
                decryptedText = Decrypt(encryptedText);
                Console.WriteLine("Decrypted text is \"{0}\"", decryptedText);
    
                Console.WriteLine("Enter \"Exit\" to exit!");
                action = Console.ReadLine();
    
                if (action.ToUpper() != "EXIT") { goto Begin; }
    
            }
            public static string Encrypt(string clearText)
            {
                string EncryptionKey = "TESTPWD@#52";
                byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
    
                using (AesManaged encryptor = new AesManaged())
                {
                    Rfc2898DeriveBytes pdb = new
                        Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                    encryptor.Key = pdb.GetBytes(32);
                    encryptor.IV = pdb.GetBytes(16);
                    using (MemoryStream ms = new MemoryStream())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            cs.Write(clearBytes, 0, clearBytes.Length);
                            cs.Close();
                        }
                        clearText = Convert.ToBase64String(ms.ToArray());
                    }
                }
                return clearText;
            }
            public static string Decrypt(string cipherText)
            {
                string EncryptionKey = "TESTPWD@#52";
                byte[] cipherBytes = Convert.FromBase64String(cipherText);
    
                using (AesManaged encryptor = new AesManaged())
                {
                    Rfc2898DeriveBytes pdb = new
                        Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
                    encryptor.Key = pdb.GetBytes(32);
                    encryptor.IV = pdb.GetBytes(16);
                    using (MemoryStream ms = new MemoryStream())
                    {
                        using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cs.Write(cipherBytes, 0, cipherBytes.Length);
                            cs.Close();
                        }
                        cipherText = Encoding.Unicode.GetString(ms.ToArray());
                    }
                }
                return cipherText;
            }
    
        }
    }
    

2 个答案:

答案 0 :(得分:1)

你的字符串的最后="部分是填充。

甚至不是加密填充,而是Base64填充。

简短版本:

 byte[] data = { 1, 2, 3, 4 };
 clearText = Convert.ToBase64String(data);
 cipherText = clearText.Replace("A==", "B==");  // crude test
 byte[] cipherBytes = Convert.FromBase64String(cipherText);

在此之后,cipherBytes仍为{ 1, 2, 3, 4 }

Base64编码使用6位/ char,因此当你有N个字节时,它将需要(N * 8)/ 6个字符。通常这意味着有一些遗留位,最后一个字符有一些空间可以播放。但只有一点点,只有最后一个字符。

答案 1 :(得分:1)

除了所说的,你需要意识到低级加密和解密只是一点点转换。它不知道输入和输出是什么以及它应该是什么。即如果你加密16个字节,修改第5个字节并解密那16个字节,你将获得与你加密的数据不对应的输出,但你也不会得到错误。

要检测更改,您需要使用某种完整性检查。这通常在高级加密方案(如OpenPGP或CMS)或协议(如SSL / TLS和SSH)中完成。