1

I am trying to make an encrypt/decrypt program in C# via AES. Here's my code:

using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Security.Cryptography;

namespace encryptingApp
{
    public class AES_Crypt
    {
        public static void Main ()
        {
            string text = "this-needs-to-be-encrypted";

            string IV = "0000000000000000";

            int ivBlockSize = 16;

            string key = "00000000000000000000000000000000";

            int keySize = 32;

            string encriptedText = Encrypt(text,key,IV);

            string decrypted = Decrypt(encriptedText, key, ivBlockSize);

        }


        public static string Encrypt(string clearText, string key, string iv )
        {

            byte[] textBytes=GetBytes(clearText);


            using (Aes encryptor = Aes.Create())
            {
                encryptor.IV =  GetBytes(iv);
                encryptor.Key = GetBytes(key);

                using (MemoryStream ms = new MemoryStream())
                {

                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(encryptor.Key,encryptor.IV), CryptoStreamMode.Write))
                    {
                        cs.Write(textBytes, 0, textBytes.Length);
                        cs.Close();
                    }
                    string rv= iv + ByteToHex(ms.ToArray()).ToLower();

                    clearText = Base64Encode(rv);
                }
            }
            return clearText;
        }



       public static string Decrypt(string encriptedText, string key, int ivBlockSize)
       {
           string decryptedText = null;

           string fullText=Base64Decode(encriptedText);

           string realIV = fullText.Substring( 0 , ivBlockSize );

           string cypherText = fullText.Substring(ivBlockSize, fullText.Length - ivBlockSize - 1);


            byte[] cypherTextInBytes = HexToByte(cypherText);

            using (Aes decryptor = Aes.Create())
            {     
                decryptor.Key = GetBytes(key);

                decryptor.IV = GetBytes(realIV);

                decryptor.Mode = CipherMode.CBC;  

                using (MemoryStream ms = new MemoryStream())
                {
                    using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(decryptor.Key,decryptor.IV), CryptoStreamMode.Read))
                    {
                        using (var sr = new StreamReader(cs))
                        {
                            decryptedText = sr.ReadToEnd();
                        }

                    }

                }
            }
            return decryptedText;
        }

        static byte[] GetBytes(string str)
        {
            return System.Text.Encoding.UTF8.GetBytes(str);
        }

        static string GetString(byte[] bytes)
        {
            return System.Text.Encoding.UTF8.GetString(bytes);
        }

        public static string Base64Encode(string plainText)
        {
                var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
                return System.Convert.ToBase64String(plainTextBytes);
        }

        public static string Base64Decode(string base64EncodedData)
        {
            var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
            return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
        }

        public static string ByteToHex(byte[] ba)
        {
            return BitConverter.ToString(ba).Replace("-", "").ToLower();
        }


        public static byte[] HexToByte(string hex)
        {

            byte[] arr = new byte[hex.Length >> 1];

            for (int i = 0; i < hex.Length >> 1; ++i)
            {
                arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
            }

            return arr;
        }

        public static int GetHexVal(char hex) 
        {
            int val = (int) hex;
            return val - (val < 58 ? 48 : 87);
        }


    }
}

The Encrypt function does his job very well and returns me the correct encrypted text. The problem exists in the Decrypt function, everything goes well (I've been printing my vars on the screen) until the StreamReader uses .ReadToEnd(). I get a CryptographyException (i get the same exception twice in only one exectuion):

Unhandled Exception:
System.Security.Cryptography.CryptographicException: Bad PKCS7 padding. Invalid length 0.        
at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (System.Security.Cryptography.PaddingMode padding, System.Int32 length, System.Int32 position) [0x0005c] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00179] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00034] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.Security.Cryptography.CryptoStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 count) [0x00318] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.StreamReader.ReadBuffer () [0x0002b] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.StreamReader.ReadToEnd () [0x00055] in <8f2c484307284b51944a1a13a14c0266>:0 
at encryptingApp.AES_Crypt.Decrypt (System.String encriptedText, System.String key, System.Int32 ivBlockSize) [0x000e4] in <f27b48dde1ea4b788e8038439b4bdb55>:0 
at encryptingApp.AES_Crypt.Main () [0x000e0] in <f27b48dde1ea4b788e8038439b4bdb55>:0


