C# 使用 File.Encrypt 加密文件,然后将其解密为内存流
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14777732/
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
Encrypt a file using File.Encrypt and then Decrypt it to memory stream
提问by user1307346
I need to implement a simple file encryption and then decrypt it, when needed, to a memory stream. The easiest way seems to do this with File.Encrypt, but is it possible to decrypt the file to memory stream, instead of decrypting the file before reading it to memory stream, and thus exposing it for a while?
我需要实现一个简单的文件加密,然后在需要时将其解密为内存流。最简单的方法似乎是使用 File.Encrypt 来做到这一点,但是是否可以将文件解密到内存流,而不是在将文件读取到内存流之前对其进行解密,从而将其暴露一段时间?
And if File.Encrypt is not the best way for this scenario, what would you recommend?
如果 File.Encrypt 不是这种情况的最佳方式,您会推荐什么?
回答by Immortal Blue
This was the first encryption code I wrote - be warned, although a good starting point to understand what's going on, static passwords and static salts are a bad idea! (thanks for highlighting this CodesInChaos)
这是我写的第一个加密代码 - 请注意,虽然是了解发生了什么的一个很好的起点,但静态密码和静态盐是一个坏主意!(感谢您突出显示此 CodesInChaos)
You can decrypt to any stream you like, including straight to a memory stream...
您可以解密到您喜欢的任何流,包括直接解密到内存流...
FileInfo file = new FileInfo("SomeFile");
using (FileStream inFs = file.OpenRead())
{
using (MemoryStream outMs = new MemoryStream())
{
encryption.Decrypt(inFs, outMs);
BinaryFormatter bf = new BinaryFormatter();
targetType target= bf.Deserialize(outMs) as targetType;
}
}
where encryption is one of these:
其中加密是其中之一:
public class EncryptionHelper
{
static SymmetricAlgorithm encryption;
static string password = "password";
static string salt = "this is my salt. There are many like it, but this one is mine.";
static EncryptionHelper()
{
encryption = new RijndaelManaged();
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, Encoding.ASCII.GetBytes(salt));
encryption.Key = key.GetBytes(encryption.KeySize / 8);
encryption.IV = key.GetBytes(encryption.BlockSize / 8);
encryption.Padding = PaddingMode.PKCS7;
}
public void Encrypt(Stream inStream, Stream OutStream)
{
ICryptoTransform encryptor = encryption.CreateEncryptor();
inStream.Position = 0;
CryptoStream encryptStream = new CryptoStream(OutStream, encryptor, CryptoStreamMode.Write);
inStream.CopyTo(encryptStream);
encryptStream.FlushFinalBlock();
}
public void Decrypt(Stream inStream, Stream OutStream)
{
ICryptoTransform encryptor = encryption.CreateDecryptor();
inStream.Position = 0;
CryptoStream encryptStream = new CryptoStream(inStream, encryptor, CryptoStreamMode.Read);
encryptStream.CopyTo(OutStream);
OutStream.Position = 0;
}
}
回答by sircodesalot
File.Encrypt
is an OS feature but it sounds like really you want to control how the encryption is done.
File.Encrypt
是一个操作系统功能,但听起来您真的想控制加密的完成方式。
http://msdn.microsoft.com/en-us/library/system.io.file.encrypt.aspx
http://msdn.microsoft.com/en-us/library/system.io.file.encrypt.aspx
// This is where the data will be written do.
MemoryStream dataStream = new MemoryStream();
// The encryption vectors
byte[] key = {145,12,32,245,98,132,98,214,6,77,131,44,221,3,9,50};
byte[] iv = {15,122,132,5,93,198,44,31,9,39,241,49,250,188,80,7};
// Build the encryption mathematician
using (TripleDESCryptoServiceProvider encryption = new TripleDESCryptoServiceProvider())
using (ICryptoTransform transform = encryption.CreateEncryptor(key, iv))
using (Stream encryptedOutputStream = new CryptoStream(dataStream, transform, CryptoStreamMode.Write))
using (StreamWriter writer = new StreamWriter(encryptedOutputStream))
{
// In this block, you do your writing, and it will automatically be encrypted
writer.Write("This is the encrypted output data I want to write");
}
Encryption is not for the faint of heart. Be forewarned though, you really should have a strong sense of regular IO and data streams before you attempt this though.
加密不适合胆小的人。但是请预先警告,在尝试之前,您确实应该对常规 IO 和数据流有很强的了解。
回答by jbtule
Implementing Crypto deceptively easy, and actually rather tedious, there are a lot of details, and the details wrong are usually what's exploited security wise. The best practice is to use a high level encryption framework that hides these details ivs, salts, mac, comparisons, padding, key rotation, and while it's not improbable for high level frameworks to have the details wrong, when they do, they get found and fixed, the code snippets on stack overflow generally do not.
实施 Crypto 看似简单,但实际上相当乏味,有很多细节,而错误的细节通常是安全明智的利用。最佳实践是使用高级加密框架来隐藏这些细节 ivs、salts、mac、比较、填充、密钥轮换,虽然高级框架不太可能有细节错误,但一旦出错,就会被发现并且已修复,堆栈溢出的代码片段通常不会。
I have been porting the Google Keyczarframework so such a high level library would exist for C#.
我一直在移植Google Keyczar框架,因此 C# 会存在这样一个高级库。
And it is usable for encrypting and decrypting io streams.
它可用于加密和解密 io 流。
Install in your project with nuget
使用nuget在您的项目中安装
PM> Install-Package Keyczar -Pre
Then create your key set. (by having a separate key set file, it gives you the ability to rotating keys in the future and prevents you from accidentally hard coding something that should not ever be hard coded.)
然后创建您的密钥集。(通过拥有一个单独的密钥集文件,它使您能够在将来轮换密钥,并防止您意外硬编码一些不应该硬编码的东西。)
PM> KeyczarTool.exe create --location=path_to_key_set --purpose=crypt
PM> KeyczarTool.exe addkey --location=path_to_key_set --status=primary
Then in your code you can use any IO stream you want for both encryption:
然后在您的代码中,您可以使用您想要的任何 IO 流进行加密:
using(var encrypter = new Encrypter("path_to_key_set"))
{
encrypter.Encrypt(plaintextStream, ciphertextStream);
}
and decryption:
和解密:
using(var crypter = new Crypter("path_to_key_set"))
{
crypter.Decrypt(ciphertextStream, plaintextStream);
}