Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a bad password cause "Padding is invalid and cannot be removed"?

I needed some simple string encryption, so I wrote the following code (with a great deal of "inspiration" from here):

    // create and initialize a crypto algorithm     private static SymmetricAlgorithm getAlgorithm(string password) {         SymmetricAlgorithm algorithm = Rijndael.Create();         Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(             password, new byte[] {             0x53,0x6f,0x64,0x69,0x75,0x6d,0x20,             // salty goodness             0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65         }         );         algorithm.Padding = PaddingMode.ISO10126;         algorithm.Key = rdb.GetBytes(32);         algorithm.IV = rdb.GetBytes(16);         return algorithm;     }      /*       * encryptString      * provides simple encryption of a string, with a given password      */     public static string encryptString(string clearText, string password) {         SymmetricAlgorithm algorithm = getAlgorithm(password);         byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);         MemoryStream ms = new MemoryStream();         CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);         cs.Write(clearBytes, 0, clearBytes.Length);         cs.Close();         return Convert.ToBase64String(ms.ToArray());     }      /*      * decryptString      * provides simple decryption of a string, with a given password      */     public static string decryptString(string cipherText, string password) {         SymmetricAlgorithm algorithm = getAlgorithm(password);         byte[] cipherBytes = Convert.FromBase64String(cipherText);         MemoryStream ms = new MemoryStream();         CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);         cs.Write(cipherBytes, 0, cipherBytes.Length);         cs.Close();                     return System.Text.Encoding.Unicode.GetString(ms.ToArray());     } 

The code appears to work fine, except that when decrypting data with an incorrect key, I get a CryptographicException - "Padding is invalid and cannot be removed" - on the cs.Close() line in decryptString.

example code:

    string password1 = "password";     string password2 = "letmein";     string startClearText = "The quick brown fox jumps over the lazy dog";     string cipherText = encryptString(startClearText, password1);     string endClearText = decryptString(cipherText, password2);     // exception thrown 

My question is, is this to be expected? I would have thought that decrypting with the wrong password would just result in nonsense output, rather than an exception.

like image 853
Blorgbeard Avatar asked Aug 14 '08 23:08

Blorgbeard


People also ask

What is padding in AES encryption?

Padding is a way to take data that may or may not be a multiple of the block size for a cipher and extend it out so that it is. This is required for many block cipher modes as they require the data to be encrypted to be an exact multiple of the block size.


2 Answers

Although this have been already answered I think it would be a good idea to explain why it is to be expected.

A padding scheme is usually applied because most cryptographic filters are not semantically secure and to prevent some forms of cryptoatacks. For example, usually in RSA the OAEP padding scheme is used which prevents some sorts of attacks (such as a chosen plaintext attack or blinding).

A padding scheme appends some (usually) random garbage to the message m before the message is sent. In the OAEP method, for example, two Oracles are used (this is a simplistic explanation):

  1. Given the size of the modulus you padd k1 bits with 0 and k0 bits with a random number.
  2. Then by applying some transformation to the message you obtain the padded message wich is encrypted and sent.

That provides you with a randomization for the messages and with a way to test if the message is garbage or not. As the padding scheme is reversible, when you decrypt the message whereas you can't say anything about the integrity of the message itself you can, in fact, make some assertion about the padding and thus you can know if the message has been correctly decrypted or you're doing something wrong (i.e someone has tampered with the message or you're using the wrong key)

like image 127
Jorge Córdoba Avatar answered Sep 20 '22 21:09

Jorge Córdoba


I experienced a similar "Padding is invalid and cannot be removed." exception, but in my case the key IV and padding were correct.

It turned out that flushing the crypto stream is all that was missing.

Like this:

            MemoryStream msr3 = new MemoryStream();             CryptoStream encStream = new CryptoStream(msr3, RijndaelAlg.CreateEncryptor(), CryptoStreamMode.Write);             encStream.Write(bar2, 0, bar2.Length);             // unless we flush the stream we would get "Padding is invalid and cannot be removed." exception when decoding             encStream.FlushFinalBlock();             byte[] bar3 = msr3.ToArray(); 
like image 27
Yaniv Avatar answered Sep 20 '22 21:09

Yaniv