2013-03-01 88 views
3

我想加密/解密字節 - 我已經做了很多關於使用SystemManagementSecurity.Cryptography中的AESManaged類的AES算法的密鑰和IV的閱讀。我閱讀James Johnson對以下問題http://www.techques.com/question/1-7025135/My-Length-of-the-data-to-decrypt-is-invalid-error的回答,他建議您在加密例程中使用隨機IV,並將IV添加到加密消息中。解密函數從加密消息的開頭剝離隨機IV以初始化解密類,然後解密其餘的字節。我試圖在下面的代碼中做到這一點。但我不斷收到「解密數據的長度無效」。當我在加密後嘗試解密時出現錯誤消息。有人可能會對可能出現的問題有所瞭解。AES管理文件加密和解密和預先初始化矢量

 USAGE: (streamToEncrypt/streamToDecrypt are System.IO.Stream) 

 using (var cryptoHelper = new AESHelper()) 
     { 
      var encryptedBytes = cryptoHelper.Encrypt(AESHelper.StreamToByteArray(streamToEncrypt)); 

     } 


using (var cryptoHelper = new AESHelper()) 
     { 
      var decryptedBytes = cryptoHelper.Decrypt(AESHelper.StreamToByteArray(streamToDecrypt));        
     } 

public class AESHelper : IDisposable 
{  
    public AesManaged AESManaged; 
    internal ICryptoTransform Encryptor { get; set; } 
    internal ICryptoTransform Decryptor { get; set; } 
    private const string KEY = "2428GD19569F9B2C2341839416C8E87G"; 
    private static readonly byte[] Salt = Encoding.ASCII.GetBytes("?pt1$8f]l4g80"); 
    private const Int32 ITERATIONS = 1042; 


    internal AESHelper() 
    { 
     AESManaged = new AesManaged(); 
     AESManaged.BlockSize = AESManaged.LegalBlockSizes[0].MaxSize; 
     AESManaged.KeySize = AESManaged.LegalKeySizes[0].MaxSize;      
     AESManaged.Mode= CipherMode.CBC; 
    } 
    public void KeyGenerator() 
    { 
     var key = new Rfc2898DeriveBytes(KEY, Salt, ITERATIONS); 
     AESManaged.Key = key.GetBytes(AESManaged.KeySize/8);   
    } 
    public byte[] Encrypt(byte[] input) 
    { 
     KeyGenerator(); 
     var ms = new MemoryStream(); 
     //Random IV 
     Encryptor = AESManaged.CreateEncryptor(AESManaged.Key, AESManaged.IV); 
     //Add the IV to the beginning of the memory stream 
     ms.Write(BitConverter.GetBytes(AESManaged.IV.Length), 0, sizeof(int)); 
     ms.Write(AESManaged.IV, 0, AESManaged.IV.Length); 
     var cs = new CryptoStream(ms, 
      Encryptor, CryptoStreamMode.Write); 
     cs.Write(input, 0, input.Length); 
     cs.Close(); 
     return ms.ToArray(); 
    } 
    public byte[] Decrypt(byte[] input) 
    { 
     KeyGenerator(); 

     // Get the initialization vector from the encrypted stream 
     var ms = new MemoryStream(input); 
     AESManaged.IV = ReadByteArray(ms); 
     Decryptor = AESManaged.CreateDecryptor(AESManaged.Key, AESManaged.IV); 
     var cs = new CryptoStream(ms, 
     Decryptor, CryptoStreamMode.Write); 
     cs.Write(input, 0, input.Length); 
     cs.Close();//Error occurs here 
     return ms.ToArray(); 
    } 

    internal static byte[] ReadByteArray(Stream s) 
    { 
     var rawLength = new byte[sizeof(int)]; 
     if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length) 
     { 
      throw new SystemException("Stream did not contain properly formatted byte array"); 
     } 
     var buffer = new byte[16]; 
     if (s.Read(buffer, 0, buffer.Length) != buffer.Length) 
     { 
      throw new SystemException("Did not read byte array properly"); 
     } 

     return buffer; 
    } 
    internal static byte[] StreamToByteArray(Stream inputStream) 
    { 
     if (!inputStream.CanRead) 
     { 
      throw new ArgumentException(); 
     } 

     // This is optional 
     if (inputStream.CanSeek) 
     { 
      inputStream.Seek(0, SeekOrigin.Begin); 
     } 

     var output = new byte[inputStream.Length]; 
     var bytesRead = inputStream.Read(output, 0, output.Length); 
     Debug.Assert(bytesRead == output.Length, "Bytes read from stream matches stream length"); 
     return output; 
    } 
    public void Dispose() 
    { 
     if (AESManaged != null) 
      ((IDisposable) AESManaged).Dispose(); 

    }} 

提前

回答

3

非常感謝也許你已經解決了這一點,但我只是把我給別人誰面臨類似的問題的答案。

由於input數組中存在附加信息而發生錯誤。在public byte[] Encrypt(byte[] input)方法中,您在寫入加密數據之前正在寫入IV長度和IV。行:

ms.Write(BitConverter.GetBytes(AESManaged.IV.Length), 0, sizeof(int)); 
ms.Write(AESManaged.IV, 0, AESManaged.IV.Length); 

public byte[] Decrypt(byte[] input)方法你正在閱讀該信息,並使用讀取IV作爲AES算法初始化向量。一切都好。然後,您正在構建CryptoStreamCryptoStreamMode.Write並通過MemoryStream對象ms獲取解密的數據。但是,通過的input數組不僅包含加密的消息,還包含在加密過程中寫入的IV。這就是爲什麼它不能解密。

你需要做的克服,這是無論是從input陣列只提取密碼數據,並把它傳遞給什麼:cs.Write(cipherData, 0, cipherData.Length);或改變模式爲CryptoStreamMode.Read和使用cs.Read(outputBuff, 0, outputBuff.Length);

也不要使用相同的MemoryStream對象來讀寫,因爲在CryptoStream會寫入它後會有一些垃圾。

+0

感謝您的幫助 - 但我已經解決了這個問題,並且完成了您的建議 – Paul 2013-05-30 08:52:41