1

I am trying to use the Rijndael method to encrypt and decrypt data. It encrypts fine but when I try to decrypt it it gives padding is invalid and cannot be removed at the line cs.FlushFinalBlock(); in the private static byte[] DecryptString(byte[] cipherData, byte[] Key, byte[] IV) method. I tried many sources like

I know this is a common question and might be even a duplicate. I searched onlne from the morning and came up with no solutions. following is my code.

    //clearText -> the string to be encrypted
    //passowrd -> encryption key
    public string EncryptString(string clearText, string Password)
    {
        // First we need to turn the input string into a byte array. 
        byte[] clearBytes =
            Encoding.Unicode.GetBytes(clearText);

        // Then, we need to turn the password into Key and IV 
        // We are using salt to make it harder to guess our key
        // using a dictionary attack - 
        // trying to guess a password by enumerating all possible words. 
        var pdb = new PasswordDeriveBytes(Password,
                                          new byte[]
                                              {
                                                  0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d,
                                                  0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76
                                              });

        // Now get the key/IV and do the encryption using the
        // function that accepts byte arrays. 
        // Using PasswordDeriveBytes object we are first getting
        // 32 bytes for the Key 
        // (the default Rijndael key length is 256bit = 32bytes)
        // and then 16 bytes for the IV. 
        // IV should always be the block size, which is by default
        // 16 bytes (128 bit) for Rijndael. 
        // If you are using DES/TripleDES/RC2 the block size is
        // 8 bytes and so should be the IV size. 
        // You can also read KeySize/BlockSize properties off
        // the algorithm to find out the sizes. 
        byte[] encryptedData = EncryptString(clearBytes,
                                             pdb.GetBytes(32), pdb.GetBytes(16));

        // Now we need to turn the resulting byte array into a string. 
        // A common mistake would be to use an Encoding class for that.
        //It does not work because not all byte values can be
        // represented by characters. 
        // We are going to be using Base64 encoding that is designed
        //exactly for what we are trying to do. 
        return Convert.ToBase64String(encryptedData);
    }
    //cipherText -> the string to be decrypted
    //passowrd -> decryption key
    public string DecryptString(string cipherText, string Password)
    {
        // First we need to turn the input string into a byte array. 
        // We presume that Base64 encoding was used 
        byte[] cipherBytes = Convert.FromBase64String(cipherText);

        // Then, we need to turn the password into Key and IV 
        // We are using salt to make it harder to guess our key
        // using a dictionary attack - 
        // trying to guess a password by enumerating all possible words. 
        var pdb = new PasswordDeriveBytes(Password,
                                          new byte[]
                                              {
                                                  0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65,
                                                  0x64, 0x76, 0x65, 0x64, 0x65, 0x76
                                              });

        // Now get the key/IV and do the decryption using
        // the function that accepts byte arrays. 
        // Using PasswordDeriveBytes object we are first
        // getting 32 bytes for the Key 
        // (the default Rijndael key length is 256bit = 32bytes)
        // and then 16 bytes for the IV. 
        // IV should always be the block size, which is by
        // default 16 bytes (128 bit) for Rijndael. 
        // If you are using DES/TripleDES/RC2 the block size is
        // 8 bytes and so should be the IV size. 
        // You can also read KeySize/BlockSize properties off
        // the algorithm to find out the sizes. 
        byte[] decryptedData = DecryptString(cipherBytes,
                                             pdb.GetBytes(32), pdb.GetBytes(16));

        // Now we need to turn the resulting byte array into a string. 
        // A common mistake would be to use an Encoding class for that.
        // It does not work 
        // because not all byte values can be represented by characters. 
        // We are going to be using Base64 encoding that is 
        // designed exactly for what we are trying to do. 
        return Encoding.Unicode.GetString(decryptedData);
    }

    // Encrypt a byte array into a byte array using a key and an IV 
    private static byte[] EncryptString(byte[] clearData, byte[] Key, byte[] IV)
    {
        // Create a MemoryStream to accept the encrypted bytes 
        var ms = new MemoryStream();

        // Create a symmetric algorithm. 
        // We are going to use Rijndael because it is strong and
        // available on all platforms. 
        // You can use other algorithms, to do so substitute the
        // next line with something like 
        //      TripleDES alg = TripleDES.Create(); 
        Rijndael alg = Rijndael.Create();

        // Now set the key and the IV. 
        // We need the IV (Initialization Vector) because
        // the algorithm is operating in its default 
        // mode called CBC (Cipher Block Chaining).
        // The IV is XORed with the first block (8 byte) 
        // of the data before it is encrypted, and then each
        // encrypted block is XORed with the 
        // following block of plaintext.
        // This is done to make encryption more secure. 

        // There is also a mode called ECB which does not need an IV,
        // but it is much less secure. 
        alg.Key = Key;
        alg.IV = IV;

        // Create a CryptoStream through which we are going to be
        // pumping our data. 
        // CryptoStreamMode.Write means that we are going to be
        // writing data to the stream and the output will be written
        // in the MemoryStream we have provided. 
        var cs = new CryptoStream(ms,
                                  alg.CreateEncryptor(), CryptoStreamMode.Write);

        // Write the data and make it do the encryption 
        cs.Write(clearData, 0, clearData.Length);

        // Close the crypto stream (or do FlushFinalBlock). 
        // This will tell it that we have done our encryption and
        // there is no more data coming in, 
        // and it is now a good time to apply the padding and
        // finalize the encryption process. 
        cs.FlushFinalBlock();

        // Now get the encrypted data from the MemoryStream.
        // Some people make a mistake of using GetBuffer() here,
        // which is not the right way. 
        byte[] encryptedData = ms.ToArray();

        return encryptedData;
    }

    private static byte[] DecryptString(byte[] cipherData,
                                        byte[] Key, byte[] IV)
    {
        // Create a MemoryStream that is going to accept the
        // decrypted bytes 
        var ms = new MemoryStream();

        // Create a symmetric algorithm. 
        // We are going to use Rijndael because it is strong and
        // available on all platforms. 
        // You can use other algorithms, to do so substitute the next
        // line with something like 
        //     TripleDES alg = TripleDES.Create(); 
        Rijndael alg = Rijndael.Create();

        // Now set the key and the IV. 
        // We need the IV (Initialization Vector) because the algorithm
        // is operating in its default 
        // mode called CBC (Cipher Block Chaining). The IV is XORed with
        // the first block (8 byte) 
        // of the data after it is decrypted, and then each decrypted
        // block is XORed with the previous 
        // cipher block. This is done to make encryption more secure. 
        // There is also a mode called ECB which does not need an IV,
        // but it is much less secure. 
        alg.Key = Key;
        alg.IV = IV;

        // Create a CryptoStream through which we are going to be
        // pumping our data. 
        // CryptoStreamMode.Write means that we are going to be
        // writing data to the stream 
        // and the output will be written in the MemoryStream
        // we have provided. 
        var cs = new CryptoStream(ms,
                                  alg.CreateDecryptor(), CryptoStreamMode.Write);

        // Write the data and make it do the decryption 
        cs.Write(cipherData, 0, cipherData.Length);

        // Close the crypto stream (or do FlushFinalBlock). 
        // This will tell it that we have done our decryption
        // and there is no more data coming in, 
        // and it is now a good time to remove the padding
        // and finalize the decryption process. 
        cs.FlushFinalBlock();

        // Now get the decrypted data from the MemoryStream. 
        // Some people make a mistake of using GetBuffer() here,
        // which is not the right way. 
        byte[] decryptedData = ms.ToArray();

        return decryptedData;
    }

