Triple DES encryption not working.

Hi,

I was taking a look at this link http://www.codeproject.com/KB/security/SimpleEncryption.aspx to try and figure out some encryption. So, I was looking at tripleDES. I found his code very hard to follow (didn't seem so simple to me!) so i wanted to break all the different objects he creates down and place into one step by step function (see below).

But, it's not working. I've stepped through his code and it looks like everything should be ok, but there is a point at which I do Dim bytEncrypt1() As Byte = ms.ToArray and my memorystream byte array had data length of 40 and so bytEncrypt1 ends up with a length of 40.

In his code though, he has a Data object that he creates like so Data(ms.ToArray) where he initializes some variables and the NEW constructor looks like

Public Sub New(ByVal b As Byte())
            _b = b
End Sub

where the ms.ToArray is passed in. So, what I have no idea about is that before it goes into the constructore I can see that ms.ToArray has data with length 40, same as me. Then suddenly, when it goes into the constructor it is now 48? I've no idea why?

Well, if no one can explain that... then does anyone know what would be wrong with my code that it doesn't work?

Thanks, Aiden
Dim Secret As String = "Pack my box with five dozen liquor jugs!"
      Dim Key As String = "MyKey"
      Dim p As New TripleDESCryptoServiceProvider

      Const DefaultIntializationVector As String = "%1Az=-@qT"
      Dim b1, b2 As Byte()
      Dim MaxBytes As Integer = 0
      Dim MinBytes As Integer = 0
      Dim StepBytes As Integer = 0
      Dim ivMaxBytes As Integer = 0
      Dim ivMinBytes As Integer = 0
      Dim ivStepBytes As Integer = 0
      Dim DefaultEncoding As Text.Encoding = System.Text.Encoding.GetEncoding("Windows-1252")
      Dim Encoding As Text.Encoding = DefaultEncoding
      Dim KeyText As String

      'His Key data object
      p.GenerateKey()
      b1 = p.Key
      MaxBytes = p.LegalKeySizes(0).MaxSize \ 8
      MinBytes = p.LegalKeySizes(0).MinSize \ 8
      StepBytes = p.LegalKeySizes(0).SkipSize \ 8
      KeyText = "MyKey"

      'His IV data object
      b2 = Encoding.GetBytes(DefaultIntializationVector)
      Array.Resize(b2, b2.Length - 1)
      ivMaxBytes = p.BlockSize \ 8
      ivMinBytes = p.BlockSize \ 8
      ivStepBytes = 0

      Dim bKey As Byte() = Encoding.GetBytes("MyKey")

      Console.WriteLine("Symmetric encryption algorithm")
      Console.WriteLine("  " & p.ToString)
      Console.WriteLine("Current key size")
      Console.WriteLine("  " & p.KeySize & " bits")
      Console.WriteLine("Possible key sizes")
      Console.WriteLine("  " & MinBytes * 8 & " bits to " & MaxBytes * 8 & " bits, in increments of " & StepBytes * 8 & " bits")
      Console.WriteLine("Initialization Vector size")
      Console.WriteLine("  " & findBytes(b2, ivMaxBytes, ivMinBytes).Length * 8 & " bits")
      Console.WriteLine()

      Console.WriteLine("Key")
      Console.WriteLine("  Text    " & getKeyText(bKey, Encoding))
      Console.WriteLine("  Hex     " & ToHex(bKey))
      Console.WriteLine("  Base64  " & ToBase64(bKey))
      Console.WriteLine()

      p.Key = findBytes(bKey, MaxBytes, MinBytes)
      p.IV = findBytes(b2, ivMaxBytes, ivMinBytes)

      Dim ms As New IO.MemoryStream
      Dim cs As New CryptoStream(ms, p.CreateEncryptor(), CryptoStreamMode.Write)
      Dim bytEncrypt As Byte() = Encoding.GetBytes(Secret)
      cs.Write(bytEncrypt, 0, bytEncrypt.Length)

      Dim bytEncrypt1() As Byte = ms.ToArray

      cs.Close()
      ms.Close()

      Console.WriteLine("Encrypted String")
      Console.WriteLine("  Hex     " & ToHex(bytEncrypt))
      Console.WriteLine("  Base64  " & ToBase64(bytEncrypt))
      Console.WriteLine()

      '************ DECRYPT
      Dim p1 As New TripleDESCryptoServiceProvider
      p1.GenerateKey()
      b1 = p1.Key

      Dim MaxBytes1 As Integer = 0
      Dim MinBytes1 As Integer = 0
      Dim StepBytes1 As Integer = 0
      Dim ivMaxBytes1 As Integer = 0
      Dim ivMinBytes1 As Integer = 0

      MaxBytes1 = p1.LegalKeySizes(0).MaxSize \ 8
      MinBytes1 = p1.LegalKeySizes(0).MinSize \ 8
      StepBytes1 = p1.LegalKeySizes(0).SkipSize \ 8

      b2 = Encoding.GetBytes(DefaultIntializationVector)
      ivMaxBytes1 = p.BlockSize \ 8
      ivMinBytes1 = p.BlockSize \ 8

      Dim bKey1 As Byte() = Encoding.GetBytes("MyKey")

      p1.Key = findBytes(bKey, MaxBytes1, MinBytes1)
      p1.IV = findBytes(b2, ivMaxBytes1, ivMinBytes1)

      Dim ms1 As New System.IO.MemoryStream(bytEncrypt, 0, bytEncrypt.Length)
      Dim bytDecrypt() As Byte = New Byte(bytEncrypt.Length - 1) {}

      Dim cs1 As New CryptoStream(ms1, p1.CreateDecryptor(), CryptoStreamMode.Read)

      Try
         cs1.Read(bytDecrypt, 0, b2.Length - 1)
      Catch ex As CryptographicException
         Throw New CryptographicException("Unable to decrypt data. The provided key may be invalid.", ex)
      Finally
         cs1.Close()
      End Try

      Console.WriteLine("decrypted string")
      Console.WriteLine("  " & getKeyText(bytDecrypt, Encoding))

      Console.WriteLine("Press ENTER to continue...")
      Console.ReadLine()

