• I removed the www from the URL, please update your bookmarks and pay attention to the bottom of the screen if using Google Chrome to allow push notifications again.

AES Encryption of a string

ahbenshaut

Well-known member
Joined
Oct 29, 2004
Messages
61
Location
Alaska
Programming Experience
5-10
greetings. I am trying to encrypt a string using the code below. The issue is I get this error and I have no clue (I'm just learning about encryption) what to do or even where to look. The SharedKey and the IV have been supplied as Hex values. The SharedKey is 64 bytes and the IV is 32 bytes.

System.Security.Cryptography.CryptographicException: 'Specified initialization vector (IV) does not match the block size for this algorithm.'

Code:
    Public Function Encrypt(ByVal strValue As String) As String
        'Create instance of a Rijndael Managed object
        Dim aes As New RijndaelManaged
        'Set appropriate values of object
        aes.Padding = PaddingMode.PKCS7
        aes.KeySize = 256
        aes.Mode = CipherMode.CBC
        'Create streams to work with encryption process
        Dim msEncrypt As New MemoryStream()
        'SharedKey = "64 byte string"
        'IV = "32 byte string"
        Dim SharedKey As Byte() = Encoding.GetEncoding(1252).GetBytes(strSharedKey)
        Dim IV As Byte() = Encoding.GetEncoding(1252).GetBytes(strIV)
        Dim csEncrypt As New CryptoStream(msEncrypt, aes.CreateEncryptor(SharedKey, IV), CryptoStreamMode.Write)
        'Convert string value to byte array
        Dim toEncrypt As Byte() = Encoding.GetEncoding(1252).GetBytes(strValue)
        toEncrypt = Encoding.Convert(Encoding.GetEncoding(1252), Encoding.UTF8, toEncrypt)
        'Perform encryption
        csEncrypt.Write(toEncrypt, 0, toEncrypt.Length)
        csEncrypt.FlushFinalBlock()
        'Return Base64 string
        Return Convert.ToBase64String(msEncrypt.ToArray())
        'Dim u As System.Text.UnicodeEncoding = System.Text.Encoding.Unicode
        'Dim a As System.Text.ASCIIEncoding = System.Text.Encoding.ASCII
        'Return a.GetByteCount(SharedKey)  '64 bytes
    End Function
Any help is mucho appreciated
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,276
Location
Norway
Programming Experience
10+
Look at .LegalBlockSizes/.LegalKeySizes, they are 128-256 bits which is 16-32 bytes. IV is usually equal to block size, default 16 bytes, but can be upped to 32 bytes it looks like.
 
Last edited:

ahbenshaut

Well-known member
Joined
Oct 29, 2004
Messages
61
Location
Alaska
Programming Experience
5-10
Well, I was able to get it to compile but I have no idea if the returned value is correct. this is what I did:

VB.NET:
    Public Function Encrypt(ByVal strValue As String) As String
        'Create instance of a Rijndael Managed object
        Dim aes As New RijndaelManaged
        'Set appropriate values of object
        aes.Padding = PaddingMode.PKCS7
        aes.KeySize = 256
        aes.Mode = CipherMode.CBC
        'Create streams to work with encryption process
        Dim msEncrypt As New MemoryStream()
        Dim SharedKey As Byte()
        'SharedKey = ""
        'IV = ""
        SharedKey = StringToByteArray(strSharedKey)
        Dim IV As Byte()
        IV = StringToByteArray(strIV)

        Dim csEncrypt As New CryptoStream(msEncrypt, aes.CreateEncryptor(SharedKey, IV), CryptoStreamMode.Write)
        'Convert string value to byte array
        Dim toEncrypt As Byte() = Encoding.GetEncoding(1252).GetBytes(strValue)
        toEncrypt = Encoding.Convert(Encoding.GetEncoding(1252), Encoding.UTF8, toEncrypt)
        'Perform encryption
        csEncrypt.Write(toEncrypt, 0, toEncrypt.Length)
        csEncrypt.FlushFinalBlock()
        'Return Base64 string
        Return Convert.ToBase64String(msEncrypt.ToArray())
    End Function

    Function StringToByteArray(text As String) As Byte()
        Dim bytes As Byte() = New Byte(text.Length \ 2 - 1) {}
        For i As Integer = 0 To text.Length - 1 Step 2
            bytes(i \ 2) = Byte.Parse(text(i).ToString() & text(i + 1).ToString(), System.Globalization.NumberStyles.HexNumber)
        Next
        Return bytes
    End Function
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,276
Location
Norway
Programming Experience
10+
It makes sense that the hex string is two hex digits per char (it can also be one) so you initially got twice key/IV the length.
You can also use this in your loop (16 is the number system base for hex):
VB.NET:
bytes(i / 2) = Convert.ToByte(text.Substring(i, 2), 16)
 
Last edited:

Herman

Well-known member
Joined
Oct 18, 2011
Messages
873
Location
Montreal, QC, CA
Programming Experience
10+
I have posted this code previously, but here it is again with the nice new code formatting... The following will encrypt strings using AES-256 and encode the result to base64, and also take a base64 string, decode it and decrypt it. This uses a unique salt every encryption (a random GUID), and the salt is prepended to the encrypted cipher text before encoding to base64. The decryption routine decodes to a byte array, and uses the salt and key to decrypt the ciphertext.

VB.NET:
Imports System.IO
Imports System.Text
Imports System.Security.Cryptography

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim MyPlainTextMessage As String = "Station 1 " & DateTime.Now.ToString()
        Dim MyKey As String = "00000000000000000000000000000000"

        Dim EncryptedCipherText As String = AESEncryptStringToBase64(MyPlainTextMessage, MyKey)

        Dim DecryptedPlainText As String = AESDecryptBase64ToString(EncryptedCipherText, MyKey)

        MessageBox.Show("Plain text: " & MyPlainTextMessage & vbCrLf & _
                        "Encrypted Base64 cipher: " & EncryptedCipherText & vbCrLf & _
                        "Decrypted plain text: " & DecryptedPlainText)
    End Sub

    Private Function AESEncryptStringToBase64(strPlainText As String, strKey As String) As String
        Dim Algo As RijndaelManaged = RijndaelManaged.Create()

        With Algo
            .BlockSize = 128
            .FeedbackSize = 128
            .KeySize = 256
            .Mode = CipherMode.CBC
            .IV = Guid.NewGuid().ToByteArray()
            .Key = Encoding.ASCII.GetBytes(strKey)
        End With


        Using Encryptor As ICryptoTransform = Algo.CreateEncryptor()
            Using MemStream As New MemoryStream
                Using CryptStream As New CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)
                    Using Writer As New StreamWriter(CryptStream)
                        Writer.Write(strPlainText)
                    End Using

                    AESEncryptStringToBase64 = Convert.ToBase64String(Algo.IV.Concat(MemStream.ToArray()).ToArray())
                End Using
            End Using
        End Using
    End Function

    Private Function AESDecryptBase64ToString(strCipherText As String, strKey As String) As String
        Dim arrSaltAndCipherText As Byte() = Convert.FromBase64String(strCipherText)

        Dim Algo As RijndaelManaged = RijndaelManaged.Create()

        With Algo
            .BlockSize = 128
            .FeedbackSize = 128
            .KeySize = 256
            .Mode = CipherMode.CBC
            .IV = arrSaltAndCipherText.Take(16).ToArray()
            .Key = Encoding.ASCII.GetBytes(strKey)
        End With


        Using Decryptor As ICryptoTransform = Algo.CreateDecryptor()
            Using MemStream As New MemoryStream(arrSaltAndCipherText.Skip(16).ToArray())
                Using CryptStream As New CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read)
                    Using Reader As New StreamReader(CryptStream)
                        AESDecryptBase64ToString = Reader.ReadToEnd()
                    End Using
                End Using
            End Using
        End Using
    End Function

End Class
 
Last edited:
Top Bottom