2013-10-18 53 views
1

我有這兩種方法哪個是幾乎複製粘貼+從http://support.microsoft.com/kb/307010C#DES文件解密最新非文本文件

當我解密的文件,如果他們是任何類型的文本文件如.txt,.xml或.html,等我可以開起來,一切都很好。任何類型的文件,不僅僅是文本,如.exe,.jpg,.pdf等,在解密時都會中斷。有什麼我做錯了嗎?這些方法使用二進制來加密/解密文件嗎?如果沒有,我可以使它成爲二進制嗎?

任何幫助,非常感謝!

public static void EncryptFile(string sInputFilename, 
     string sOutputFilename, 
     string sKey) 
    { 
     FileStream fsInput = new FileStream(sInputFilename, 
      FileMode.Open, 
      FileAccess.Read); 

     FileStream fsEncrypted = new FileStream(sOutputFilename, 
      FileMode.Create, 
      FileAccess.Write); 
     DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); 
     DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey); 
     DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey); 
     ICryptoTransform desencrypt = DES.CreateEncryptor(); 
     CryptoStream cryptostream = new CryptoStream(fsEncrypted, 
      desencrypt, 
      CryptoStreamMode.Write); 

     byte[] bytearrayinput = new byte[fsInput.Length]; 
     fsInput.Read(bytearrayinput, 0, bytearrayinput.Length); 
     cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length); 
     cryptostream.Close(); 
     fsInput.Close(); 
     fsEncrypted.Close(); 
    } 

    public static void DecryptFile(string sInputFilename, 
     string sOutputFilename, 
     string sKey) 
    { 
     DESCryptoServiceProvider DES = new DESCryptoServiceProvider(); 
     //A 64 bit key and IV is required for this provider. 
     //Set secret key For DES algorithm. 
     DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey); 
     //Set initialization vector. 
     DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey); 

     //Create a file stream to read the encrypted file back. 
     FileStream fsread = new FileStream(sInputFilename, 
      FileMode.Open, 
      FileAccess.Read); 
     //Create a DES decryptor from the DES instance. 
     ICryptoTransform desdecrypt = DES.CreateDecryptor(); 
     //Create crypto stream set to read and do a 
     //DES decryption transform on incoming bytes. 
     CryptoStream cryptostreamDecr = new CryptoStream(fsread, 
      desdecrypt, 
      CryptoStreamMode.Read); 
     //Print the contents of the decrypted file. 
     StreamWriter fsDecrypted = new StreamWriter(sOutputFilename); 
     fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd()); 
     fsDecrypted.Flush(); 
     fsDecrypted.Close(); 
     fsread.Close(); 
     cryptostreamDecr.Close(); 
    } 
+0

加密不在乎它正在加密的字節。 –

+0

我能以某種方式寫入額外的字節嗎?或者可能太少? –

回答

3

我不知道這是什麼寫的文章的傢伙在抽菸,但:

DESCryptoServiceProvider desCrypto = 
    (DESCryptoServiceProvider)DESCryptoServiceProvider.Create(); 

return ASCIIEncoding.ASCII.GetString(desCrypto.Key); 

不會讓你一個有效的密鑰。至少有一個問題是,用於加密的密鑰與您用於解密的密鑰不同,因爲您無法將字節轉換爲ASCII,並且像這樣返回。

如果你想治療的關鍵作爲一個字符串,你可能想要的是:

string keyAsString = Convert.ToBase64String(desCrypto.Key); 

然後,當你希望把它放回字節,而不是ASCIIEncoding.ASCII.GetBytes,你會做:

byte[] key = Convert.FromBase64String(keyAsString); 

編輯

有一噸多的錯文章了。我會說忽略那個,找到一個更好的例子。

編輯

這裏的工作的例子,我用我的標準的加密需要一個非常乾淨的基本AES。一些在物品上的主要改進有:

  • 正確創建的關鍵
  • 當前算法(AES 256位密鑰)的
  • 隨機IV
  • 緩衝文件的訪問,而不是讀/寫在一個塊
  • 包裝紙全部一次性對象整個文件中using

除此之外,它是相同的淺ic想法。

