5

我们有一个旧的 ASP.NET 站点,它在此处使用加密方法:

http://www.codekeep.net/snippets/af1cd375-059a-4175-93d7-25eea2c5c660.aspx

当我们调用以下方法时,页面加载非常缓慢,最终返回 Connection Reset:

Decrypt(" ", true);

如果在后续的页面请求中多次调用该方法,应用程序池将关闭

这发生在运行 .NET framework v3.5 的 Windows 2008 服务器上。

我将问题缩小到TransformFinalBlock()电话。

注意:在 Cassini 上,我没有收到连接超时;而是引发以下异常:

System.Security.Cryptography.CryptographicException: Bad Data

为其他字符串调用 Decrypt() 在任何环境中都不会出现问题。

为什么会这样?这是 TripleDESCryptoServiceProvider 中的错误吗?

显然,我可以过滤 cipherString 以拒绝 " " 并避免这个特定问题。但是,我担心我不怀疑的其他一些 cipherString 值会导致 DoS。

更新 2011.06.28

以下是重现该问题的最少代码:

// problem occurs when toEncryptArray is an empty array {}
      byte[] toEncryptArray = {};

      MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
      byte[] keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes("dummy_key"));
      hashmd5.Clear();

      TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
      tdes.Key = keyArray;
      tdes.Mode = CipherMode.ECB;
      tdes.Padding = PaddingMode.PKCS7;
      ICryptoTransform cTransform = tdes.CreateDecryptor();

      // the following line can crashes the ASP.NET Application Pool (may need to call multiple times).
      byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

      tdes.Clear();
4

2 回答 2

1

如上所述,问题在于解密逻辑不能正确处理输入密码是零长度数组的情况。

为此创建了一张票:

http://connect.microsoft.com/VisualStudio/feedback/details/678150/denial-of-service-in-tripledescryptoserviceprovider

请注意,在运行 .NET Framework 4.0 时似乎可以正常工作。

于 2011-07-05T19:35:13.717 回答
0

最后一个块是填充的位置。在您的示例中,单个空格是第一个和最后一个块。DES/Triple DES 是 64 位分组密码,密文应该是 8 字节(64 位)的倍数。

我没有测试它的环境,但是您是否尝试过使用填充选项?填充更多空格是不行的,因为填充不匹配。

一个常见的填充方案是PKCS5。对于单个字节(加密到空格字符),您的纯文本应该是 hex :

0x?? 0x07 0x07 0x07 0x07 0x07 0x07 0x07

但在您的代码示例中,需要一个 base64 输入。这意味着您的输入字符串必须是:

  • 12个字符的倍数
  • 有效的 base64 字符串

可以拒绝任何其他字符串。

true值看起来像一个 MAC,这意味着您输入的纯文本应该后跟一个哈希(代码中的 MD5)。它可以帮助您检测密文的更改。当您加密二进制数据时,它很有用。如果您可以轻松检测到乱码的纯文本,则可以将其设置为 false。

于 2011-06-23T02:07:59.110 回答