Help with Encryption... Please

napoleonjones

Member
Joined
Mar 24, 2007
Messages
18
Programming Experience
Beginner
I am working on an encryption class to be used with Access/Excel around the office, but I keep running into problems. At first I kept getting an error while decrypting stating that the padding was invalid when I attempted to close the stream. I set the padding = none and now it seems to run correctly while encrypting the string, but decryption does not return the original string. Can somebody please help.

VB.NET:
Private Function EString(ByVal Text As String, ByVal Password As String) As String
        Try
            Dim RJDLM As New RijndaelManaged

            Dim key As New Rfc2898DeriveBytes(Password, salt)
            With RJDLM

                .KeySize = 256
                .Key = key.GetBytes(.KeySize / 8)
                .IV = key.GetBytes(.BlockSize / 8)
                .Padding = PaddingMode.None
            End With


            Dim BTText As Byte() = ASCII.GetBytes(Text)
            Dim Encryptor As ICryptoTransform = RJDLM.CreateEncryptor

            Dim MemStream As New MemoryStream
            Dim EncryptStream As New CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)
            EncryptStream.Write(BTText, 0, BTText.Length)
            EncryptStream.Flush()
            EncryptStream.Close()

            Dim BTOutput As Byte() = MemStream.ToArray
            Dim Output As String = ASCII.GetString(BTOutput)
            MemStream.Close()

            Return Output
        Catch exCrypto As CryptographicException
            MsgBox(exCrypto.Message & vbNewLine & exCrypto.StackTrace & vbNewLine & exCrypto.Source, MsgBoxStyle.Critical, "Cryptographic Exception")
        Catch ex As Exception
            MsgBox(ex.Message & vbNewLine & ex.StackTrace & vbNewLine & ex.Source, MsgBoxStyle.Critical, "Unhandled Exception")
        End Try

    End Function

    Private Function DString(ByVal Text As String, ByVal Password As String) As String
        Try
            Dim RJDLM As New RijndaelManaged

            Dim key As New Rfc2898DeriveBytes(Password, salt)
            With RJDLM
                .KeySize = 256
                .Key = key.GetBytes(.KeySize / 8)
                .IV = key.GetBytes(.BlockSize / 8)
                .Padding = PaddingMode.None
            End With

            Dim BTText As Byte() = ASCII.GetBytes(Text)
            Dim Decryptor As ICryptoTransform = RJDLM.CreateDecryptor

            Dim MemStream As New MemoryStream
            Dim DecryptStream As New CryptoStream(MemStream, Decryptor, CryptoStreamMode.Write)
            DecryptStream.Write(BTText, 0, BTText.Length)
            DecryptStream.Flush()
            DecryptStream.Close()

            Dim BTOutput As Byte() = MemStream.ToArray
            Dim Output As String = ASCII.GetString(BTOutput)
            MemStream.Close()


            Return Output
        Catch exCrypto As CryptographicException
            MsgBox(exCrypto.Message & vbNewLine & exCrypto.StackTrace & vbNewLine & exCrypto.Source, MsgBoxStyle.Critical, "Cryptographic Exception")
        Catch ex As Exception
            MsgBox(ex.Message & vbNewLine & ex.StackTrace & vbNewLine & ex.Source, MsgBoxStyle.Critical, "Unhandled Exception")
        End Try
    End Function
 
Several problems here.
  • For this keysize the key is 32 bytes and IV 16 bytes.
  • You haven't posted salt, but it should be a byte array of minimum 8 bytes, else you get a random key each time you create a new Rfc2898DeriveBytes.
  • If you don't want to pad your data exact yourself you must specify a padding for RijndaelManaged.
  • The excrypted bytes you convert to ASCII string, this is not possible because ASCII encoding have a very limited range and the encrypted bytes may be any byte value, if you need to convert the encrypted bytes to a string use Convert.ToBase64String. To the get encrypted bytes back from that string use Convert.FromBase64String.
 
Ok, thank you very much for your help. I made the changes you suggested, but I am still getting errors. In my first post I also forgot to mention that the salt was declared outside of the functions. I originally used the string variable for the salt, but upon your advice I converted it to a byte array. Now I am getting an error during the conversion stating Invalid length for 64 bit char array. Also before using a sentence, I was just using random characters as the salt, but upon converting from base 64 string I received an invalid character error.

