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