[ERROR] FATAL UNHANDLED EXCEPTION: System.Security.Cryptography.CryptographicException: Bad PKCS7 padding. Invalid length 0.    
at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (System.Security.Cryptography.PaddingMode padding, System.Int32 length, System.Int32 position) [0x0005c] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00179] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00034] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.Security.Cryptography.CryptoStream.FlushFinalBlock () [0x0001b] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.Security.Cryptography.CryptoStream.Dispose (System.Boolean disposing) [0x00011] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.Stream.Close () [0x00000] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.StreamReader.Dispose (System.Boolean disposing) [0x0001c] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.TextReader.Dispose () [0x00000] in <8f2c484307284b51944a1a13a14c0266>:0 
at encryptingApp.AES_Crypt.Decrypt (System.String encriptedText, System.String key, System.Int32 ivBlockSize) [0x000f8] in <f27b48dde1ea4b788e8038439b4bdb55>:0 
at encryptingApp.AES_Crypt.Main () [0x000e0] in <f27b48dde1ea4b788e8038439b4bdb55>:0

I think I should fix the Streamreader, but I don't know what to do, I've been here for hours! It seems that the program is trying to read something that has 0-length or something.

I even tried looking for more decrypting functions over the internet but none of them works for me (I'm doing this without RijndaelManaged nor salts). Im compiling in MacOS.

  • A bad padding error can also be caused by incorrect decryption. For debugging try decrypting without PKCS#7 padding and examine the result to see if it is decrypted correctly to avoid the padding error, it probably isn't. – zaph Dec 05 '16 at 13:09
  • But I didn't choose to decrypt with PKCS7. Do you know how do I disable it? – Gerardo Reichl Dec 05 '16 at 13:21
  • Read the documentation and dig down to the defaults. Note that without padding encryption is limited to input that has a length that is an exact multiple of the block size so padding is generally required. – zaph Dec 05 '16 at 13:38
  • Possible duplicate of [Bad PKCS7 Padding error: Invalid length 106](http://stackoverflow.com/questions/23824020/bad-pkcs7-padding-error-invalid-length-106) – huse.ckr Dec 05 '16 at 13:40
  • Zaph is right. Note that each possible plaintext block maps to one ciphertext block and therefore one ciphertext block maps to exactly one plaintext block. Decryption therefore won't fail until you have a bad padding exception (or it may not even fail at all, while still producing the wrong result, if the padding is correct by sheer luck). – Maarten Bodewes Dec 05 '16 at 14:10
  • I will try to specify the Padding or to make sure I'm using the correct one. – Gerardo Reichl Dec 05 '16 at 14:19

1 Answers1

0

Why are there so many strings in your code? Cryptography works on bytes, get rid of all the strings.

  • Your IV (which should ideally be generated/emitted by Encrypt, not passed in to it) is read as a UTF-8 string. If it had any characters that wasn't in ASCII 0-127 it would not have a 1:1 string length to byte[] length.
    • It's also really hard for you to provide a string with the iv 0x00000000000000000000000000000003
  • Similar for your key.
  • You are emitting as the IV+Ciphertext blob Base64Encode(UTF8Bytes(Concat(ivString, Hex(ciphertextBytes)))).
    • Base64Encode(Concat(ivBytes, ciphertextBytes)) involves two fewer transforms. So it's less error-prone, and faster.
  • When you get into Decrypt you do apply all the transforms correctly to undo what you've done, but you need to know externally how many characters make up the IV. Since you've added UTF8 processing into the mix you don't actually know it.
    • So your Decrypt IV gets the following treatment
      • Base64Decode
      • UTF8BytesToString
      • Substring
      • UTF8StringToBytes
    • If there were no strings involved you'd just have Base64Decode and Copy.

My gut feeling is that if you just treat everything as byte[] your problems will go away. (Yes, your data to protect can be text, so hitting it with UTF8StringToBytes right off the bat is good)

bartonjs
  • 30,352
  • 2
  • 71
  • 111