Open in new window

AidenAAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gnoonCommented:
>what would be wrong with my code
1. Array.Resize(b2, b2.Length - 1) should be removed from ENCRYPT part
2. Please post your code of findBytes() and getKeyText()
0
AidenAAuthor Commented:
well the thing is, his code works... and there is something he does to set the maximum size of the... key i think it is. The key can only be 128bytes or something like that. So, when you enter your key it is cut to well actually 8 bytes i think (i'm not totally sure what it's doing to be honest as you can probably tell!)

Ok, let me clarify.

His key is a byte array of {77,121,75,101,121,0,0,0,0,0,0,0,0,0,0,0} so it's of length 16
the IV looks like {37,49,65,122,61,45,64,113,84} and is of length 9 and this comes from his line of code
dim b as byte() = Me.Encoding.GetBytes("%1Az=-@qT")

The odd thing there is that there is a point at which the last byte of the IV disappears and it becomes of length 8  {37,49,65,122,61,45,64,113} i.e. the 84 is gone. And I can't see how it happens in fact. One second it is of length 9, then it steps into another function and is suddenly of length 8 and nothing that I can see what set.

Something also happens with the data array (the data to be encrypted). First it is of length 40 and then he runs the code ms.toarray() and suddenly it's 48? In my code it remains at 40.

So... my array.resize was an attempt to remove the 84 part even though I can't see exactly how is code does it. My other functions (see below) are just an attempt to mirror functions in his code so I can break up his classes and use them
Function findBytes(ByVal _b As Byte(), ByVal _MaxBytes As Integer, ByVal _MinBytes As Integer) As Byte()

      If _MaxBytes > 0 Then
         If _b.Length > _MaxBytes Then
            Dim b(_MaxBytes - 1) As Byte
            Array.Copy(_b, b, b.Length)
            _b = b
         End If
      End If
      If _MinBytes > 0 Then
         If _b.Length < _MinBytes Then
            Dim b(_MinBytes - 1) As Byte
            Array.Copy(_b, b, _b.Length)
            _b = b
         End If
      End If
      Return _b

   End Function
   Function getKeyText(ByVal _b As Byte(), ByVal Encoding As Text.Encoding) As String
      If _b Is Nothing Then
         Return ""
      Else
         '-- need to handle nulls here; oddly, C# will happily convert
         '-- nulls into the string whereas VB stops converting at the
         '-- first null!
         Dim i As Integer = Array.IndexOf(_b, CType(0, Byte))
         If i >= 0 Then
            Return Encoding.GetString(_b, 0, i)
         Else
            Return Encoding.GetString(_b)
         End If
      End If
   End Function
   Friend Function ToHex(ByVal ba() As Byte) As String
      If ba Is Nothing OrElse ba.Length = 0 Then
         Return ""
      End If
      Const HexFormat As String = "{0:X2}"
      Dim sb As New StringBuilder
      For Each b As Byte In ba
         sb.Append(String.Format(HexFormat, b))
      Next
      Return sb.ToString
   End Function
   Friend Function ToBase64(ByVal b() As Byte) As String
      If b Is Nothing OrElse b.Length = 0 Then
         Return ""
      End If
      Return Convert.ToBase64String(b)
   End Function

Open in new window

