我目前正在从.NET Core 3.1升级到.NET 6,而我的变化或奇怪的行为使我变得越来越多。
这是我的代码,在.NET Core 3.1中完美工作:
public static byte[] Decrypt<SymmetricAlgorithmType>(byte[] securedData, SymmetricEncryptionOptions symetricEncryptionOptions)
where SymmetricAlgorithmType : SymmetricAlgorithm, new()
{
SymmetricAlgorithm symetric = new SymmetricAlgorithmType
{
Key = symetricEncryptionOptions.Key,
IV = symetricEncryptionOptions.InitializationVector
};
byte[] bytes = new byte[securedData.Length];
MemoryStream? memoryStream = new MemoryStream(securedData);
CryptoStream encryptionStream = new CryptoStream(memoryStream, symetric.CreateDecryptor(), CryptoStreamMode.Read);
int realBytes = encryptionStream.Read(bytes, 0, bytes.Length);
encryptionStream.Close();
byte[] realByteArray = new byte[realBytes];
Array.Copy(bytes, realByteArray, realBytes);
return realByteArray;
}
运行我的单元测试时,使用一些示例数据, secureddata
的大小为32。字节的数量实际读取为23(也可以看到)在 reenbytes
变量中),将它们放入正确尺寸的 rehebytearray
中。
在.NET 6中运行完全相同的代码,我现在得到16而不是23个,它的内容是在内容中。
因此,我想,我将代码重写以创建一个wire循环,该循环断开直到读取0字节:
MemoryStream? memoryStream = new MemoryStream(securedData);
CryptoStream encryptionStream = new CryptoStream(memoryStream, symetric.CreateDecryptor(), CryptoStreamMode.Read);
byte[] buffer = new byte[securedData.Length];
int totalRead = 0;
while (totalRead < buffer.Length)
{
int bytesRead = encryptionStream.Read(buffer, totalRead, 16);
if (bytesRead == 0)
{
break;
}
totalRead += bytesRead;
}
return buffer;
因此,在第一次运行时,我获得了16个字节,第二个运行将返回7字节,但是一旦循环第三次运行,我得到例外:
System.ArgumentOutOfRangeException: 'Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. (Parameter 'count')'
上面看到的代码是根据下面的文章,其中提到了.NET 6中的破坏变化:
我到目前为止唯一的解决方法就是通过字节。因此,如上所述,相同的代码,但使用: 1
而不是 16
: encryptionstream.read(buffer,totalRead,1);
注意我使用 system.security.cryptography.rijndaelmaned
作为 symmetricalGorithm
,其16尺寸字节阵列为键,也是16个字节数AS IV和 cryptostostostromeam 不支持 seek
或 slice
。
因此,我想知道这是.NET 6中的错误还是我现在做错了什么,但是在.NET Core 3中还可以吗?
I am currently upgrading from .NET Core 3.1 to .NET 6 and I came accross a breaking change or an odd behavior.
This is my code, that works perfectly in .NET Core 3.1:
public static byte[] Decrypt<SymmetricAlgorithmType>(byte[] securedData, SymmetricEncryptionOptions symetricEncryptionOptions)
where SymmetricAlgorithmType : SymmetricAlgorithm, new()
{
SymmetricAlgorithm symetric = new SymmetricAlgorithmType
{
Key = symetricEncryptionOptions.Key,
IV = symetricEncryptionOptions.InitializationVector
};
byte[] bytes = new byte[securedData.Length];
MemoryStream? memoryStream = new MemoryStream(securedData);
CryptoStream encryptionStream = new CryptoStream(memoryStream, symetric.CreateDecryptor(), CryptoStreamMode.Read);
int realBytes = encryptionStream.Read(bytes, 0, bytes.Length);
encryptionStream.Close();
byte[] realByteArray = new byte[realBytes];
Array.Copy(bytes, realByteArray, realBytes);
return realByteArray;
}
When running my unit test, with some sample data, the size of securedData
is 32. The number of bytes actually read is 23 (also seen in the realBytes
variable) and those are put into realByteArray
of the correct size.
Running the exact same code in .NET 6, I now get 16 instead of 23, which crops the content.
So I thought, I rewrite the code to create a while loop that breaks until 0 bytes are read:
MemoryStream? memoryStream = new MemoryStream(securedData);
CryptoStream encryptionStream = new CryptoStream(memoryStream, symetric.CreateDecryptor(), CryptoStreamMode.Read);
byte[] buffer = new byte[securedData.Length];
int totalRead = 0;
while (totalRead < buffer.Length)
{
int bytesRead = encryptionStream.Read(buffer, totalRead, 16);
if (bytesRead == 0)
{
break;
}
totalRead += bytesRead;
}
return buffer;
So on the first run, I get 16 bytes, the second run returns 7 bytes, but as soon as the loop runs the third time, I get the exception:
System.ArgumentOutOfRangeException: 'Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection. (Parameter 'count')'
The code seen above is according to the following article, where the breaking change in .NET 6 is mentioned:
https://learn.microsoft.com/en-US/dotnet/core/compatibility/core-libraries/6.0/partial-byte-reads-in-streams
The only workaround I have so far is to read it byte by byte. So the same code, as seen above, but using: 1
instead of 16
: encryptionStream.Read(buffer, totalRead, 1);
Note that I use a System.Security.Cryptography.RijndaelManaged
as SymmetricAlgorithm
with a 16 size byte array as key and also 16 size byte array as IV and the CryptoStream
does not support Seek
or Slice
.
So I am wondering if this is a bug in .NET 6 or I am doing something totally wrong now, but was okay in .NET Core 3?
发布评论
评论(1)
错误是你的。
从任何
读取
调用返回的字节数是一个实现细节 - 它必须是 emage 或 nothing (eof)。所以数字更改:很好。但是,问题在这里:参数仍然需要有效,当您接近缓冲区末尾时它们不是。相反:
现在,它总是说“尽可能多地说,填充缓冲区”,而不是“读取16个字节,无论缓冲区中剩下多少空间”。
The error is yours.
The number of bytes returned from any
Read
call is an implementation detail - it just has to be something or nothing (EOF). So the number changing: is fine. The problem, however, is here:The parameters still need to be valid, which they aren't as you approach the end of the buffer. Consider instead:
Now it always says "as much as you can, filling the buffer", rather than "read up to 16 bytes, regardless of how much space is left in the buffer".