2

我们有一个使用实体框架在 C# MVC 应用程序中加密的数据库字段。该部分适用于加密和解密。我们需要在 SSRS 报告中显示解密的数据。

我采用了 Decrypt 方法并将其转换为 VB.Net 并放置在报告后面的代码中。调用StreamReader'sReadToEnd方法时发生错误。我们在网上找到了一些关于在尝试关闭已经关闭的流时出现问题的参考资料。此流仅被读取一次,我们正在读取整个流,因此此时不应关闭它。

我尝试Length - 1从 cryptoStream 读取字节,但没有引发错误。如果我尝试读取Length字节,我会得到同样的错误。如果我只读取一个字节,然后只读取最后一个字节,我会得到同样的错误。堆栈跟踪和代码如下。任何帮助将不胜感激。


堆栈跟踪:

    at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
   at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Stream.Dispose()
   at ReportExprHostImpl.CustomCodeProxy.Decrypt(String ciphertext)

代码:

public function Decrypt(byval ciphertext as string) as string
  dim message as string
  dim key as string
  dim saltSize as integer
  saltsize = 32
  key = "KEYGOESHERE"

  dim allTheBytes as byte()
  allTheBytes = Convert.FromBase64String(ciphertext)

  dim saltBytes as byte()
  saltBytes = new byte(saltsize) {}

  dim ciphertextBytes as byte()
  ciphertextBytes = new byte(allTheBytes.Length - saltSize) {}

  dim i as integer
  for i = 0 to saltsize - 1
    saltBytes(i) = allTheBytes(i)
  next i

  for i = saltSize to (allTheBytes.Length - 1)
    ciphertextBytes(i - saltSize) = allTheBytes(i)
  next i

  try
    using keyDerivationFunction as System.Security.Cryptography.Rfc2898DeriveBytes = new System.Security.Cryptography.Rfc2898DeriveBytes(key, saltBytes)
      dim keyBytes as byte()
      keyBytes = keyDerivationFunction.GetBytes(32)
      dim ivBytes as byte()
      ivBytes = keyDerivationFunction.GetBytes(16)

      using aesManaged as System.Security.Cryptography.AesManaged = new System.Security.Cryptography.AesManaged()
        aesManaged.Padding = System.Security.Cryptography.PaddingMode.PKCS7
        aesManaged.Mode = System.Security.Cryptography.CipherMode.CBC

        using decryptor as System.Security.Cryptography.ICryptoTransform = aesManaged.CreateDecryptor(keyBytes, ivBytes)
          using memoryStream as System.IO.MemoryStream = new System.IO.MemoryStream(ciphertextBytes)
            using cryptoStream as System.Security.Cryptography.CryptoStream = new System.Security.Cryptography.CryptoStream(memoryStream, decryptor, System.Security.Cryptography.CryptoStreamMode.Read)
              using streamReader as System.IO.StreamReader = new System.IO.StreamReader(cryptoStream)
                message = streamReader.ReadToEnd()
                return message
              end using
            end using
          end using
        end using
      end using
    end using
  catch e as Exception
    return e.StackTrace
  end try
end function
4

1 回答 1

1

这听起来像一个填充错误。首先,CBC 模式下的 AES 需要精确的消息大小才能解密,即块大小的 N 倍(16 字节)。如果消息具有此大小,则 AES CBC 密文将始终解密。任何其他问题只能与填充有关。所以发生的情况是最后破译的纯文本没有正确的填充,并且发生异常。

有趣的来了; 在以下情况下会发生此错误:

  • 二进制 AES 密钥不相同;
  • 如果算法或模式不正确,或者使用了错误的填充算法;
  • 如果最后两个块之一被破坏;
  • 如果加密的最后一部分在操作中丢失。

换句话说,如果出现问题,它很可能会在删除填充字节期间出现。如果运气不好,最后一个不正确的块仍然以01十六进制的字节值结尾,并且填充成功,表明填充不能替代完整性保护。

于 2012-09-28T21:44:57.007 回答