using System; 
using System.IO; 
using System.Security.Cryptography; 

namespace ConsoleApplication12 
{ 
    class Program 
    { 
     private const int KEY_SIZE_BYTES = 32; 
     private const int IV_SIZE_BYTES = 16; 

     static void Main(string[] args) 
     { 
      var rand = new Random(); 
      using (var fs = File.Open(@"C:\temp\input.bin", FileMode.Create, FileAccess.Write, FileShare.None)) 
      { 
       byte[] buffer = new byte[10000]; 
       for (int i = 0; i < 100; ++i) 
       { 
        rand.NextBytes(buffer); 
        fs.Write(buffer, 0, buffer.Length); 
       } 
      } 
      string key = GenerateRandomKey(); 
      Encrypt(@"C:\temp\input.bin", @"C:\temp\encrypted.bin", key); 
      Decrypt(@"C:\temp\encrypted.bin", @"C:\temp\decyrypted.bin", key); 
     } 

     static string GenerateRandomKey() 
     { 
      byte[] key = new byte[KEY_SIZE_BYTES]; 
      using (var rng = RandomNumberGenerator.Create()) 
      { 
       rng.GetBytes(key); 
      } 
      return Convert.ToBase64String(key); 
     } 

     static void Encrypt(string inputFile, string outputFile, string key) 
     { 
      const int BUFFER_SIZE = 8192; 
      byte[] buffer = new byte[BUFFER_SIZE]; 
      byte[] keyBytes = Convert.FromBase64String(key); 
      byte[] ivBytes = new byte[IV_SIZE_BYTES]; 
      using (var rng = RandomNumberGenerator.Create()) 
      { 
       rng.GetBytes(ivBytes); 
      } 
      using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
      { 
       using (var outputStream = File.Open(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) 
       { 
        outputStream.Write(ivBytes, 0, ivBytes.Length); 
        using (var cryptoAlgo = Aes.Create()) 
        { 
         using (var encryptor = cryptoAlgo.CreateEncryptor(keyBytes, ivBytes)) 
         { 
          using (var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write)) 
          { 
           int count; 
           while ((count = inputStream.Read(buffer, 0, buffer.Length)) > 0) 
           { 
            cryptoStream.Write(buffer, 0, count); 
           } 
          } 
         } 
        } 
       } 
      } 
     } 

     static void Decrypt(string inputFile, string outputFile, string key) 
     { 
      const int BUFFER_SIZE = 8192; 
      byte[] buffer = new byte[BUFFER_SIZE]; 
      byte[] keyBytes = Convert.FromBase64String(key); 
      byte[] ivBytes = new byte[IV_SIZE_BYTES]; 
      using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
      { 
       inputStream.Read(ivBytes, 0, ivBytes.Length); 
       using (var outputStream = File.Open(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) 
       { 
        using (var cryptoAlgo = Aes.Create()) 
        { 
         using (var decryptor = cryptoAlgo.CreateDecryptor(keyBytes, ivBytes)) 
         { 
          using (var cryptoStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read)) 
          { 
           int count; 
           while ((count = cryptoStream.Read(buffer, 0, buffer.Length)) > 0) 
           { 
            outputStream.Write(buffer, 0, count); 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 

因爲IV是隨機的,你會看到技術上的另一個小的差異。當加密文件時,你首先將IV寫入加密文件(這不是祕密,所以你直接寫出來)。當解密文件時,您會讀取前幾個字節來檢索IV,然後文件的其餘部分將包含實際的加密數據。隨機IV的目的是,每次運行它時,相同的明文文件都會加密成不同的加密文件。

這裏的Main方法演示加密,隨機密鑰。如果你想使用密碼,這是一個更多的工作,但你可以實現PBKDF2可能有十幾行代碼。

+0

好的,謝謝你的信息。我會盡力找到一個更好的例子。 –

+0

@LandonHammond我的答案已經用完整的AES示例進行了編輯。你可以用它作爲起點,並根據需要調整它。 –

+1

正如原始問題PBKDF2的註釋OP構建到.NET中一樣,它被稱爲[Rfc2898DeriveBytes](http://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rfc2898derivebytes.aspx ) –