0
gnoonCommented:
Size of both Key and IV are changed to an appropriate size by Array.Copy(), and he calculates the size from default key size of the selected algorithm (TripleDES).

For example, TripleDES has default as follows
Key size (bytes) min = 16, max = 24 (step by 8)
IV size (bytes) min = 8, max = 8

The key, "MyKey", is converted to an 5-byte array, and then Array.Copy() expands it to be 16-byte (min size of key) array.
Also, "%1Az=-@qT" is converted to 9-byte array, and then Array.Copy() reduces it to be 8-byte (max size of IV) array.

PS. I saw 40 bytes of plain data, and 48 bytes of encrypted data in debug mode.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AidenAAuthor Commented:
ok thanks for clarifying the array.copy thing... don't ever use that so guess i hadn't realised what was going on there for some reason.

but it helped me solve the issue of the 40 to 48 bytes also since obviously my data wasn't being encrypted... if 40 is plain and 48 is encrypted. The reason then is because the data wasn't being written... and that can only be because the stream wasn't closed at the right point. So... all I had to do was switch the code above so that it looks like

cs.Close()
ms.Close()
Dim bytEncrypt1() As Byte = ms.ToArray

i.e. close the stream first and then do ms.ToArray

So, that all seemed to work fine now then (well the encryption part... i'm sure i can figure out the decyrption part then also)

Thanks again.

Aiden (i've posted full code below just in case someone else is interested)


Sub Encrypt()

      Dim Secret As String = "Pack my box with five dozen liquor jugs!"
      Dim Key As String = "MyKey"
      Dim p As New TripleDESCryptoServiceProvider

      Const DefaultIntializationVector As String = "%1Az=-@qT"
      Dim b1, b2 As Byte()
      Dim MaxBytes As Integer = 0
      Dim MinBytes As Integer = 0
      Dim StepBytes As Integer = 0
      Dim ivMaxBytes As Integer = 0
      Dim ivMinBytes As Integer = 0
      Dim ivStepBytes As Integer = 0
      Dim DefaultEncoding As Text.Encoding = System.Text.Encoding.GetEncoding("Windows-1252")
      Dim Encoding As Text.Encoding = DefaultEncoding
      Dim KeyText As String

      'His Key data object
      p.GenerateKey()
      b1 = p.Key
      MaxBytes = p.LegalKeySizes(0).MaxSize \ 8
      MinBytes = p.LegalKeySizes(0).MinSize \ 8
      StepBytes = p.LegalKeySizes(0).SkipSize \ 8
      KeyText = "MyKey"

      'His IV data object
      b2 = Encoding.GetBytes(DefaultIntializationVector)
      ivMaxBytes = p.BlockSize \ 8
      ivMinBytes = p.BlockSize \ 8
      b2 = findBytes(b2, ivMaxBytes, ivMinBytes)
      ivStepBytes = 0

      Dim bKey As Byte() = Encoding.GetBytes("MyKey")

      Console.WriteLine("Symmetric encryption algorithm")
      Console.WriteLine("  " & p.ToString)
      Console.WriteLine("Current key size")
      Console.WriteLine("  " & p.KeySize & " bits")
      Console.WriteLine("Possible key sizes")
      Console.WriteLine("  " & MinBytes * 8 & " bits to " & MaxBytes * 8 & " bits, in increments of " & StepBytes * 8 & " bits")
      Console.WriteLine("Initialization Vector size")
      Console.WriteLine("  " & findBytes(b2, ivMaxBytes, ivMinBytes).Length * 8 & " bits")
      Console.WriteLine()

      Console.WriteLine("Key")
      Console.WriteLine("  Text    " & getKeyText(bKey, Encoding))
      Console.WriteLine("  Hex     " & ToHex(bKey))
      Console.WriteLine("  Base64  " & ToBase64(bKey))
      Console.WriteLine()

      p.Key = findBytes(bKey, MaxBytes, MinBytes)
      p.IV = findBytes(b2, ivMaxBytes, ivMinBytes)

      Dim ms As New IO.MemoryStream
      Dim cs As New CryptoStream(ms, p.CreateEncryptor(), CryptoStreamMode.Write)
      Dim bytEncrypt As Byte() = Encoding.GetBytes(Secret)
      cs.Write(bytEncrypt, 0, bytEncrypt.Length)

      cs.Close()
      ms.Close()

      Dim bytEncrypt1() As Byte = ms.ToArray


      Console.WriteLine("Encrypted String")
      Console.WriteLine("  Hex     " & ToHex(bytEncrypt1))
      Console.WriteLine("  Base64  " & ToBase64(bytEncrypt1))
      Console.WriteLine()

   End Sub

Open in new window

0
AidenAAuthor Commented:
final reason is cause of problem
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Encryption

From novice to tech pro — start learning today.

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.