I'm trying to figure out how to encrypt / decrypt a string in VB.Net.
I followed the example given here and wrote the following code (below). There's a text box, an "encrypt" button, and a "decrypt" button. The idea is to type something into the text box ("like 'hello world'"), click "encrypt", and see the encrypted version appear in the text box. Clicking "decrypt" should then take you back to the original string.
But when I try to encrypt I get an error when I try to "FlushFinalBlock". The error is: "Length of the data to encrypt is invalid".
The "decrypt" part is a total shot in the dark, as the example quoted above only deals with encryption, not decryption. I'm sure it's wrong, but since I can't get "encrypt" to work I haven't tested it yet.
Can anyone tell me why this doesn't work?
Imports System.Data.SqlClient
Imports System.IO
Imports System.Security.Cryptography
Public Class Form1
Private cryptObj As RijndaelManaged
Private KEY_128 As Byte() = {42, 1, 52, 67, 231, 13, 94, 101, 123, 6, 0, 12, 32, 91, 4, 111, 31, 70, 21, 141, 123, 142, 234, 82, 95, 129, 187, 162, 12, 55, 98, 23}
Private IV_128 As Byte() = {234, 12, 52, 44, 214, 222, 200, 109, 2, 98, 45, 76, 88, 53, 23, 78}
Private enc As System.Text.UTF8Encoding = New System.Text.UTF8Encoding()
Private Sub btnEncrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEncrypt.Click
Dim sPlainText As String = Me.TextBox1.Text
If Not String.IsNullOrEmpty(sPlainText) Then
Dim bPlainText As Byte() = Me.enc.GetBytes(Me.TextBox1.Text)
Dim ms As MemoryStream = New MemoryStream()
Dim cs As CryptoStream = New CryptoStream(ms, cryptObj.CreateEncryptor(), CryptoStreamMode.Write)
cs.Write(bPlainText, 0, sPlainText.Length)
cs.FlushFinalBlock()
Me.TextBox1.Text = Me.enc.GetString(ms.ToArray())
End If
End Sub
Private Sub btnDecrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDecrypt.Click
Dim sCipherText = Me.TextBox1.Text
Dim ms As MemoryStream = New MemoryStream()
Dim cs As CryptoStream = New CryptoStream(ms, cryptObj.CreateDecryptor(), CryptoStreamMode.Read)
cs.Read(Me.enc.GetBytes(sCipherText), 0, sCipherText.Length)
Me.TextBox1.Text = Me.enc.GetString(ms.ToArray())
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.cryptObj = New RijndaelManaged()
Me.cryptObj.BlockSize = 128
Me.cryptObj.KeySize = 128
Me.cryptObj.Mode = CipherMode.ECB
Me.cryptObj.Padding = PaddingMode.None
Me.cryptObj.Key = KEY_128
Me.cryptObj.IV = IV_128
End Sub
End Class
Ultimately I found the answer here:
http://www.obviex.com/samples/Encryption.aspx
His example seems a little over-complicated. I'm sure it represents a more general and flexible case, but I was able to do away with the "saltPhrase", the "initVector", and the use of "PasswordDeriveBytes", which apparently is deprecated anyway, but I also avoided its nastily named replacement: Rfc2898DeriveBytes.
The following lets you enter a string of any length, encrypt it, and re-decrypt it.
Imports System.Data.SqlClient
Imports System.IO
Imports System.Security.Cryptography
Public Class Form1
Private enc As System.Text.UTF8Encoding
Private encryptor As ICryptoTransform
Private decryptor As ICryptoTransform
Private Sub btnEncrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEncrypt.Click
Dim sPlainText As String = Me.TextBox1.Text
If Not String.IsNullOrEmpty(sPlainText) Then
Dim memoryStream As MemoryStream = New MemoryStream()
Dim cryptoStream As CryptoStream = New CryptoStream(memoryStream, Me.encryptor, CryptoStreamMode.Write)
cryptoStream.Write(Me.enc.GetBytes(sPlainText), 0, sPlainText.Length)
cryptoStream.FlushFinalBlock()
Me.TextBox1.Text = Convert.ToBase64String(memoryStream.ToArray())
memoryStream.Close()
cryptoStream.Close()
End If
End Sub
Private Sub btnDecrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDecrypt.Click
Dim cypherTextBytes As Byte() = Convert.FromBase64String(Me.TextBox1.Text)
Dim memoryStream As MemoryStream = New MemoryStream(cypherTextBytes)
Dim cryptoStream As CryptoStream = New CryptoStream(memoryStream, Me.decryptor, CryptoStreamMode.Read)
Dim plainTextBytes(cypherTextBytes.Length) As Byte
Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
memoryStream.Close()
cryptoStream.Close()
Me.TextBox1.Text = Me.enc.GetString(plainTextBytes, 0, decryptedByteCount)
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim KEY_128 As Byte() = {42, 1, 52, 67, 231, 13, 94, 101, 123, 6, 0, 12, 32, 91, 4, 111, 31, 70, 21, 141, 123, 142, 234, 82, 95, 129, 187, 162, 12, 55, 98, 23}
Dim IV_128 As Byte() = {234, 12, 52, 44, 214, 222, 200, 109, 2, 98, 45, 76, 88, 53, 23, 78}
Dim symmetricKey As RijndaelManaged = New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Me.enc = New System.Text.UTF8Encoding
Me.encryptor = symmetricKey.CreateEncryptor(KEY_128, IV_128)
Me.decryptor = symmetricKey.CreateDecryptor(KEY_128, IV_128)
End Sub
End Class