AshOoO
AshOoO

Reputation: 1148

Unrecognized unicode result from AES decryption

I try to build simple AES encryption helper to encrypt/decrypt some strings Fist, I have an issue with Padding mode wherein decryption it only accepts if Zero otherwise an error about padding occurs! The second issue is when I try to encrypt simple string "Hello World," it got encrypted, and I have the base64 string, but when trying to decrypt, there's no error, but a weird unknown character is shown! like 㡲啁䎰廾ử靱힩㡲啁䎰廾ử靱힩 My code:

        private static int keySizes = 256;
        private static int blockSize = 128;
        private static PaddingMode pMode = PaddingMode.Zeros;
        private static CipherMode cMode = CipherMode.ECB;
        private static byte[] key = GenEncryptionKey();
        private const string passphrase = @"StartYourMorningWithASmile";

    private static byte[] GenEncryptionKey()
    {
        HashAlgorithm hash = MD5.Create();
        return hash.ComputeHash(Encoding.Unicode.GetBytes(passphrase));
    }

    private static AesManaged CreateCryptor()
    {
        AesManaged cryptor = new AesManaged();
        cryptor.KeySize = keySizes;
        cryptor.BlockSize = blockSize;
        cryptor.Padding = pMode;
        cryptor.Key = key;
        cryptor.Mode = cMode;
        cryptor.GenerateIV();
        return cryptor;
    }
public static string EncryptParams(string reqVal)
        {
            string cipherText = "";

            if (string.IsNullOrEmpty(reqVal) || reqVal.Length < 1)
                throw new ArgumentNullException();
            byte[] plainBytes = Encoding.Unicode.GetBytes(reqVal);

            using (var cryptor = CreateCryptor())
            {
                ICryptoTransform encryptor = cryptor.CreateEncryptor();
                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                    {
                        cs.Write(plainBytes, 0, plainBytes.Length);

                    }
                    byte[] cipherBytes = ms.ToArray();
                    cipherText = Convert.ToBase64String(cipherBytes);
                }
                cryptor.Clear();
            }
            return cipherText;

        }



        public static string DecryptParams(string resVal)
        {
            var data = Convert.FromBase64String(resVal);
            byte[] cipherBytes = new byte[data.Length];
            string plainText = "";

            using (var crypto = CreateCryptor())
            {


                ICryptoTransform Dec = crypto.CreateDecryptor();
                using (MemoryStream ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Write))
                    {
                        cs.Write(cipherBytes, 0, cipherBytes.Length);
                        plainText = Encoding.Unicode.GetString(ms.ToArray());
                    }
                }
                crypto.Clear();
            }

            return plainText;
        }

Upvotes: 1

Views: 917

Answers (2)

AshOoO
AshOoO

Reputation: 1148

Thanks to Oguz

Below is my description method after edit

public static string DecryptParams(string resVal)
        {
            var data = Convert.FromBase64String(resVal);
            byte[] cipherBytes = new byte[data.Length];
            string plainText = "";

            using (var crypto = CreateCryptor())
            {  
                ICryptoTransform Dec = crypto.CreateDecryptor();
                using (MemoryStream ms = new MemoryStream(data))
                {
                    using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
                    {
                        cs.Read(cipherBytes, 0, cipherBytes.Length);
                        plainText = Encoding.Unicode.GetString(cipherBytes.ToArray());
                    }
                }
                crypto.Clear();
            }

            return plainText;
        }

one more thing about the return result after the decryption I got the original string plus \0\0\0\0 so I use myString.TrimEnd('\0') to solve that.

Upvotes: 0

Oguz Ozgul
Oguz Ozgul

Reputation: 7187

UPDATE 1:

Please set also the IV yourself to achieve successful decryption, as @maarten-bodewes pointed out. I missed that part and the decryption somehow worked (?) with your existing code, but you always should provide the same key and IV to a symmetric encryption algorithm to have it work both ways.

ORIGINAL ANSWER:

Your decryption fails (produces incorrect results) because you implemented the decryption part incorrectly (by using CryptoStreamMode.Write instead of CryptoStreamMode.Read) and besides feeding the decryption stream all zero bytes

At the point of execution of

cs.Write(cipherBytes, 0, cipherBytes.Length);

the variable cipherBytes is all zero. The real encrypted buffer is in the data variable which you only use to set the length of cipherBytes

So change your decryption method to this.

BONUS: After correcting the decryption part, you can specify the padding as you wish! I tested with PKCS7 and it is ok.

public static string DecryptParams(string resVal)
{
    var cipherBytes = Convert.FromBase64String(resVal);
    string plainText = "";

    using (var crypto = CreateCryptor())
    {
        ICryptoTransform Dec = crypto.CreateDecryptor();
        using (MemoryStream ms = new MemoryStream(cipherBytes))
        {
            using (var cs = new CryptoStream(ms, Dec, CryptoStreamMode.Read))
            {
                byte[] decryptBlock = new byte[4096];
                MemoryStream decryptStream = new MemoryStream();
                int readBytes;
                while ((readBytes = cs.Read(decryptBlock, 0, 4096)) > 0)
                {
                    decryptStream.Write(decryptBlock, 0, readBytes);
                }
                plainText = Encoding.Unicode.GetString(decryptStream.ToArray());
            }
        }
        crypto.Clear();
    }

    return plainText;
}

Hope this helps.

Upvotes: 2

Related Questions