1

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;
    }
Community
  • 1
  • 1
A.Goutam
  • 3,422
  • 9
  • 42
  • 90
  • You are hashing the password when you decrypt `passwordBytes = SHA256.Create().ComputeHash(passwordBytes);`, but not when encrypt – pedrofb Mar 08 '17 at 09:21
  • @pedrofb what i need to do when i Decrypt – A.Goutam Mar 08 '17 at 09:22
  • @pedrofb thanks i removed that line and now it works . Thanks – A.Goutam Mar 08 '17 at 09:26
  • happy to help!. I posted it as an answer – pedrofb Mar 08 '17 at 09:31
  • 1
    Just using a hash function is not sufficient and just adding a salt does little to improve the security. Instead iIterate over an HMAC with a random salt for about a 100ms duration and save the salt with the hash. Use functions such as `PBKDF2`, `password_hash`, `Bcrypt` and similar functions. The point is to make the attacker spend a lot of time finding passwords by brute force. – zaph Mar 08 '17 at 12:38
  • 1
    **Never use [ECB mode](http://crypto.stackexchange.com/q/14487/13022)**. It's deterministic and therefore not semantically secure. You should at the very least use a randomized mode like [CBC](http://crypto.stackexchange.com/q/22260/13022) or [CTR](http://crypto.stackexchange.com/a/2378/13022). It is better to authenticate your ciphertexts so that attacks like a [padding oracle attack](http://crypto.stackexchange.com/q/18185/13022) are not possible. This can be done with authenticated modes like GCM or EAX, or with an [encrypt-then-MAC](http://crypto.stackexchange.com/q/202/13022) scheme. – Artjom B. Mar 08 '17 at 19:30

2 Answers2

3

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.

bartonjs
  • 30,352
  • 2
  • 71
  • 111
1

You are hashing the password when you decrypt,

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

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

pedrofb
  • 37,271
  • 5
  • 94
  • 142