XTEA Encryption?

Is there code or a library available somewhere that allows Xojo to handle XTEA encryption? I use it in Java all the time with B4X Compilers, but in my new Xojo app I have to be able to handle XTEA, but I cant find anything out there with simple google searches.

Was wondering if someone could lead me in the right direction. Thanks!

https://en.wikipedia.org/wiki/XTEA
there’s c reference code on the page
and a google search for XTEA finds other implementations that could be ported (python etc)

I saw that but what went through my mind at the time was C =/= Xojo.

So I dont know how to copy and paste the C code into xojo and make it work.

I am not a C programmer or anything other than BASIC. I use a couple different compilers, one of them is the Xojo compiler, and the B4X compiler which translates BASIC/VB6 style code over to Java, and then compiles.

So when I saw that, I got lost, and unsure what to do.

At the bottom of the Wikipedia page are links to implementations in other languages. Java, JavaScript or Python aren’t that different from Xojo.

Visual Basic

You won’t copy and paste the code, you’d need to interpret the logic and write new code. Pick the implementation you’re most familiar with and work from that as your source.

I’ll take a stab. Here is a strict translation from the C code, but I have nothing to test it against.

Protected Sub Encipher(numRounds As UInt32, v() As UInt32, key() As UInt32)
  dim v0 as UInt32 = v( 0 )
  dim v1 as UInt32 = v( 1 )
  dim sum as UInt32
  const delta as UInt32 = &h9E3779B9
  
  dim lastRound as UInt32 = numRounds - 1
  for i as UInt32 = 0 to lastRound
    v0 = v0 + ( _
    ( Bitwise.ShiftLeft( v1, 4, 32 ) xor Bitwise.ShiftRight( v1, 5, 32 ) ) xor _
    ( sum + key( sum and 3 ) ) _
    )
    sum = sum + delta
    v1 = v1 + ( _
    ( ( Bitwise.ShiftLeft( v0, 4, 32 ) xor Bitwise.ShiftRight( v0, 5, 32 ) ) + v0 ) xor _
    ( sum + key( Bitwise.ShiftRight( sum, 11, 32 ) and 3 ) ) _
    )
  next i
  
  v( 0 ) = v0
  v( 1 ) = v1
  
  #if false 
    //
    // Original C code
    //
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
    for (i=0; i < num_rounds; i++) {
      v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
      sum += delta;
      v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
      }
      v[0]=v0; v[1]=v1;
      }
      
  #endif
End Sub

And decipher:

Protected Sub Decipher(numRounds As UInt32, v() As UInt32, key() As UInt32)
  dim v0 as UInt32 = v( 0 )
  dim v1 as UInt32 = v( 1 )
  const delta as UInt32 = &h9E3779B9
  dim sum as UInt32 = delta * numRounds
  
  dim lastRound as UInt32 = numRounds - 1
  for i as UInt32 = 0 to lastRound
    v1 = v1 - ( _
    ( ( Bitwise.ShiftLeft( v0, 4, 32 ) xor Bitwise.ShiftRight( v0, 5, 32 ) ) + v0 ) xor _
    ( sum + key( Bitwise.ShiftRight( sum, 11, 32 ) and 3 ) ) _
    )
    sum = sum - delta
    v0 = v0 - ( _
    ( ( Bitwise.ShiftLeft( v1, 4, 32 ) xor Bitwise.ShiftRight( v1, 5, 32 ) ) + v1 ) xor _
    ( sum + key( sum and 3 ) ) _
    )
  next i
  
  v( 0 ) = v0
  v( 1 ) = v1
  
  #if false
    //
    // Original C code
    //
    void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    for (i=0; i < num_rounds; i++) {
      v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
      sum -= delta;
      v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
      }
      v[0]=v0; v[1]=v1;
      }
  #endif
End Sub

Now I feel even more stupid.

Trying to figure out how to take that, and encode “hello world” with a Hex String based Key…

Seems the formula only works with Integers, and everything I need to work with is text based. Looking at the VB source code mentioned above to see if it clues me into any STring <-> UInt functions.

Nevermind, the MemoryBlock :slight_smile:

Ok, something is wrong somewhere. (I am not an algorithm guy so I am less likely to figure it out).

But, This site here: http://www.bierkandt.org/encryption/symmetric_encryption.php

ecb mode, key 1234567812345678, Text is “Hello Wo” (just to fill 8 bytes)

Gives me a result of: XTEA: 3d3147376932abd0

This result matched identically under the same conditions when I ran it under Java, using the same subroutine I had used for the last few years.

In Xojo, This is my setup:

Dim datablock as New Memoryblock(8)  '8 bytes, 2 UInt32 Blocks
Dim Keyblock as New MemoryBlock(16) '128 bit key, 4 Uin32 Blocks

Keyblock = "1234567812345678"
datablock = "Hello Wo"

arg = Encipher(32, Array(datablock.UInt32Value(0), datablock.UInt32Value(1)), Array(keyblock.uint32value(0), keyblock.uint32value(1), keyblock.uint32value(2), keyblock.uint32value(3)))

stdout.writeline(arg)

this does NOT match anything, I get this instead:
26A90517980A5390

Here is the code I used (slightly modified from above, only on return)

Public Function Encipher(numRounds As UInt32, v() As UInt32, key() As UInt32) as String
  dim v0 as UInt32 = v( 0 )
  dim v1 as UInt32 = v( 1 )
  dim sum as UInt32
  const delta as UInt32 = &h9E3779B9
  
  dim lastRound as UInt32 = numRounds - 1
  for i as UInt32 = 0 to lastRound
    v0 = v0 + ( _
    ( Bitwise.ShiftLeft( v1, 4, 32 ) xor Bitwise.ShiftRight( v1, 5, 32 ) ) xor _
    ( sum + key( sum and 3 ) ) _
    )
    sum = sum + delta
    v1 = v1 + ( _
    ( ( Bitwise.ShiftLeft( v0, 4, 32 ) xor Bitwise.ShiftRight( v0, 5, 32 ) ) + v0 ) xor _
    ( sum + key( Bitwise.ShiftRight( sum, 11, 32 ) and 3 ) ) _
    )
  next i
  
  
  
  Return Hex32(v0) + Hex32(v1)
  
  'v( 0 ) = v0
  'v( 1 ) = v1
  
  //#if false 
  //
  // Original C code
  //
  //unsigned int i;
  //uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
  //for (i=0; i < num_rounds; i++) {
  //v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
  //sum += delta;
  //v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
  //}
  //v[0]=v0; v[1]=v1;
  //}
  
  //#endif
End Function

Then Hex32 (found elsewhere)

Public Function Hex32(value As Int32) as String
  Const prefix = "00000000" // A 32-bits value is 8 digits long at max
  
  Return Right(prefix + Hex(value), 8)  // We always return 8 characters
End Function

Thoughts?

I found an error, the + v1 was missing on the top part of the formula, which changed the result, but still isnt the correct one.

I have been all up and down this thing and cannot seem to figure it out. I broke everything down as simple as I thought I could get it, but its still broken. I need help!!!

Here is where I am at now. I broke the algorithm down to step by step, 1 thing at a time just in case the order of operations differs, and resulted in a different result which is still NOT the same! I have 8-bit microprocessor XTEA code that does work, and matches the Java output, so I tried to follow that when breaking down the algo but no avail.

Dim datablock as New Memoryblock(8)  '8 bytes, 2 UInt32 Blocks
Dim Keyblock as New MemoryBlock(16) '128 bit key, 4 Uin32 Blocks

keyblock.byte(0) = 1
keyblock.byte(1) = 1
keyblock.byte(2) = 1
keyblock.byte(3) = 1
keyblock.byte(4) = 1
keyblock.byte(5) = 1
keyblock.byte(6) = 1
keyblock.byte(7) = 1
keyblock.byte(8) = 1
keyblock.byte(9) = 1
keyblock.byte(10) = 1
keyblock.byte(11) = 1
keyblock.byte(12) = 1
keyblock.byte(13) = 1
keyblock.byte(14) = 1
keyblock.byte(15) = 1

Datablock.byte(0) = 2
Datablock.byte(1) = 2
Datablock.byte(2) = 2
Datablock.byte(3) = 2
Datablock.byte(4) = 2
Datablock.byte(5) = 2
Datablock.byte(6) = 2
Datablock.byte(7) = 2

'Keyblock = "1234567812345678"
'datablock = "Hello Wo"

arg = Encipher(32, Array(datablock.UInt32Value(0), datablock.UInt32Value(1)), Array(keyblock.uint32value(0), keyblock.uint32value(1), keyblock.uint32value(2), keyblock.uint32value(3)))

stdout.writeline(arg)

Here is my modified XTEA block:

dim v0 as UInt32 = v( 0 )
dim v1 as UInt32 = v( 1 )
dim x, y, z as uint32
dim sum as UInt32
const delta as UInt32 = &h9E3779B9

dim lastRound as UInt32 = numRounds - 1
for i as UInt32 = 0 to lastRound
  x = v1 * pow(2, 4)   
  y = v1 / pow(2, 5)
  z = x xor y
  z = z + v1
  x = key(Sum and 3)
  x = x + sum
  y = z xor x
  v0 = v0 + y
  sum = sum + delta
  x = v0 * pow(2, 4)
  y = v0 / pow(2, 5)
  z = x xor y
  z = z + v0
  x = sum / pow(2, 11)
  y = key(x and 3)
  y = y + sum
  x = z xor y
  v1 = v1 + z
next i

'  v0 = v0 + (((v1 * pow(2, 4)) xor (v1 / pow(2, 5))) + v1) xor (sum + key(sum and 3))

Return Hex32(v0) + Hex32(v1)

I changed the bitwise shift to POW multiplications because it was int32 and not 64. the result was still the exact same, so I didnt change anything by doing that.

Could it just be a matter of changing LittleEndian on the MemoryBlocks?

I think that was it. This code matches it exactly.

Protected Function Encipher(numRounds As UInt32, data As String, key As String) as String
  if key = "" or data = "" then
    return data
  end if
  if data.LenB > 8 or key.LenB > 16 then
    raise new OutOfBoundsException
  end if
  
  dim mbData as new MemoryBlock( 8 )
  mbData.LittleEndian = false
  mbData.StringValue( 0, data.LenB ) = data
  
  dim mbKey as new MemoryBlock( 16 )
  mbKey.LittleEndian = false
  mbKey.StringValue( 0, key.LenB ) = key
  dim k( 3 ) as UInt32
  k( 0 ) = mbKey.UInt32Value( 0 )
  k( 1 ) = mbKey.UInt32Value( 4 )
  k( 2 ) = mbKey.UInt32Value( 8 )
  k( 3 ) = mbKey.UInt32Value( 12 )
  
  dim v0 as UInt32 = mbData.UInt32Value( 0 )
  dim v1 as UInt32 = mbData.UInt32Value( 4 )
  dim sum as UInt32
  const delta as UInt32 = &h9E3779B9
  
  dim lastRound as UInt32 = numRounds - 1
  for i as UInt32 = 0 to lastRound
    v0 = v0 + ( _
    ( ( Bitwise.ShiftLeft( v1, 4, 32 ) xor Bitwise.ShiftRight( v1, 5, 32 ) ) + v1 ) xor _
    ( sum + k( sum and 3 ) ) _
    )
    sum = sum + delta
    v1 = v1 + ( _
    ( ( Bitwise.ShiftLeft( v0, 4, 32 ) xor Bitwise.ShiftRight( v0, 5, 32 ) ) + v0 ) xor _
    ( sum + k( Bitwise.ShiftRight( sum, 11, 32 ) and 3 ) ) _
    )
  next i
  
  mbData.UInt32Value( 0 ) = v0
  mbData.UInt32Value( 4 ) = v1
  return mbData
  
  #if false 
    //
    // Original C code
    //
    void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], sum=0, delta=0x9E3779B9;
    for (i=0; i < num_rounds; i++) {
      v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
      sum += delta;
      v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
      }
      v[0]=v0; v[1]=v1;
      }
      
  #endif
End Function

That function does indeed work!

How in the **** did I miss all of that? I thought using all 1s and 2s would eliminate an endianness problem but it didnt. Maybe it was being converted to &h31 and I didnt know it?

The updated Decipher:

Protected Function Decipher(numRounds As UInt32, encrypted As String, key As String) as String
  if key = "" or encrypted = "" then
    return encrypted
  end if
  if encrypted.LenB > 8 or key.LenB > 16 then
    raise new OutOfBoundsException
  end if
  
  dim mbData as new MemoryBlock( 8 )
  mbData.LittleEndian = false
  mbData.StringValue( 0, encrypted.LenB ) = encrypted
  
  dim mbKey as new MemoryBlock( 16 )
  mbKey.LittleEndian = false
  mbKey.StringValue( 0, key.LenB ) = key
  dim k( 3 ) as UInt32
  k( 0 ) = mbKey.UInt32Value( 0 )
  k( 1 ) = mbKey.UInt32Value( 4 )
  k( 2 ) = mbKey.UInt32Value( 8 )
  k( 3 ) = mbKey.UInt32Value( 12 )
  
  dim v0 as UInt32 = mbData.UInt32Value( 0 )
  dim v1 as UInt32 = mbData.UInt32Value( 4 )
  const delta as UInt32 = &h9E3779B9
  dim sum as UInt32 = delta * numRounds
  
  dim lastRound as UInt32 = numRounds - 1
  for i as UInt32 = 0 to lastRound
    v1 = v1 - ( _
    ( ( Bitwise.ShiftLeft( v0, 4, 32 ) xor Bitwise.ShiftRight( v0, 5, 32 ) ) + v0 ) xor _
    ( sum + k( Bitwise.ShiftRight( sum, 11, 32 ) and 3 ) ) _
    )
    sum = sum - delta
    v0 = v0 - ( _
    ( ( Bitwise.ShiftLeft( v1, 4, 32 ) xor Bitwise.ShiftRight( v1, 5, 32 ) ) + v1 ) xor _
    ( sum + k( sum and 3 ) ) _
    )
  next i
  
  mbData.UInt32Value( 0 ) = v0
  mbData.UInt32Value( 4 ) = v1
  return mbData
  
  #if false
    //
    // Original C code
    //
    void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
    unsigned int i;
    uint32_t v0=v[0], v1=v[1], delta=0x9E3779B9, sum=delta*num_rounds;
    for (i=0; i < num_rounds; i++) {
      v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);
      sum -= delta;
      v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
      }
      v[0]=v0; v[1]=v1;
      }
  #endif
End Function

Your right, it does indeed work.

I took the code I was working with from last night, changed the littleendian to false, But I see an additional mistake, I was passing uint32 with indexes of 0, and 1, and 2, etc…

So I fixed it to 0, 4 and then 0, 4, 8, 12. ( never used a memoryblock before in my life so I didnt know that)

Presto, it worked as yours above. So thats what it was.