C# 从加密流读取到流的末尾
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9724598/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading from a cryptostream to the end of the stream
提问by David
I'm having some trouble with the code below. I have a file in a temporary location which is in need of encryption, this function encrypts that data which is then stored at the "pathToSave" location.
我在使用下面的代码时遇到了一些问题。我在临时位置有一个需要加密的文件,此函数会对该数据进行加密,然后将其存储在“pathToSave”位置。
On inspection is does not seem to be handling the whole file properly - There are bits missing from my output and I suspect it has something to do with the while loop not running through the whole stream.
检查时似乎没有正确处理整个文件 - 我的输出中缺少一些位,我怀疑这与没有在整个流中运行的 while 循环有关。
As an aside, if I try and call CryptStrm.Close() after the while loop I receive an exception. This means that if I attempt to decrypt the file, I get a file already in use error!
顺便说一句,如果我尝试在 while 循环之后调用 CryptStrm.Close() ,我会收到一个异常。这意味着如果我尝试解密文件,我会收到一个文件已在使用中的错误!
Tried all the usual and Ive looked on here at similar issues, any help would be great.
尝试了所有通常的方法,我在这里查看了类似的问题,任何帮助都会很棒。
Thanks
谢谢
public void EncryptFile(String tempPath, String pathToSave)
{
try
{
FileStream InputFile = new FileStream(tempPath, FileMode.Open, FileAccess.Read);
FileStream OutputFile = new FileStream(pathToSave, FileMode.Create, FileAccess.Write);
RijndaelManaged RijCrypto = new RijndaelManaged();
//Key
byte[] Key = new byte[32] { ... };
//Initialisation Vector
byte[] IV = new byte[32] { ... };
RijCrypto.Padding = PaddingMode.None;
RijCrypto.KeySize = 256;
RijCrypto.BlockSize = 256;
RijCrypto.Key = Key;
RijCrypto.IV = IV;
ICryptoTransform Encryptor = RijCrypto.CreateEncryptor(Key, IV);
CryptoStream CryptStrm = new CryptoStream(OutputFile, Encryptor, CryptoStreamMode.Write);
int data;
while (-1 != (data = InputFile.ReadByte()))
{
CryptStrm.WriteByte((byte)data);
}
}
catch (Exception EncEx)
{
throw new Exception("Encoding Error: " + EncEx.Message);
}
}
EDIT:
编辑:
I've made the assumption that my problem is with Encryption. My Decrypt might be the culprit
我假设我的问题出在加密上。我的解密可能是罪魁祸首
public String DecryptFile(String encryptedFilePath)
{
FileStream InputFile = new FileStream(encryptedFilePath, FileMode.Open, FileAccess.Read);
RijndaelManaged RijCrypto = new RijndaelManaged();
//Key
byte[] Key = new byte[32] { ... };
//Initialisation Vector
byte[] IV = new byte[32] { ... };
RijCrypto.Padding = PaddingMode.None;
RijCrypto.KeySize = 256;
RijCrypto.BlockSize = 256;
RijCrypto.Key = Key;
RijCrypto.IV = IV;
ICryptoTransform Decryptor = RijCrypto.CreateDecryptor(Key, IV);
CryptoStream CryptStrm = new CryptoStream(InputFile, Decryptor, CryptoStreamMode.Read);
String OutputFilePath = Path.GetTempPath() + "myfile.name";
StreamWriter OutputFile = new StreamWriter(OutputFilePath);
OutputFile.Write(new StreamReader(CryptStrm).ReadToEnd());
CryptStrm.Close();
OutputFile.Close();
return OutputFilePath;
}
回答by pstrjds
Well, there are several things going wrong here.
好吧,这里有几件事出了问题。
1. Your setting the size of the IV too large. If you have a key size of 256, the IV for Rijndael is 16 bytes. If you try to set the key with more bytes than that you will get an exception.IV size should be set to Block size / 8 see MSDNso the IV size you have is correct.
1.你设置的IV的尺寸太大了。如果密钥大小为 256,则 Rijndael 的 IV 为 16 字节。如果您尝试使用更多字节设置密钥,则会出现异常。IV 大小应设置为 Block size / 8请参阅 MSDN,因此您拥有的 IV 大小是正确的。
- You have a padding mode of None. Unless your data is exactly the correct block size, then you are going to have problems. You probably want to pick a padding mode.
- You typically need to call FlushFInalBlock when done writing to the crypto stream when you are encrypting to ensure all of the data is written to the stream.
- 您的填充模式为 None。除非您的数据是完全正确的块大小,否则您将遇到问题。您可能想要选择一种填充模式。
- 在加密时完成写入加密流后,您通常需要调用 FlushFInalBlock 以确保所有数据都写入流中。
I am posting some sample code using memory streams to show the encrypting and decrypting.
我正在发布一些使用内存流的示例代码来显示加密和解密。
var tempData = "This is the text to encrypt. It's not much, but it's all there is.";
using (var rijCrypto = new RijndaelManaged())
{
byte[] encryptedData;
rijCrypto.Padding = System.Security.Cryptography.PaddingMode.ISO10126;
rijCrypto.KeySize = 256;
using (var input = new MemoryStream(Encoding.Unicode.GetBytes(tempData)))
using (var output = new MemoryStream())
{
var encryptor = rijCrypto.CreateEncryptor();
using (var cryptStream = new CryptoStream(output, encryptor, CryptoStreamMode.Write))
{
var buffer = new byte[1024];
var read = input.Read(buffer, 0, buffer.Length);
while (read > 0)
{
cryptStream.Write(buffer, 0, read);
read = input.Read(buffer, 0, buffer.Length);
}
cryptStream.FlushFinalBlock();
encryptedData = output.ToArray();
}
}
using (var input = new MemoryStream(encryptedData))
using (var output = new MemoryStream())
{
var decryptor = rijCrypto.CreateDecryptor();
using (var cryptStream = new CryptoStream(input, decryptor, CryptoStreamMode.Read))
{
var buffer = new byte[1024];
var read = cryptStream.Read(buffer, 0, buffer.Length);
while (read > 0)
{
output.Write(buffer, 0, read);
read = cryptStream.Read(buffer, 0, buffer.Length);
}
cryptStream.Flush();
var result = Encoding.Unicode.GetString(output.ToArray());
}
}
}
回答by Simon Smith
The KeySize must be specified first. This looks like a bug e.g. this works
必须首先指定 KeySize。这看起来像一个错误,例如这有效
using (var aes = new AesManaged())
{
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
aes.IV = iv;
aes.Key = passwordHash;
aes.Padding = PaddingMode.PKCS7;
but this doesn't
但这并没有
using (var aes = new AesManaged())
{
aes.Mode = CipherMode.CBC;
aes.IV = iv;
aes.Key = passwordHash;
aes.Padding = PaddingMode.PKCS7;
aes.KeySize = 256;
回答by SLdragon
Another way to read CryptoStream is to using CopyTo methord:
另一种读取 CryptoStream 的方法是使用 CopyTo 方法:
...
using (var output = new MemoryStream())
{
cryptStream.CopyTo(output);
return output.ToArray();
}
...

