Question Encryptor/Decryptor not working.

seinkraft

Member
Joined
Sep 28, 2008
Messages
19
Programming Experience
5-10
The code should receive an byte array and return it encrypted. At this point that is working fine, but the decriptor has a problem, it doesnt write the same bytes of teh original file.

It adds o or remove some bytes from the end. And the original file and decoded file doesn't match.

Please help.

VB.NET:
Public Function EncryptBytes(ByVal pass As String, ByVal bytes() As Byte)

        Dim myRijndael As New RijndaelManaged
        myRijndael.Padding = PaddingMode.None
        myRijndael.Mode = CipherMode.CBC
        myRijndael.KeySize = 256
        myRijndael.BlockSize = 256

        Dim encrypted() As Byte
        Dim key() As Byte = CreateKey(pass)
        Dim IV() As Byte = CreateIV(pass)

        Dim encryptor As ICryptoTransform = myRijndael.CreateEncryptor(key, IV)

        Dim msEncrypt As New MemoryStream()
        Dim csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)

        csEncrypt.Write(bytes, 0, bytes.Length)

        encrypted = msEncrypt.ToArray()

        Return encrypted

    End Function

    Public Function DecryptBytes(ByVal pass As String, ByVal bytes() As Byte)

        Dim myRijndael As New RijndaelManaged
        myRijndael.Padding = PaddingMode.None
        myRijndael.Mode = CipherMode.CBC
        myRijndael.KeySize = 256
        myRijndael.BlockSize = 256

        Dim decrypted() As Byte
        Dim key() As Byte = CreateKey(pass)
        Dim IV() As Byte = CreateIV(pass)

        Dim decryptor As ICryptoTransform = myRijndael.CreateDecryptor(key, IV)

        Dim msEncrypt As New MemoryStream()
        Dim csEncrypt As New CryptoStream(msEncrypt, decryptor, CryptoStreamMode.Write)

        csEncrypt.Write(bytes, 0, bytes.Length)

        decrypted = msEncrypt.ToArray()

        Return decrypted

    End Function

    Private Function CreateKey(ByVal strPassword As String) As Byte()
        Dim chrData() As Char = strPassword.ToCharArray

        Dim intLength As Integer = chrData.GetUpperBound(0)

        Dim bytDataToHash(intLength) As Byte

        For i As Integer = 0 To chrData.GetUpperBound(0)
            bytDataToHash(i) = CByte(Asc(chrData(i)))
        Next

        Dim SHA512 As New System.Security.Cryptography.SHA512Managed

        Dim bytResult As Byte() = SHA512.ComputeHash(bytDataToHash)

        Dim bytKey(31) As Byte

        For i As Integer = 0 To 31
            bytKey(i) = bytResult(i)
        Next

        Return bytKey

    End Function

    Private Function CreateIV(ByVal strPassword As String) As Byte()
        Dim chrData() As Char = strPassword.ToCharArray

        Dim intLength As Integer = chrData.GetUpperBound(0)

        Dim bytDataToHash(intLength) As Byte

        For i As Integer = 0 To chrData.GetUpperBound(0)
            bytDataToHash(i) = CByte(Asc(chrData(i)))
        Next

        Dim SHA512 As New System.Security.Cryptography.SHA512Managed

        Dim bytResult As Byte() = SHA512.ComputeHash(bytDataToHash)

        Dim bytIV(31) As Byte

        For i As Integer = 32 To 47
            bytIV(i - 32) = bytResult(i)
        Next

        Return bytIV

    End Function
 
You are using padding = none. You might want to check what "padding" means ;)

Hint: Rijndael ist a block cypher that works on certain block sizes. What happens if the input is not a multiple of the block size? That's where padding comes into the game.
 
In addition you also have to Close/Clear the CryptoStream when done using it.
 
Yep, but if i change or remove the blocksize I get this warning "pecified initialization vector (IV) does not match the block size for this algorithm" when this line is running:

VB.NET:
Dim encryptor As ICryptoTransform = myRijndael.CreateEncryptor(key, IV)
 
