2016-07-19 11 views
2

ファイルを暗号化および復号化できるコンソールアプリケーションを作成しようとしています。暗号化されたファイルにカスタムファイル拡張子「.aes」(例:samplefile.aes)を付けました。問題は暗号化されたファイルの元の拡張子を特定する方法がないためです。 AES 256暗号化ファイルからファイルタイプを取得する可能性はありますか?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拡張子を削除するだけで済むということです。ちょうどこれが良い方法かどうか疑問に思っていますか?

+0

元のファイル名などすべてのメタデータを含むファイルデータに、あらかじめ定義されたヘッダーを追加して、すべてを暗号化します。拡張子の開示が気にならない場合は、ヘッダを暗号化されたデータの前に付けることができます。 –

+0

パスワードのハッシュではなく、派生キーを使用する必要があります。 –

答えて

0

暗号化によってファイルの種類を隠す必要がある場合は、ユーザーの要件です。ファイルの種類ではなく、コンテンツを保護したいだけかもしれません。ファイルサイズは "攻撃者"にヒントを与えることもできます。この種のメタデータを非表示にする必要がある場合は、それもあなた次第です。

拡張子がないと、ファイルのフィンガープリントを使用してファイルの内容を確認することができます。多くのファイル形式は、それらが何であるかのヒントを与えます。たとえば、.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」を入力するときに3番目のヒットとして与えられました。

拡張機能は必ずしも明確に定義されているわけではないので、元の拡張機能をこのように戻すことはできません。これを可能にするには、拡張子を平文(ファイル名で)に保存してファイル名のサイズ(!)を増やすか、データと共に暗号化して保存する必要があります。そのために暗号化プロトコルを作成する必要があります。