How to encrypt / decrypt only first few bytes of a file (the rest should be unencrypted)?

瘦欲@ 提交于 2019-12-13 05:42:39

问题


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:

  1. read first 4 bytes as integer
  2. read encrypted stream as many bytes as your integer says
  3. decrypt and write no new file
  4. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!