使用AES加密文件时使用FileStream的异常 [英] Exception with FileStream when encrpyting files with AES

查看:99
本文介绍了使用AES加密文件时使用FileStream的异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,


我真的很挣这个例外。


我有一个用AES加密数据的功能(GCM )。我使用的是MemoryStream,但我只是因为文件较大而导致OOM错误。所以我刚刚切换到FileStream。但这给了我一个Cryptography.CryptographicException。我找不到任何解决方案,所以
我在这里问。


我的代码:

 

public static string EncryptString(string PlainString,byte [] KEY,byte [] AUTH_DATA,string BufferPath)
{
if(string.IsNullOrEmpty(PlainString))
{
抛出新的ArgumentNullException("嘿!我需要加密的文本在哪里?(PlainString为null或为空)");
}
if(KEY.Length == 0)
{
抛出新的ArgumentNullException("我需要一个关键来做魔术!(数组KEY的长度等于0) )");
}
if(AUTH_DATA.Length == 0)
{
抛出新的ArgumentNullException("我需要知道你是否知道这个词!(数组AUTH_DATA的长度)等于0");
}
使用(AuthenticatedAesCng aes = new AuthenticatedAesCng())
{
byte [] DATA = Encoding.UTF8.GetBytes(PlainString);
byte [] IV = GenerateIV();
byte [] saltbytes = new byte [] {1,2,3,4,5,6,7,8};
var key = new Rfc2898DeriveBytes (KEY,saltbytes,1000);
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
aes.CngMode = CngChainingMode.Gcm;
aes.AuthenticatedData = AUTH_D ATA;

使用(FileStream ms = new FileStream(BufferPath,FileMode.Create))
using(IAuthenticatedCryptoTransform THE_WIZARD = aes.CreateAuthenticatedEncryptor())
using(CryptoStream cs = new CryptoStream( ms,THE_WIZARD,CryptoStreamMode.Write))
{
//写入并检索加密数据
cs.Write(DATA,0,DATA.Length);
cs.FlushFinalBlock();
byte [] CHIPHER_TEXT = File.ReadAllBytes(BufferPath);

//获取TAG和新数组for hodling EncryptedData
byte [] TAG = THE_WIZARD.GetTag();
byte [] EncryptedData = new byte [CHIPHER_TEXT.Length + aes.IV.Length + AUTH_DATA.Length];

//用数据
aes.IV.CopyTo(EncryptedData,0)填充EncryptedData;
AUTH_DATA.CopyTo(EncryptedData,IV_LENGTH);
CHIPHER_TEXT.CopyTo(EncryptedData,IV_LENGTH + TAG_LENGTH);

//返回加密数据
返回Convert.ToBase64String(EncryptedData);
}

}

异常详情:


- 抛出:cs.Write(DATA,0,DATA.Length);


- e.Message = Er是een onjuiste参数doorgegeven een functie的一个服务(发送到的无效参数)服务或功能)


- HRESULT:-2146233296。



非常感谢任何帮助!




Hugo Woesthuis

解决方案

Hello HugoDev2002,

 byte [] CHIPHER_TEXT = File.ReadAllBytes(BufferPath); 
//获取TAG和新数组for hodling EncryptedData
byte [] TAG = THE_WIZARD.GetTag();
byte [] EncryptedData = new byte [CHIPHER_TEXT.Length + aes.IV.Length + AUTH_DATA.Length];

//用数据
aes.IV.CopyTo(EncryptedData,0)填充EncryptedData;

byte [] CHIPHER_TEXT = File.ReadAllBytes(BufferPath);




上面的代码显示您一次读取所有字节并重新创建一个与之前具有相同长度的字节数组。当您尝试读取大文件时,这是一项疯狂的内存工作。至于解决方法,您需要将文件字节分成块。在AES标准
规范中,每个块只能包含128位(16字节)。你可以使用下面的方法来读取每个块。

 using(FileStream fs = new FileStream(fileName,FileMode.Open,FileAccess.Read))
{
var buffer = new byte [bufferCapacity];
fs.Read(buffer,0,bufferCapacity);
}

