Mr. Menhall has invented his own encryption algorithm and promised to give the flag to anyone who manages to decipher the message:
vWsMajX21l6BdKwDxaRA3utqhpvFL0V=
def hashcrypt(msg, key):
token = hashlib.sha1(key).digest()
res = ""
for c in msg:
n = ord(c) ^ 0xfe ^ 0xc3 ^ 0x42 ^ 0x21
n ^= 0xc2 ^ ord(token[0])
n ^= 0xf3 ^ ord(token[1])
n ^= 0x27 ^ ord(token[2])
n ^= 0x4c ^ ord(token[3])
n ^= 0x21 ^ ord(token[4])
n ^= 0xfe ^ ord(token[5])
n ^= 0xa3 ^ ord(token[6])
n ^= 0xf0 ^ ord(token[7])
n ^= 0x11 ^ ord(token[6])
n ^= 0x54 ^ ord(token[5])
n ^= 0xca ^ ord(token[4])
n ^= 0x3c ^ ord(token[3])
n ^= 0x20 ^ ord(token[2])
n ^= 0xd1 ^ ord(token[1])
n ^= 0xf2 ^ ord(token[0])
res += chr(n)
token = hashlib.sha1(chr(n)).digest()
return res.encode('base64').encode('rot13')
token = hashlib.sha1(key).digest()
res = ""
for c in msg:
n = ord(c) ^ 0xfe ^ 0xc3 ^ 0x42 ^ 0x21
n ^= 0xc2 ^ ord(token[0])
n ^= 0xf3 ^ ord(token[1])
n ^= 0x27 ^ ord(token[2])
n ^= 0x4c ^ ord(token[3])
n ^= 0x21 ^ ord(token[4])
n ^= 0xfe ^ ord(token[5])
n ^= 0xa3 ^ ord(token[6])
n ^= 0xf0 ^ ord(token[7])
n ^= 0x11 ^ ord(token[6])
n ^= 0x54 ^ ord(token[5])
n ^= 0xca ^ ord(token[4])
n ^= 0x3c ^ ord(token[3])
n ^= 0x20 ^ ord(token[2])
n ^= 0xd1 ^ ord(token[1])
n ^= 0xf2 ^ ord(token[0])
res += chr(n)
token = hashlib.sha1(chr(n)).digest()
return res.encode('base64').encode('rot13')
We need to code the reverse function to decrypt the cypher text.
Looking more closely, we notice most of the tokens (token[0] -> token[6]) are nulling each other because the operator between them is XOR: A^B^B = A
Also the token will get overwritten at each step with the sha1 hash of the previous cypher byte: We can decrypt all the chars except the first one.
import hashlib
def hashdecrypt(msg, key):
msg = msg.decode('rot13').decode('base64')
token = hashlib.sha1(key).digest()
res = ""
for c in msg:
n = ord(c) ^ 0xfe ^ 0xc3 ^ 0x42 ^ 0x21
n ^= 0xc2
n ^= 0xf3
n ^= 0x27
n ^= 0x4c
n ^= 0x21
n ^= 0xfe
n ^= 0xa3
n ^= 0xf0 ^ ord(token[7])
n ^= 0x11
n ^= 0x54
n ^= 0xca
n ^= 0x3c
n ^= 0x20
n ^= 0xd1
n ^= 0xf2
res += chr(n)
token = hashlib.sha1(c).digest()
return res
msg = "vWsMajX21l6BdKwDxaRA3utqhpvFL0V="
plaintext = hashdecrypt(msg, "unknown")
print "plaintext=", plaintext
def hashdecrypt(msg, key):
msg = msg.decode('rot13').decode('base64')
token = hashlib.sha1(key).digest()
res = ""
for c in msg:
n = ord(c) ^ 0xfe ^ 0xc3 ^ 0x42 ^ 0x21
n ^= 0xc2
n ^= 0xf3
n ^= 0x27
n ^= 0x4c
n ^= 0x21
n ^= 0xfe
n ^= 0xa3
n ^= 0xf0 ^ ord(token[7])
n ^= 0x11
n ^= 0x54
n ^= 0xca
n ^= 0x3c
n ^= 0x20
n ^= 0xd1
n ^= 0xf2
res += chr(n)
token = hashlib.sha1(c).digest()
return res
msg = "vWsMajX21l6BdKwDxaRA3utqhpvFL0V="
plaintext = hashdecrypt(msg, "unknown")
print "plaintext=", plaintext
Output:
plaintext= 9_lied_no_flag_for_you!
Guessing time… “i_lied_no_flag_for_you!” was the correct flag.