Who said anything about removing blocksize, you have to set a Padding different than None, the default for Rijndael is PKCS7.
 
True...

Well I've done some tests using different paddings. The left window is teh original file and the right the decrypted file. They match all along the file but not the end.

With ANSIX923, PKCS7 and ISO10126 the decrited file is shorter than the original file. Tested with images and the file still works.
15yquw.jpg


With Zero and None the decrited file is nearly equal than the original file. Tested with images and the file still works.
nh1chh.jpg
 
I ran your code before replying to this thread, only fixing padding and closing the CryptoStreams, it encrypted and decrypted fine.
 
Yeah, it encrypts and decryts fine. But not with the same bytes length of the original file.

For example, a file of 201.917 bytes length when is encrypted the encrypted file is 201.888 bytes length and when I decrypt it the file is 201.888 bytes length.

I need that the decrypted file should have the same bytes lenght of the original.

original byte length = decrypted byte length

(and yes, i've closed cryptostream, not here but yes on my app)
 
Sorry, but I fail to reproduce your problem, all tests pass here with your code (as per fixed).
 
Btw, if your claimed decrypted bytes count equals the encoded bytes count, wouldn't that indicate that you're actually mixing these up somehow?
 
Not the decripted with the encripted. The decripted with the original.

I've added:
VB.NET:
csEncrypt.FlushFinalBlock()

And that solves a bit the error.
 
Close/Clear calls Dispose which calls FlushFinalBlock automatically, so adding that makes no difference.
 
I did it! Thanks for the answers.

This the working code:

VB.NET:
Public Function EncryptBytes(ByVal pass As String, ByVal bytes() As Byte)

        Dim myRijndael As New RijndaelManaged
        myRijndael.Padding = PaddingMode.PKCS7
        myRijndael.Mode = CipherMode.CBC
        myRijndael.KeySize = 256
        myRijndael.BlockSize = 256

        Dim encrypted() As Byte
        Dim key() As Byte = CreateKey(pass)
        Dim IV() As Byte = CreateIV(pass)

        Dim encryptor As ICryptoTransform = myRijndael.CreateEncryptor(key, IV)

        Dim msEncrypt As New MemoryStream()
        Dim csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)

        csEncrypt.Write(bytes, 0, bytes.Length)
        csEncrypt.FlushFinalBlock()

        encrypted = msEncrypt.ToArray()

        Return encrypted

        msEncrypt.Close()
        csEncrypt.Close()

    End Function

    Public Function DecryptBytes(ByVal pass As String, ByVal bytes() As Byte)

        Dim myRijndael As New RijndaelManaged
        myRijndael.Padding = PaddingMode.PKCS7
        myRijndael.Mode = CipherMode.CBC
        myRijndael.KeySize = 256
        myRijndael.BlockSize = 256

        Dim decrypted() As Byte
        Dim key() As Byte = CreateKey(pass)
        Dim IV() As Byte = CreateIV(pass)

        Dim decryptor As ICryptoTransform = myRijndael.CreateDecryptor(key, IV)

        Dim msDecrypt As New MemoryStream()
        Dim csDecrypt As New CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write)

        csDecrypt.Write(bytes, 0, bytes.Length)
        csDecrypt.FlushFinalBlock()

        decrypted = msDecrypt.ToArray()

        Return decrypted

        msDecrypt.Close()
        csDecrypt.Close()

    End Function

Note: If the paswword for decrypt is differento to the password used in encryption the decoder trows an exception on csDecrypt.FlushFinalBlock().
 
And therein lied your problem, you get contents from the MemoryStream before the encryption is finished, and you return that content without closing the CryptoStream. Not that the latter problem would matter for the final result, you already jumped out at the ToArray call. The Return call is the last code line executed in that function.
seinkraft said:
encrypted = msEncrypt.ToArray()
Return encrypted
msEncrypt.Close()
This is the correct order:
VB.NET:
msEncrypt.Close()
Return msEncrypt.ToArray()
And as I explained drop that FlushFinalBlock call, that is already taken care of from the Close call.
 
Back
Top