A.Goutam
A.Goutam

Reputation: 3494

padding is invalid and cannot be removed decrypt value

Hello I want to encrypt and Decrypt Text . My encrypt code is working fine and matching the value that i want. But when i want Decrypt this is giving error padding is invalid and cannot be removed . In below code first i am giving my Encrypt and Decrypt both code. Also i have to fix this error Stack overflow link, StackoverlFlow Link 2 but not fix it .

string getHashKey1 = EncryptText("10002:1486703720424", "hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF");

Result = 1ltQFLRGNif73uCNzi0YEvBqLKiRgx6fWsk5e/GcTQc=

 string reverseKey = DecryptText('1ltQFLRGNif73uCNzi0YEvBqLKiRgx6fWsk5e/GcTQc=', "hpIw4SgN)TxJdoQj=GKo)p83$uHePgoF");

When i add in AES_Decrypt aes.Padding = PaddingMode.Zeros; i get below result. Result : -����y�7�t���Ij���,���� Z��$�

public string EncryptText(string input, string password)
    {
        string result = "";
        try
        {
            // Get the bytes of the string
            byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
            byte[] passwordBytes = Encoding.UTF8.GetBytes(password);

            byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);

             result = Convert.ToBase64String(bytesEncrypted);
            return result;
        }
        catch (Exception ex)
        {

        }

        return result;
    }

public byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
    {
        byte[] encryptedBytes = null;
        try
        {     
            using (MemoryStream ms = new MemoryStream())
            {
                using (Aes aes = Aes.Create())
                {
                    aes.Key = passwordBytes;
                    aes.Mode = CipherMode.ECB;

                    // "zero" IV
                    aes.IV = new byte[16];

                    using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                        cs.Close();
                    }
                    encryptedBytes = ms.ToArray();
                }
            }
        }
        catch (Exception ex)
        {

        }            
        return encryptedBytes;
    }

Above code is working fine for encrypt . Below code is giving error padding is invalid and cannot be removed

 public string DecryptText(string input, string password)
    {
        // Get the bytes of the string
        byte[] bytesToBeDecrypted = Convert.FromBase64String(input);
        byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
        passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

        byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);

        string result = Encoding.UTF8.GetString(bytesDecrypted);

        return result;
    }


 public byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
    {
        byte[] decryptedBytes = null;

        using (MemoryStream ms = new MemoryStream())
        {
            using (Aes aes = Aes.Create())
            {
                aes.Key = passwordBytes;
                aes.Mode = CipherMode.ECB;
                aes.IV = new byte[16];                  

                using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                    cs.Close();  // here i am getting error 
                }
                decryptedBytes = ms.ToArray();
            }
        }

        return decryptedBytes;
    }

Upvotes: 1

Views: 443

Answers (2)

bartonjs
bartonjs

Reputation: 33178

You have two problems:

1) (Already pointed out by pedrofb): You use UTF8.GetBytes in encrypt, but SHA256(UTF8.GetBytes()) in decrypt.

You shouldn't do either of these methods, but instead should use a proper Password-Based Key-Derivation Function, such as PBKDF2. In .NET PBKDF2 is available via the Rfc2898DeriveBytes class.

byte[] salt = 8 or more bytes that you always pass in as the same.
// (salt could be fixed for your application,
// but if you have users it should be unique per user and stored along with the output value)
int iterations = 100000;
// Or bigger. If you were making a user management system you
// should write this number down, too, so you can increase it over time;
// it should be whatever number makes it take 100ms or more on the fastest relevant computer)
Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt, iterations);
passwordBytes = pbkdf2.GetBytes(16); // 16 = AES128, 24 = AES192, 32 = AES256.

2) You use Base64-encoding in encrypt, but UTF8.GetBytes in decrypt.

Bonus problems:

3) You are using Electronic Codebook (ECB) chaining. Cipher Block Chaining (CBC) is recommended over ECB.

To use CBC properly, let a random initialization vector (IV) be generated in encrypt (which is done automatically when you create a new Aes object, or you can call GenerateIV() in encrypt if you re-use the object). Then you can just prepend the IV (which will always be 16 bytes for AES) to the ciphertext. In decrypt you can either a) chop off the first 16 bytes and assign it as the IV (then decrypt the rest of the data) or b) decrypt the whole blob and ignore the first 16 bytes of decrypted output.

Upvotes: 3

pedrofb
pedrofb

Reputation: 39271

You are hashing the password when you decrypt,

passwordBytes = SHA256.Create().ComputeHash(passwordBytes);

but not when encrypt. This means you are using different passwords

Upvotes: 1

Related Questions