簡體   English   中英

如何從AES 256加密文件中獲取文件類型

[英]How to get file type from AES 256 encrypted file

我正在嘗試制作一個可以加密和解密文件的控制台應用程序。 我給加密文件一個自定義文件擴展名“ .aes”(例如samplefile.aes),現在的問題是,當我解密該文件時,沒有辦法確定加密后文件的原始擴展名是什么。 我是否有可能從AES 256加密文件中獲取文件類型?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;

namespace FileEncryption
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Environment.ExitCode = 1;
                Console.Error.WriteLine(Strings.CommandlineUsage);
                return;
            }

            bool encrypt = args[0].StartsWith("-e", StringComparison.InvariantCultureIgnoreCase);
            bool decrypt = args[0].StartsWith("-d", StringComparison.InvariantCultureIgnoreCase);

            if (!(encrypt || decrypt))
            {
                Environment.ExitCode = 1;
                Console.Error.WriteLine(Strings.CommandlineUnknownMode);
                return;
            }

            string inputname = (args.Length >= 3) ? args[2] : null;

            if (inputname != null && !File.Exists(inputname))
            {
                Environment.ExitCode = 2;
                Console.Error.WriteLine(Strings.CommandlineInputFileNotFound);
                return;
            }

            byte[] passwordBytes = Encoding.UTF8.GetBytes(args[1]);
            // Hash the password with SHA256
            passwordBytes = SHA256Managed.Create().ComputeHash(passwordBytes);

            try
            {
                if (encrypt)
                {
                    //Encrypt file                   
                    byte[] bytesToBeEncrypted = File.ReadAllBytes(inputname);
                    byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);

                    //Save encrypted file
                    string fileEncrypted = inputname.Remove(inputname.IndexOf('.')) + ".aes";
                    File.WriteAllBytes(fileEncrypted, bytesEncrypted);
                }
                else
                {
                    byte[] bytesToBeDecrypted = File.ReadAllBytes(inputname);
                    byte[] bytesDecrypted = AES_Decrypt(bytesToBeDecrypted, passwordBytes);

                    string file = inputname;
                    File.WriteAllBytes(file, bytesDecrypted);
                }
                Environment.ExitCode = 0;
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(string.Format(Strings.CommandlineError, ex.Message));
            }        
        }


        //***********************************************************************************************
        // --- HELPER FUNCTIONS ---
        //*

        //Encrypt File
        public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
        {
            byte[] encryptedBytes = null;

            // Set your salt here, change it to meet your flavor:
            // The salt bytes must be at least 8 bytes.
            byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;

                    var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);

                    AES.Mode = CipherMode.CBC;

                    using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                        cs.Close();
                    }
                    encryptedBytes = ms.ToArray();
                }
            }

            return encryptedBytes;
        }

        //Decrypt File
        public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
        {
            byte[] decryptedBytes = null;

            // Set your salt here, change it to meet your flavor:
            // The salt bytes must be at least 8 bytes.
            byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

            using (MemoryStream ms = new MemoryStream())
            {
                using (RijndaelManaged AES = new RijndaelManaged())
                {
                    AES.KeySize = 256;
                    AES.BlockSize = 128;

                    var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
                    AES.Key = key.GetBytes(AES.KeySize / 8);
                    AES.IV = key.GetBytes(AES.BlockSize / 8);

                    AES.Mode = CipherMode.CBC;

                    using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
                        cs.Close();
                    }
                    decryptedBytes = ms.ToArray();
                }
            }

            return decryptedBytes;
        }
    }
}

我知道加密文件的本質不是識別原始擴展名。 我要做的是,當我加密文件時,將給它.originalextension.aes(例如picture.png.aes),然后當我對其解密時,我只需要刪除.aes擴展名。 只想知道這是一個好方法嗎?

用戶是否需要通過加密隱藏文件類型。 您可能只想保護內容而不是文件類型。 請注意,文件大小還可以提示“攻擊者”。 是否需要隱藏這種元數據也取決於您。

如果沒有擴展名,您可能會使用文件指紋查看文件內容。 許多文件格式都會提示它們是什么。 例如,當然可以猜測.txt文件的字符編碼。 JPG文件具有JPG標頭,zip存檔等也具有此類標頭。通常,這些工具輸出MIME文件類型(因為擴展名不一定總是定義或標准化得很好)。

在GNU系統上,您可以使用file命令行。 這種指紋也可用於許多內容管理系統(CMS)。 因此,您可以使用您的語言查看CMS,並嘗試在其中過濾掉file命令功能。

或者,現在您知道了正確的搜索關鍵字,您可以在StackOverflow上的此處找到它: 使用.NET,如何根據文件簽名(而不是將擴展名作為第3個匹配項輸入時)給出文件的MIME類型?指紋文件類型為c#mime”。

請注意,由於擴展名的定義並不總是那么好,因此您可能無法以這種方式找回原始擴展名。 為此,您需要將擴展​​名以純文本格式(在文件名中)存儲,以增加文件名大小(!),也可以將其與數據一起加密存儲。 您必須為此創建一個加密協議。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM