2011-06-24 42 views
1

我試圖使用對稱加密來加密一些數據,並存儲解密數據到MemoryStream中所需的密鑰。 (雖然我知道這一點在安全方面確實很愚蠢,但我將使用RSA來加密對稱密鑰。不過,現在我試圖讓這部分工作。)在VB.NET中,將AES密鑰和加密數據寫入同一個MemoryStream不起作用

I使用FileHelpers庫解析我的分隔符(分號,因爲我不認爲我會在數據中有分號)的數據。不幸的是,在我的解密函數中,當它解析時,它只返回一條記錄。而且,如果我顯示在該函數結尾處創建的整個加密數據字符串,它似乎不會使用多個記錄。

我想知道是否當我創建新的cryptostream時,它默認爲內存流的開始,所以當我編寫我的加密數據時,它會覆蓋剛剛寫入內存流的數據。你認爲這是對的嗎?

感謝您的幫助!

Private Function Encrypt(ByVal data As String) As String 
    Dim utf8 As New UTF8Encoding 
    ' Convert string data to byte array 
    Dim inBytes() As Byte = utf8.GetBytes(data) 
    ' Create memory stream for storing the data we've manipulated 
    Dim ms As New MemoryStream() 

    Dim aes As New RijndaelManaged() 
    aes.KeySize = 256 

    Dim cs As New CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write) 

    ' Write key to beginning of memory stream 
    ms.Write(aes.Key, 0, aes.Key.Length) 
    ' Add semicolon delimiter to memory stream 
    ms.Write(utf8.GetBytes(";"), 0, utf8.GetBytes(";").Length) 
    ' Write IV to memory stream 
    ms.Write(aes.IV, 0, aes.IV.Length) 
    ' Write semicolon delimiter to memory stream 
    ms.Write(utf8.GetBytes(";"), 0, utf8.GetBytes(";").Length) 
    ' Ensure that the data we've just written is in the memory stream, before 
    ' we add the encrypted data 
    ms.Flush() 

    ' Write the encrypted data 
    cs.Write(inBytes, 0, inBytes.Length) ' encrypt 
    cs.FlushFinalBlock() 

    ' Return encrypted data as string 
    Return Convert.ToBase64String(ms.GetBuffer(), 0, ms.Length) 
End Function 

回答

1

下面是如何實現這一目的的快速示例。我已經包含了EncryptDecrypt,因爲在雙方都遵循相同的模式顯然很重要。我會留下相關的錯誤檢查等給你:)

Imports System.Security.Cryptography 
Imports System.IO 
Imports System.Text 

Module Module1 

    Sub Main() 
    Dim encrypted As String = Encrypt("Here is the data") 
    Dim decrypted As String = Decrypt(encrypted) 
    Console.WriteLine(decrypted) 
    Console.ReadKey() 
    End Sub 

    Private Function Encrypt(clearText As String) As String 
    Dim aes As New RijndaelManaged 
    aes.KeySize = 256 

    Using ms As New MemoryStream 
     ms.WriteByte(aes.Key.Length) 
     ms.Write(aes.Key, 0, aes.Key.Length) 
     ms.WriteByte(aes.IV.Length) 
     ms.Write(aes.IV, 0, aes.IV.Length) 

     Using cs As New CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write) 
     Dim bytes() As Byte = Encoding.UTF8.GetBytes(clearText) 
     cs.Write(bytes, 0, bytes.Length) 
     End Using 

     Return Convert.ToBase64String(ms.ToArray()) 
    End Using 
    End Function 

    Private Function Decrypt(cipherText As String) As String 
    Dim ms As New MemoryStream(Convert.FromBase64String(cipherText)) 

    Dim keyLength As Byte = ms.ReadByte() 
    Dim key(keyLength - 1) As Byte 
    ms.Read(key, 0, keyLength) 

    Dim ivLength As Byte = ms.ReadByte() 
    Dim iv(ivLength - 1) As Byte 
    ms.Read(iv, 0, ivLength) 

    Dim dataOffset As Integer = ms.Position 

    Dim aes As New RijndaelManaged() 
    aes.Key = key 
    aes.IV = iv 

    Using cs As New CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read) 
     Using sr As New StreamReader(cs, Encoding.UTF8) 
     Return sr.ReadToEnd() 
     End Using 
    End Using 
    End Function 
End Module 
1

你爲什麼要寫內存流?直接寫入Crypto流,然後從內存流中讀取加密的數據。這是一個C#版本的AES加密。

aesEncryptor是你aes.CreateEncryptor()

 private byte[] encryptWithAes(ICryptoTransform aesEncryptor, byte[] data) 
     { 
      MemoryStream memStream = null; //stream to write encrypted data to 
      CryptoStream cryptoStream = null; //crypto stream to encrypt data 

      try 
      { 
       memStream = new MemoryStream(); 

       //initiate crypto stream telling it to write the encrypted data to the memory stream 
       cryptoStream = new CryptoStream(memStream, aesEncryptor, CryptoStreamMode.Write); 

       //write the data to the memory stream 
       cryptoStream.Write(data, 0, data.Length); 
      } 
      catch (Exception ee) 
      { 
       //rethrow 
       throw new Exception("Error while encrypting with AES: ", ee); 
      } 
      finally 
      { 
       //close 'em 
       if (cryptoStream != null) 
        cryptoStream.Close(); 
       if (memStream != null) 
        memStream.Close(); 
      } 

      //return the encrypted data 
      return memStream.ToArray(); 
     } 

這可以被稱爲例如:

public byte[] doEncrypt(byte[] dataToEncrypt) 
{ 
      RijndaelManaged aesAlg = new RijndaelManaged(); 
      aesAlg.KeySize = AES_KEY_SIZE; 
      aesAlg.GenerateKey(); 
      aesAlg.GenerateIV(); 
      aesAlg.Mode = CipherMode.CBC; 
      aesAlg.Padding = PaddingMode.PKCS7; 

      byte[] aesKey = aesAlg.Key; 
      byte[] aesIV = aesAlg.IV; 

      byte[] encryptedData = encryptWithAes(aesAlg.CreateEncryptor(), dataToEncrypt); 

      //store your aesKey, aesIV, and encryptedData together however you want 
} 

你不應該delemit二進制數據與任何字符,監守當你去再回來,你會讀數據必須對整個緩衝區進行編碼,包括密鑰和IV,一旦編碼完畢,就可以在任意位置隨機選擇分隔符。而是將密鑰長度存儲爲一個字節,然後存儲密鑰。當您讀取數據時,您可以將第一個字節(密鑰長度)作爲整數讀取,然後知道要讀取多少密鑰。這對你有意義嗎?

+0

我正在寫密鑰和IV到內存流,因爲我想保持這樣的數據可以解密。我的目標是每次隨機生成對稱密鑰,然後用戶使用RSA密鑰對其進行加密。因此,我需要用加密數據存儲對稱密鑰。 –

+0

@Sam,那個內存流應該只能被加密流用來寫加密的數據(並且爲你讀取加密的數據)。如果要存儲IV和密鑰,請使用不同的緩衝區,然後將其附加到從內存流中讀取的加密數據 –

+0

@Sam,添加了獲取IV,密鑰和加密數據的示例 –