Encryption/Decryption Changes File Size


P

Phillip Ian

Version: VS 2005

I took the sample code from help about encrypting and decrypting
strings, and changed it to work directly with byte arrays and get the
key and IV values from functions I've written to privide them. No
other changes were made...

Friend Function EncryptBytes(ByVal Data() As Byte, ByVal APassphrase
As String) As Byte()
Try
' Create a MemoryStream.
Dim mStream As New MemoryStream

' Create a CryptoStream using the MemoryStream
' and the passed key and initialization vector (IV).
Dim cStream As New CryptoStream(mStream, New
TripleDESCryptoServiceProvider().CreateEncryptor(GetKey(APassphrase),
GetIV(APassphrase)), CryptoStreamMode.Write)

' Write the byte array to the crypto stream and flush it.
cStream.Write(Data, 0, Data.Length)
cStream.FlushFinalBlock()

' Get an array of bytes from the
' MemoryStream that holds the
' encrypted data.
Dim ret As Byte() = mStream.ToArray()

' Close the streams.
cStream.Close()
mStream.Close()

' Return the encrypted buffer.
Return ret
Catch e As CryptographicException
Console.WriteLine("A Cryptographic error occurred: " & e.Message)
Return Nothing
End Try
End Function

Friend Function DecryptBytes(ByVal Data() As Byte, ByVal APassphrase
As String) As Byte()
Try
' Create a new MemoryStream using the passed
' array of encrypted data.
Dim msDecrypt As New MemoryStream(Data)

' Create a CryptoStream using the MemoryStream
' and the passed key and initialization vector (IV).
Dim csDecrypt As New CryptoStream(msDecrypt, New
TripleDESCryptoServiceProvider().CreateDecryptor(GetKey(APassphrase),
GetIV(APassphrase)), CryptoStreamMode.Read)

' Create buffer to hold the decrypted data.
Dim fromEncrypt(Data.Length) As Byte

' Read the decrypted data out of the crypto stream
' and place it into the temporary buffer.
csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length)

'Convert the buffer into a string and return it.
Return fromEncrypt
Catch e As CryptographicException
Console.WriteLine("A Cryptographic error occurred: " & e.Message)
Return Nothing
End Try
End Function

When I encrypt and decrypt a file, the file ends up with extra blank
bytes on the end of it. My encrypt/decrypt routine is as follows:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim fin As New FileStream("test.jpg", FileMode.Open)
Dim mugshot(fin.Length) As Byte
fin.Read(mugshot, 0, fin.Length)
fin.Close()
MessageBox.Show(mugshot.Length)

Dim encrypted() As Byte
encrypted = EncryptBytes(mugshot, "This is a test...")
MessageBox.Show(encrypted.Length)

Dim decrypted() As Byte
decrypted = DecryptBytes(encrypted, "This is a test...")
MessageBox.Show(decrypted.Length)

Dim fout As New FileStream("testout.jpg", FileMode.Create)
fout.Write(decrypted, 0, decrypted.Length)
fout.Close()
End Sub

This doesn't seem to bother the jpeg files...they read just fine. But
what if it WASN'T a jpeg? Is it the encrypt/decrypt routine or the
file IO stuff that's adding the extra bytes?

Any help appreciated.
 
Ad

Advertisements

D

DazedAndConfused

The following line sets fromEncypt to the same size as data length (actually
data length + 1)
so you have 9 extra (0) bytes at the end. I think the 8 bytes are the
encryption key.

' Create buffer to hold the decrypted data.

Dim fromEncrypt(Data.Length ) As Byte



you could do this:

' Create buffer to hold the decrypted data.

Dim fromEncrypt(Data.Length - 9) As Byte

or

I think the right way is something like this (NOTE: in DecryptBytes that
"CryptoStreamMode.Write" is Write NOT Read - This is NOT a mistype, it needs
to be this way, the same is true for csDecrypt.Write, then change Return to
msDecrypt.ToArray , you will also be writing directly from Data, no need for
fromEncrypt) . For more information on this go to:

http://blogs.gotdotnet.com/ivanmed/PermaLink.aspx/01380bfa-caf5-40b9-ace6-5973106935a4



Friend Function DecryptBytes(ByVal Data() As Byte, ByVal APassphrase
As String) As Byte()
Try
' Create a new MemoryStream using the passed
' array of encrypted data.
Dim msDecrypt As New MemoryStream(Data)

