Skip to content

Instantly share code, notes, and snippets.

@rgrove
Created June 1, 2009 22:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rgrove/121843 to your computer and use it in GitHub Desktop.
Save rgrove/121843 to your computer and use it in GitHub Desktop.
RC4-drop[256] (aka MARK-4) implementation in JavaScript. Minifies to 511 bytes using YUI Compressor.
/**
* RC4-drop[256] (aka MARK-4) implementation in JavaScript.
*
* @module rc4
*/
/**
* @class RC4
* @static
*/
var RC4 = (function () {
var baseState, self;
/**
* Key scheduling algorithm. Returns a state array based on the specified
* <em>key</em>.
*
* @method init
* @param {String} key
* @return {Array} key state
* @private
*/
function init(key) {
var j = 0,
keylen = key.length,
state,
i, x;
if (!baseState) {
// The base state is just an array of numbers from 0 to 255, so we
// only calculate it once to avoid doing unnecessary work.
baseState = [];
for (i = 0; i < 256; ++i) {
baseState[i] = i;
}
}
state = baseState.concat(); // ensures a copy instead of a reference
for (i = 0; i < 256; ++i) {
j = (j + state[i] + key.charCodeAt(i % keylen)) % 256;
x = state[i];
state[i] = state[j];
state[j] = x;
}
return state;
}
self = {
/**
* Decrypts the specified ciphertext using the specified key. This
* method is actually just an alias for encrypt().
*
* @method decrypt
* @param {String} key
* @param {String} text
* @return {String} decrypted text
* @static
* @see encrypt()
*/
decrypt: function (key, text) {
return self.encrypt(key, text);
},
/**
* Pseudo-random generation algorithm. Encrypts the specified plaintext
* using the specified key, discarding the first 256 bytes of the
* keystream to mitigate the Fluhrer/Mantin/Shamir attack.
*
* @method encrypt
* @param {String} key
* @param {String} text
* @return {String} encrypted text
* @static
* @see decrypt()
*/
encrypt: function (key, text) {
var i = 0,
j = 0,
len = text.length + 256,
pos = 0,
result = '',
state = init(key),
x;
// Nothing to encrypt if the plaintext is empty.
if (len > 256) {
for (pos = 0; pos < len; ++pos) {
i = (i + 1) % 256;
j = (j + state[i]) % 256;
x = state[i];
state[i] = state[j];
state[j] = x;
// Discard the first 256 bytes of the keystream to mitigate the
// Fluhrer/Mantin/Shamir attack. See
// http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/rc4_wep.ps
if (pos > 255) {
result += String.fromCharCode(text.charCodeAt(pos - 256) ^ state[(state[i] + state[j]) % 256]);
}
}
}
return result;
}
};
return self;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment