简体   繁体   中英

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. The key and IV are derived from predefined password using 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. and I received my original text back.

On step #3 I was expecting an error from the program but it decrypted the wrong text.

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:

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.

And not even cryptographic padding but Base64 padding.

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 }

Base64 encoding uses 6 bits/char, so when you have N bytes it will need (N*8)/6 chars. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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