2
votes

In my app on windows phone 8 I need to encrypt-decrypt data using DESede/CBC/PKCS5Padding with PBKDF2 key.
I found example how to encrypt using Bouncy Castle:
http://www.go4expert.com/articles/bouncy-castle-net-implementation-triple-t24829/
And I was able to encrypt my data (text), but I can't decrypt my encrypted data using this code. When I'm trying to call DoFinal() it throws exception "pad block corrupted".
Maybe I missed something in decrypting?
Maybe somebody knows alternative library (way) on windows phone 8 for encryption using DESede/CBC/PKCS5Padding with PBKDF2 key?

using Raksha.Crypto;
using Raksha.Crypto.Engines;
using Raksha.Crypto.Modes;
using Raksha.Crypto.Paddings;
using Raksha.Crypto.Parameters;
using System;
using System.Security.Cryptography;
using System.Text;

namespace MyNamespace
{
  class EncryptDecrypt
  {
      Rfc2898DeriveBytes key;
      BufferedBlockCipher cipherEncrypt;
      BufferedBlockCipher cipherDecrypt;
      private readonly int ITERACTIONCOUNT = 1000;
      private readonly int KEY_LENGTH = 24; 

      public EncryptDecrypt(string passPhrase, string salt)
      {
          byte[] SALT = Encoding.UTF8.GetBytes(salt);
          key = new Rfc2898DeriveBytes(passPhrase, SALT, ITERACTIONCOUNT);

          DesEdeEngine desede = new DesEdeEngine();

          cipherEncrypt = new PaddedBufferedBlockCipher(new CbcBlockCipher(desede));
          cipherDecrypt = new PaddedBufferedBlockCipher(new CbcBlockCipher(desede));
          DesEdeParameters p = new DesEdeParameters(key.GetBytes(KEY_LENGTH));

          cipherEncrypt.Init(true, p);
          cipherDecrypt.Init(false, p);
      }

  public byte[] Encrypt(byte[] dataToEncrypt)
      {
          try
          {
              byte[] outbytes = cipherEncrypt.DoFinal(dataToEncrypt);
              return outbytes;
          }
          catch(Exception ex)
          {
              System.Diagnostics.Debug.WriteLine("Encrypt() Exception: " + ex.Message);
              return new byte[] { 0 };
          }
      }

      public byte[] Decrypt(byte[] dataToDecrypt)
      {
          try
          {
              byte[] result = cipherDecrypt.DoFinal(dataToDecrypt);
              return result;
          }
          catch(CryptoException ex)
          {
              System.Diagnostics.Debug.WriteLine("Decrypt() Exception: " + ex.Message);
      // ex.Message: pad block corrupted
              return new byte[] { 0 };
          }
      }
   }
2
Did you store or transfer the ciphertext (the output of the encryption function) somewhere somehow?Maarten Bodewes
@owlstead In this case I just put encrypted bytes to decrypt functions without any changes (for test) like: EncryptDecrypt encrypt = new EncryptDecrypt("000000", "Adobe Photoshop"); byte[] encrypted = encrypt.Encrypt(Encoding.UTF8.GetBytes("some text")); byte[] decrypted = encrypt.Decrypt(encrypted); And when in Decrypt function I call DoFinal() it throws exception "pad block corrupted"tsiganoff
Hmm, although I don't know what Raksha.Crypto is, I'm otherwise stumped.Maarten Bodewes
@owlstead Raksha.Crypto is the same as Org.BouncyCastle.Cryptotsiganoff
I would guess its persisting state between encrypt/decrypt. Try newing up a new object just to do the decryption.PaulG

2 Answers

2
votes

I solved the problem!
The DesEdeEngine must be initialized with first parameter true.

DesEdeEngine desede = new DesEdeEngine();
desede.Init(true, key);

I don't know why but it's does't matter that I use the same object of DesEdeEngine in the cipher to decrypt.

In a nutshell the DesEdeEngine by default is initialized as decryptor, and instead of encrypt it's decrypt block of padding bytes. And when PaddedBufferedBlockCipher in DoFinal() call PadCount() where value of last byte must be > 0 and < 8 I was getting value like 48 or 123 or something like this and it's threw an exception "pad block corrupted".

Thanks to all who participated.

1
votes

There are many things that can cause a "Bad Padding" error. Basically anything that causes the end of the last block not to match the expected padding will throw the error. Possible causes include: incorrect padding setting, incorrect key, corrupted cyphertext and others.

To try and diagnose the problem, set the decryption side to NoPadding. This will accept anything, and allow you to examine the output:

  • complete garbage: you probably have an error in the key or different mode settings.

  • first block garbage: you may have a key error or an IV error.

  • last block garbage: likely a corrupt end to the cyphertext file.

  • a correct decryption with some strange bytes after: the strange bytes are the padding.

If it really is just the padding, then set the decryption function to expect that sort of padding. Otherwise check that the key/IV/cyphertext is byte-for-byte the same for both encryption and decryption.

It is vital that you set a padding mode after diagnosis. NoPadding is insecure.

In the case of your code I cannot see where you set the PKCS5 padding. I assume the CBC mode is set internally in CbcBlockCipher(desede).