' Create a CryptoStream using the MemoryStream
' and the passed key and initialization vector (IV).
Dim csDecrypt As New CryptoStream(msDecrypt, New
TripleDESCryptoServiceProvider().CreateDecryptor(GetKey(APassphrase),
GetIV(APassphrase)), CryptoStreamMode.Write) <=== Changed this line

' Create buffer to hold the decrypted data.
Dim fromEncrypt(Data.Length) As Byte

' Read the decrypted data out of the crypto stream
' and place it into the temporary buffer.
csDecrypt.Write(Data, 0, Data.Length -1) <=== Changed this line

'Convert the buffer into a string and return it.
Return msDecrypt.ToArray <==== Changed this line.


Catch e As CryptographicException
Console.WriteLine("A Cryptographic error occurred: " & e.Message)
Return Nothing
End Try
End Function
 
D

DazedAndConfused

The following line sets fromEncypt to the same size as data length (actually
data length + 1)
so you have 9 extra (0) bytes at the end. I think the 8 bytes are the
encryption key.

' Create buffer to hold the decrypted data.

Dim fromEncrypt(Data.Length ) As Byte



you could do this:

' Create buffer to hold the decrypted data.

Dim fromEncrypt(Data.Length - 9) As Byte

or

I think the right way is something like this (NOTE: in DecryptBytes that
"CryptoStreamMode.Write" is Write NOT Read - This is NOT a mistype, it needs
to be this way, the same is true for csDecrypt.Write, then change Return to
msDecrypt.ToArray , you will also be writing directly from Data, no need for
fromEncrypt) . For more information on this go to:

http://blogs.gotdotnet.com/ivanmed/PermaLink.aspx/01380bfa-caf5-40b9-ace6-5973106935a4



Friend Function DecryptBytes(ByVal Data() As Byte, ByVal APassphrase
As String) As Byte()
Try
' Create a new MemoryStream using the passed
' array of encrypted data.
Dim msDecrypt As New MemoryStream(Data)

' Create a CryptoStream using the MemoryStream
' and the passed key and initialization vector (IV).
Dim csDecrypt As New CryptoStream(msDecrypt, New
TripleDESCryptoServiceProvider().CreateDecryptor(GetKey(APassphrase),
GetIV(APassphrase)), CryptoStreamMode.Write) <=== Changed this line

' Create buffer to hold the decrypted data.
Dim fromEncrypt(Data.Length) As Byte

' Read the decrypted data out of the crypto stream
' and place it into the temporary buffer.
csDecrypt.Write(Data, 0, Data.Length -1) <=== Changed this line

'Convert the buffer into a string and return it.
Return msDecrypt.ToArray <==== Changed this line.


Catch e As CryptographicException
Console.WriteLine("A Cryptographic error occurred: " & e.Message)
Return Nothing
End Try
End Function
 
D

DazedAndConfused

P.S. I was able to get rid of the extra bytes in the encryption by changing
the code as shown below.
I have noticed Memory Streams work differently then File streams. As I am
just learning Cryptography and am actually encrypting differently then you
are, I am not sure of the impact of this.

I would (and am going to) play with this to find out the answers. Another
article that would be worth going through is
http://www.dotnetdevs.com/articles/UsingEncryption.aspx

If you want things to look like they are secure you can short cut it, but if
you want things to be secure, it looks like there is a bit more work to do.
That is where I am with it now.

HTH

' Write the byte array to the crypto stream and flush it.
'cStream.Write(Data, 0, Data.Length)

'cStream.FlushFinalBlock()

' Initialize a buffer

Dim bufferLen As Integer = 4096

Dim buffer(bufferLen) As Byte

Dim bytesRead As Integer

' Create buffer to hold the decrypted data.

Dim toEncrypt As New MemoryStream

Dim s As Stream

toEncrypt.Write(Data, 0, Data.Length)

toEncrypt.Position = 0



Do

' Read a chunk of data from the MemoryStream

bytesRead = toEncrypt.Read(buffer, 0, bufferLen)

' Decrypt it

cStream.Write(buffer, 0, bytesRead)

Loop While bytesRead <> 0
 
Ad

Advertisements

G

Guest

The problem occurs because the TripleDES algorithm will only work on 16 bytes
of data. So, the Encrypt must pad the data to make it an even multiple of 16
in order to encrypt it.

Make sure you call FlushFinalBlock on the stream when you are decrypting so
the padded characters are removed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top