Search code examples
c#encryptionaesencryption-symmetric

AES decrypted message not matching the original message


I am trying to Encrypt and Decrypt a string using AES256. But The decrypted string is not matching the original one. I am not sure, but maybe I am getting the Encoding part wrong.

I am using CSPRNG to generate the IV and PBDKF2 for generating a Key to be used for AES Encryption

Program.cs:

using System;
using System.Text;

namespace AESEncryptionUtility
{
    class Program
    {
        private static string _pass = "MasterPass";
        private static string _msg = "Mohit";
        private static byte[] key = EncryptionUtility.GenerateKey(_pass, 32);
        private static byte[] IV = EncryptionUtility.GenerateSalt(16);
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            byte[] encrypted = Encrypt(_msg);
            byte[] decrypted = Decrypt(Encoding.ASCII.GetString(encrypted));
        }

        public static byte[] Encrypt(string msg)
        {
            byte[] asciiBytesOriginal = Encoding.ASCII.GetBytes(_msg);
            byte[] encrypted = EncryptionUtility.Encrypt(asciiBytesOriginal, key, IV);
            Console.WriteLine("encrypted started");
            foreach(var b in encrypted)
            {
                Console.Write(b + " ");
            }
            Console.WriteLine("\nencrypted ended");
            return encrypted;
        }

        public static byte[] Decrypt(string cipher)
        {
            byte[] asciiBytes = Encoding.ASCII.GetBytes(cipher);
            byte[] originalBytes = EncryptionUtility.Decrypt(asciiBytes, key, IV);
            Console.WriteLine("decrypted started");
            foreach(var b in originalBytes)
            {
                Console.Write(b + " ");
            }
            Console.WriteLine("\ndecrypted ended");
            string original = Encoding.ASCII.GetString(originalBytes);
            Console.WriteLine("original string: " + original);
            return originalBytes;
        }
    }
}

EncryptionUtility.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace AESEncryptionUtility
{
    public static class EncryptionUtility
    {
        public static byte[] Encrypt(byte[] plainBytes, byte[] key, byte[] IV)
        {
            byte[] encrypted = null;
            using (AesCryptoServiceProvider aesAlgo = new AesCryptoServiceProvider())
            {
                aesAlgo.Key = key;
                aesAlgo.BlockSize = 128;
                aesAlgo.Mode = CipherMode.CBC;
                //aesAlgo.Padding = PaddingMode.PKCS7;
                aesAlgo.Padding = PaddingMode.Zeros;
                aesAlgo.IV = IV;
                ICryptoTransform encryptor = aesAlgo.CreateEncryptor();
                encrypted = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);

            }
            return encrypted;
        }

        public static byte[] Decrypt(byte[] cipherBytes, byte[] key, byte[] IV)
        {
            byte[] decrypted = null;
            using (AesCryptoServiceProvider aesAlgo = new AesCryptoServiceProvider())
            {
                aesAlgo.Key = key;
                aesAlgo.BlockSize = 128;
                aesAlgo.Mode = CipherMode.CBC;
                //aesAlgo.Padding = PaddingMode.PKCS7;
                aesAlgo.Padding = PaddingMode.Zeros;
                aesAlgo.IV = IV;
                ICryptoTransform decryptor = aesAlgo.CreateDecryptor();
                decrypted = decryptor.TransformFinalBlock(cipherBytes, 0, cipherBytes.Length);
            }
            return decrypted;

        }
        public static byte[] GenerateKey(string masterPassword, int size) //size in bytes
        {
            byte[] salt = GenerateSalt(size);
            Rfc2898DeriveBytes pbfdk = new Rfc2898DeriveBytes(masterPassword, salt, 20000);
            return pbfdk.GetBytes(size);

        }

        public static byte[] GenerateSalt(int size) //size in bytes
        {
            RNGCryptoServiceProvider generator = new RNGCryptoServiceProvider();
            byte[] salt = new byte[size];
            generator.GetNonZeroBytes(salt);
            return salt;
        }

    }
}

Solution

  • You can't convert arbitrary binary data to a string:

    byte[] decrypted = Decrypt(Encoding.ASCII.GetString(encrypted));
    

    And expect it to, just by chance, make sense as the particular character encoding you have chosen. It doesn't work that way. Encryption algorithms operate on bytes, not strings. If you change the following, your code will work:

    ...
    public static byte[] Decrypt(byte[] cipher)
    {
        byte[] asciiBytes = cipher;
        ...