Skip to content

Instantly share code, notes, and snippets.

@bryc
Last active March 6, 2021 11:26
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 bryc/46026abe00f18461a2d6dc23245ea6f3 to your computer and use it in GitHub Desktop.
Save bryc/46026abe00f18461a2d6dc23245ea6f3 to your computer and use it in GitHub Desktop.
RC4
function rc4(key, data) {
var output = [], S = [], tmp, i, j = 0;
for (i = 0; i < 256; i++) {
S[i] = i;
}
for (i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key.length]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
}
i = 0, j = 0;
for (var k = 0; k < data.length; k++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
tmp = S[i];
S[i] = S[j];
S[j] = tmp;
output[k] = data[k] ^ S[(S[i] + S[j]) % 256];
}
return output;
}
function rc4(key, msg) {
function swap(S, i, j) {var tmp=S[j];S[j]=S[i];S[i]=tmp;}
function ksa(key) {
for (var S=[],i=j=0; i<256; i++) {S[i] = i;}
for (i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key.length]) % 256;
swap(S, i, j);
} return S;
}
var output = [], S = ksa(key);
for (var k=j=i=0; k < msg.length; k++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
swap(S, i, j);
output[k] = msg[k] ^ S[(S[i] + S[j]) % 256];
}
return output;
}
// S2 = KSA(S1) - S2 produced by key of entire S1 table (better, but possibly incorrect)
function rc4a(key, msg) {
function swap(S, i, j) {
var tmp = S[j]; S[j] = S[i]; S[i] = tmp;
}
function xorout(msg, keystream) {
for(var cipher = [], i = 0; i < msg.length; i++) {
cipher[i] = msg[i] ^ keystream[i];
} return cipher;
}
function rc4_ksa(key) {
for (var S=[],i=j=0; i<256; i++) {S[i] = i;}
for (i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key.length]) % 256;
swap(S, i, j);
} return S;
}
function rc4a_prga(S1, S2) {
var keystream = [];
for (var k=j1=j2=i=0; k<msg.length; k+=2) {
i = (i + 1) % 256;
j1 = (j1 + S1[i]) % 256;
swap(S1, i, j1);
keystream[k] = S2[(S1[i] + S1[j1]) % 256];
if(msg[k + 1] === undefined) {break;} // skip j2 if next byte in msg doesn't exist
j2 = (j2 + S2[i]) % 256;
swap(S2, i, j2);
keystream[k + 1] = S1[(S2[i] + S2[j2]) % 256];
} return keystream;
}
var S1 = rc4_ksa(key);
var S2 = rc4_ksa(S1);
var keystream = rc4a_prga(S1, S2);
var output = {
plain: msg,
cipher: xorout(msg, keystream), // final xor of msg<->keystream
keystream: keystream,
S1: S1,
S2: S2,
key1: key
}
return output;
}
// S1 = S2 (a popular, yet incorrect approach)
function rc4a(key, msg) {
function swap(S, i, j) {
var tmp = S[j]; S[j] = S[i]; S[i] = tmp;
}
function xorout(msg, keystream) {
for(var cipher = [], i = 0; i < msg.length; i++) {
cipher[i] = msg[i] ^ keystream[i];
} return cipher;
}
function rc4_ksa(key) {
for (var S=[],i=j=0; i<256; i++) {S[i] = i;}
for (i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key.length]) % 256;
swap(S, i, j);
} return S;
}
function rc4a_prga(S1, S2) {
var keystream = [];
for (var k=j1=j2=i=0; k<msg.length; k+=2) {
i = (i + 1) % 256;
j1 = (j1 + S1[i]) % 256;
swap(S1, i, j1);
keystream[k] = S2[(S1[i] + S1[j1]) % 256];
if(msg[k + 1] === undefined) {break;} // skip j2 if next byte in msg doesn't exist
j2 = (j2 + S2[i]) % 256;
swap(S2, i, j2);
keystream[k + 1] = S1[(S2[i] + S2[j2]) % 256];
} return keystream;
}
var S1 = rc4_ksa(key);
var S2 = rc4_ksa(key);
var keystream = rc4a_prga(S1, S2);
var output = {
plain: msg,
cipher: xorout(msg, keystream), // final xor of msg<->keystream
keystream: keystream,
S1: S1,
S2: S2,
key1: key
}
return output;
}
function rc4a(key, msg) {
function swap(S, i, j) {
var tmp = S[j]; S[j] = S[i]; S[i] = tmp;
}
function xorout(msg, keystream) {
for(var cipher = [], i = 0; i < msg.length; i++) {
cipher[i] = msg[i] ^ keystream[i];
} return cipher;
}
function rc4_ksa(key) {
for (var S=[],i=j=0; i<256; i++) {S[i] = i;}
for (i = 0; i < 256; i++) {
j = (j + S[i] + key[i % key.length]) % 256;
swap(S, i, j);
} return S;
}
function rc4_prga(S) {
var keystream = [];
for (var k=i=j=0; k<key.length; k++) {
i = (i + 1) % 256;
j = (j + S[i]) % 256;
swap(S, i, j);
keystream[k] = S[(S[i] + S[j]) % 256];
} return keystream;
}
function rc4a_prga(S1, S2) {
var keystream = [];
for (var k=j1=j2=i=0; k<msg.length; k+=2) {
i = (i + 1) % 256;
j1 = (j1 + S1[i]) % 256;
swap(S1, i, j1);
keystream[k] = S2[(S1[i] + S1[j1]) % 256];
if(msg[k + 1] === undefined) {break;} // skip j2 if next byte in msg doesn't exist
j2 = (j2 + S2[i]) % 256;
swap(S2, i, j2);
keystream[k + 1] = S1[(S2[i] + S2[j2]) % 256];
} return keystream;
}
var S1 = rc4_ksa(key);
var key2 = rc4_prga(S1.slice(0)); // Clone S1 so rc4_prga doesn't alter original
var S2 = rc4_ksa(key2);
var keystream = rc4a_prga(S1, S2);
var output = {
plain: msg,
cipher: xorout(msg, keystream), // final xor of msg<->keystream
keystream: keystream,
S1: S1,
S2: S2,
key1: key,
key2: key2
}
return output;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment