SSRS Decrypting database column throws error “Value cannot be null. Parameter name: inputBuffer”

北城余情 提交于 2019-12-24 01:17:05

问题


We have a database field that is encrypted in a C# MVC app using Entity Framework. That part works fine for encrypting and decrypting. We need to show this data decrypted in an SSRS report.

I've taken the Decrypt method and converted it to VB.Net and placed in the code behind of the report. The error occurs when calling the StreamReader's ReadToEnd method. We've found some references online about there being an issue trying to close a stream that's already closed. This stream is only being read from one time and we're reading the entire stream so it should not be closed at that point.

I tried reading Length - 1 bytes from the cryptoStream and that did not throw an error. If I try to read Length bytes, I get the same error. If I read all but one byte and then read only the last byte I get the same error. Stack trace and code are below. Any help would be greatly appreciated.


Stacktrace:

    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)

Code:

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

回答1:


This sounds like a padding error. First of all, AES in CBC mode requires an exact message size for decryption, N times the blocksize (of 16 bytes). If the message has this size then AES CBC ciphertext will always decrypt. Any other problem can only be related to padding really. So what happens is that the last deciphered plain text does not have the correct padding, and an exception occurs.

Now comes the fun part; this error occurs when:

  • the binary AES key is not identical;
  • if the algorithm or mode is incorrect or if the wrong padding algorithm is used;
  • if one of the last two blocks is mangled;
  • if the last part of the encryption is missing in action.

In other words, if something is wrong, it is likely that it will turn up during the removal of the padding bytes. If you are unlucky, the last incorrect block still ends with a byte value of 01 hexadecimal, and padding succeeds, showing that padding is no substitution for integrity protection.



来源:https://stackoverflow.com/questions/12641266/ssrs-decrypting-database-column-throws-error-value-cannot-be-null-parameter-na

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!