Thank you very much :) PS : i grabbed this code from online and edited a bit to suit my program

Community
  • 1
  • 1
Hasitha Shan
  • 2,900
  • 6
  • 42
  • 83

1 Answers1

1

You need to get past the exception so you can diagnose what is going on. In order to do that, you need to set the decryption side only to expect no padding. That will let it accept anything. Once you have done that, you can have a look at what is emerging from your decryption and start diagnosing faults. Note that this is not a solution, it is a way to ignore the exception. Whatever is causing the exception is still there.

Have a look at what emerges. Is is all garbage? Is it part garbage and part the original plaintext? If it is mixed, where does the garbage appear: at the start, at the end, both, in the middle somewhere? Tell us what you see and we can point you to probable causes of the problems.

When everything is working, set both encryption and decryption to PKCS#7 padding. Do not leave the no padding in place.

rossum
  • 15,344
  • 1
  • 24
  • 38
  • Hey thanx for the reply..okey i wil try those steps you told and see what happns (y) thanx again :) – Hasitha Shan Jun 19 '13 at 03:20
  • hi, with `PaddingMode.None` it gives the proper output. but how to make this work with padding. from ur suggestion, padding it is essential ryt? – Hasitha Shan Jun 19 '13 at 03:23
  • Padding is needed if the plaintext is not a whole number of bytes. Just explicitly set the padding to PKCS7 (or PKCS5) for both encryption and decryption. – rossum Jun 19 '13 at 10:38
  • Whoops. Too late to edit: "Padding is needed if the plaintext is not a whole number of **blocks**." – rossum Jun 19 '13 at 20:46
  • okey thanx i will try..the string am decrypting and encrypting contains alaphabatic character, numbers and special caracters also. – Hasitha Shan Jun 20 '13 at 03:31