Happy Valentine's Day! I'm unfortunately spending my Valentine's Day working on my CS131 homework. I'm getting bored so I wrote something for my professor. To keep it secret, I encrypted it with a Vigenere cipher with a really long key (161 characters long!)
As a hint, I gave you the first part of the message I encrypted. Surely, you still can't figure it out though?
Flag format is lactf{xxx} with only lower case letters, numbers, and underscores between the braces.
- Solving Vigener cipher
- Given:
- the first part of the message
- length of the key
To find the key, I write the following python script.
def find_key(intro, ct):
def find_key_char(m, c):
if not m.isalpha():
return None
base = ord('a') if m.islower() else ord('A')
a = ord(m) - base
b = ord(c) - base
shift = (b - a) % 26
return chr(ord('A') + shift)
assert len(intro) == len(ct)
keys = [ find_key_char(intro[i], ct[i]) for i in range(len(intro)) ]
keys = list(filter(lambda x: x is not None, keys))
return "".join(keys)
with open("intro.txt", 'r') as file:
intro = file.read()
with open("ct.txt", 'r') as file:
ct = file.read()
key = find_key(intro, ct[:len(intro)])
assert len(ken) == 161 # failed 134
The key is not complete, but we can fill the space with random character and continue the decryption. By doing that, we can recover most of the text. Some will be random text and hopefully it won't effect the flag.
key = key + "A" * ( 161 - len(ke) )
assert len(key) == 161
# vigenere_decrypt is generated by ChatGPT
assert intro == vigenere_decrypt(ct[:len(intro)], key)
print(vigenere_decrypt(ct, key))
The decrypted text did contain some random text, but it doesn't effect the flag.
...
wrm ~cuamyh/umlofikjayrvplzcwm.gdt | less lactf{known_plaintext_and_were_off_to_the_races}
...