• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 460
  • Last Modified:

VB.NET AES Encryption

Sorry, encryption newbie here.  Can someone provide some feedback on this AES encryption algorithm?
        Public Shared Function SampleEncryptAES2Base64(ByVal dataToEncrypt As String, ByVal Password As String) As String
            Dim keyBytes As Byte() = UTF8Encoding.UTF8.GetBytes(Password) 
            Dim rfc As New Rfc2898DeriveBytes(Password, keyBytes, 1000)

            ' Use the AES managed encryption provider
            Dim encryptor As New AesManaged()
            encryptor.Key = rfc.GetBytes(16)
            encryptor.IV = rfc.GetBytes(16)

            Using ms As New MemoryStream()
                Using encrypt As New CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)
                    Dim dataBytes As Byte() = New UTF8Encoding(False).GetBytes(dataToEncrypt)
                    encrypt.Write(dataBytes, 0, dataBytes.Length)
                    encrypt.FlushFinalBlock()
                    encrypt.Close()
                    Return Convert.ToBase64String(ms.ToArray())
                End Using
            End Using
        End Function

Open in new window

Specifically:
1) Is it possible to determine if this AES-128, 256 or 512?
2) Does the fact the encryptor.Key and encryptor.IV are the same make this less secure?

Thanks.
0
eeyo
Asked:
eeyo
  • 3
  • 3
  • 2
  • +1
3 Solutions
 
ste5anSenior DeveloperCommented:
1) The numbers in AES denote the KeySize. AesManaged support only keys up to 256 bit.

2) No. It makes it useless. Cause the IV is not a secret per se. But one of its properties is randomness. Thus Key=IV violates this. Also this value is often called nonce (number used once).
0
 
eeyoAuthor Commented:
Thanks.  Too bad it is limited to 256.
As for the key-IV issue: if I created a new variable as "rfcIV" as below with a different number of iterations as below, would this be more secure/random as the IV?
Dim rfc As New Rfc2898DeriveBytes(Password keyBytes, 1000)
Dim rfcIV As New Rfc2898DeriveBytes(Password, keyBytes, 1001)

Open in new window

0
 
ste5anSenior DeveloperCommented:
The IV is designed to get different output for the same key and plaintext. So that an attacker cannot count symbols or words or patterns. Thus it should be different for each message.
But when it is different for each message, how do I know it to decrypt a cipher? Cause you send the IV with message. That's also the reason, why the key should be never the calculation base of the IV, cause maybe there is inverse operation, which would reveal the key.
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
btanExec ConsultantCommented:
encryptor.Key = rfc.GetBytes(16) - from this it means 16 bytes which is 128bits so it is AES128
agree with expert, key = IV is wrong at the start. IV has the properties
  1. Unique: must not be repeated for any message encrypted with a given key
  2. Unpredictable: an attacker who observes any number of messages and their IVs should have no information to predict the next one with probability of success greater than 50% per bit (i.e., indistinguishable from random)
Use the RNGCryptoServiceProvider to generate cryptographically strong sequences.
Imports System.Security.Cryptography

Public Function GenerateKey(ByVal Length As Integer) As Byte()
    Dim ReturnArray(Length - 1) As Byte
    Using RNG As New RNGCryptoServiceProvider
        RNG.GetBytes(ReturnArray)
    End Using
    Return ReturnArray
End Function
Example usage:

AES.Key = GenerateKey(16)
AES.IV = GenerateKey(16)
0
 
