# CryptoHack write-up ## Introduction ### Finding Flags #### Problem > Each challenge is designed to help introduce you to a new piece of cryptography. Solving a challenge will require you to find a "flag". > > These flags will usually be in the format `crypto{y0ur_f1rst_fl4g}`. The flag format helps you verify that you found the correct solution. > > Try submitting this flag into the form below to solve your first challenge. #### Solution Simply submit `crypto{y0ur_f1rst_fl4g}` ### Great Snakes #### Problem > Modern cryptography involves code, and code involves coding. CryptoHack provides a good opportunity to sharpen your skills. > > Of all modern programming languages, Python 3 stands out as ideal for quickly writing cryptographic scripts and attacks. For more information about why we think Python is so great for this, please see the [FAQ](https://cryptohack.org/faq#python3). > > Run the attached Python script and it will output your flag. > > **Challenge files**: > - [great_snakes.py](https://cryptohack.org/static/challenges/great_snakes_35381fca29d68d8f3f25c9fa0a9026fb.py) #### Solution Download `great_snakes.py` file and run it with Python 3. ```shell python3 great_snakes.py ``` ```shell > crypto{z3n_0f_py0n} ``` ### Network Attacks #### Problem > Several of the challenges are dynamic and require you to talk to our challenge servers over the network. This allows you to perform man-in-the-middle attacks on people trying to communicate, or directly attack a vulnerable service. To keep things consistent, our interactive servers always send and receive JSON objects. > > Python makes such network communication easy with the telnetlib module. Conveniently, it's part of Python's standard library, so let's use it for now. > > For this challenge, connect to `socket.cryptohack.org` on port `11112`. Send a JSON object with the key buy and value flag. > The example script below contains the beginnings of a solution for you to modify, and you can reuse it for later challenges. > Connect at `nc socket.cryptohack.org 11112` > Challenge files: > - [telnetlib_example.py](https://cryptohack.org/static/challenges/telnetlib_example_dbc6ff5dc4dcfac568d7978a801d3ead.py) #### Solution Download `telnetlib_example.py` and change "clothes" in line 31 to "flag" ```shell! b"Welcome to netcat's flag shop!\n" b'What would you like to buy?\n' b"I only speak JSON, I hope that's ok.\n" b'\n' {'flag': 'crypto{sh0pp1ng_f0r_fl4g5}'} ``` ## General ### ASCII #### Problem >ASCII is a 7-bit encoding standard which allows the representation of text using the integers 0-127. > >Using the below integer array, convert the numbers to their corresponding ASCII characters to obtain a flag. > >``[99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125]`` > :bulb: In Python, the `chr()` function can be used to convert an ASCII ordinal number to a character (the `ord()` function does the opposite). #### Solution The integer array is in the Python syntax so you can copy it and paste in Python code. After pasted the array, with each element in the array, you can use `chr()` to print the ASCII character in that index. #### Code ```python! array = [99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125] for element in array: print(chr(element), end = "") print() ``` ```shell > crypto{ASCII_pr1nt4bl3} ``` ### Hex #### Problem > When we encrypt something the resulting ciphertext commonly has bytes which are not printable ASCII characters. If we want to share our encrypted data, it's common to encode it into something more user-friendly and portable across different systems. > > Hexadecimal can be used in such a way to represent ASCII strings. First each letter is converted to an ordinal number according to the ASCII table (as in the previous challenge). Then the decimal numbers are converted to base-16 numbers, otherwise known as hexadecimal. The numbers can be combined together, into one long hex string. > > Included below is a flag encoded as a hex string. Decode this back into bytes to get the flag. > > `63727970746f7b596f755f77696c6c5f62655f776f726b696e675f776974685f6865785f737472696e67735f615f6c6f747d` > :bulb: In Python, the `bytes.fromhex()` function can be used to convert hex to bytes. The `.hex()` instance method can be called on byte strings to get the hex representation. >Resources: > - [ASCII table](https://www.rapidtables.com/code/text/ascii-table.html) > - [Wikipedia: Hexadecimal](https://en.wikipedia.org/wiki/Hexadecimal) #### Solution Copy the hex string to Python code and use `bytes.fromhex()` to change it to bytes string and tou can read it. #### Code ```python3! code = "63727970746f7b596f755f77696c6c5f62655f776f726b696e675f776974685f6865785f737472696e67735f615f6c6f747d" print(bytes.fromhex(code)) ``` ```shell! > b'crypto{You_will_be_working_with_hex_strings_a_lot}' ``` ### Base64 #### Problem > Another common encoding scheme is Base64, which allows us to represent binary data as an ASCII string using an alphabet of 64 characters. One character of a Base64 string encodes 6 binary digits (bits), and so 4 characters of Base64 encode three 8-bit bytes. > > Base64 is most commonly used online, so binary data such as images can be easily included into HTML or CSS files. > > Take the below hex string, decode it into bytes and then encode it into Base64. > > `72bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf` > :bulb: In Python, after importing the base64 module with import base64, you can use the `base64.b64encode()` function. Remember to decode the hex first as the challenge description states. #### Solution Decode the hex string to bytes with `bytes.fromhex()` and then encode it to Base64 wit `b64encode()` #### Code ```python3! from base64 import b64encode code = "72bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf" bytesString = bytes.fromhex(code) b64code = b64encode(bytesString) print(b64code) ``` ```shell! > b'crypto/Base+64+Encoding+is+Web+Safe/' ``` ### Bytes and Big Integers #### Problem > Cryptosystems like RSA works on numbers, but messages are made up of characters. How should we convert our messages into numbers so that mathematical operations can be applied? > > The most common way is to take the ordinal bytes of the message, convert them into hexadecimal, and concatenate. This can be interpreted as a base-16/hexadecimal number, and also represented in base-10/decimal. > > To illustrate: > ``` > message: HELLO > ascii bytes: [72, 69, 76, 76, 79] > hex bytes: [0x48, 0x45, 0x4c, 0x4c, 0x4f] > base-16: 0x48454c4c4f > base-10: 310400273487 > ``` > Convert the following integer back into a message: > `11515195063862318899931685488813747395775516287289682636499965282714637259206269` > :bulb: Python's `PyCryptodome` library implements this with the methods `bytes_to_long()` and `long_to_bytes()`. You will first have to install `PyCryptodome` and import it with `from Crypto.Util.number import *`. For more details check the [FAQ](https://cryptohack.org/faq/#install). #### Solution Use `long_to_bytes()` to change the number to bytes #### Code ```python! from Crypto.Util.number import long_to_bytes() number = 11515195063862318899931685488813747395775516287289682636499965282714637259206269 print(long_to_bytes(number)) ```