CRYPTOHACK
Discover the world of cryptography, from classic ciphers to modern encryption techniques, all in one place.
Introduction to CryptoHack
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.
Answer - crypto{y0ur_f1rst_fl4g}
#!/usr/bin/env python3
import sys
# import this
if sys.version_info.major == 2:
print("You are running Python 2, which is no longer supported. Please update to Python 3.")
ords = [81, 64, 75, 66, 70, 93, 73, 72, 1, 92, 109, 2, 84, 109, 66, 75, 70, 90, 2, 92, 79]
print("Here is your flag:")
print("".join(chr(o ^ 0x32) for o in ords))
Code Explanation
#!/usr/bin/env python3
Shebang Line: This tells the system to use Python 3 to run this script.
Import Statements
import sys
Imports the sys
module: Used to check the version of Python running the script.
# import this
Commented out: The line import this
would display "The Zen of Python," a list of aphorisms that capture the philosophy of Python, but it's commented out, so it does nothing.
Python Version Check
if sys.version_info.major == 2:
print("You are running Python 2, which is no longer supported. Please update to Python 3.")
This checks if the script is being run with Python 2. If so, it prints a message advising the user to switch to Python 3. Python 2 is outdated and no longer maintained.
Encrypted Data
ords = [81, 64, 75, 66, 70, 93, 73, 72, 1, 92, 109, 2, 84, 109, 66, 75, 70, 90, 2, 92, 79]
ords
is a list of integers that represent encrypted data.
Decryption Process
print("Here is your flag:")
print("".join(chr(o ^ 0x32) for o in ords))
Decryption Logic:
chr(o ^ 0x32)
: For each integero
in theords
list, a bitwise XOR operation is performed with0x32
(which is 50 in decimal). The result is then converted to a character usingchr()
.o ^ 0x32
: The XOR operation is used to decrypt each integer. XOR is a common operation used in simple encryption and decryption.
Result:
"".join(...)
: Joins all the decrypted characters into a single string, which is printed as the flag.
How XOR Works
XOR (exclusive OR) is a bitwise operation that returns
1
if the bits are different and0
if they are the same. It is often used in encryption because applying the same operation twice with the same key will return the original value. In this case,0x32
is the key used for both encryption and decryption.
Output
The script decrypts the integers in
ords
and prints the hidden flag.
Answer - crypto{z3n_0f_pyth0n}
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]
In Python, the chr()
function can be used to convert an ASCII ordinal number to a character (the ord()
function does the opposite).
Solution
# This script converts an array of ASCII ordinal numbers into a string using Python's chr() function
# Define the array of ASCII ordinal numbers
ascii_numbers = [99, 114, 121, 112, 116, 111, 123, 65, 83, 67, 73, 73, 95, 112, 114, 49, 110, 116, 52, 98, 108, 51, 125]
# Convert each number to its corresponding character using chr() and join them into a single string
flag = ''.join(chr(number) for number in ascii_numbers)
# Print the resulting flag
print("The flag is:", flag)
Explanation
The code converts a list of ASCII ordinal numbers into a string:
It uses
chr()
to transform each number into a character.It joins all characters into a single string.
Finally, it prints the string as the flag.
Result: A readable flag from the given numbers.
Answer - crypto{ASCII_pr1nt4bl3}
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
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.
Solution
# Script to decode a hex string to ASCII
# Given hex string
hex_string = "63727970746f7b596f755f77696c6c5f62655f776f726b696e675f776974685f6865785f737472696e67735f615f6c6f747d"
# Convert hex string to bytes
decoded_bytes = bytes.fromhex(hex_string)
# Convert bytes to ASCII string
decoded_string = decoded_bytes.decode('ascii')
# Print the result
print("Decoded String:", decoded_string)
Explanation
This script decodes a given hexadecimal string into an ASCII text. Here's a short explanation of what each part does:
hex_string: The given hexadecimal string represents encoded text.
bytes.fromhex(hex_string): Converts the hex string into a sequence of bytes.
decode('ascii'): Translates the byte sequence into an ASCII string.
print: Outputs the decoded ASCII string.
Answer - crypto{You_will_be_working_with_hex_strings_a_lot}
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
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
import base64
# Given hex string
hex_string = "72bca9b68fc16ac7beeb8f849dca1d8a783e8acf9679bf9269f7bf"
# Step 1: Decode the hex string to bytes
decoded_bytes = bytes.fromhex(hex_string)
# Step 2: Encode the bytes into Base64
base64_encoded = base64.b64encode(decoded_bytes)
# Step 3: Convert the Base64 bytes to a string
base64_string = base64_encoded.decode('ascii')
# Print the result
print("Base64 Encoded String:", base64_string)
Explanation
This script takes a hexadecimal string, decodes it to bytes, and then re-encodes it in Base64 format. Here’s a concise explanation:
hex_string: A given string in hexadecimal format, where each pair of characters represents a byte.
bytes.fromhex(hex_string): Converts the hexadecimal string into a sequence of raw bytes.
base64.b64encode(decoded_bytes): Encodes the byte sequence into Base64, a commonly used encoding for binary data.
.decode('ascii'): Converts the Base64-encoded byte sequence into a readable ASCII string.
print: Outputs the final Base64-encoded string.
In short: The script converts a hex-encoded string to a Base64-encoded string and prints it.
Answer - crypto/Base+64+Encoding+is+Web+Safe/
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
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 *
.
Convert the following integer back into a message:
11515195063862318899931685488813747395775516287289682636499965282714637259206269
Solution
from Crypto.Util.number import long_to_bytes
# Given large integer
large_integer = 11515195063862318899931685488813747395775516287289682636499965282714637259206269
# Convert the integer to bytes and then decode to ASCII
message = long_to_bytes(large_integer).decode('ascii')
# Print the result
print("Decoded Message:", message)
Explanation
This script converts a large integer into a readable ASCII message using the long_to_bytes
function from the Crypto.Util.number
module. Here’s a breakdown of what the code does:
large_integer: A very large integer that represents encoded data.
long_to_bytes(large_integer): Converts the large integer into a sequence of bytes. This is a common step in cryptography when dealing with large numbers that encode text.
.decode('ascii'): Translates the byte sequence into a readable ASCII string.
print: Outputs the decoded ASCII message.
In Short:
The script decodes a large integer into an ASCII message. It does this by first converting the integer to bytes and then decoding those bytes into text.
Answer - crypto{3nc0d1n6_4ll_7h3_w4y_d0wn}
Last updated
Was this helpful?