eeyoAuthor Commented:
Thanks for the explanation, ste5an.  This makes sense for sending a series of messages.  However, if this is being used inside a desktop application to save and retrieve passwords, etc. from a handful (let's say 3) of local files (as private documents, not to be sent elsewhere through internet, etc.), would it make sense to just hard code a random IVs for the file?  As the file continues to be updated, would it be OK to continue to use the same IV or should I keep changing the IV with each file update and track the IV as well?
0
 
David Johnson, CD, MVPOwnerCommented:
 myAes.KeySize = 256

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

Module Module1


    Public Sub Main()
        Try

            Dim original As String = "Here is some data to encrypt!"

            ' Create a new instance of the AesCryptoServiceProvider
            ' class.  This generates a new key and initialization 
            ' vector (IV).
            Using myAes As New AesCryptoServiceProvider()
                myAes.KeySize = 256
                Console.WriteLine("256 / 8 = 32 should be " & myAes.Key.Length.ToString)
                Console.WriteLine("128 / 8 = 16 should be " & myAes.IV.Length.ToString)

                ' Encrypt the string to an array of bytes.
                Dim encrypted As Byte() = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV)

                ' Decrypt the bytes to a string.
                Dim roundtrip As String = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV)

                'Display the original data and the decrypted data.
                Console.WriteLine("Original:   {0}", original)
                Console.WriteLine("Round Trip: {0}", roundtrip)
            End Using
        Catch e As Exception
            Console.WriteLine("Error: {0}", e.Message)
        End Try
        Console.ReadKey()
    End Sub 'Main

    Function EncryptStringToBytes_Aes(ByVal plainText As String, ByVal Key() As Byte, ByVal IV() As Byte) As Byte()
        ' Check arguments.
        If plainText Is Nothing OrElse plainText.Length <= 0 Then
            Throw New ArgumentNullException("plainText")
        End If
        If Key Is Nothing OrElse Key.Length <= 0 Then
            Throw New ArgumentNullException("Key")
        End If
        If IV Is Nothing OrElse IV.Length <= 0 Then
            Throw New ArgumentNullException("IV")
        End If
        Dim encrypted() As Byte
        ' Create an AesCryptoServiceProvider object
        ' with the specified key and IV.
        Using aesAlg As New AesCryptoServiceProvider()

            aesAlg.Key = Key
            aesAlg.IV = IV

            ' Create a decrytor to perform the stream transform.
            Dim encryptor As ICryptoTransform = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV)

            ' Create the streams used for encryption.
            Dim msEncrypt As New MemoryStream()
            Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
                Using swEncrypt As New StreamWriter(csEncrypt)
                    'Write all data to the stream.
                    swEncrypt.Write(plainText)
                End Using
                encrypted = msEncrypt.ToArray()

            End Using
        End Using

        ' Return the encrypted bytes from the memory stream.
        Return encrypted

    End Function 'EncryptStringToBytes_Aes

    Function DecryptStringFromBytes_Aes(ByVal cipherText() As Byte, ByVal Key() As Byte, ByVal IV() As Byte) As String
        ' Check arguments.
        If cipherText Is Nothing OrElse cipherText.Length <= 0 Then
            Throw New ArgumentNullException("cipherText")
        End If
        If Key Is Nothing OrElse Key.Length <= 0 Then
            Throw New ArgumentNullException("Key")
        End If
        If IV Is Nothing OrElse IV.Length <= 0 Then
            Throw New ArgumentNullException("IV")
        End If
        ' Declare the string used to hold
        ' the decrypted text.
        Dim plaintext As String = Nothing

        ' Create an AesCryptoServiceProvider object
        ' with the specified key and IV.
        Using aesAlg As New AesCryptoServiceProvider()

            aesAlg.Key = Key
            aesAlg.IV = IV

            ' Create a decrytor to perform the stream transform.
            Dim decryptor As ICryptoTransform = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV)

            ' Create the streams used for decryption.
            Using msDecrypt As New MemoryStream(cipherText)

                Using csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)

                    Using srDecrypt As New StreamReader(csDecrypt)

                        ' Read the decrypted bytes from the decrypting stream
                        ' and place them in a string.
                        plaintext = srDecrypt.ReadToEnd()
                    End Using
                End Using
            End Using
        End Using
        Return plaintext

    End Function 'DecryptStringFromBytes_Aes 

End Module

Open in new window

0
 
btanExec ConsultantCommented:
As long as the IV remain unique to the each file, it is alright for "hardcode". The random would be generated from RNG. Reencryption of the same updated file does not need to change the existing IV.
0
 
eeyoAuthor Commented:
Thanks to all.  For any other newbies reading this later on, I figured out that the IV (Initiation Vector):
1) should be uniquely generated, preferably every time a new message needs to be encrypted.  This is mainly used to prevent someone from trying to look for patterns to crack the encrypted message.  Re-using the same IV makes it easier to crack.  Worse, don't generate the IV based off the password.  Even worse, don't make it the same as the password.
2) while the password can remain the same, the IV should be changed with every new message
3) can be manually generated or created through one of many cryptoservices
4) does not need to be "encrypted"
5) can be pre-pended to the beginning of a final encrypted stream.
6) during decryption, the unencrypted IV at the beginning of a stream can then be used with the password to decrypt the rest of the message stream (the encrypted payload)
7) therefore, no need to track or save the IV anywhere except in the message stream itself

More reference info:

AesCryptoServiceProvider Class
Good AES Initialization Vector practice
2
 
btanExec ConsultantCommented:
Just a minor add on, the mode of symmetric operation determines the size of the IV. This is usually the same as the block size but it doesn't have to be. For instance, for (AES-)GCM the default IV size is 12 bytes
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

  • 3
  • 3
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now