Help with small RC4 bug

Just starting out? Need help? Post your questions and find answers here.
firace
Addict
Addict
Posts: 947
Joined: Wed Nov 09, 2011 8:58 am

Help with small RC4 bug

Post by firace »

Could anyone help fixing this?
I'm not getting the expected result (see below), due to the 00 bytes I think...

Note: I"m aware RC4 is not secure, just using this as an exercise.

[EDIT] replaced the example with a shorter one for clarity

Code: Select all

Procedure.s RC4(key.s, str.s)
  Dim s.a(255)
  Protected i, j = 0, x, res.s = ""
  
  ; Initialize the S array
  For i = 0 To 255
    s(i) = i
  Next
  
  ; Key scheduling
  For i = 0 To 255
    j = (j + s(i) + Asc(Mid(key, (i % Len(key)) + 1, 1))) % 256
    x = s(i)
    s(i) = s(j)
    s(j) = x
  Next
  
  i = 0
  j = 0
  
  ; Stream generation and XOR with input
  For y = 1 To Len(str)
    i = (i + 1) % 256
    j = (j + s(i)) % 256
    x = s(i)
    s(i) = s(j)
    s(j) = x
    current.s = Hex (Asc(Mid(str, y, 1)) ! s((s(i) + s(j)) % 256) )
    current = RSet(current, 2, "0")
    res + current.s
  Next
    
  ProcedureReturn res  
EndProcedure

Procedure.s Hex2Bin(hex.s)
  Protected i, result.s = ""
  For i = 1 To Len(hex) Step 2
    result + Chr(Val("$" + Mid(hex, i, 2)))
  Next
;   Debug "h2b: " + Len(hex) + " --- " +  result
  ProcedureReturn result
EndProcedure


Procedure.s MY_RC4(key.s, datachunk.s)
  ProcedureReturn LCase(RC4(Hex2Bin(key), Hex2Bin(datachunk)))
EndProcedure


; Debug MY_RC4("75bb8b07f0ddf2898ebab9cb745911983ac6c0da7f3be675fb44c4368818bb8f", "145709a333593ddcc28bb217b5023983101269669e32037b9da0f91c77ffed7f4c")
Debug MY_RC4("75bb8b07f0ddf2898ebab9cb745911983ac6c0da7f3be675fb44c4368818bb8f", "4e434e434e434e43160000002493255b2e0000000000000000000100c04e554c4c")


;; expected:  145709a333593ddcc28bb217b5023983101269669e32037b9da0f91c77ffed7f4c
;; getting:   145709a333593ddcc2af2132cabf1d187047252a

Axolotl
Addict
Addict
Posts: 872
Joined: Wed Dec 31, 2008 3:36 pm

Re: Help with small RC4 bug

Post by Axolotl »

Sorry, cannot help you with that.
Maybe you should compare your code with something like this:
Implementation-of-rc4-algorithm (in C++)
Or you can use Debug to get results inbetween, to check the correct calculation?
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Help with small RC4 bug

Post by infratec »

Yes, the problem are the 00 in your data.
You need to handle it as binary data:

Code: Select all

CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf

Structure AsciiArray_Structure
  a.a[0]
EndStructure

Procedure.i RC4(*Input.AsciiArray_Structure, *Key.AsciiArray_Structure)
  
  Protected L.i, i.a, j.a, X.i, n.i, Temp.a, z.a
  Protected Dim s.a(255)
  Protected *Result.AsciiArray_Structure
  
  
  If *Input And *Key
    
    L = MemorySize(*key)
    
    For i = 0 To 255
      s(i) = i
    Next i
    
    For i = 0 To 255
      ;j = (j + s(i) + *key\a[i % L]) % 256
      j = (j + s(i) + *key\a[i % L]) & $FF
      Swap s(i), s(j)
    Next i
    
    X = MemorySize(*Input)
    
    *Result = AllocateMemory(X, #PB_Memory_NoClear)
    If *Result
      
      i = 0
      j = 0
      For n = 0 To X - 1
        ;i = (i + 1) % 256
        i = (i + 1) & $FF
        ;j = (j + s(i)) % 256
        j = (j + s(i)) & $FF
        Swap s(i), s(j)
        ;z = s((s(i) + s(j)) % 256)
        z = s((s(i) + s(j)) & $FF)
        *Result\a[n] = z ! *Input\a[n]
      Next n
      
    EndIf
    
  EndIf
  
  ProcedureReturn *Result
  
EndProcedure



Procedure.s RC4String(Key$, DataChunk$)
  
  Protected.i KeyLen, DataChunkLen, i
  Protected *Key.AsciiArray_Structure, *DataChunk.AsciiArray_Structure, *Result.AsciiArray_Structure
  Protected Result$
  
  
  KeyLen = Len(Key$)
  If KeyLen & 1
    Key$ = "0" + Key$
    KeyLen + 1
  EndIf
  
  KeyLen / 2
  
  *Key = AllocateMemory(KeyLen, #PB_Memory_NoClear)
  If *Key
    KeyLen - 1
    For i = 0 To KeyLen
      *Key\a[i] = Val("$" + Mid(Key$, 1 + (i * 2), 2))
    Next i
    
    DataChunkLen = Len(DataChunk$)
    If DataChunkLen & 1
      DataChunk$ = "0" + DataChunk$
      DataChunkLen + 1
    EndIf
    
    DataChunkLen / 2
    
    *DataChunk = AllocateMemory(DataChunkLen, #PB_Memory_NoClear)
    If *DataChunk
      DataChunkLen - 1
      For i = 0 To DataChunkLen
        *DataChunk\a[i] = Val("$" + Mid(DataChunk$, 1 + (i * 2), 2))
      Next i
      
      *Result = RC4(*DataChunk, *Key)
      If *Result
        
        For i = 0 To MemorySize(*Result) - 1
          Result$ + RSet(Hex(*Result\a[i]), 2, "0")
        Next i
        
        FreeMemory(*Result)
      EndIf
      
      FreeMemory(*DataChunk)
    EndIf
    
    FreeMemory(*Key)
  EndIf
  
  ProcedureReturn Result$
  
EndProcedure


CompilerIf #PB_Compiler_IsMainFile
  Debug RC4String("75bb8b07f0ddf2898ebab9cb745911983ac6c0da7f3be675fb44c4368818bb8f", "4e434e434e434e43160000002493255b2e0000000000000000000100c04e554c4c")
  Debug "145709a333593ddcc28bb217b5023983101269669e32037b9da0f91c77ffed7f4c"
CompilerEndIf
Since % 256 is slow, I replaced it with & $FF, which is faster.
firace
Addict
Addict
Posts: 947
Joined: Wed Nov 09, 2011 8:58 am

Re: Help with small RC4 bug

Post by firace »

Many thanks infratec, I'll study this carefully.

I'm always impressed by the quality of your code 8)
Post Reply