如何仅加密/解密文件的前几个字节(其余部分应未加密)?
How to encrypt / decrypt only first few bytes of a file (the rest should be unencrypted)?
因此,我已经在 C# 中实现了加密/解密算法,该算法在加密/解密任何文件时都能正常工作。
我现在的问题是,我怎样才能只加密(然后解密)文件的前几个(兆)字节。
例如:我有一个 2GB 的文件,我只想加密其中的 3MB。
我尝试了一些方法,但没有任何效果如我所愿。我试图计算读取的字节数,如果读取的字节数超过限制(3MB),则停止加密并继续将正常(未加密数据)写入文件。但是解密后,出现了"padding"异常等等。再比如:我(用这个方法)"successfully"加密了一个50kb的.txt文件的20kb,但是解密后,.txt文件的最后一行还有一些 "strange" 字符 - 所以这不起作用(如果我想要 exaple 加密图像 - 仍然在解密后 "damaged")。
加密我用这个函数:
public static bool Encrypt(string inputFilePath, string outputfilePath, string EncryptionKey)
{
try
{
using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open))
{
using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create))
{
fsInput.Position = 0;
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (CryptoStream cs = new CryptoStream(fsOutput, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead;
int byteWriteCounter = 0;
do
{
bytesRead = fsInput.Read(buffer, 0, bufferLen);
//my method
if(byteWriteCounter <= 20000){ //if readed bytes <= 20kb
cs.Write(buffer, 0, bytesRead); // then encrypt
}else{ // if bytes are over 20kb
fsOutput.Write(buffer, 0, bytesRead); //write normal (unecrypted)
}
byteWriteCounter += bytesRead;
} while (bytesRead != 0);
return true;
}
}
}
}
}
catch (SystemException se)
{
Console.WriteLine(se);
return false;
}
}
对于解密(我用的)类似function/method:
public static bool Decrypt(string inputFilePath, string outputfilePath, string EncryptionKey)
{
try
{
using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open))
{
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create))
{
using (CryptoStream cs = new CryptoStream(fsOutput, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead;
int byteWriteCounter = 0;
do
{
bytesRead = fsInput.Read(buffer, 0, bufferLen);
//my method
if(byteWriteCounter <= 20000){ //if readed bytes <= 20kb
cs.Write(buffer, 0, bytesRead); // then decrypt
}else{ // if bytes are over 20kb
fsOutput.Write(buffer, 0, bytesRead); //write normal data
}
byteWriteCounter += bytesRead;
} while (bytesRead != 0);
}
}
}
}
return true;
}
catch (SystemException s)
{
Console.WriteLine(s);
return false;
}
}
为此,您需要确切知道加密流中有多少字节。在将加密流写入新的部分加密文件之前,您可以轻松地写入 4 个字节的整数。然后,当您解密文件时,您会读取前 4 个字节,并且您确切知道要使用 CryptoStream 读取多少字节。为此,您基本上需要按如下方式分块读取文件:
- 读取前 4 个字节作为整数
- 读取你的整数表示的字节数的加密流
- 解密并写入无新文件
- 从部分加密的文件到新的完全解密的文件未改变的字节数
因此,我已经在 C# 中实现了加密/解密算法,该算法在加密/解密任何文件时都能正常工作。 我现在的问题是,我怎样才能只加密(然后解密)文件的前几个(兆)字节。
例如:我有一个 2GB 的文件,我只想加密其中的 3MB。
我尝试了一些方法,但没有任何效果如我所愿。我试图计算读取的字节数,如果读取的字节数超过限制(3MB),则停止加密并继续将正常(未加密数据)写入文件。但是解密后,出现了"padding"异常等等。再比如:我(用这个方法)"successfully"加密了一个50kb的.txt文件的20kb,但是解密后,.txt文件的最后一行还有一些 "strange" 字符 - 所以这不起作用(如果我想要 exaple 加密图像 - 仍然在解密后 "damaged")。
加密我用这个函数:
public static bool Encrypt(string inputFilePath, string outputfilePath, string EncryptionKey)
{
try
{
using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open))
{
using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create))
{
fsInput.Position = 0;
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (CryptoStream cs = new CryptoStream(fsOutput, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead;
int byteWriteCounter = 0;
do
{
bytesRead = fsInput.Read(buffer, 0, bufferLen);
//my method
if(byteWriteCounter <= 20000){ //if readed bytes <= 20kb
cs.Write(buffer, 0, bytesRead); // then encrypt
}else{ // if bytes are over 20kb
fsOutput.Write(buffer, 0, bytesRead); //write normal (unecrypted)
}
byteWriteCounter += bytesRead;
} while (bytesRead != 0);
return true;
}
}
}
}
}
catch (SystemException se)
{
Console.WriteLine(se);
return false;
}
}
对于解密(我用的)类似function/method:
public static bool Decrypt(string inputFilePath, string outputfilePath, string EncryptionKey)
{
try
{
using (FileStream fsInput = new FileStream(inputFilePath, FileMode.Open))
{
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (FileStream fsOutput = new FileStream(outputfilePath, FileMode.Create))
{
using (CryptoStream cs = new CryptoStream(fsOutput, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
int bufferLen = 4096;
byte[] buffer = new byte[bufferLen];
int bytesRead;
int byteWriteCounter = 0;
do
{
bytesRead = fsInput.Read(buffer, 0, bufferLen);
//my method
if(byteWriteCounter <= 20000){ //if readed bytes <= 20kb
cs.Write(buffer, 0, bytesRead); // then decrypt
}else{ // if bytes are over 20kb
fsOutput.Write(buffer, 0, bytesRead); //write normal data
}
byteWriteCounter += bytesRead;
} while (bytesRead != 0);
}
}
}
}
return true;
}
catch (SystemException s)
{
Console.WriteLine(s);
return false;
}
}
为此,您需要确切知道加密流中有多少字节。在将加密流写入新的部分加密文件之前,您可以轻松地写入 4 个字节的整数。然后,当您解密文件时,您会读取前 4 个字节,并且您确切知道要使用 CryptoStream 读取多少字节。为此,您基本上需要按如下方式分块读取文件:
- 读取前 4 个字节作为整数
- 读取你的整数表示的字节数的加密流
- 解密并写入无新文件
- 从部分加密的文件到新的完全解密的文件未改变的字节数