【问题标题】:How to get file type from AES 256 encrypted file如何从 AES 256 加密文件中获取文件类型
【发布时间】:2016-07-19 04:31:18
【问题描述】:

我正在尝试制作一个可以加密和解密文件的控制台应用程序。我给加密文件一个自定义文件扩展名“.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 扩展名。只是想知道这是不是一个好方法?

【问题讨论】:

  • 您可以在包含您想要的任何元数据(例如原始文件名)的文件数据前添加一个定义明确的标题,然后加密所有内容。如果您不关心披露扩展名,您可以将标头添加到加密数据中。
  • 您应该使用派生密钥而不是密码的哈希值。

标签: c# encryption cryptography aes


【解决方案1】:

是否需要加密隐藏文件类型是用户要求。您可能只想保护内容而不是文件类型。请注意,文件大小也可以提示“攻击者”。是否需要隐藏此类元数据也取决于您。

如果没有扩展名,您可以使用文件指纹来查看文件内容。许多文件格式对它们是什么给出了某种暗示。例如,当然可以猜测 .txt 文件的字符编码。 JPG 文件具有 JPG 标头,zip 档案等也是如此。通常这些工具输出 MIME 文件类型(因为扩展名并不总是那么明确或标准化)。

在 GNU 系统上,您可以使用 file 命令行。这种指纹识别也用于许多内容管理系统 (CMS)。因此,您可以查看以您的语言显示的 CMS,并尝试过滤掉其中的 file 命令功能。

或者,现在您知道正确的搜索关键字,您可以在 StackOverflow 上找到它:Using .NET, how can you find the mime type of a file based on the file signature not the extension 在输入“指纹文件类型 c# mime”时被列为第三次点击。

请注意,由于扩展名的定义并不总是那么明确,因此您可能无法以这种方式取回原始扩展名。为此,您需要以明文(在文件名中)存储扩展名以增加文件名大小(!),或者您可以将其与数据一起加密存储。你必须为此创建一个加密协议。

【讨论】:

    猜你喜欢
    • 2016-11-14
    • 2020-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多