C#Bouncy Castle没有解密,Exception:pad block corrupted

时间:2014-05-19 14:31:04

标签: c# windows-phone-8 cryptography bouncycastle

在我的Windows Phone 8应用程序中,我需要使用带有PBKDF2密钥的DESede / CBC / PKCS5Padding加密解密数据。
我找到了如何使用Bouncy Castle加密的示例:
http://www.go4expert.com/articles/bouncy-castle-net-implementation-triple-t24829/
我能够加密我的数据(文本),但我无法使用此代码解密我的加密数据。 当我尝试调用DoFinal()时,它会抛出异常" pad块损坏"。
也许我在解密时错过了一些东西?
也许有人知道Windows Phone 8上的替代库(方式)使用DESede / CBC / PKCS5Padding和PBKDF2密钥进行加密?

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 个答案:

答案 0 :(得分:2)

我解决了这个问题! 必须使用第一个参数true初始化DesEdeEngine。

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

我不知道为什么,但我在解密密码中使用DesEdeEngine的相同对象并不重要。

简而言之,DesEdeEngine默认情况下被初始化为decryptor,而不是加密它的填充字节的解密块。当DoFinal()中的PaddedBufferedBlockCipher调用PadCount()时,其中最后一个字节的值必须是> 0和< 8我得到了像48或123这样的价值或类似的东西,并且它引发了一个异常" pad block corrupted"。

感谢所有参与者。

答案 1 :(得分:1)

有很多事情可能导致“填充不良”错误。基本上任何导致最后一个块结束不匹配预期填充的东西都会引发错误。可能的原因包括:填充设置不正确,密钥错误,密文错误等。

要尝试诊断问题,请将解密端设置为NoPadding。这将接受任何内容,并允许您检查输出:

  • 完全垃圾:您可能在密钥或不同模式设置中出错。

  • 第一次阻止垃圾:您可能遇到密钥错误或IV错误。

  • 最后一个块垃圾:可能是cyphertext文件的损坏结束。

  • 正确的解密后面有一些奇怪的字节:奇怪的字节是填充。

如果它只是填充,那么设置解密函数以期望这种填充。否则,检查加密和解密的密钥/ IV / cyphertext byte-to-byte 是否相同。

至关重要您在诊断后设置了填充模式。 NoPadding是不安全的。

对于您的代码,我无法看到您设置PKCS5填充的位置。我假设CBC模式是在CbcBlockCipher(desede)内部设置的。