简体   繁体   English

如何从AES 256加密文件中获取文件类型

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

I'm trying to make a console application that can encrypt and decrypt file. 我正在尝试制作一个可以加密和解密文件的控制台应用程序。 I gave encrypted file a custom file extension ".aes" (eg samplefile.aes) now the problem is when I decrypt the file there is no way to identify what is the original extension of the file when it was encrypted. 我给加密文件一个自定义文件扩展名“ .aes”(例如samplefile.aes),现在的问题是,当我解密该文件时,没有办法确定加密后文件的原始扩展名是什么。 Is there any chance I can get file type from AES 256 encrypted file ? 我是否有可能从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;
        }
    }
}

I know that the nature of encrypted file is not to identify original extension. 我知道加密文件的本质不是识别原始扩展名。 What I was going to do is that when I encrypt the file I will give it .originalextension.aes (eg picture.png.aes) and then when I decrypt it I just need to remove .aes extension. 我要做的是,当我加密文件时,将给它.originalextension.aes(例如picture.png.aes),然后当我对其解密时,我只需要删除.aes扩展名。 Just wondering is this a good way or not? 只想知道这是一个好方法吗?

If the file type is required to be hidden by the encryption or not is a user requirement. 用户是否需要通过加密隐藏文件类型。 You may just want to protect the content and not the file type. 您可能只想保护内容而不是文件类型。 Note that the file size can also give hints to an "attacker". 请注意,文件大小还可以提示“攻击者”。 It's also up to you if you need to hide that kind of meta-data. 是否需要隐藏这种元数据也取决于您。

Without the extension you may have a look at the file contents by using file fingerprinting. 如果没有扩展名,您可能会使用文件指纹查看文件内容。 Many file formats give some kind of hint on what they are. 许多文件格式都会提示它们是什么。 For instance, it's certainly possible to guess the character encoding of .txt files. 例如,当然可以猜测.txt文件的字符编码。 JPG files have JPG headers, same goes for zip archives etc. etc. Usually these tools output the MIME file type (as the extension is not always that well defined or standardized). JPG文件具有JPG标头,zip存档等也具有此类标头。通常,这些工具输出MIME文件类型(因为扩展名不一定总是定义或标准化得很好)。

On GNU systems you may use the file command line for that. 在GNU系统上,您可以使用file命令行。 This kind of fingerprinting is also used for many content management systems (CMS). 这种指纹也可用于许多内容管理系统(CMS)。 So you can have a look at the CMS in your language and try to filter out the file command functionality in there. 因此,您可以使用您的语言查看CMS,并尝试在其中过滤掉file命令功能。

Or, now you know the right search keywords, you can simply find it here on StackOverflow: Using .NET, how can you find the mime type of a file based on the file signature not the extension was given as 3rd hit when typing in "fingerprint file type c# mime". 或者,现在您知道了正确的搜索关键字,您可以在StackOverflow上的此处找到它: 使用.NET,如何根据文件签名(而不是将扩展名作为第3个匹配项输入时)给出文件的MIME类型?指纹文件类型为c#mime”。

Note that, because extensions are not always that well defined, you may not get back the original extension this way. 请注意,由于扩展名的定义并不总是那么好,因此您可能无法以这种方式找回原始扩展名。 To allow this you need to store the extension in plaintext (in the filename) growing the file name size (!) or you can store it encrypted together with the data. 为此,您需要将扩展​​名以纯文本格式(在文件名中)存储,以增加文件名大小(!),也可以将其与数据一起加密存储。 You'd have to create an encryption protocol for that. 您必须为此创建一个加密协议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM