Skip to content

Code Tip: How to Implement the ARC4 Encryption Algorithm

ARC4 is a symmetric encryption algorithm fast and easy to implement. Being symmetric does means that it uses the same function with the same key (varying from 40 to 2048 bits) both for cyphering and de-cyphering a block of data.

Is it the most secure or robust encryption algorithm around? Not really. But it provides a good amount of performance and you can take further steps in order to correct some of its flaws. So, continue reading if you are interested in having this one in your developer toolset implemented as a Class with separate methods to encrypt and decrypt a block of information (even if it uses the same function in both cases).

Add a new Class to your project and name it ARC4. Next, add the three properties needed to implement it:

  • Name: mBox
  • Type: MemoryBlock
  • Scope: Private
  • Name: mKeyBlock
  • Type: MemoryBlock
  • Scope: Private
  • Name: mKeyLength
  • Type: Integer
  • Scope: Private

ARC4 uses a main state box with a length of 256 bytes and the first one will be the one pointed by the mBox property. The second one, mKeyBlock, is declared as a MemoryBlock just to be more efficient in accessing the individual bytes of the provided Key. Lastly, the mKeyLength property is just a convenience property so we can access the original Key length from our Methods.

Now, let’s add the required Class methods, starting with the Constructor. This one will let the user provide the Key string as part of the instance initialization; so we don’t need to provide it again every time we want to encrypt or decrypt a new block of data.

With our ARC4 class selected in the Navigator, add a new method and type the following values in the Inspector Panel:

  • Name: Constructor
  • Parameters: Key As String
  • Scope: Public

Next, type the following snippet of code in the associated Code Editor for the method:

// If Key is not an empty String
// We call the Key method in order
// to initialize the State box

If Not (key.IsEmpty) Then
  Me.Key = key
Else
  // Empty String, so we raise an exception
  Raise New RuntimeException(kkeynotinitialized,Integer(ARCError.KeyNotInitialized))
End If

As you can see, the main thing that the Constructor does is call the Key Method; it’s in charge of initializing the required state box with the provided key. If the key is an empty String, it will raise a Runtime Exception giving a descriptive error message an error number.

Now, let’s add the Key method to our RC4 class:

  • Name: Key
  • Parameters: Assigns Value As String
  • Scope: Public

Being a Public method means that you can change the Key String without needing to create a new instance, if that is what you want to do. For example, you may want to initialize the Class instance using a key, encrypt some blocks of data using that one and then change to a different key in order to encrypt other blocks of data. Just remember that you’ll need to use the same keys in order to reverse to plain data those blocks encrypted with a given key.

In addition, the use of the Assigns keyword is simply syntactic sugar to make it possible to call the method using the equal operator to pass along the required parameter instead of using the regular syntax when calling a method in Xojo code. So, for example, you can use call it using:

MyRC4Instance.Key = "MySecretKey"

Instead of:

MyRC4Instance.Key("MySecretKey")

This is the code snippet that’s going to execute this method:

// Disabling some features for better speed
#Pragma DisableBackgroundTasks
#Pragma DisableBoundsChecking
#Pragma NilObjectChecking False
#Pragma StackOverflowChecking False

// Initialize the index values
Var mFirstIndex As UInt8
Var mSecondIndex As UInt8

// Let's check that this is not an Empty Key String
If Not (value.IsEmpty) Then

  // Trim key length if greater than 256 = max 2048 bits supported by ARC4
  If value.Length > 256 Then value = value.Left(256)

  // Pad the key if it is less than the required min 40 bits (5 bytes)
  // We are going to pad the key repeating the remaining 'n' characters
  // from the begining of the key.
  If value.Length < 5 Then

    Var pad As Integer = 5-value.Length

    value = value + value.Left(pad)

  End If

  // Initialize the State Box if this is the first call to the method.
  // The State box has a maximum of 256 bytes.
  If mBox = Nil Then mBox = New MemoryBlock(256)

  // Just in case there is an older Key in use
  // Let's get rid of the old MemoryBlock storing it
  // And create a new one with the Key lenght (in bytes)
  mKeyBlock = Nil
  mkeyBlock = value
  mKeyLength = value.Length

  // Required initialization of the State Box
  For n As Integer = mFirstIndex To 255
    mBox.UInt8Value(n) = n
  Next

  mFirstIndex = 0

  // Last step on State Box initialization
  // Permutation of values in the State Box
  // using for that the provided Key.

  For n As Integer = mFirstIndex To 255

    mSecondIndex = (mSecondIndex + mBox.UInt8Value(n) + mkeyblock.UInt8Value(n Mod mKeyLength)) Mod 256

    SwapValues(n,mSecondIndex)

  Next

Else

  // If the provided key is an empty String, we raise a new Runtime Exception
  // with a descriptive error message and error number.
  Raise New RuntimeException(kKeyNotInitialized, Integer(ARCError.KeyNotInitialized))
End If

As you can see, both the Constructor and the Key methods raise a Runtime Exception if the provided Key is an empty string. Both the message and error number are defined as a Constant (the message error) and an Enumerator (Error value) as part of the class itself. So go ahead and add a Constant to the ARC4 class using these values:

  • Constant Name: kKeyNotInitialized
  • Default Value: Key Not Initialized
  • Type: String
  • Scope: Protected

And for the Enumerator:

  • Name: ARCError
  • Type: Integer
  • Scope: Public
  • Value: KeyNotInitialized = -1

In addition, the Key method calls the SwapValues method in order to make the values permutation in the State Box. So add a new method using these values in the Inspector Panel:

  • Method Name: SwapValues
  • Parameters: FirstValue As UInt8, SecondValue As UInt8
  • Scope: Private

While the code to type in the associated Code Editor will be:

Var tmp As UInt8

tmp = mBox.UInt8Value(SecondValue)
mBox.UInt8Value(SecondValue) = mBox.UInt8Value(FirstValue)
mBox.UInt8Value(FirstValue) = tmp

Now just two additional methods left to be added to the class- the ones in charge of encrypting and decrypting a given block of data.

In order to encrypt the data, add a new Method with the following values in the Inspector Panel:

  • Method Name: Encrypt
  • Parameters: Value As String
  • Return Type: MemoryBlock
  • Scope: Public

And with the following block of code in the associated Code Editor:

// Disabling some features for better speed
#Pragma DisableBackgroundTasks
#Pragma DisableBoundsChecking
#Pragma NilObjectChecking False
#Pragma StackOverflowChecking False

// Index initialization
Var mFirstIndex As Integer
Var mSecondIndex As Integer

Var k As UInt8

// If we have a non initialized mKeyBlock
// that means that the key has not being initialized
// so we raise an exception
If mKeyBlock <> Nil Then

  // Initialize Key again

  me.Key = mKeyBlock.StringValue(0,mKeyBlock.Size)

  // Let's put the text to encrypt into a memoryblock
  // so it is faster to iterate through their bytes
  Var target As MemoryBlock = value
  Var temp As UInt8
  Var maxSize As Integer = target.Size-1

  // And we calculate the new bytes values (encrypted values)
  // using the ARC4 algorithm
  // Basically, every byte in the source block will be XORed
  // with the calculated byte from the State box.
  For n As Integer = 0 To maxSize

    mFirstIndex = (mFirstIndex + 1) Mod 256
    mSecondIndex = (mSecondIndex + mBox.UInt8Value(mFirstIndex)) Mod 256

    SwapValues(mFirstIndex,mSecondIndex)

    k = mBox.UInt8Value((mBox.UInt8Value(mFirstIndex) + mBox.UInt8Value(mSecondIndex)) Mod 256)

    target.UInt8Value(n) = target.UInt8Value(n) Xor k
  Next

  //…and return the block of data already encrypted
  Return target

Else
  Raise New RuntimeException(kKeyNotInitialized, Integer(ARCError.KeyNotInitialized))
End If

And the last Method, the one in charge of decrypting a block of ARC4 encrypted data:

  • Method Name: Decrypt
  • Parameters: Source As MemoryBlock
  • Return Type: MemoryBlock
  • Scope: Public

Typing the following code fragment in the associated Code Editor:

If Not (Source Is Nil) Then

  // Simply call the same method we use to
  // encrypt data, avoiding code duplication
  // and returning the now deciphered data to the caller
  Return Me.Encrypt(Source)

End If

And, that’s all! If you are interested in more information about the ARC4 algorithm you can read this article on the Wikipedia. Or better yet, read the excellent books “Applied Cryptography” and “Cryptography Engineering” to dig in even more on this and other cyphering algorithms. Of course, remember that the Crypto module included in the Xojo framework has a good bunch of these ready to use!

Of course, you also can download the Xojo example project that includes this Class ready to use from this link.