#!/usr/bin/env python3 import itertools import requests import string URL = "https://projecteuler.net/project/resources/p059_cipher.txt" def get_ciphertext(url): resp = requests.get(url) return resp.text def generate_keys(letters, length): perms = itertools.permutations(letters, length) yield from perms def ints_to_string(numbers): return [chr(num) for num in numbers] def string_to_ints(letters): return [ord(letter) for letter in letters] def xor_lists(xs, ys): if len(xs) != len(ys): raise Exception("Lists must be the same length") return [a ^ b for a, b in zip(xs, ys)] def main(): text = get_ciphertext(URL) cipher = [int(num) for num in text.split(',')] letters = string.ascii_lowercase common_words = ["the", "of", "to", "and", "in", "is", "it", "that"] for perm in generate_keys(letters, 3): key = "".join(list(perm)) cycled = string_to_ints(list(key * (len(cipher) // len(key)))) decrypt = "".join(ints_to_string(xor_lists(cipher, cycled))) if all(word in decrypt for word in common_words): print("Decrypted passage:") print(decrypt) print("Key: {0}".format(key)) print("Sum: {0}".format(sum(xor_lists(cipher, cycled)))) if __name__ == "__main__": main()