Wednesday, April 20, 2011

Using AesCryptoServiceProvider in VB.NET

My problem is actually a bit more complicated than just how to use AES in VB.NET, since what I'm really trying to do is use AES in VB.NET from within a Java application across JACOB. But for now, what I need to focus on is the AES implementation itself.

Here's my encryption code

Public Function EncryptAES(ByVal toEncrypt As String, ByVal key As String) As Byte()
    Dim keyArray = Convert.FromBase64String(key)
    Dim toEncryptArray = Encoding.Unicode.GetBytes(toEncrypt)

    Dim aes = New AesCryptoServiceProvider
    aes.Key = keyArray
    aes.Mode = CipherMode.ECB
    aes.Padding = PaddingMode.ISO10126
    Dim encryptor = aes.CreateEncryptor()

    Dim encrypted = encryptor.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length)
    aes.Clear()

    Return encrypted
End Function

Once back in the Java code, I turn the byte array into a hexadecimal String.

Now, to reverse the process, here's my decryption code

Public Function DecryptAES(ByVal toDecrypt As String, ByVal key As String) As Byte()
    Dim keyArray = Convert.FromBase64String(key)
    Dim toDecryptArray = Convert.FromBase64String(toDecrypt)

    Dim aes = New AesCryptoServiceProvider
    aes.Key = keyArray
    aes.Mode = CipherMode.ECB
    aes.Padding = PaddingMode.ISO10126
    Dim decryptor = aes.CreateDecryptor()

    Dim decrypted = decryptor.TransformFinalBlock(toDecryptArray, 0, toDecryptArray.Length)
    aes.Clear()
    Return decrypted
End Function

When I run the decryption code, I get the following error message

Padding is invalid and cannot be removed.

From stackoverflow
  • OK, so there were a couple of things wrong with my original code.

    For one, no debugging. I had to add an internal test to verify that my code could encrypt and decrypt before wrapping it in Java. That was silly of me.

    Two: the TransformFinalBlock method of both the encryptor and decryptor objects doesn't seem to perform as advertised.

    Enough talk. Here's the code

    Public Function EncryptAES(ByVal clearText As String, ByVal key As String) As String
    
        ' prepare input
        Dim keyBytes = Convert.FromBase64String(key)
        Dim sourceBytes = Encoding.Unicode.GetBytes(clearText)
    
        ' prepare encryption provider
        Dim aes = New AesCryptoServiceProvider
        aes.Key = keyBytes
        aes.Mode = CipherMode.ECB
        aes.Padding = PaddingMode.ISO10126
        Dim encryptor = aes.CreateEncryptor()
    
        Dim ms = New MemoryStream
        Dim cs = New CryptoStream(ms, encryptor, CryptoStreamMode.Write)
        cs.Write(sourceBytes, 0, sourceBytes.Length)
        cs.FlushFinalBlock()
        Dim encrypted = Convert.ToBase64String(ms.ToArray())
    
        'Dim decrypted = DecryptAES(encrypted, key)
        'If Not EventLog.SourceExists("CryptoBridge") Then
        '   EventLog.CreateEventSource("CryptoBridge", "CryptoBridge")
        'End If
        'Dim log As New EventLog
        'log.Source = "CryptoBridge"
        'log.WriteEntry(clearText & ":" & decrypted)
    
        aes.Clear()
        cs.Dispose()
        ms.Dispose()
    
        Return encrypted
    End Function
    
    Public Function DecryptAES(ByVal base64Cipher As String, ByVal key As String) As String
        Dim keyBytes = Convert.FromBase64String(key)
        Dim cipherBytes = Convert.FromBase64String(base64Cipher)
    
        ' prepare decryption provider
        Dim aes = New AesCryptoServiceProvider
        aes.Key = keyBytes
        aes.Mode = CipherMode.ECB
        aes.Padding = PaddingMode.ISO10126
        Dim decryptor = aes.CreateDecryptor()
    
        Dim ms = New MemoryStream(cipherBytes)
        Dim cs = New CryptoStream(ms, decryptor, CryptoStreamMode.Read)
    
        Dim decryptedBytes As Byte()
        ReDim decryptedBytes(cipherBytes.Length)
    
        Dim readByteCount = cs.Read(decryptedBytes, 0, decryptedBytes.Length)
        Dim decrypted = Encoding.Unicode.GetString(decryptedBytes, 0, readByteCount)
    
        aes.Clear()
        cs.Dispose()
        ms.Dispose()
    
        Return decrypted
    End Function
    

    Next, I'll be modifying this code to bump up the AES algorithm to 256-bit and CBC cipher mode, which requires an initial vector (IV) value. This adds a level of complexity to the implementation that I wasn't ready to add until the rest worked 100% of the time.

    Thanks to all those who commented on my issue.

    Cheeso : Curious - why would you not just use the AES Ciphers that are included in Java? as opposed to going across JACOB?

2 comments:

Paul brown said...

Thanks for posting this info. I just want to let you know that I just check out your site and I find it very interesting and informative. I can't wait to read lots of your posts.
cs代写

Paul brown said...

i really like this article please keep it up.
java代写

Post a Comment