Porting JQuery RC4 encryption to c# .Net 3.5



Recently I had a task that involved unencrypting an encrypted query string that had been encrypted on the front end using JQuery’s RC4 encryption located in file: JQuery.rc4.js. I needed to un-encrypt the encrypted string in the c# code-behind:

Below is a line for line port of the JQuery.rc4.js. library functions I needed.

I made use of Microsoft.JScript library which I added to the references.

Below is the Ported c# code i wrote:

using System;
using Microsoft.JScript;

namespace PrayingBearCreations
{
/// <summary>
/// Conversion into c# of the JQuery rc4 Encryption in JQuery.rc4.js Code
/// Robert Bertora Nov 2010
/// </summary>

class rc4EncryptionJQueryTranslation
{
//ORIGINAL
//$.extend({ hexEncode: function(data) {
//    var b16D = ‘0123456789abcdef’; var b16M = new Array();
//    for (var i = 0; i < 256; i++) { b16M[i] = b16D.charAt(i >> 4) + b16D.charAt(i & 15); }
//    var result = new Array(); for (var i = 0; i < data.length; i++) { result[i] = b16M[data.charCodeAt(i)]; }
//    return result.join(”);
private string hexEncode(string data)
{
string[] b16M = new string[256];
for (var i = 0; i < 256; i++)
{
b16M[i] = Microsoft.JScript.StringConstructor.fromCharCode(i);
}

string[] result = new string[data.Length];
for (var i = 0; i < data.Length; i++)
{
string keyLetter = data.Substring(i, 1);
char keyChar = keyLetter[0];
int keyCharInt = (int)keyChar;

result[i] = b16M[keyCharInt];
}
return String.Join(“”, result);
}

//}, hexDecode: function(data) {
//    var b16D = ‘0123456789abcdef’; var b16M = new Array();
//    for (var i = 0; i < 256; i++) { b16M[b16D.charAt(i >> 4) + b16D.charAt(i & 15)] = String.fromCharCode(i); }
//    if (!data.match(/^[a-f0-9]*$/i)) return false; if (data.length % 2) data = ‘0’ + data;
//    var result = new Array(); var j = 0; for (var i = 0; i < data.length; i += 2) { result[j++] = b16M[data.substr(i, 2)]; }
//    return result.join(”);
private string hexDecode(string data)
{
string[] b16M = new string[256];

for (var i = 0; i < 256; i++)
{
//{ b16M[b16D.charAt(i >> 4) + b16D.charAt(i & 15)] = String.fromCharCode(i); }
//I noticed above line is complete overkill for what its actually doing, c# below is simplified:
//this also means we don’t need:  var b16D = ‘0123456789abcdef’ line
b16M[i] = Microsoft.JScript.StringConstructor.fromCharCode(i);
}

if ((data.Length % 2)>0) data = “0” + data;

string[] result = new string[data.Length];
int j = 0;
for (int i = 0; i < data.Length; i += 2)
{
string hex256 = data.Substring(i, 2);
int decValue = int.Parse(hex256, System.Globalization.NumberStyles.HexNumber);
result[j++] = b16M[decValue];
}
string ReturnString = String.Join(“”, result);
return ReturnString;
}

//ORIGINAL
// rc4Encrypt: function(key, pt) {
//    s = new Array(); for (var i = 0; i < 256; i++) { s[i] = i; }; var j = 0; var x;
//    for (i = 0; i < 256; i++) { j = (j + s[i] + key.charCodeAt(i % key.length)) % 256; x = s[i]; s[i] = s[j]; s[j] = x; }
//    i = 0; j = 0; var ct = ”; for (var y = 0; y < pt.length; y++) {
//        i = (i + 1) % 256; j = (j + s[i]) % 256; x = s[i]; s[i] = s[j]; s[j] = x;
//        ct += String.fromCharCode(pt.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
//    } return ct;
private string rc4Encrypt(string key, string pt)
{
string[] s = new string[256];
for (int i = 0; i < 256; i++)
{
s[i] = i.ToString();
};

int j = 0; string x;
for (int i = 0; i < 256; i++)
{
string keyLetter = key.Substring(i % key.Length, 1);
char keyChar = keyLetter[0];
int keyCharInt = (int)keyChar;

j = (j + System.Convert.ToInt32(s[i]) + System.Convert.ToInt32(keyCharInt)) % 256;
x = s[i];
s[i] = s[j];
s[j] = x;
}

int i2 = 0; j = 0;
string ct = “”;
for (var y = 0; y < pt.Length; y++)
{
i2 = (i2 + 1) % 256;
j = (j + System.Convert.ToInt32(s[i2])) % 256;
x = s[i2]; s[i2] = s[j]; s[j] = x;

string keyLetter = pt.Substring(y, 1);
char keyChar = keyLetter[0];
int keyCharInt = (int)keyChar;

ct += Microsoft.JScript.StringConstructor.fromCharCode((keyCharInt ^ System.Convert.ToInt32(s[(System.Convert.ToInt32(s[i2]) + System.Convert.ToInt32(s[j])) % 256])).ToString());
}
return ct;

}

private string rc4Decrypt(string key, string pt)
{
return rc4Encrypt(key, pt);
}

//ORGINAL
//}, rc4EncryptStr: function(str, key) {
//    return $.hexEncode($.rc4Encrypt(key, unescape(encodeURIComponent(str))));
public string rc4EncryptStr(string key, string str)
{
string encodedURI = Microsoft.JScript.GlobalObject.encodeURIComponent(str);
string unEscapedStr = Microsoft.JScript.GlobalObject.unescape(encodedURI);
return hexEncode(rc4Encrypt(key, unEscapedStr));
}

//ORIGINAL
//}, rc4DecryptStr: function(hexStr, key) { return decodeURIComponent(escape($.rc4Decrypt(key, $.hexDecode(hexStr)))); }
public string rc4DecryptStr(string key, string hexStr)
{
return Microsoft.JScript.GlobalObject.decodeURIComponent(Microsoft.JScript.GlobalObject.escape(rc4Decrypt(key, hexDecode(hexStr))));
}

}
}

//////////////////////////////////////////////////////

Calling code:

rc4EncryptionJQueryTranslation rc4 = new rc4EncryptionJQueryTranslation();
DecryptedQueryString = rc4.rc4DecryptStr(“YourEncryptionSafeKey”, EncryptedQueryString);




Tags: , ,

3 Responses to “Porting JQuery RC4 encryption to c# .Net 3.5”

  1. Justin says:

    I cant seem to get this class to function correctly…
    It manages to encode text but it generates random characters which it fails to decrypt… The encrypted string that is generated is an invalid string:-(
    Any ideas of whats going on?

  2. Robert Bertora says:

    Hi,

    Try this:

    When calling :
    public string rc4DecryptStr(string key, string hexStr)

    make sure that your key, has at least 12 characters in it

    Robert.

  3. Geert says:

    When encrypting in Jquery and decrypting using your function, everything works sweet. When encrypting using your function and decrypting in JQuery, it doesn’t work, as your hexEncode doesn’t produce Hexadecimals. I’ve solved it by using a function ToHex(byte[] bytes) and applying correct encoding.