> For the complete documentation index, see [llms.txt](https://security.andreasbreum.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://security.andreasbreum.com/cryptology/cryptohack/course-introduction-to-cryptohack/general-xor.md).

# General - XOR

## XOR Starter

*"Given the string `label`, XOR each character with the integer `13`. Convert these integers back to a string and submit the flag as `crypto{new_string}`."*

The following script should do the trick of printing the flag.

{% code overflow="wrap" lineNumbers="true" %}

```python
#!/usr/bin/env python3

def xor_encrypt(s: str, key: int) -> str:
    """
    Encrypts a string using XOR with a key.
    """
    new_string = ""
    for c in s:
        new_string += chr(ord(c) ^ key)
    return new_string


def main():
    s = "label"
    key = 13
    encrypted_string = xor_encrypt(s, key)
    print("crypto{{{}}}".format(encrypted_string))


if __name__ == "__main__":
    main()

```

{% endcode %}

## XOR Properties

We get the following outputs where three random keys have been XOR'd together and with the flag:

{% code overflow="wrap" lineNumbers="true" %}

```
KEY1 = a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313 
KEY2 ^ KEY1 = 37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e 
KEY2 ^ KEY3 = c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1 
FLAG ^ KEY1 ^ KEY3 ^ KEY2 = 04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf
```

{% endcode %}

The flag is in the last line. It is xored with KEY1, KEY2 and KEY3. Thus, all we need to do is to xor that line with all these keys. Lines 1 and 3 contains those combinations.

That is, `KEY1 ^ KEY2 ^ KEY3 ^ FLAG ^ KEY1 ^ KEY3 ^ KEY2 = FLAG`

{% code overflow="wrap" lineNumbers="true" %}

```python
#!/usr/bin/env python3
from pwnlib.util.fiddling import xor

KEY1 = bytes.fromhex('a6c8b6733c9b22de7bc0253266a3867df55acde8635e19c73313')
KEY2_KEY1 = bytes.fromhex('37dcb292030faa90d07eec17e3b1c6d8daf94c35d4c9191a5e1e')
KEY2_KEY3 = bytes.fromhex('c1545756687e7573db23aa1c3452a098b71a7fbf0fddddde5fc1')
FLAG_KEY1_KEY3_KEY2 = bytes.fromhex('04ee9855208a2cd59091d04767ae47963170d1660df7f56f5faf')

rm_key1 = xor(KEY1,FLAG_KEY1_KEY3_KEY2)
flag = xor(KEY2_KEY3, rm_key1)
print(flag)
```

{% endcode %}

## Favourite byte

*For the next few challenges, you'll use what you've just learned to solve some more XOR puzzles.*\
\
*I've hidden some data using XOR with a single byte, but that byte is a secret. Don't forget to decode from hex first.*\
\
*`73626960647f6b206821204f21254f7d694f7624662065622127234f726927756d`"*

We know that the flag starts with 'c' as it follows the format *crypto{flag}*.

So, to find the one byte key we can xor the first byte of the string with the int value of 'c'.&#x20;

{% code overflow="wrap" lineNumbers="true" %}

```python
#!/usr/bin/env python3
from pwnlib.util.fiddling import xor

s = bytes.fromhex('73626960647f6b206821204f21254f7d694f7624662065622127234f726927756d')

key = s[0] ^ ord('c')
print(xor(s, key))
```

{% endcode %}

## You either know, XOR you don't

*"I've encrypted the flag with my secret key, you'll never be able to guess it.*\
\
*`0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104`"*

This challenge is similar to the previous one. We start with the fact that we know the flag start like this `crypto{`.

{% code overflow="wrap" lineNumbers="true" %}

```python
#!/usr/bin/env python3
from pwnlib.util.fiddling import xor

s = bytes.fromhex('0e0b213f26041e480b26217f27342e175d0e070a3c5b103e2526217f27342e175d0e077e263451150104')

known_plain_txt = 'crypto{'
print(xor(s, known_plain_txt))
# Outputs: b'myXORke+y_Q\x0bHOMe$~seG8bGURN\x04DFWg)a|\x1dTM!an\x7f'
# From this we derive the key
key = 'myXORkey'
print(xor(s, key))
```

{% endcode %}
