问题
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