或者您可以使用
构造函数
  of Memory类到特定大小。(我不建议)

 MemoryStream(int capacity)

祝你好运,


Neil Hu


Hi there,

I am really struggling with this exception.

I have a function to encrypt data with AES (GCM). I was using a MemoryStream, but I was only getting OOM errors with larger files. So I just switched to a FileStream. But that gives me an Cryptography.CryptographicException. I can't find any solution, so I ask here.

My code:

public static string EncryptString(string PlainString, byte[] KEY, byte[] AUTH_DATA, string BufferPath) { if (string.IsNullOrEmpty(PlainString)) { throw new ArgumentNullException("Hey! Where is the text I need to encrypt? (PlainString is null or empty)"); } if (KEY.Length == 0) { throw new ArgumentNullException("I need a key to do magic! (The length of the array KEY equals 0)"); } if (AUTH_DATA.Length == 0) { throw new ArgumentNullException("I need to know if you know the word! (The length of the array AUTH_DATA equals 0"); } using (AuthenticatedAesCng aes = new AuthenticatedAesCng()) { byte[] DATA = Encoding.UTF8.GetBytes(PlainString); byte[] IV = GenerateIV(); byte[] saltbytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; var key = new Rfc2898DeriveBytes(KEY, saltbytes, 1000); aes.KeySize = 256; aes.BlockSize = 128; aes.Key = key.GetBytes(aes.KeySize/8); aes.IV = key.GetBytes(aes.BlockSize / 8); aes.CngMode = CngChainingMode.Gcm; aes.AuthenticatedData = AUTH_DATA; using (FileStream ms = new FileStream(BufferPath, FileMode.Create)) using (IAuthenticatedCryptoTransform THE_WIZARD = aes.CreateAuthenticatedEncryptor()) using (CryptoStream cs = new CryptoStream(ms, THE_WIZARD, CryptoStreamMode.Write)) { // Write through and retrieve encrypted data cs.Write(DATA, 0, DATA.Length); cs.FlushFinalBlock(); byte[] CHIPHER_TEXT = File.ReadAllBytes(BufferPath); //Get TAG and new array for hodling EncryptedData byte[] TAG = THE_WIZARD.GetTag(); byte[] EncryptedData = new byte[CHIPHER_TEXT.Length + aes.IV.Length + AUTH_DATA.Length]; //Fill EncryptedData with the data aes.IV.CopyTo(EncryptedData, 0); AUTH_DATA.CopyTo(EncryptedData, IV_LENGTH); CHIPHER_TEXT.CopyTo(EncryptedData, IV_LENGTH + TAG_LENGTH); //Return encrypted data return Convert.ToBase64String(EncryptedData); } }

Exception details:

- Throws at: cs.Write(DATA, 0, DATA.Length);

- e.Message = Er is een onjuiste parameter doorgegeven aan een service of een functie (Invalid parameter sent to service or function)

- HRESULT: -2146233296.

Any help is very appreciated!


Hugo Woesthuis

解决方案

Hello HugoDev2002,

byte[] CHIPHER_TEXT = File.ReadAllBytes(BufferPath);
//Get TAG and new array for hodling EncryptedData
byte[] TAG = THE_WIZARD.GetTag();
byte[] EncryptedData = new byte[CHIPHER_TEXT.Length + aes.IV.Length + AUTH_DATA.Length];

//Fill EncryptedData with the data
aes.IV.CopyTo(EncryptedData, 0);

byte[] CHIPHER_TEXT = File.ReadAllBytes(BufferPath);


The above code shows that you read all bytes one time and recreate a byte array that has the same length with previous. It's crazy memory job when you try to read large files. As for a workaround, You need divide the file bytes into blocks. In the AES standard specification, the each block can only contain 128 bits(16 Byte). You could use the below method to read each blocks.

using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
   var buffer = new byte[bufferCapacity ]; 
   fs.Read(buffer, 0, bufferCapacity);
}

Or you could use constructor of Memory class to specific size.(I don't suggest)

MemoryStream(int capacity)

Best regards,

Neil Hu


这篇关于使用AES加密文件时使用FileStream的异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