Once again thanks for the help.


VB.NET:
Private salt As String = "THis is the salt that I will be using to salt the things that require salting"
    Private btsalt As Byte() = Convert.FromBase64String(salt)

Private Function EString(ByVal Text As String, ByVal Password As String) As String
        Try
            Dim RJDLM As New RijndaelManaged

            Dim key As New Rfc2898DeriveBytes(Password, btsalt)
            With RJDLM

                .KeySize = 32
                .Key = key.GetBytes(.KeySize)
                .IV = key.GetBytes(.BlockSize)
                .Padding = PaddingMode.PKCS7
            End With


            Dim BTText As Byte() = Convert.FromBase64String(Text)
            Dim Encryptor As ICryptoTransform = RJDLM.CreateEncryptor

            Dim MemStream As New MemoryStream
            Dim EncryptStream As New CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write)
            EncryptStream.Write(BTText, 0, BTText.Length)
            EncryptStream.Flush()
            EncryptStream.Close()

            Dim BTOutput As Byte() = MemStream.ToArray
            Dim Output As String = Convert.ToBase64String(BTOutput)
            MemStream.Close()

            Return Output
        Catch exCrypto As CryptographicException
            MsgBox(exCrypto.Message & vbNewLine & exCrypto.StackTrace & vbNewLine & exCrypto.Source, MsgBoxStyle.Critical, "Cryptographic Exception")
        Catch ex As Exception
            MsgBox(ex.Message & vbNewLine & ex.StackTrace & vbNewLine & ex.Source, MsgBoxStyle.Critical, "Unhandled Exception")
        End Try

    End Function

    Private Function DString(ByVal Text As String, ByVal Password As String) As String
        Try
            Dim RJDLM As New RijndaelManaged

            Dim key As New Rfc2898DeriveBytes(Password, btsalt)
            With RJDLM
                .KeySize = 32
                .Key = key.GetBytes(.KeySize)
                .IV = key.GetBytes(.BlockSize)
                .Padding = PaddingMode.PKCS7
            End With

            Dim BTText As Byte() = Convert.FromBase64String(Text)
            Dim Decryptor As ICryptoTransform = RJDLM.CreateDecryptor

            Dim MemStream As New MemoryStream
            Dim DecryptStream As New CryptoStream(MemStream, Decryptor, CryptoStreamMode.Write)
            DecryptStream.Write(BTText, 0, BTText.Length)
            DecryptStream.Flush()
            DecryptStream.Close()

            Dim BTOutput As Byte() = MemStream.ToArray
            Dim Output As String = Convert.ToBase64String(BTOutput)
            MemStream.Close()


            Return Output
        Catch exCrypto As CryptographicException
            MsgBox(exCrypto.Message & vbNewLine & exCrypto.StackTrace & vbNewLine & exCrypto.Source, MsgBoxStyle.Critical, "Cryptographic Exception")
        Catch ex As Exception
            MsgBox(ex.Message & vbNewLine & ex.StackTrace & vbNewLine & ex.Source, MsgBoxStyle.Critical, "Unhandled Exception")
        End Try
    End Function
 
Ok, I changed the encoding to UTF32 and that seems to be working and I also changed the padding to zeros. It encrypts fine, but it won't decrypt. After stepping through the code and comparing keys and IVs, I noticed that the IVs are different. How is that possible when I am using the same method as I am during encryption?
 
For this keysize the key is 32 bytes and IV 16 bytes.
"this keysize" refers to you posting keysize 256 first. I haven't checked the length of key and IV for a 32 bit keysize.

You fully misunderstood the purpose of base64 encoding. This is a generic encoding used when you have byte data that can not be translated to normal string encoding (because it is not string data) and you still want to store/transfer it as a string.
When you have plain English text you can use Ascii encoding to get the string bytes. These bytes you can encrypt. The encrypted bytes can in no way be encoded back to plain text encoding, because it contain byte values that does not fit in the character range of any normal encoding. So you use the Base64 encoding to translate the encrypted bytes into a pseudo string, it looks like just garble but it is a carefully composed string that can be translated back to same byte array as original source.
When decrypting the process is simply reversed, the Base64 encoded string is translated back to the encrypted bytes, the encrypted bytes is decrypted, the decrypted bytes is translated back to English plain text with Ascii encoding.
 
Back
Top