问题
So, I have implemented in C# Encryption / Decryption algorithm which works perfectly fine when Encrypting / Decrypting any file. And my question now is, how can I Encrypt (then Decrypt) only first few (mega)bytes of a file.
For example: I have a 2GB file and I want to encrypt only 3MB of this file.
I have tried some things, but nothing worked as I wanted to. I have tried to count readed bytes and if readed bytes are over the limit (3MB) then stop encrypting and just continue to write normal (unecrypted data) to file. But after decryption, the "padding" exception appeared, etc. Another example: I had (with this method) "successfully" encrypted 20kb of a 50kb .txt file, but after decryption, the last line in .txt file had still some "strange" charachters - so this is not working (If i want for exaple encrypted image - is still after decryption "damaged").
For encryption I use this function:
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;
}
}
For decryption (I use) is similar 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;
}
}
回答1:
To achieve this you need to know exactly how many bytes are in the encrypted stream. You can easily write integer, which is 4 bytes, before writing encrypted stream to your new partially encrypted file. Then, when you decrypt the file you read first 4 bytes, and you know exactly how many bytes to read with your CryptoStream. For this you basically need to read files in chunks as follows:
- read first 4 bytes as integer
- read encrypted stream as many bytes as your integer says
- decrypt and write no new file
- pump bytes unchanged from partially encrypted file to a new fully decrypted file
来源:https://stackoverflow.com/questions/27925571/how-to-encrypt-decrypt-only-first-few-bytes-of-a-file-the-rest-should-be-unen