【发布时间】:2021-06-25 17:35:46
【问题描述】:
我正在编写一个用于发送和接收 AES 加密文件的应用程序。我有两个功能,一个用于发送:
public async Task SendFileAsync()
{
var buffer = new byte[1024];
using (Aes aesAlg = Aes.Create())
{
// tcpHandler.stream is a NetworkStream
using (ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV))
{
using (Stream fileStream = await selectedFile.OpenStreamForReadAsync())
{
using (CryptoStream csEncrypt = new CryptoStream(tcpHandler.stream, encryptor, CryptoStreamMode.Write, true))
{
while (stream.Position < selectedFileSize)
{
int nowRead = fileStream.Read(buffer, 0, buffer.Length); // read bytes from file
csEncrypt.Write(buffer, 0, nowRead); // write bytes to CryptoStream (which writes to NetworkStream)
}
}
}
}
}
await tcpHandler.stream.FlushAsync()
}
还有一个用于接收:
public async Task ReceiveFileAsync()
{
var buffer = new byte[1024];
BinaryFormatter formatter = new BinaryFormatter();
int messageLength = tcpHandler.ReadMessageLength();
int totalBytesRead = 0;
using (Aes aesAlg = Aes.Create())
{
// tcpHandler.stream is a NetworkStream
using (ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
{
using (var fileStream = await newFile.OpenStreamForWriteAsync())
{
using (CryptoStream csDecrypt = new CryptoStream(tcpHandler.stream, decryptor, CryptoStreamMode.Read, true))
{
while (totalBytesRead < messageLength)
{
// calculate how many bytes have to be read in this iteration
var toRead = Math.Min(buffer.Length, messageLength - totalBytesRead);
var nowRead = csDecrypt.Read(buffer, 0, toRead); // read bytes from CryptoStream
totalBytesRead += nowRead; // sum read bytes
fileStream.Write(buffer, 0, nowRead); // write decrypted bytes to file
}
}
}
}
}
}
问题是ReceiveFileAsync() 在最后一个csDecrypt.Read(buffer, 0, toRead) 上阻塞了自己,就好像csDecrypt 流中没有足够的数据一样。但是,当我关闭(终止进程)发送应用程序时,接收应用程序正确接收最后一个缓冲区。
当我将using (CryptoStream csEncrypt = new CryptoStream(tcpHandler.stream, encryptor, CryptoStreamMode.Write, true)) 的最后一个参数更改为false 时,也会发生同样的事情 - 它使 CryptoStream 在处理基本流 (tcpHandler.stream) 时关闭它。
如果我在SendFileAsync() 末尾添加tcpHandler.stream.Close(),它也会有所帮助。
简而言之,在我关闭发送 NetworkStream (tcpHandler.stream) 之前,我发送的最后一个缓冲区不会被接收,无论是通过关闭/处置它还是关闭应用程序。
我尝试将await tcpHandler.stream.FlushAsync() 添加为SendFileAsync() 的最后一行,但没有帮助。有什么想法我应该怎么做才能解决这个问题?
编辑:使用嵌套的 using 语句更新代码。
【问题讨论】:
-
您使用的块是错误的。它们需要嵌套(不是串行的)。 using 块中的对象位于块外。对象文件流在流被写入后被释放。
-
@jdweng 我嵌套了
using块,但同样的事情发生了。 -
发布更新代码。
-
@jdweng 贴出代码
-
在收到所有数据之前,您无法解密文件。加密数据以块为单位,您无法解密部分块。 while 循环必须在尝试解密之前读取整个消息。
标签: c# stream cryptography aes networkstream