c# - 为什么我能够使用 AES 256 位解密来解密修改后的加密数据

标签 c# .net encryption cryptography aes

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

我按照下面的说明测试了我的程序:

  1. 将示例文本输入我的程序并捕获加密文本。
  2. 将相同的加密文本输入程序并验证解密文本与我的原始文本相同。
  3. 修改了来自步骤 2 的加密文本中“=”之前的字母(进入下一个字母表)并使用相同的 key AD IV 解密。我收到了我的原始文本。

在第 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;
        }

    }
}

最佳答案

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

甚至不是加密填充,而是 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 位/字符,因此当您有 N 个字节时,它将需要 (N*8)/6 个字符。通常这意味着有一些剩余位,最后一个字符有一些空间可以播放。但只有一点点,而且只在最后一个字符中。

关于c# - 为什么我能够使用 AES 256 位解密来解密修改后的加密数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22397394/

相关文章:

C# 2010 Express - 缺少指针

c# - 如何创建圆形截面?

c# - 如何在 radtreeview 项目中显示多于一张图像(wpf - telerik)

c# - 是否有超过 4 个参数的 Func 对象?

php - 在 MySQL DB 中存储 'sensitive' 数据

c# - 在ContinueWith中使用Wait捕获异常是否可以?

c# - 如果所有单词都包含特定符号,则为正则表达式

c# - DllImport 不工作

javax.crypto.BadPaddingException : Data must start with zero

c++ - 如何解密回 RSA c++ 的字符串值