2016-12-05 240 views
1

我想通過AES在C#中製作一個加密/解密程序。 這裏是我的代碼:c#AES解密

using System; 
using System.IO; 
using System.Text; 
using System.Linq; 
using System.Security.Cryptography; 

namespace encryptingApp 
{ 
    public class AES_Crypt 
    { 
     public static void Main() 
     { 
      string text = "this-needs-to-be-encrypted"; 

      string IV = "0000000000000000"; 

      int ivBlockSize = 16; 

      string key = "00000000000000000000000000000000"; 

      int keySize = 32; 

      string encriptedText = Encrypt(text,key,IV); 

      string decrypted = Decrypt(encriptedText, key, ivBlockSize); 

     } 


     public static string Encrypt(string clearText, string key, string iv) 
     { 

      byte[] textBytes=GetBytes(clearText); 


      using (Aes encryptor = Aes.Create()) 
      { 
       encryptor.IV = GetBytes(iv); 
       encryptor.Key = GetBytes(key); 

       using (MemoryStream ms = new MemoryStream()) 
       { 

        using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(encryptor.Key,encryptor.IV), CryptoStreamMode.Write)) 
        { 
         cs.Write(textBytes, 0, textBytes.Length); 
         cs.Close(); 
        } 
        string rv= iv + ByteToHex(ms.ToArray()).ToLower(); 

        clearText = Base64Encode(rv); 
       } 
      } 
      return clearText; 
     } 



     public static string Decrypt(string encriptedText, string key, int ivBlockSize) 
     { 
      string decryptedText = null; 

      string fullText=Base64Decode(encriptedText); 

      string realIV = fullText.Substring(0 , ivBlockSize); 

      string cypherText = fullText.Substring(ivBlockSize, fullText.Length - ivBlockSize - 1); 


      byte[] cypherTextInBytes = HexToByte(cypherText); 

      using (Aes decryptor = Aes.Create()) 
      {  
       decryptor.Key = GetBytes(key); 

       decryptor.IV = GetBytes(realIV); 

       decryptor.Mode = CipherMode.CBC; 

       using (MemoryStream ms = new MemoryStream()) 
       { 
        using (CryptoStream cs = new CryptoStream(ms, decryptor.CreateDecryptor(decryptor.Key,decryptor.IV), CryptoStreamMode.Read)) 
        { 
         using (var sr = new StreamReader(cs)) 
         { 
          decryptedText = sr.ReadToEnd(); 
         } 

        } 

       } 
      } 
      return decryptedText; 
     } 

     static byte[] GetBytes(string str) 
     { 
      return System.Text.Encoding.UTF8.GetBytes(str); 
     } 

     static string GetString(byte[] bytes) 
     { 
      return System.Text.Encoding.UTF8.GetString(bytes); 
     } 

     public static string Base64Encode(string plainText) 
     { 
       var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); 
       return System.Convert.ToBase64String(plainTextBytes); 
     } 

     public static string Base64Decode(string base64EncodedData) 
     { 
      var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); 
      return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); 
     } 

     public static string ByteToHex(byte[] ba) 
     { 
      return BitConverter.ToString(ba).Replace("-", "").ToLower(); 
     } 


     public static byte[] HexToByte(string hex) 
     { 

      byte[] arr = new byte[hex.Length >> 1]; 

      for (int i = 0; i <hex.Length>> 1; ++i) 
      { 
       arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); 
      } 

      return arr; 
     } 

     public static int GetHexVal(char hex) 
     { 
      int val = (int) hex; 
      return val - (val < 58 ? 48 : 87); 
     } 


    } 
} 

加密函數做他的工作非常出色,並返回我正確的加密文本。問題存在於Decrypt函數中,一切順利(我一直在屏幕上打印我的變量),直到StreamReader使用.ReadToEnd()。我得到一個CryptographyException(我得到相同的異常兩次在只有一個exectuion):

