Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions Uncategorized/RC4/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# RC4 (Keystream + Stream Cipher)

📌 Description
--------------

**RC4** (Rivest Cipher 4) is a symmetric stream cipher designed by Ron Rivest in 1987. It is known for its simplicity and speed in software, generating a **pseudorandom keystream** that is combined with plaintext to produce ciphertext.

RC4 has historically been used in protocols such as SSL/TLS and WEP, but it is now considered insecure due to multiple discovered vulnerabilities.

* * * * *

⚙️ Keystream Generation (Pseudo-Random Generation)
--------------------------------------------------

RC4 operates using an internal state consisting of:

- A permutation array `S` of 256 bytes
- Two indices `i` and `j`

### 1\. Key-Scheduling Algorithm (KSA)

Initializes the permutation `S` using the secret key:

- Start with:

S[i] = i for i = 0..255\
j = 0

- For each `i`:

j = (j + S[i] + key[i mod keylength]) mod 256\
swap(S[i], S[j])

This step mixes the key into the internal state.

* * * * *

### 2\. Pseudo-Random Generation Algorithm (PRGA)

Generates the keystream byte-by-byte:

- For each output byte:

i = (i + 1) mod 256\
j = (j + S[i]) mod 256\
swap(S[i], S[j])\
t = (S[i] + S[j]) mod 256\
output S[t]

The resulting sequence is a **pseudorandom keystream** used for encryption.

* * * * *

🔐 Encryption & Decryption (XOR)
--------------------------------

RC4 is a stream cipher, meaning encryption is performed by combining the keystream with plaintext using **bitwise XOR**:

ciphertext = plaintext ⊕ keystream

Decryption uses the same operation:

plaintext = ciphertext ⊕ keystream

This works because XOR is its own inverse.

* * * * *

⚠️ Weaknesses
-------------

RC4 is no longer considered secure due to several well-known issues:

- **Biased keystream output**\
Early bytes of the keystream are statistically biased, leaking information about the key.
- **Weak key scheduling (KSA)**\
Certain key patterns lead to predictable states, enabling attacks such as the Fluhrer--Mantin--Shamir attack.
- **Key reuse / related-key vulnerabilities**\
Reusing keys or combining keys improperly can expose secret information.
- **No built-in authentication**\
RC4 is vulnerable to bit-flipping attacks if not combined with a message authentication mechanism.
- **Deprecated in modern protocols**\
Due to these weaknesses, RC4 has been removed or prohibited in modern standards (e.g., TLS).

* * * * *

📊 Example Outputs
------------------

The following examples are adapted from RC4 Wikipedia article.\
The **first row has been verified against this implementation**.

| Key | Keystream | Plaintext | Ciphertext |
| --- | --- | --- | --- |
| Key | EB9F7781B734CA72A719... | Plaintext | BBF316E8D940AF0AD3 |
| Wiki | 6044DB6D41B7... | pedia | 1021BF0420 |
| Secret | 04D46B053CA87B59... | Attack at dawn | 45A01F645FC35B383552544B9BF5 |

* * * * *

📚 References
-------------

- [Wikipedia](https://en.wikipedia.org/wiki/RC4)
153 changes: 153 additions & 0 deletions Uncategorized/RC4/code.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Run on https://algorithm-visualizer.org/

// import visualization libraries {
const { Tracer, Array1DTracer, ChartTracer, LogTracer, Randomize, Layout, VerticalLayout } = require('algorithm-visualizer');
// }

// Define tracer variables {
const chart = new ChartTracer();
const chart_T = new ChartTracer();
const tracer = new Array1DTracer();
const tracer_T = new Array1DTracer();
const logger = new LogTracer();
const stream_logger = new LogTracer();
Layout.setRoot(new VerticalLayout([chart, tracer_T, stream_logger]));
// Layout.setRoot(new VerticalLayout([chart, tracer_T, logger, stream_logger])); // *uncomment this line to see indexes actual values at runtime*
// }

// Define working variables
let N = 256; // <--- set here desired S size (default 256)
const S = Array(N);
const T = Array(N);
const secret = [];
const key = "Key"; // <-- set here secret key (any keysize <=N)
for(let i=0; i<key.length; i++) {
secret[i] = key.charCodeAt(i); // ASCII conversion
}
const STREAMSIZE = 15; // <-- set here the keystream size (numbers to be generated)
const plaintext = ""
// + "Plaintext" // <-- *[OPTIONAL]: uncomment to encrypt (XOR) with generated keystream*
var j = 0;
var i = 0;
let k = [];




// STEP 1: INITIALIZE
// Array S gets initialized with 0...N values
for (let z=0; z<N; z++) {
S[z] = z;
}

// Secret key is copied over to match N size
for(let z=0, pwd_ix=0; z<N; z++, pwd_ix++) {
pwd_ix = pwd_ix % secret.length;
T[z] = secret[pwd_ix];
}
// logger {
logger.println(`original array = [${S.join(', ')}]`);
logger.println("j = " + j);
logger.println("i = " + i);
// }

// tracer {
tracer.set(S);
tracer.chart(chart);
tracer_T.set(T);
tracer_T.chart(chart_T);
Tracer.delay();
// }



// STEP 2: Initial permutation of S
for(let i=0; i < N; i++) {
logger.println("(" + (j + S[i] + T[i]) + ")")
j = (j + S[i] + T[i]) % N;
// logger {
logger.println("j = " + j);
logger.println("i = " + i);
// }
// visualize {
tracer.select(i);
tracer.select(j);

tracer_T.select(i);
Tracer.delay();
tracer_T.deselect(i);
// }
// SWAP
swap(i, j, S);
}

// STEP 3: Stream Generation
i=0; j=0;
for(let ix=0; ix<STREAMSIZE; ix++) {
i = (i+1) % N;
j = (j + S[i]) % N;
// visualize {
tracer.select(i);
tracer.select(j);
Tracer.delay();
//}

// SWAP
swap(i, j, S);

const t = (S[i] + S[j]) % N;
// visualize {
tracer.select(t);
Tracer.delay();
//}

k.push(S[t]);
// logger {
logger.println("t = " + t);
stream_logger.println("Generated stream: " + k);
// }
// deselect visualize {
tracer.deselect(t);
// }
}

// [OPTIONAL] STEP 4: Encryption
if(plaintext !== "") {
let converted_plaintext = 0;
let ciphertext = "";
let ciphertext_num = [];

logger.println(plaintext.length);
for(let i=0; i<plaintext.length && i<k.length; i++) {
converted_plaintext = plaintext.charCodeAt(i);

ciphertext_num.push(converted_plaintext ^ k[i]); // XOR
ciphertext = ciphertext.concat(String.fromCharCode(ciphertext_num[i]));
}

stream_logger.println("Encrypted text: " + ciphertext);
stream_logger.println("Encrypted text (numeric values): " + ciphertext_num);
}


// Utility functions {
function swap(elem1, elem2, array) {
let temp = array[elem1];
array[elem1] = array[elem2];
array[elem2] = temp;

// visualize {
tracer.patch(elem1, array[elem1]);
tracer.patch(elem2, array[elem2]);
Tracer.delay();
tracer.depatch(elem1);
tracer.depatch(elem2);
// }
// deselect visualize {
tracer.deselect(elem1);
tracer.deselect(elem2);
//}

return;
}
// }