Cyber Security Lab Writeup
Cryptography Analysis Lab
Five practical investigations into how ciphertext can be identified, generated, decrypted, and validated - from classical frequency analysis to AES tooling and RSA key mathematics.
Project overview
Applying cryptographic theory to observable evidence.
This university project was not one isolated encryption exercise. It required me to move between classical cryptanalysis, bit-level stream-cipher operation, modern block modes, command-line investigation, and public-key mathematics.
My role in each task was to show the reasoning behind the result. I measured ciphertext characteristics before naming a cipher, traced an LFSR state by state, compared how block modes changed image structure, tested decryption assumptions systematically, and checked whether RSA parameters satisfied the mathematics required for a valid key pair.
Investigation map
Use frequencies, repeated fragments, and index of coincidence to distinguish cipher families.
Trace an LFSR, extract the usable keystream, and encrypt plaintext with XOR.
Encrypt image data with CBC and CTR and explain why visible structure disappears.
Read file and hash clues, test OpenSSL settings, and validate a successful AES decryption.
Derive RSA values and diagnose why an invalid exponent pair fails to recover its message.
01 / Classical cryptanalysis
I identified two ciphers from measurable behaviour.
I began with two unknown ciphertexts. Rather than guessing from appearance, I compared letter distributions, repeated fragments, and the index of coincidence. The first text produced an index of coincidence of approximately 0.041, with a relatively flat distribution. Testing likely key lengths and splitting the text by key position produced columns that behaved like separate Caesar shifts, supporting a Vigenere identification.
The second text produced an index of coincidence of approximately 0.069, much closer to normal English. Its frequency distribution was uneven and identical fragments repeated throughout the ciphertext. That preservation of patterns supported a monoalphabetic substitution cipher, where one plaintext letter consistently maps to one ciphertext letter.
| Evidence | Ciphertext 1 | Ciphertext 2 |
|---|---|---|
| Index of coincidence | Approx. 0.041 | Approx. 0.069 |
| Frequency shape | Flatter, less English-like | Strongly uneven, English-like |
| Repeated patterns | Changed with key position | Preserved consistently |
| Conclusion | Vigenere cipher | Monoalphabetic substitution |
I then recovered readable plaintext by deriving the Vigenere shifts column by column and building a substitution mapping from common letter and word patterns. The important lesson was that cipher identification should be justified by multiple signals; one frequency chart is useful, but the conclusion becomes much stronger when coincidence, repetition, and successful recovery agree.
02 / LFSR stream cipher
I traced the generator before using its output.
The stream-cipher task used a six-bit Linear Feedback Shift Register as a pseudorandom generator. I documented each register state, calculated the feedback bit with XOR, shifted the register, and recorded the output. Because the first six output bits represented the seed period and were excluded, I continued the LFSR long enough to obtain ten usable bits for the plaintext.
| Value | Bit sequence |
|---|---|
| Plaintext P | 1011010111 |
| Usable keystream K | 1110110001 |
| Ciphertext C = P XOR K | 0101100110 |
This made the weakness of the design concrete. A six-bit LFSR has a small, deterministic state space and a limited period. Over a longer message the keystream can repeat or be reconstructed, so the exercise is useful for understanding stream-cipher mechanics but not suitable as strong encryption.
03 / Block cipher modes
I used image encryption to compare CBC and CTR.
I encrypted bitmap data with OpenSSL using AES in CBC and CTR modes, then inspected the resulting images. In both outputs the original penguin structure disappeared and the image resembled random noise. The visual result was similar, but the reason each mode achieved it was different.
Each plaintext block is combined with the previous ciphertext block, with an IV used for the first block. Repeated plaintext blocks therefore produce different ciphertext in context.
Successive counter values are encrypted to create changing keystream blocks, which are XORed with the plaintext. Repeated image blocks do not receive the same keystream.
The comparison helped me understand why mode selection matters as much as the block cipher itself. ECB leaks repeated structure; CBC hides it through chaining, while CTR hides it through a unique counter stream and also allows independent block processing.
04 / AES decryption investigation
I treated decryption as a sequence of testable assumptions.
The AES task supplied an encrypted file and a password-hash clue. I first recognised the hash prefix as SHA-256-crypt metadata,
then used John the Ripper in the course virtual machine to recover and verify the password. I separately inspected the encrypted
file and found the Salted__ header used by OpenSSL's salted format.
My initial AES-128 attempts did not produce readable output. Instead of treating those failures as dead ends, I varied one assumption at a time: block mode, message digest, and password-based key derivation. The combination that produced coherent plaintext was AES-128-CTR with PBKDF2 and SHA-256.
openssl enc -d -aes-128-ctr -pbkdf2 -md sha256 \
-in ciphertext3.txt -out plaintext3.txt \
-pass pass:[REDACTED]
I validated the result by checking that the complete output was readable and internally consistent, not merely that OpenSSL returned without an error. This task taught me to separate three different pieces of evidence: a password hash is not an AES key, a file header can reveal the tool and storage format, and correct decryption depends on reproducing the original mode and KDF settings.
05 / RSA cryptosystem
I derived one valid key and diagnosed one invalid pair.
For the valid example, I calculated the modulus and Euler totient from p = 59 and q = 47, then used the
extended Euclidean algorithm to find the private exponent for e = 17. This produced n = 2773,
phi(n) = 2668, and d = 157. Applying modular exponentiation to a supplied hash value produced a signature of 126.
| Check | Result | Meaning |
|---|---|---|
gcd(17, 2668) | 1 | The public exponent is valid. |
17 x 157 mod 2668 | 1 | The private exponent is the required inverse. |
65^157 mod 2773 | 126 | RSA signature result for the supplied hash. |
A second example intentionally used e = 20 with phi(n) = 3120. Because
gcd(20, 3120) = 20, the public exponent was not coprime with the totient. The supplied private exponent also failed
the inverse check. Encryption returned a ciphertext, but decryption produced 1160 instead of the original message
11. This showed that producing numbers is not proof of a valid RSA system; the key parameters must satisfy the required relationships.
What I learned
The common skill was evidence-driven troubleshooting.
Across all five tasks, I learned to avoid jumping straight to a tool or algorithm name. I had to collect evidence, form a likely explanation, test it, and then check whether the result behaved as expected. That same method connected statistical cipher clues, register-state tracing, image patterns, OpenSSL failures, and RSA arithmetic.
- Use several measurements together when identifying an unknown cipher.
- Trace stateful algorithms carefully enough that every output bit can be explained.
- Understand what an encryption mode changes, not only which command invokes it.
- Treat failed decryption attempts as information about incorrect assumptions.
- Validate cryptographic parameters before trusting an encryption or signature result.
What this project demonstrated
The project gave me practical experience moving between mathematical reasoning and security tooling. It demonstrated that I can document a technical process, explain why a result occurred, troubleshoot configurations methodically, and distinguish a result that merely looks plausible from one that satisfies the underlying cryptographic rules.