diff --git a/cryptography/cpa/DESCRIPTION.md b/cryptography/cpa/DESCRIPTION.md new file mode 100644 index 0000000..6b49c8c --- /dev/null +++ b/cryptography/cpa/DESCRIPTION.md @@ -0,0 +1,23 @@ +Though the core of the AES crypto algorithm is thought to be secure (not _proven_ to be, though: no one has managed to do that! But no one has managed to significantly break the crypto in the 20+ years of its use, either), this core only encrypts 128-bit (16 byte) blocks at a time. +To actually _use_ AES in practice, one must build a _cryptosystem_ on top of it. + +In the previous level, we used the AES-[ECB](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)) cryptosystem: an Electronic Codebook Cipher where every block is indendently encrypted by the same key. +This system is quite simple but, as we will discover here, extremely susceptible to a certain class of attack. + +Cryptosystems are held to very high standard of [ciphertext indistinguishability](https://en.wikipedia.org/wiki/Ciphertext_indistinguishability). +That is, an attacker that lacks the key to the cryptosystem should not be able to distinguish between pairs of ciphertext based on the plaintext that was encrypted. +For example, if the attacker looks at ciphertexts `UVSDFGIWEHFBFFCA` and `LKXBFVYASLJDEWEU`, and is able to determine that the latter was produced from the plaintext `EEEEFFFFGGGGHHHH` (or, in fact, figure out _any_ information about the plaintext at all!), the cryptosystem is considered broken. +This property must hold even if the attacker already knows part or all of the plaintext, a setting known as the [Known Plaintext Attack](https://en.wikipedia.org/wiki/Known-plaintext_attack), _or can even control part or all of the plaintext_, a setting known as the [Chosen Plaintext Attack](https://en.wikipedia.org/wiki/Chosen-plaintext_attack)! + +ECB is susceptible to both known and chosen plaintext attack. +Because every block is encrypted with the same key, with no other modifications, an attacker can observe identical ciphertext across different blocks that have identical plaintext. +Moreover, if the attacker can choose or learn the plaintext associated with some of these blocks, they can carefully build a mapping from known-plaintext to known-ciphertext, and use that as a lookup table to decrypt other matching ciphertext! + +In this level, you will do just this: you will build a codebook mapping from ciphertext to chosen plaintext, then use that to decrypt the flag. +Good luck! + +---- +**HINT:** +You might find it helpful to automate interactions with this challenge. +You can do so using the `pwntools` Python package. +Check out [this pwntools cheatsheet](https://gist.github.com/anvbis/64907e4f90974c4bdd930baeb705dedf) from a fellow pwn.college student! diff --git a/cryptography/cpa/run b/cryptography/cpa/run new file mode 100755 index 0000000..47af572 --- /dev/null +++ b/cryptography/cpa/run @@ -0,0 +1,27 @@ +#!/opt/pwn.college/python + +from base64 import b64encode, b64decode +from Crypto.Cipher import AES +from Crypto.Util.Padding import pad +from Crypto.Random import get_random_bytes + +flag = open("/flag", "rb").read() + +key = get_random_bytes(16) +cipher = AES.new(key=key, mode=AES.MODE_ECB) + +while True: + print("Choose an action?") + print("1. Encrypt chosen plaintext.") + print("2. Encrypt part of the flag.") + if (choice := int(input("Choice? "))) == 1: + pt = input("Data? ").strip().encode() + elif choice == 2: + index = int(input("Index? ")) + length = int(input("Length? ")) + pt = flag[index:index+length] + else: + break + + ct = cipher.encrypt(pad(pt, cipher.block_size)) + print(f"Result: {b64encode(ct).decode()}") diff --git a/cryptography/level-4/DESCRIPTION.md b/cryptography/level-4/DESCRIPTION.md index 8b7ec68..60c341e 100644 --- a/cryptography/level-4/DESCRIPTION.md +++ b/cryptography/level-4/DESCRIPTION.md @@ -14,7 +14,7 @@ AES _must_ operate on complete blocks. If the plaintext is _shorter_ than a block (e.g., `AAAABBBB`), it will be _padded_ to the block size, and the padded plaintext will be encrypted. Different AES "modes" define what to do when the plaintext is longer than one block. -In this challenge, we are using the simplest mode: "[Electronic CodeBook (ECB)](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB))". +In this challenge, we are using the simplest mode: "[Electronic Codebook (ECB)](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB))". In ECB, each block is encrypted separately with the same key and simply concatenated together. So if you are encrypting something like `AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH`, it will be split into two plaintext blocks (`AAAABBBBCCCCDDDD` and `EEEEFFFFGGGGHHHH`), encrypted separately (resulting, let's imagine, in `UVSDFGIWEHFBFFCA` and `LKXBFVYASLJDEWEU`), then concatenated (resulting the ciphertext `UVSDFGIWEHFBFFCALKXBFVYASLJDEWEU`). diff --git a/cryptography/module.yml b/cryptography/module.yml index 026b379..1b8af49 100644 --- a/cryptography/module.yml +++ b/cryptography/module.yml @@ -17,6 +17,8 @@ challenges: name: Many-time Pad - id: level-4 name: AES +- id: cpa + name: Chosen-plaintext Attack - id: level-5 name: level5 - id: level-6