简体   繁体   English

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

[英]Why am I able to decrypt modified encrypt data using AES 256Bit decryption

I have created a simple program for encryption and decryption. 我创建了一个简单的加密和解密程序。 I am using the AESManaged class in this program. 我在这个程序中使用AESManaged类。 The key and IV are derived from predefined password using Rfc2898DeriveBytes . 密钥和IV是使用Rfc2898DeriveBytes从预定义密码Rfc2898DeriveBytes

I tested my program as explained below: 我测试了我的程序,如下所述:

  1. Inputted sample text into my program and captured encrypted text. 将示例文本输入到我的程序中并捕获加密文本。
  2. Inputted same encrypted text into program and verified decrypted text is same as my original text. 将相同的加密文本输入到程序中并验证的解密文本与我的原始文本相同。
  3. Modified the letter before "=" in the encrypted text from step2 (into next alphabet) and decrypted using same key ad IV. 修改了来自步骤2的加密文本中的“=”之前的字母(进入下一个字母表)并使用相同的密钥广告IV解密。 and I received my original text back. 我收到了我的原始文本。

On step #3 I was expecting an error from the program but it decrypted the wrong text. 在第3步,我期待程序出错,但它解密了错误的文本。

Can some one please help me to understand what is going wrong in my program and how to stop my program from decrypting wrong data. 有人可以帮我理解我的程序出了什么问题,以及如何阻止我的程序解密错误的数据。

Here is my program output: 这是我的程序输出:

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: 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;
        }

    }
}

That last =" part of your string is padding. 那个last ="你的字符串的一部分是填充。

And not even cryptographic padding but Base64 padding. 甚至加密填充,但Base64填充。

The short version: 简短版本:

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

After this, cipherBytes will still be { 1, 2, 3, 4 } 在此之后, cipherBytes仍然是{ 1, 2, 3, 4 }

Base64 encoding uses 6 bits/char, so when you have N bytes it will need (N*8)/6 chars. Base64编码使用6位/字符,所以当你有N个字节时,它将需要(N * 8)/ 6个字符。 Usually this means that there are some left-over bits and the last char has some room to play. 通常这意味着有一些遗留位,最后一个字符有一些空间可以播放。 But only a little and only in the last char. 但只有一点点,只有最后一个字符。

Besides what is said you need to realize that low-level encryption and decryption is just a bit transformation. 除了所说的,你需要意识到低级加密和解密只是一点点转换。 It doesn't know what input and output is and what it should be. 它不知道输入和输出是什么以及它应该是什么。 Ie if you encrypt 16 bytes, modify the 5th byte and decrypt those 16 bytes back, you will get output which doesn't correspond to the data you encrypted, but you won't get an error either. 即如果你加密16个字节,修改第5个字节并解密那16个字节,你将获得与你加密的数据不对应的输出,但你也不会得到错误。

For changes to be detected you need to employ some kind of integrity checking. 要检测更改,您需要使用某种完整性检查。 This is usually done in high-level encryption schemes such as OpenPGP or CMS or protocols like SSL/TLS and SSH. 这通常在高级加密方案(如OpenPGP或CMS)或协议(如SSL / TLS和SSH)中完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM