RC4 method for iOS

Greetings All,

I found a nice RC4 Method on the forum , which is working perfectly for desktop App. :

link text

Thanks to Michael for all his optimization !

Does anyone has migrate it for iOS ?

Thanks,
Fred

For reference, here’s the optimized code (6th version) for the old framework…

Presumably one must use Xojo.Core.Memoryblock and make sure the pointers are working correctly - I’ve not done any iOS development so I am only guessing…

Function rc4v6(dataString as string, keyString as string) As string
  // highly optimized version of the RC4 algorithm written for Xojo 2014 
  // uses pointers and MemoryBlocks for speed
  // written to follow the pseudo-code algorithm described here:  http://en.wikipedia.org/wiki/Rc4
  #Pragma DisableBackgroundTasks
  #Pragma DisableBoundsChecking
  #Pragma NilObjectChecking False
  #Pragma StackOverflowChecking False
  
  
  Dim mbPlaintext as MemoryBlock = dataString  // input data
  dim Plaintext as Ptr = mbPlaintext // a pointer, used for speed
  
  Dim mbCyphertext as New MemoryBlock(mbPlaintext.Size)    // output data, same size as input
  dim Cyphertext as Ptr = mbCyphertext // a pointer, used for speed
  
  dim mbKey as MemoryBlock = keyString  // the key, as a MemoryBlock
  dim Key as Ptr = mbKey
  
  dim keylength as integer = mbKey.size
  
  
  // do the Key Scheduling Algorithm (KSA)
  dim mbS as new MemoryBlock(256)
  dim S as Ptr = mbS // a pointer, used for speed
  
  // first, fill it with Identity (0-255)
  for i as integer = 0 to 255
    S.byte(i) = i
  next
  
  // now, do the KSA
  dim i,j as integer
  for i = 0 to 255
    j = (j + S.byte(i) + Key.byte(i mod keylength) ) mod 256
    // swap values of S[i] and S[j]
    dim tmp as Byte = S.byte(j)
    S.byte(j) = S.byte(i)
    S.byte(i) = tmp
  next
  
  
  // now, do the encoding
  i = 0
  j = 0
  
  dim U as integer = mbPlaintext.Size-1 // iterate from 0...U
  for x as integer = 0 to U
    i= (i + 1 ) mod 256
    j = (j + S.byte(i) ) mod 256
    // swap values of S[i] and S[j]
    dim tmp as Byte = S.byte(j)
    S.byte(j) = S.byte(i)
    S.byte(i) = tmp
    
    // K is the keystream value which is XORed with the Plaintext to make the Cyphertext
    dim K as Byte  = S.byte( (S.byte(i) + S.byte(j))  mod 256)
    
    Cyphertext.byte(x) = Plaintext.byte(x) XOR K
  next
  
  return mbCyphertext
End Function

I tried the rc4v6 version and it fails for most binary data but works great for standard ascii/base64 encrypted data…

I’ve stuck with the original code as found at Xojo Developer’s Spot and have had no issue with binary/ascii/unicode/non-unicode data…

Function RC4(strData as string, strKey as String) As string
  #If Not DebugBuild
    #pragma DisableBackgroundTasks
    #pragma DisableBoundsChecking
    #pragma DisableAutoWaitCursor
    #pragma StackOverflowchecking False
    #pragma NilObjectChecking False
  #EndIf
  Dim MM As MemoryBlock = strData
  Dim MM2 As New MemoryBlock(LenB(strData))
  Dim memAsciiArray(255) As Integer
  Dim memKeyArray(255)   As Integer
  Dim memJump As Integer
  Dim memTemp As Integer
  Dim memY As Integer
  Dim intKeyLength As Integer
  Dim intIndex As Integer
  Dim intT As Integer
  Dim intX As Integer
 
  intKeyLength = Len(strKey)
 
  For intIndex = 0 To 255
    memKeyArray(intIndex) = Asc(Mid(strKey, ((intIndex) Mod (intKeyLength)) + 1, 1))
  Next
 
  For intIndex = 0 To 255
    memAsciiArray(intIndex) = intIndex
  Next
 
  For intIndex = 0 To 255
    memJump = (memJump + memAsciiArray(intIndex) + memKeyArray(intIndex)) Mod 256
    memTemp = memAsciiArray(intIndex)
    memAsciiArray(intIndex) = memAsciiArray(memJump)
    memAsciiArray(memJump) = memTemp
  Next
 
  intIndex = 0
  memJump = 0
 
  For intX = 1 To MM2.Size
    intIndex = (intIndex + 1) Mod 256
    memJump = (memJump + memAsciiArray(intIndex)) Mod 256
    intT = (memAsciiArray(intIndex) + memAsciiArray(memJump)) Mod 256
    memTemp = memAsciiArray(intIndex)
    memAsciiArray(intIndex) = memAsciiArray(memJump)
    memAsciiArray(memJump) = memTemp
    memY = memAsciiArray(intT)
    mm2.Byte(intX - 1) = bitwise.bitxor(Val("&h" + Hex(MM.Byte(IntX - 1))), bitwise.bitxor(memTemp,memY))
  Next
 
  Return MM2
End Function

I can provide a demo if you want Michael that demonstrates the rc4v6 failing and corrupting the data.

In theory this is probably a “new” vs. “old” framework issue (not a iOS vs OS X issue). My guess would be that perhaps Pointer.Byte() is defined differently?

I did a quick & dirty migration of the original RC4 (less efficient), to get me over a hump, if it’s of any help to you.

[code]Function RC4(strData as text, strKey as text) As text
Dim MM as MemoryBlock = TextEncoding.UTF8.ConvertTextToData(strData)
Dim MM2 as new MutableMemoryBlock(mm.Size)
dim memAsciiArray(255) as integer
dim memKeyArray(255) as integer
dim memJump as integer
dim memTemp as integer
dim memY as integer
dim intKeyLength as integer
dim intIndex as integer
dim intT as integer
dim intX as integer

dim textRoll as text=“1234567890ABCDEF”+strKey
strKey=textRoll.right(16)

intKeyLength = strKey.Length

for intIndex = 0 to 255
dim index as Integer=(intIndex mod intKeyLength)+1
dim t as text
if index<strKey.Length then t=strKey.Mid(index,1)
memKeyArray(intIndex) = asc(t)
next

for intIndex = 0 to 255
memAsciiArray(intIndex) = intIndex
next

for intIndex = 0 to 255
memJump = (memJump + memAsciiArray(intIndex) + memKeyArray(intIndex)) mod 256
memTemp = memAsciiArray(intIndex)
memAsciiArray(intIndex) = memAsciiArray(memJump)
memAsciiArray(memJump) = memTemp
next

intIndex = 0
memJump = 0

for intX = 1 to MM2.Size
intIndex = (intIndex + 1) mod 256
memJump = (memJump + memAsciiArray(intIndex)) mod 256
intT = (memAsciiArray(intIndex) + memAsciiArray(memJump)) mod 256
memTemp = memAsciiArray(intIndex)
memAsciiArray(intIndex) = memAsciiArray(memJump)
memAsciiArray(memJump) = memTemp
memY = memAsciiArray(intT)
if intX < mm2.Size then
mm2.Int16Value(intX - 1) = MM.Int16Value(IntX - 1) Xor (memTemp xor memY)
end if
next

return TextEncoding.UTF8.ConvertDataToText(MM2)
End Function
[/code]