I'm attempting to use symmetric encryption to encrypt some data, and store the key necessary to decrypt with the data in a MemoryStream. (While I know that this alone is really dumb security-wise, I'm going to use RSA to encrypt the symmetric key. Right now, though, I'm trying to just get this part to work.)
I'm using the FileHelpers library to parse the data for my delimiter (the semicolon, as I don't believe I'll ever have a semicolon in the data). Unfortunately, in my decryption function, when it's parsing, it only returns back one record. And, if I show the entire string of encrypted data created at the end of this function, it doesn't appear to be using multiple records.
I'm wondering if when I create the new cryptostream, it's defaulting to the beginning of the memory stream, so when I write my encrypted data, it overwrites the data I had just written to the memory stream. Do you think that's right?
Thanks for your help!
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
Here is a quick sample of how you can achieve this. I have included both the Encrypt
and Decrypt
because it is obviously important that you follow the same pattern on both sides. I will leave the relevant error checking etc. to you :)
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