Last active
June 6, 2025 21:10
-
-
Save Timo614/d06a4cdab7d9ad3e89e6a2668f181a1e to your computer and use it in GitHub Desktop.
kryptos-k1-k3.ipynb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "view-in-github", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "<a href=\"https://colab.research.google.com/gist/Timo614/d06a4cdab7d9ad3e89e6a2668f181a1e/kryptos-k1-k3.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "\n", | |
| "import sys\n", | |
| "\n", | |
| "MORSE_CODE_DICT = {\n", | |
| " \".-\": \"A\", \"-...\": \"B\", \"-.-.\": \"C\", \"-..\": \"D\", \".\": \"E\",\n", | |
| " \"..-.\": \"F\", \"--.\": \"G\", \"....\": \"H\", \"..\": \"I\", \".---\": \"J\",\n", | |
| " \"-.-\": \"K\", \".-..\": \"L\", \"--\": \"M\", \"-.\": \"N\", \"---\": \"O\",\n", | |
| " \".--.\": \"P\", \"--.-\": \"Q\", \".-.\": \"R\", \"...\": \"S\", \"-\": \"T\",\n", | |
| " \"..-\": \"U\", \"...-\": \"V\", \".--\": \"W\", \"-..-\": \"X\", \"-.--\": \"Y\",\n", | |
| " \"--..\": \"Z\",\n", | |
| " \"-----\": \"0\", \".----\": \"1\", \"..---\": \"2\", \"...--\": \"3\", \"....-\": \"4\",\n", | |
| " \".....\": \"5\", \"-....\": \"6\", \"--...\": \"7\", \"---..\": \"8\", \"----.\": \"9\",\n", | |
| " \".-.-.-\": \".\", \"--..--\": \",\", \"..--..\": \"?\", \".----.\": \"'\",\n", | |
| " \"-.-.--\": \"!\", \"-..-.\": \"/\", \"-.--.\": \"(\", \"-.--.-\": \")\",\n", | |
| " \".-...\": \"&\", \"---...\": \":\", \"-.-.-.\": \";\", \"-...-\": \"=\",\n", | |
| " \".-.-.\": \"+\", \"-....-\": \"-\", \"..--.-\": \"_\", \".-..-.\": \"\\\"\",\n", | |
| " \"...-..-\": \"$\", \".--.-.\": \"@\",\n", | |
| " \"...---...\": \"SOS\"\n", | |
| "}\n", | |
| "\n", | |
| "def normalize_morse_string(raw_string):\n", | |
| " unicode_dots = [\"\\u00B7\", \"\\u22C5\", \"\\u2022\", \"\\u2219\"]\n", | |
| " unicode_dashes = [\"\\u2013\", \"\\u2014\", \"\\u2212\"]\n", | |
| " normalized_chars = []\n", | |
| " for ch in raw_string:\n", | |
| " if ch in unicode_dots:\n", | |
| " normalized_chars.append(\".\")\n", | |
| " elif ch in unicode_dashes:\n", | |
| " normalized_chars.append(\"-\")\n", | |
| " else:\n", | |
| " normalized_chars.append(ch)\n", | |
| " return \"\".join(normalized_chars)\n", | |
| "\n", | |
| "def decode_morse_letter(pattern, morse_dict, unknown_patterns):\n", | |
| " if pattern in morse_dict:\n", | |
| " return morse_dict[pattern]\n", | |
| " else:\n", | |
| " unknown_patterns.append(pattern)\n", | |
| " return \"?\"\n", | |
| "\n", | |
| "def decode_full_morse_string(morse_string, morse_dict):\n", | |
| " unknown_patterns = []\n", | |
| " decoded_lines = []\n", | |
| " for line in morse_string.split(\"\\n\"):\n", | |
| " words = line.split(\"\\t\")\n", | |
| " decoded_words = []\n", | |
| " for word_chunk in words:\n", | |
| " word_chunk = word_chunk.strip()\n", | |
| " if not word_chunk:\n", | |
| " continue\n", | |
| " letter_patterns = word_chunk.split(\" \")\n", | |
| " decoded_letters = []\n", | |
| " for pat in letter_patterns:\n", | |
| " pat = pat.strip()\n", | |
| " if not pat:\n", | |
| " continue\n", | |
| " decoded_char = decode_morse_letter(pat, morse_dict, unknown_patterns)\n", | |
| " decoded_letters.append(decoded_char)\n", | |
| " decoded_words.append(\"\".join(decoded_letters))\n", | |
| " decoded_lines.append(\" \".join(decoded_words))\n", | |
| " decoded_text = \"\\n\".join(decoded_lines)\n", | |
| " return decoded_text, unknown_patterns\n", | |
| "\n", | |
| "if __name__ == \"__main__\":\n", | |
| " RAW_MORSE_SEGMENTS = [\n", | |
| " \"· · ···- ·· ·-· – ··- ·- ·-·· ·-·· -.-- · \\t · · · · · · ·· -· ···- ·· ··· ·· -··· ·-·· ·\",\n", | |
| " \". -.. .. --. . - .- .-.. . . . \\t .. -. - . .-. .--. .-. . - .- - .. -\",\n", | |
| " \". . ... .... .- -.. --- .-- . . \\t ..-. --- .-. -.-. . ... . . . . .\",\n", | |
| " \".-.. ..- -.-. .. -.. . . . \\t -- . -- --- .-. -.-- .\",\n", | |
| " \"- .. ... -.-- --- ..- .-. \\t .--. --- ... .. - .. --- -. .\",\n", | |
| " \".-. --.-\",\n", | |
| " \"...---...\"\n", | |
| " ]\n", | |
| " RAW_MORSE_INPUT = \"\\t\\n\".join(RAW_MORSE_SEGMENTS)\n", | |
| " normalized = normalize_morse_string(RAW_MORSE_INPUT)\n", | |
| " decoded_text, unknowns = decode_full_morse_string(normalized, MORSE_CODE_DICT)\n", | |
| " print(normalized)\n", | |
| " print(decoded_text)" | |
| ], | |
| "metadata": { | |
| "id": "jcGHKIz2-pHS", | |
| "outputId": "574cbd61-da9a-4a9b-96cc-60e9422b319c", | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| } | |
| }, | |
| "execution_count": 1, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| ". . ...- .. .-. - ..- .- .-.. .-.. -.-- . \t . . . . . . .. -. ...- .. ... .. -... .-.. .\t\n", | |
| ". -.. .. --. . - .- .-.. . . . \t .. -. - . .-. .--. .-. . - .- - .. -\t\n", | |
| ". . ... .... .- -.. --- .-- . . \t ..-. --- .-. -.-. . ... . . . . .\t\n", | |
| ".-.. ..- -.-. .. -.. . . . \t -- . -- --- .-. -.-- .\t\n", | |
| "- .. ... -.-- --- ..- .-. \t .--. --- ... .. - .. --- -. .\t\n", | |
| ".-. --.-\t\n", | |
| "...---...\n", | |
| "EEVIRTUALLYE EEEEEEINVISIBLE\n", | |
| "EDIGETALEEE INTERPRETATIT\n", | |
| "EESHADOWEE FORCESEEEEE\n", | |
| "LUCIDEEE MEMORYE\n", | |
| "TISYOUR POSITIONE\n", | |
| "RQ\n", | |
| "SOS\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "metadata": { | |
| "id": "pCQtN7AstLj5" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "import string\n", | |
| "import re\n", | |
| "import math\n", | |
| "from collections import OrderedDict, Counter\n", | |
| "from enum import Enum\n", | |
| "from typing import List, Dict, Tuple\n", | |
| "\n", | |
| "class Vigenere:\n", | |
| " @staticmethod\n", | |
| " def generate_table(alphabet: str) -> Tuple[List[str], List[int]]:\n", | |
| " seen = set()\n", | |
| " keyword_chars = []\n", | |
| " for c in alphabet:\n", | |
| " uc = c.upper()\n", | |
| " if 'A' <= uc <= 'Z' and uc not in seen:\n", | |
| " seen.add(uc)\n", | |
| " keyword_chars.append(uc)\n", | |
| " # 2) Fill out to full A–Z\n", | |
| " for letter in string.ascii_uppercase:\n", | |
| " if letter not in seen:\n", | |
| " keyword_chars.append(letter)\n", | |
| " seen.add(letter)\n", | |
| " # 3) Create lookup: letter → index in keyword array\n", | |
| " keyword_array = keyword_chars[:26]\n", | |
| " abc_lookup_table = [0] * 26\n", | |
| " for idx, letter in enumerate(keyword_array):\n", | |
| " abc_lookup_table[ord(letter) - 65] = idx\n", | |
| " return keyword_array, abc_lookup_table\n", | |
| "\n", | |
| " @staticmethod\n", | |
| " def generate_codex(abc_lookup_table: List[int], keyword: str) -> List[int]:\n", | |
| " \"\"\"\n", | |
| " Turn each char of 'keyword' into its index in the table.\n", | |
| " \"\"\"\n", | |
| " codex = []\n", | |
| " for letter in keyword:\n", | |
| " uc = letter.upper()\n", | |
| " if 'A' <= uc <= 'Z':\n", | |
| " codex.append(abc_lookup_table[ord(uc) - 65])\n", | |
| " return codex\n", | |
| "\n", | |
| " def __init__(self, alphabet: str, keyword: str):\n", | |
| " self.keyword_array, self.abc_lookup_table = self.generate_table(alphabet)\n", | |
| " self.codex = self.generate_codex(self.abc_lookup_table, keyword)\n", | |
| "\n", | |
| " def decrypt(self, ciphertext: str) -> str:\n", | |
| " result = []\n", | |
| " idx = 0\n", | |
| " codex_len = len(self.codex)\n", | |
| " for c in ciphertext:\n", | |
| " if c.isalpha():\n", | |
| " uc = c.upper()\n", | |
| " shift = self.codex[idx % codex_len]\n", | |
| " base_idx = self.abc_lookup_table[ord(uc) - 65]\n", | |
| " dec_idx = (26 + base_idx - shift) % 26\n", | |
| " result.append(self.keyword_array[dec_idx])\n", | |
| " idx += 1\n", | |
| " else:\n", | |
| " result.append(c)\n", | |
| " return ''.join(result)\n", | |
| "\n", | |
| " def encrypt_with_index(self, plaintext: str, codex_start: int) -> str:\n", | |
| " \"\"\"\n", | |
| " Standard Vigenère encryption but allowing a nonzero initial position\n", | |
| " in the repeating key (codex).\n", | |
| " \"\"\"\n", | |
| " result = []\n", | |
| " codex_idx = codex_start % len(self.codex)\n", | |
| " for c in plaintext:\n", | |
| " if c.isalpha():\n", | |
| " uc = c.upper()\n", | |
| " # find plaintext letter in keyword_array\n", | |
| " kw_idx = self.keyword_array.index(uc)\n", | |
| " enc_idx = (self.codex[codex_idx] + kw_idx) % 26\n", | |
| " result.append(self.keyword_array[enc_idx])\n", | |
| " codex_idx = (codex_idx + 1) % len(self.codex)\n", | |
| " else:\n", | |
| " result.append(c)\n", | |
| " return ''.join(result)\n", | |
| "\n", | |
| " def encrypt(self, plaintext: str) -> str:\n", | |
| " \"\"\"Encrypt starting at codex index 0.\"\"\"\n", | |
| " return self.encrypt_with_index(plaintext, 0)\n", | |
| "\n", | |
| "\n", | |
| "def apply_pattern(text: str, pattern: List[int]) -> str:\n", | |
| " \"\"\"\n", | |
| " Shift the entire alphabet by each integer in 'pattern' in sequence,\n", | |
| " then apply that final mapping to 'text'.\n", | |
| " \"\"\"\n", | |
| " alphabet = string.ascii_uppercase\n", | |
| " shifted = alphabet\n", | |
| " mapping = {}\n", | |
| " for shift in pattern:\n", | |
| " s = shift % 26\n", | |
| " shifted = shifted[s:] + shifted[:s]\n", | |
| " mapping = {alphabet[i]: shifted[i] for i in range(26)}\n", | |
| " # map only uppercase letters; leave others untouched\n", | |
| " return ''.join(mapping.get(c.upper(), c) if c.isalpha() else c for c in text)\n", | |
| "\n", | |
| "\n", | |
| "def generate_plaintext_letter_mapping() -> Dict[str, Dict[str, str]]:\n", | |
| " \"\"\"\n", | |
| " Build mapping: plaintext_letter → (encrypted_letter → key_letter)\n", | |
| " using Vigenère keyed off 'KRYPTOS'.\n", | |
| " \"\"\"\n", | |
| " mapping: Dict[str, Dict[str, str]] = {}\n", | |
| " for plain in string.ascii_uppercase:\n", | |
| " inner = {}\n", | |
| " for key_char in string.ascii_uppercase:\n", | |
| " vig = Vigenere(\"KRYPTOS\", key_char)\n", | |
| " enc = vig.encrypt(plain)\n", | |
| " inner[enc] = key_char\n", | |
| " mapping[plain] = inner\n", | |
| " return mapping\n", | |
| "\n", | |
| "\n", | |
| "def find_shift_keys(encrypted_text: str, plaintext: str) -> OrderedDict:\n", | |
| " \"\"\"\n", | |
| " For each Caesar shift 0–25, unshift the encrypted text and\n", | |
| " derive the Vigenère key stream that maps unshifted→plaintext.\n", | |
| " \"\"\"\n", | |
| " pt_map = generate_plaintext_letter_mapping()\n", | |
| " results = OrderedDict()\n", | |
| " for shift in range(26):\n", | |
| " shifted_enc = apply_pattern(encrypted_text, [-shift])\n", | |
| " key_text = ''.join(\n", | |
| " pt_map.get(p, {}).get(e, '')\n", | |
| " for e, p in zip(shifted_enc, plaintext)\n", | |
| " )\n", | |
| " results[shift] = key_text\n", | |
| " return results\n", | |
| "\n", | |
| "\n", | |
| "def find_pre_shift_keys(encrypted_text: str, plaintext: str) -> OrderedDict:\n", | |
| " \"\"\"\n", | |
| " Similar to above but shift the plaintext first, then compare.\n", | |
| " \"\"\"\n", | |
| " pt_map = generate_plaintext_letter_mapping()\n", | |
| " results = OrderedDict()\n", | |
| " for shift in range(26):\n", | |
| " shifted_plain = apply_pattern(plaintext, [-shift])\n", | |
| " key_text = ''.join(\n", | |
| " pt_map.get(sp, {}).get(ec, '')\n", | |
| " for ec, sp in zip(encrypted_text, shifted_plain)\n", | |
| " )\n", | |
| " results[shift] = key_text\n", | |
| " return results\n", | |
| "\n", | |
| "class Direction(Enum):\n", | |
| " Right = 1\n", | |
| " Left = 2\n", | |
| "\n", | |
| "class Shift:\n", | |
| " def __init__(self, column_size: int, rotation_direction: Direction):\n", | |
| " self.column_size = column_size\n", | |
| " self.rotation_direction = rotation_direction\n", | |
| "\n", | |
| "def transpose(mat: List[List[str]]) -> List[List[str]]:\n", | |
| " max_cols = max(len(row) for row in mat)\n", | |
| " return [\n", | |
| " [row[i] if i < len(row) else ' ' for row in mat]\n", | |
| " for i in range(max_cols)\n", | |
| " ]\n", | |
| "\n", | |
| "def transform_text(\n", | |
| " text: str, column_width: int, rotation_direction: Direction\n", | |
| ") -> str:\n", | |
| " padding = (column_width - len(text) % column_width) % column_width\n", | |
| " if rotation_direction == Direction.Right:\n", | |
| " chars = list(text) + ['\\0'] * padding\n", | |
| " chunks = [chars[i:i+column_width] for i in range(0, len(chars), column_width)]\n", | |
| " else:\n", | |
| " inverse = math.ceil(len(text) / column_width)\n", | |
| " sep = inverse * (column_width - padding)\n", | |
| " part1 = text[:sep]\n", | |
| " part2 = text[sep:]\n", | |
| " chunks = [list(part1[i:i+inverse]) for i in range(0, len(part1), inverse)]\n", | |
| " for i in range(0, len(part2), inverse-1):\n", | |
| " chunk = list(part2[i:i+(inverse-1)])\n", | |
| " chunk.insert(0, '\\0')\n", | |
| " chunks.append(chunk)\n", | |
| " trans = transpose(chunks)\n", | |
| " cols = [''.join(reversed(r)) for r in trans]\n", | |
| " combined = ''.join(cols)\n", | |
| " if rotation_direction == Direction.Left:\n", | |
| " combined = combined[::-1]\n", | |
| " return ''.join(c for c in combined if c.isalpha())\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "eIlxlFFgvmWS", | |
| "outputId": "a3b8b3e1-5f4c-41f5-d9a0-f60ff054bd22" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "EMUFPHZLRFAXYUSDJKZLDKRNSHGNFIVJYQTQUXQBQVYUVLLTREVJYQTMKYRDMFD\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "plaintext = \"BETWEENSUBTLESHADINGANDTHEABSENCEOFLIGHTLIESTHENUANCEOFIQLUSION\"\n", | |
| "cipher = Vigenere(\"KRYPTOS\", \"PALIMPSEST\")\n", | |
| "encoded = cipher.encrypt(plaintext)\n", | |
| "print(encoded)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "jNryUnQuwI5V", | |
| "outputId": "6f01079f-e52f-43e5-f3e0-ae9f7ca8e002" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Decrypted text: BETWEENSUBTLESHADINGANDTHEABSENCEOFLIGHTLIESTHENUANCEOFIQLUSION\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "ciphertext = \"EMUFPHZLRFAXYUSDJKZLDKRNSHGNFIVJYQTQUXQBQVYUVLLTREVJYQTMKYRDMFD\"\n", | |
| "cipher = Vigenere(\"KRYPTOS\", \"PALIMPSEST\")\n", | |
| "decoded = cipher.decrypt(ciphertext)\n", | |
| "print(\"Decrypted text:\", decoded)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "plaintext = \"ITWASTOTALLYINVISIBLEHOWSTHATPOSSIBLE?THEYUSEDTHEEARTHSMAGNETICFIELDXTHEINFORMATIONWASGATHEREDANDTRANSMITTEDUNDERGRUUNDTOANUNKNOWNLOCATIONXDOESLANGLEYKNOWABOUTTHIS?THEYSHOULDITSBURIEDOUTTHERESOMEWHEREXWHOKNOWSTHEEXACTLOCATION?ONLYWWTHISWASHISLASTMESSAGEXTHIRTYEIGHTDEGREESFIFTYSEVENMINUTESSIXPOINTFIVESECONDSNORTHSEVENTYSEVENDEGREESEIGHTMINUTESFORTYFOURSECONDSWESTXLAYERTWO\"\n", | |
| "cipher = Vigenere(\"KRYPTOS\", \"ABSCISSA\")\n", | |
| "encoded = cipher.encrypt(plaintext)\n", | |
| "print(encoded)" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "X05onQVdLbya", | |
| "outputId": "ff256c9c-0d15-4907-f3c9-ca0b7e4873ee" | |
| }, | |
| "execution_count": 5, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "VFPJUDEEHZWETZYVGWHKKQETGFQJNCEGGWHKK?DQMCPFQZDQMMIAGPFXHQRLGTIMVMZJANQLVKQEDAGDVFRPJUNGEUNAQZGZLECGYUXUEENJTBJLBQCRTBJDFHRRYIZETKZEMVDUFKSJHKFWHKUWQLSZFTIHHDDDUVH?DWKBFUFPWNTDFIYCUQZEREEVLDKFEZMOQQJLTTUGSYQPFEUNLAVIDXFLGGTEZ?FKZBSFDQVGOGIPUFXHHDRKFFHQNTGPUAECNUVPDJMQCLQUMUNEDFQELZZVRRGKFFVOEEXBDMVPNFQXEZLGREDNQFMPNZGLFLPMRJQYALMGNUVPDXVKPDQUMEBEDMHDAFMJGZNUPLGESWJLLAETG\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "ciphertext = \"VFPJUDEEHZWETZYVGWHKKQETGFQJNCEGGWHKK?DQMCPFQZDQMMIAGPFXHQRLGTIMVMZJANQLVKQEDAGDVFRPJUNGEUNAQZGZLECGYUXUEENJTBJLBQCRTBJDFHRRYIZETKZEMVDUFKSJHKFWHKUWQLSZFTIHHDDDUVH?DWKBFUFPWNTDFIYCUQZEREEVLDKFEZMOQQJLTTUGSYQPFEUNLAVIDXFLGGTEZ?FKZBSFDQVGOGIPUFXHHDRKFFHQNTGPUAECNUVPDJMQCLQUMUNEDFQELZZVRRGKFFVOEEXBDMVPNFQXEZLGREDNQFMPNZGLFLPMRJQYALMGNUVPDXVKPDQUMEBEDMHDAFMJGZNUPLGEWJLLAETG\"\n", | |
| "cipher = Vigenere(\"KRYPTOS\", \"ABSCISSA\")\n", | |
| "decoded = cipher.decrypt(ciphertext)\n", | |
| "print(\"Decrypted text:\", decoded)" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "UHsVKujELb14", | |
| "outputId": "d06fe4f5-1617-4837-d62a-37cd46252af8" | |
| }, | |
| "execution_count": 6, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Decrypted text: ITWASTOTALLYINVISIBLEHOWSTHATPOSSIBLE?THEYUSEDTHEEARTHSMAGNETICFIELDXTHEINFORMATIONWASGATHEREDANDTRANSMITTEDUNDERGRUUNDTOANUNKNOWNLOCATIONXDOESLANGLEYKNOWABOUTTHIS?THEYSHOULDITSBURIEDOUTTHERESOMEWHEREXWHOKNOWSTHEEXACTLOCATION?ONLYWWTHISWASHISLASTMESSAGEXTHIRTYEIGHTDEGREESFIFTYSEVENMINUTESSIXPOINTFIVESECONDSNORTHSEVENTYSEVENDEGREESEIGHTMINUTESFORTYFOURSECONDSWESTIDBYROWS\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 7, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "L-Tjj0oow1Dh", | |
| "outputId": "ccb69ca2-a812-4af9-b596-3bd362b6dc44" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "=== find_shift_keys ===\n", | |
| "Shift= 0 → PALIMPSEST\n", | |
| "Shift= 1 → YSKHQYCQZP\n", | |
| "Shift= 2 → RIYGBRODBY\n", | |
| "Shift= 3 → KOWFAKTCDR\n", | |
| "Shift= 4 → ZTJESZPBXK\n", | |
| "Shift= 5 → LPZDIXYAWZ\n", | |
| "Shift= 6 → QYRYOWESVL\n", | |
| "Shift= 7 → JRIOTVGOOQ\n", | |
| "Shift= 8 → IKHRPHBTUJ\n", | |
| "Shift= 9 → HZGKYLRPQI\n", | |
| "Shift=10 → GXVZRGDYNH\n", | |
| "Shift=11 → VWFXKFFRMG\n", | |
| "Shift=12 → XVEAZEKNLV\n", | |
| "Shift=13 → NHDCXDZVJX\n", | |
| "Shift=14 → FLCTWNXMIN\n", | |
| "Shift=15 → UGBWVUALHF\n", | |
| "Shift=16 → WFASHJWJGU\n", | |
| "Shift=17 → EESBLCVIFW\n", | |
| "Shift=18 → DDOVGMUXTE\n", | |
| "Shift=19 → CNTUFQQKAD\n", | |
| "Shift=20 → MUPQEBNUPC\n", | |
| "Shift=21 → BJUPDAMHYM\n", | |
| "Shift=22 → ACXNNSLWRB\n", | |
| "Shift=23 → SMQMUIJZKA\n", | |
| "Shift=24 → OQNLJOIGCS\n", | |
| "Shift=25 → TBMJCTHFEO\n", | |
| "\n", | |
| "=== find_pre_shift_keys ===\n", | |
| "Shift= 0 → PALIMPSEST\n", | |
| "Shift= 1 → TBIJNTAJWO\n", | |
| "Shift= 2 → FCQLQOBWUG\n", | |
| "Shift= 3 → CDRBUSZHKD\n", | |
| "Shift= 4 → GEMSVACFAH\n", | |
| "Shift= 5 → HNJETIDXXI\n", | |
| "Shift= 6 → IJYMRFEZVJ\n", | |
| "Shift= 7 → JQPCOJFKBL\n", | |
| "Shift= 8 → AUTASLGLCB\n", | |
| "Shift= 9 → OVUNAMHRDS\n", | |
| "Shift=10 → DWOQBNIYRE\n", | |
| "Shift=11 → LHSUZDJPEM\n", | |
| "Shift=12 → BFAFWBLTFC\n", | |
| "Shift=13 → SLBVYGMOGA\n", | |
| "Shift=14 → MXCWCQKSHN\n", | |
| "Shift=15 → NIDXKEWAIQ\n", | |
| "Shift=16 → QGEZXCRBJU\n", | |
| "Shift=17 → EZFKDUYCLF\n", | |
| "Shift=18 → UKGREVPDMV\n", | |
| "Shift=19 → VRHYFWTMNW\n", | |
| "Shift=20 → WMVPPHUIQX\n", | |
| "Shift=21 → XYNTGXNNYZ\n", | |
| "Shift=22 → ZPWOHZXQZK\n", | |
| "Shift=23 → KTXGIKOUPR\n", | |
| "Shift=24 → ROZDJRVVTY\n", | |
| "Shift=25 → YSKHLYQGOP\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "encrypted = \"EMUFPHZLRF\"\n", | |
| "plaintext = \"BETWEENSUB\"\n", | |
| "\n", | |
| "shift_keys = find_shift_keys(encrypted, plaintext)\n", | |
| "print(\"=== find_shift_keys ===\")\n", | |
| "for shift, keystream in shift_keys.items():\n", | |
| " print(f\"Shift={shift:2d} → {keystream}\")\n", | |
| "\n", | |
| "pre_shift_keys = find_pre_shift_keys(encrypted, plaintext)\n", | |
| "print(\"\\n=== find_pre_shift_keys ===\")\n", | |
| "for shift, keystream in pre_shift_keys.items():\n", | |
| " print(f\"Shift={shift:2d} → {keystream}\")" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 8, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "-KSu_bELxHBx", | |
| "outputId": "a90a1678-3f3d-45fd-c52c-70cf897ef8d1" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Encode matches expected: True\n", | |
| "Decode matches original: True\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "plaintext = (\n", | |
| " \"SLOWLYDESPARATLYSLOWLYTHEREMAINSOFPASSAGED\"\n", | |
| " \"EBRISTHATENCUMBEREDTHELOWERPARTOFTHEDOORWA\"\n", | |
| " \"YWASREMOVEDWITHTREMBLINGHANDSIMADEATINYBRE\"\n", | |
| " \"ACHINTHEUPPERLEFTHANDCORNERANDTHENWIDENING\"\n", | |
| " \"THEHOLEALITTLEIINSERTEDTHECANDLEANDPEEREDI\"\n", | |
| " \"NTHEHOTAIRESCAPINGFROMTHECHAMBERCAUSEDTHEF\"\n", | |
| " \"LAMETOFLICKERBUTPRESENTLYDETAILSOFTHEROOMW\"\n", | |
| " \"ITHINEMERGEDFROMTHEMISTXCANYOUSEEANYTHINGQ\"\n", | |
| ")\n", | |
| "\n", | |
| "ciphertext = (\n", | |
| " \"ENDYAHROHNLSRHEOCPTEOIBIDYSHNAIACHTNREYULDSLLSLLNOHSNOSMRWXMNE\"\n", | |
| " \"TPRNGATIHNRARPESLNNELEBLPIIACAEWMTWNDITEENRAHCTENEUDRETNHAEOE\"\n", | |
| " \"TFOLSEDTIWENHAEIOYTEYQHEENCTAYCREIFTBRSPAMHHEWENATAMATEGYEERLB\"\n", | |
| " \"TEEFOASFIOTUETUAEOTOARMAEERTNRTIBSEDDNIAAHTTMSTEWPIEROAGRIEWFEB\"\n", | |
| " \"AECTDDHILCEIHSITEGOEAOSDDRYDLORITRKLMLEHAGTDHARDPNEOHMGFMFEUHE\"\n", | |
| " \"ECDMRIPFEIMEHNLSSTTRTVDOHW\"\n", | |
| ")\n", | |
| "\n", | |
| "step1 = transform_text(plaintext, 42, Direction.Right)\n", | |
| "calc_cipher = transform_text(step1, 14, Direction.Right)\n", | |
| "print(\"Encode matches expected:\", calc_cipher == ciphertext)\n", | |
| "\n", | |
| "step1_dec = transform_text(ciphertext, 14, Direction.Left)\n", | |
| "decoded = transform_text(step1_dec, 42, Direction.Left)\n", | |
| "print(\"Decode matches original:\", decoded == plaintext)\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 9, | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "S21Ma_vjyyKt", | |
| "outputId": "114a72bd-c4bf-4a74-e996-ad96f507a86e" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "EASTNORTHEAST\n", | |
| "=== find_shift_keys ===\n", | |
| "Shift= 0 → RDUMRIYWOYNKY\n", | |
| "Shift= 1 → KNHLDXTJTRCUW\n", | |
| "Shift= 2 → ZCWKFKMZPKBHJ\n", | |
| "Shift= 3 → XBZYKHLRFZAWZ\n", | |
| "Shift= 4 → WAGWZGJIYXSZR\n", | |
| "Shift= 5 → VSFJXFZHRWOGI\n", | |
| "Shift= 6 → HOEZAUIGKVTFH\n", | |
| "Shift= 7 → LTQRWEHVZHPEG\n", | |
| "Shift= 8 → GPDIVDGFXLYQV\n", | |
| "Shift= 9 → FYCHUCFEWGRDF\n", | |
| "Shift=10 → ERBGQBEDVFKCE\n", | |
| "Shift=11 → DKAVNADCUEMBD\n", | |
| "Shift=12 → NMSFMSCBQDUAC\n", | |
| "Shift=13 → UUOELOBANNLSB\n", | |
| "Shift=14 → JLTDJTASEUJOA\n", | |
| "Shift=15 → CJPCIPSOHJITS\n", | |
| "Shift=16 → MIYBHYXTDCHPO\n", | |
| "Shift=17 → QHRASQRPCMWYT\n", | |
| "Shift=18 → BWNSCWWUBQZRP\n", | |
| "Shift=19 → AZVOONVXABQNU\n", | |
| "Shift=20 → SQMTTMUQJAGVX\n", | |
| "Shift=21 → IGLPPLQNMSVMQ\n", | |
| "Shift=22 → OVJUYJPMGIXLN\n", | |
| "Shift=23 → TXIXEZOLSOFJM\n", | |
| "Shift=24 → PFXQGRKKITEIL\n", | |
| "Shift=25 → YEKNBVNYLPDXK\n", | |
| "\n", | |
| "=== find_pre_shift_keys ===\n", | |
| "Shift= 0 → RDUMRIYWOYNKY\n", | |
| "Shift= 1 → YMKJYRCUSPROK\n", | |
| "Shift= 2 → PIAUPYKKATXFO\n", | |
| "Shift= 3 → TNXYQPXABOYPF\n", | |
| "Shift= 4 → OQVNTQDXCSPRP\n", | |
| "Shift= 5 → GUBLOTEVDHTGR\n", | |
| "Shift= 6 → DVCPSOFBEEOHG\n", | |
| "Shift= 7 → HGDTASPCFIVIH\n", | |
| "Shift= 8 → IEROBAGDQJQSI\n", | |
| "Shift= 9 → JJEVCBHRLLZJS\n", | |
| "Shift=10 → LWFSDCIEUMSLJ\n", | |
| "Shift=11 → BHGAEDJFVCWML\n", | |
| "Shift=12 → SFHBFELGWAUNM\n", | |
| "Shift=13 → EXICGFMHXFAQN\n", | |
| "Shift=14 → MZJDUGNIINBUQ\n", | |
| "Shift=15 → CKLEMUQJGDCVU\n", | |
| "Shift=16 → ALMFVMULMBKWV\n", | |
| "Shift=17 → NRNGWVVMZQDXW\n", | |
| "Shift=18 → QYQHXWTNJUEZX\n", | |
| "Shift=19 → UPYIZXRQHVFAZ\n", | |
| "Shift=20 → FTZWJZOYKGGTA\n", | |
| "Shift=21 → VOPQHJSZRWHBT\n", | |
| "Shift=22 → WSTXNHAPYXICB\n", | |
| "Shift=23 → XAOZKNBTNZJDC\n", | |
| "Shift=24 → ZBSKLKZOPKLED\n", | |
| "Shift=25 → KCWRILWSTRMYE\n", | |
| "\n", | |
| "\n", | |
| "BERLINCLOCK\n", | |
| "=== find_shift_keys ===\n", | |
| "Shift= 0 → ELYOIECBAQK\n", | |
| "Shift= 1 → DGTTLGBESVJ\n", | |
| "Shift= 2 → CFMGFBLAODI\n", | |
| "Shift= 3 → MELIORASTCH\n", | |
| "Shift= 4 → BDJDHDSOPBG\n", | |
| "Shift= 5 → ANZPJFOTYLF\n", | |
| "Shift= 6 → SUIFTKTGQAE\n", | |
| "Shift= 7 → OJHHPZPIWSD\n", | |
| "Shift= 8 → TCGYYXYDNOC\n", | |
| "Shift= 9 → PMFREARPMTB\n", | |
| "Shift=10 → YQEKRWKFLPA\n", | |
| "Shift=11 → RBDCKVZHJYZ\n", | |
| "Shift=12 → KACZZUXYZRY\n", | |
| "Shift=13 → ZSBXXQJRRKX\n", | |
| "Shift=14 → LIAWWNNKVZW\n", | |
| "Shift=15 → QOSVVMICIXV\n", | |
| "Shift=16 → JTXUULHZXJU\n", | |
| "Shift=17 → IPRQQJGXKNT\n", | |
| "Shift=18 → HYWNNIFWHIS\n", | |
| "Shift=19 → GRVMMHUVGHR\n", | |
| "Shift=20 → VKULDSWUFGQ\n", | |
| "Shift=21 → XZQJGCMQUFP\n", | |
| "Shift=22 → NXPBCOENEUO\n", | |
| "Shift=23 → FWOEBTQMDWN\n", | |
| "Shift=24 → UVKAAPVLCMM\n", | |
| "Shift=25 → WHNSSYDJBEL\n", | |
| "\n", | |
| "=== find_pre_shift_keys ===\n", | |
| "Shift= 0 → ELYOIECBAQK\n", | |
| "Shift= 1 → FMCVJFDZNUD\n", | |
| "Shift= 2 → QNKSLGECQVE\n", | |
| "Shift= 3 → LQXAMTNDUTF\n", | |
| "Shift= 4 → UUDBNHJEFRG\n", | |
| "Shift= 5 → VPECQIQFVOH\n", | |
| "Shift= 6 → WKFDUJUGWSI\n", | |
| "Shift= 7 → XTPEVLVHXAJ\n", | |
| "Shift= 8 → IOGFWMWIZBL\n", | |
| "Shift= 9 → GSHGONHJKZM\n", | |
| "Shift=10 → MAIHYQFLRWN\n", | |
| "Shift=11 → ZXJISULMYYR\n", | |
| "Shift=12 → JVLWAVXKPCX\n", | |
| "Shift=13 → HRMQBWIWTKY\n", | |
| "Shift=14 → KBNXCOGROXP\n", | |
| "Shift=15 → RZQZKYZYGDT\n", | |
| "Shift=16 → YWUKXSKPDEO\n", | |
| "Shift=17 → NCVRPARTHFV\n", | |
| "Shift=18 → PDTMDBMUIPQ\n", | |
| "Shift=19 → TERJRCYNJGZ\n", | |
| "Shift=20 → OYOUZKPXLHS\n", | |
| "Shift=21 → SFSYEXTOBIW\n", | |
| "Shift=22 → AGANFPOVSJU\n", | |
| "Shift=23 → BHBLGDSQELA\n", | |
| "Shift=24 → CIZPTRASMMB\n", | |
| "Shift=25 → DJWTHZBACNC\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "encrypted = \"FLRVQQPRNGKSS\"\n", | |
| "plaintext = \"EASTNORTHEAST\"\n", | |
| "print(plaintext)\n", | |
| "\n", | |
| "shift_keys = find_shift_keys(encrypted, plaintext)\n", | |
| "print(\"=== find_shift_keys ===\")\n", | |
| "for shift, keystream in shift_keys.items():\n", | |
| " print(f\"Shift={shift:2d} → {keystream}\")\n", | |
| "\n", | |
| "pre_shift_keys = find_pre_shift_keys(encrypted, plaintext)\n", | |
| "print(\"\\n=== find_pre_shift_keys ===\")\n", | |
| "for shift, keystream in pre_shift_keys.items():\n", | |
| " print(f\"Shift={shift:2d} → {keystream}\")\n", | |
| "\n", | |
| "encrypted = \"NYPVTTMZFPK\"\n", | |
| "plaintext = \"BERLINCLOCK\"\n", | |
| "\n", | |
| "print(\"\\n\")\n", | |
| "print(plaintext)\n", | |
| "shift_keys = find_shift_keys(encrypted, plaintext)\n", | |
| "print(\"=== find_shift_keys ===\")\n", | |
| "for shift, keystream in shift_keys.items():\n", | |
| " print(f\"Shift={shift:2d} → {keystream}\")\n", | |
| "\n", | |
| "pre_shift_keys = find_pre_shift_keys(encrypted, plaintext)\n", | |
| "print(\"\\n=== find_pre_shift_keys ===\")\n", | |
| "for shift, keystream in pre_shift_keys.items():\n", | |
| " print(f\"Shift={shift:2d} → {keystream}\")\n", | |
| "\n" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [], | |
| "metadata": { | |
| "id": "DE7RNlMQRy-M" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| } | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "provenance": [], | |
| "authorship_tag": "ABX9TyNo6RZszLovhoWEMSdePX4W", | |
| "include_colab_link": true | |
| }, | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "name": "python3" | |
| }, | |
| "language_info": { | |
| "name": "python" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 0 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment