Rating:

the encryption is entirely bitwise, so by encrypting two plaintexts, one with all zeros and one with all ones, key recovery becomes trivial

(bitwise means each bit is encrypted individually, there's no mixing going on like with a good cipher like AES)

```py

from pwn import *

def hex2bin(n):

i = int(n,16) # convert to int

b = bin(i)[2:] # convert to binary

l = len(n) # get length

p = l*4-len(b) # get number of zeros omitted

b = "0"*p+b # add leading zeros to binary

return b # return binary

def bin2hex(n):

i = int(n,2)

h = hex(i)[2:]

l = len(n)

p = l//4-len(h)

h = "0"*p+h

return h

def encrypt(p, z, o):

p = hex2bin(p)

z = hex2bin(z)

o = hex2bin(o)

res = ""

for i in range(len(p)):

if p[i] == '0':

res += z[i]

else:

res += o[i]

return bin2hex(res)

conn = remote('crypto.2021.chall.actf.co', 21602)

# get zeros

conn.send(b"1\n")

conn.recv()

conn.send(b"0"*64+b"\n")

conn.recv()

zeros = conn.recv().split(b"\n")[0].decode()

print("Zeros:",zeros)

# get ones

conn.send(b"1\n")

conn.recv()

conn.send(b"f"*64+b"\n")

ones = conn.recv().split(b"\n")[0].decode()

print("Ones:",ones)

# encrypt and send

conn.send(b"2\n")

while True:

c = conn.recv()

if c[0] == ord("W"):

print(c.decode())

conn.close()

exit()

ct = c.replace(b'Encrypt this: ',b'').split(b'\n')[0].decode()

e = encrypt(ct,zeros,ones)

conn.send(e.encode()+b"\n")

```

Original writeup (https://github.com/williamsolem/writeups/blob/main/%C3%A5ngstromCTF%202021/actf_home_rolled_crypto_solve.py).