RC4 Encryption

Share your advanced PureBasic knowledge/code with the community.
User avatar
Frarth
Enthusiast
Enthusiast
Posts: 241
Joined: Tue Jul 21, 2009 11:11 am
Location: On the planet
Contact:

RC4 Encryption

Post by Frarth »

I have not seen much about RC4 encryption on this forum, so I decided to post this example. I ported it from VB, optimized it for PB and added the DEK (default encryption key) feature. Might come in handy for someone.

Code: Select all

Structure AsciiType
  a.a[0]
EndStructure

#Encrypt_DEK_Size = 49

DataSection
  ; default encryption key
  _Encrypt_DEK:
  Data.a 16, 125, 235, 199, 173, 38, 21
  Data.a 41, 45, 61, 44, 7, 183, 47
  Data.a 18, 109, 71, 3, 19, 154, 78
  Data.a 106, 9, 122, 91, 8, 34, 11
  Data.a 82, 79, 25, 61, 158, 33, 111
  Data.a 8, 3, 26, 16, 233, 133, 17
  Data.a 26, 78, 253, 156, 227, 89, 43
EndDataSection

Procedure.s Encrypt_DEK()
  Protected Key.s{#Encrypt_DEK_Size}
  CopyMemory(?_Encrypt_DEK, @Key, SizeOf(Ascii) * #Encrypt_DEK_Size)
  ProcedureReturn Key
EndProcedure

Procedure.s Encrypt_RC4(Text.s, Key.s = "")
  Protected *TAscText.AsciiType
  Protected *TAscKey.AsciiType
  Protected tLen.i, kLen.i, i.i
  Protected Dim rb.a(255), a.a, b.a
  ; text length
  tLen = Len(Text)
  If tLen = 0
    ProcedureReturn ""
  EndIf
  ; key length
  If Len(Key) = 0
    Key = Encrypt_DEK()
  EndIf
  ; key length <= 256
  kLen = Len(Key)
  If kLen > 256
    kLen = 256
    Key = Left(Key, kLen)
  EndIf
  ; key address
  *TAscKey = @Key
  a = 0
  ; table
  For i = 0 To 255
    rb(i) = i
    a = (a + rb(i) + *TAscKey\a[i % kLen]) & $FF
    Swap rb(i), rb(a)
  Next
  ; text address
  *TAscText = @Text
  a = 0
  b = 0
  ; encrypt/decrypt
  For i = 0 To tLen - 1
    a = (a + 1) & $FF
    b = (b + rb(a)) & $FF
    Swap rb(a), rb(b)
    PokeA(*TAscText + i, *TAscText\a[i] ! rb((rb(a) + rb(b)) & $FF))
  Next
  ; return result
  ProcedureReturn Text
EndProcedure

; Example 1 (using default encryption key)
Define Text.s = Encrypt_RC4("Testing this algorithm")
Debug Text ;encrypted
Debug Encrypt_RC4(Text) ;decrypted

; Example 2 (using a password)
Define Password.s = "my password"
Define Text.s = Encrypt_RC4("Testing this algorithm", Password)
Debug Text ;encrypted
Debug Encrypt_RC4(Text, Password) ;decrypted
PureBasic 5.41 LTS | Xubuntu 16.04 (x32) | Windows 7 (x64)
User avatar
Frarth
Enthusiast
Enthusiast
Posts: 241
Joined: Tue Jul 21, 2009 11:11 am
Location: On the planet
Contact:

Re: RC4 Encryption

Post by Frarth »

A slightly adjusted version I use to encrypt/decrypt database records.

Code: Select all

Structure AsciiType
  a.a[0]
EndStructure

#Encrypt_DEK_Size = 49

DataSection
  ; default encryption key
  _Encrypt_DEK:
  Data.a 16, 125, 235, 199, 173, 38, 21
  Data.a 41, 45, 61, 44, 7, 183, 47
  Data.a 18, 109, 71, 3, 19, 154, 78
  Data.a 106, 9, 122, 91, 8, 34, 11
  Data.a 82, 79, 25, 61, 158, 33, 111
  Data.a 8, 3, 26, 16, 233, 133, 17
  Data.a 26, 78, 253, 156, 227, 89, 43
EndDataSection

Procedure.s Encrypt_DEK()
  Protected Key.s{#Encrypt_DEK_Size}
  CopyMemory(?_Encrypt_DEK, @Key, SizeOf(Ascii) * #Encrypt_DEK_Size)
  ProcedureReturn Key
EndProcedure

Procedure Encrypt_RC4(*Text, Key.s = "")
  Protected *TAscText.AsciiType
  Protected *TAscKey.AsciiType
  Protected tLen.i, kLen.i, i.i
  Protected Dim rb.a(255), a.a, b.a
  ; text length
  tLen = MemorySize(*Text)
  If tLen = 0
    ProcedureReturn
  EndIf
  ; key length
  If Len(Key) = 0
    Key = Encrypt_DEK()
  EndIf
  ; key length <= 256
  kLen = Len(Key)
  If kLen > 256
    kLen = 256
    Key = Left(Key, kLen)
  EndIf
  ; key address
  *TAscKey = @Key
  a = 0
  ; table
  For i = 0 To 255
    rb(i) = i
    a = (a + rb(i) + *TAscKey\a[i % kLen]) & $FF
    Swap rb(i), rb(a)
  Next
  ; text address
  *TAscText = *Text
  a = 0
  b = 0
  ; encrypt/decrypt
  For i = 0 To tLen - 1
    a = (a + 1) & $FF
    b = (b + rb(a)) & $FF
    Swap rb(a), rb(b)
    PokeA(*TAscText + i, *TAscText\a[i] ! rb((rb(a) + rb(b)) & $FF))
  Next
EndProcedure

; Example 1: encrypt record before writing it to file
CopyMemory(*Record, *Buffer, RecordSize)
Encrypt_RC4(*Buffer, EncryptionKey)
WriteData(Handle, *Buffer, RecordSize)

; Example 2: decrypt record after reading it from file
ReadData(Handle, *Buffer, RecordSize)
Encrypt_RC4(*Buffer, EncryptionKey)
CopyMemory(*Buffer, *Record, RecordSize)
PureBasic 5.41 LTS | Xubuntu 16.04 (x32) | Windows 7 (x64)
UserOfPure
Enthusiast
Enthusiast
Posts: 469
Joined: Sun Mar 16, 2008 9:18 am

Re: RC4 Encryption

Post by UserOfPure »

Frarth wrote:I have not seen much about RC4 encryption on this forum
You didn't search properly then. There's lots of discussions and code examples dealing with RC4.
User avatar
Frarth
Enthusiast
Enthusiast
Posts: 241
Joined: Tue Jul 21, 2009 11:11 am
Location: On the planet
Contact:

Re: RC4 Encryption

Post by Frarth »

UserOfPure wrote:
Frarth wrote:I have not seen much about RC4 encryption on this forum
You didn't search properly then. There's lots of discussions and code examples dealing with RC4.
Like I said, I have not seen *much*. I searched for 'RC4 encryption' ('RC4' is too short apparently), and found these (which seem to be from the same code):
http://www.purebasic.fr/english/viewtop ... encryption
http://www.purebasic.fr/english/viewtop ... encryption
http://www.purebasic.fr/english/viewtop ... hlight=rc4

If I search the forum, I first look at the subject. If, in this example 'RC4' or something close to it is in the subject I know what I will get. If I look into all subjects with say 'encryption', I may spend an entire afternoon finding what I'm looking for.
PureBasic 5.41 LTS | Xubuntu 16.04 (x32) | Windows 7 (x64)
Post Reply