Unhandled Exception: 
System.Security.Cryptography.CryptographicException: Bad PKCS7 padding. Invalid length 0.   
at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (System.Security.Cryptography.PaddingMode padding, System.Int32 length, System.Int32 position) [0x0005c] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00179] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00034] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.Security.Cryptography.CryptoStream.Read (System.Byte[] buffer, System.Int32 offset, System.Int32 count) [0x00318] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.StreamReader.ReadBuffer() [0x0002b] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.StreamReader.ReadToEnd() [0x00055] in <8f2c484307284b51944a1a13a14c0266>:0 
at encryptingApp.AES_Crypt.Decrypt (System.String encriptedText, System.String key, System.Int32 ivBlockSize) [0x000e4] in <f27b48dde1ea4b788e8038439b4bdb55>:0 
at encryptingApp.AES_Crypt.Main() [0x000e0] in <f27b48dde1ea4b788e8038439b4bdb55>:0 


[ERROR] FATAL UNHANDLED EXCEPTION: System.Security.Cryptography.CryptographicException: Bad PKCS7 padding. Invalid length 0.  
at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (System.Security.Cryptography.PaddingMode padding, System.Int32 length, System.Int32 position) [0x0005c] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00179] in <8f2c484307284b51944a1a13a14c0266>:0 
at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00034] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.Security.Cryptography.CryptoStream.FlushFinalBlock() [0x0001b] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.Security.Cryptography.CryptoStream.Dispose (System.Boolean disposing) [0x00011] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.Stream.Close() [0x00000] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.StreamReader.Dispose (System.Boolean disposing) [0x0001c] in <8f2c484307284b51944a1a13a14c0266>:0 
at System.IO.TextReader.Dispose() [0x00000] in <8f2c484307284b51944a1a13a14c0266>:0 
at encryptingApp.AES_Crypt.Decrypt (System.String encriptedText, System.String key, System.Int32 ivBlockSize) [0x000f8] in <f27b48dde1ea4b788e8038439b4bdb55>:0 
at encryptingApp.AES_Crypt.Main() [0x000e0] in <f27b48dde1ea4b788e8038439b4bdb55>:0 

我想我應該可以解決的StreamReader,但我不知道該怎麼辦,我已經好幾個小時了!看來這個程序正在嘗試讀取長度爲0或者其他東西的東西。

我甚至試圖通過互聯網尋找更多的解密功能,但他們都沒有爲我工作(我沒有RijndaelManaged也沒有鹽)。我在MacOS編譯。

+0

錯誤的解密也可能導致錯誤的填充錯誤。對於調試嘗試解密沒有PKCS#7填充和檢查結果,看看它是否正確解密,以避免填充錯誤,它可能不是。 – zaph

+0

但我沒有選擇用PKCS7解密。你知道我該如何禁用它嗎? –

+0

閱讀文檔並挖掘到默認值。請注意,如果沒有填充加密,則限制輸入的長度爲塊大小的精確倍數,因此通常需要填充。 – zaph

回答

0

爲什麼你的代碼中有太多的字符串?密碼學處理字節,擺脫所有的字符串。

  • 您的IV(理想情況下應該由Encrypt生成/發送,不傳遞給它)讀取爲UTF-8字符串。如果它有任何不是ASCII 0-127的字符,它將不會有長度爲1:1的字符串長度爲byte []長度。
    • 它也真難爲你提供一個字符串與IV 0x00000000000000000000000000000003
  • 類似爲您的鑰匙。
  • 您正在發佈爲IV +密文blob Base64Encode(UTF8Bytes(Concat(ivString,Hex(ciphertextBytes))))。
    • Base64Encode(Concat(ivBytes,ciphertextBytes))涉及兩個較少的轉換。所以它不太容易出錯,而且速度更快。
  • 當你進入解密你做正確適用所有的變換來撤消你做了什麼,但你需要知道外面有多少個字符組成IV。由於您已將UTF8處理添加到混音中,因此您並不知道它。
    • 所以你解密IV得到了如下處理
      • Base64Decode
      • UTF8BytesToString
      • 子串
      • UTF8StringToBytes
    • 如果沒有涉及到的字符串你得到的也Base64Decode和複製。

我的直覺是,如果你只是把一切都爲你byte[]問題就會迎刃而解。 (是的,你要保護的數據可以是文本,所以用UTF8StringToBytes直接擊球就可以了)