{ "cells": [ { "cell_type": "markdown", "id": "660c0928-a36c-43b1-8e1c-46cfea272d71", "metadata": {}, "source": [ "# Homework 1\n", "Ondřej Hladůvka" ] }, { "cell_type": "markdown", "id": "e67bab4c-3578-47df-8fab-50c8c0ba9703", "metadata": {}, "source": [ "### Task 1\n", "Assume that the Affine cipher is implemented in Z97, not in Z26. (Imagine that we just extended\n", "alphabet, added a set of special symbols. But the first 26 letters stay the same as in English alphabet.)" ] }, { "cell_type": "markdown", "id": "28810138-4e3e-4a37-91af-5514b0770d4a", "metadata": {}, "source": [ "1. Write down encryption and decryption functions for this modification of Affine cipher." ] }, { "cell_type": "code", "execution_count": 20, "id": "93b6d070-f162-4d4a-85df-b3617214343e", "metadata": {}, "outputs": [], "source": [ "#For modulo 26:\n", "#Enc(pt_char) = a · pt_char + b( mod 26)\n", "#Dec(ct_char) = a^−1 · (ct_char − b)( mod 26)\n", "#where a^−1 is multiplicative inverse of a modulo 26\n", "\n", "# for other modulos we just need to find multiplicative inverses in it\n", "import math\n", "\n", "# multiplicative inverse of a modulo 97\n", "def inverse_mod97(i : int):\n", " return pow(i, -1, 97)\n", "\n", "def encrypt_mod97(pt_char : int, a_k : int, b_k : int):\n", " return (a_k * pt_char + b_k) % 97\n", "\n", "def decrypt_mod97(ct_char : int, a_k : int, b_k : int):\n", " return (inverse_mod97(a_k) * (ct_char - b)) % 97" ] }, { "cell_type": "markdown", "id": "b98f3507-8326-4d6e-a7a6-80b43e3a75ca", "metadata": {}, "source": [ "2. What is the number of possible keys?" ] }, { "cell_type": "code", "execution_count": 21, "id": "9307241e-be54-4543-b436-79a40892836f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Possible independent multiplicative key parts: 96\n", "Possible independent additive key parts: 97\n", "All possible keys: 9312\n" ] } ], "source": [ "from math import gcd\n", "\n", "# Euler's totient function\n", "def phi(n):\n", " amount = 0 \n", " for k in range(1, n + 1):\n", " if gcd(n, k) == 1:\n", " amount += 1\n", " return amount\n", "\n", "print(\"Possible independent multiplicative key parts:\", phi(97))\n", "print(\"Possible independent additive key parts:\", 97)\n", "print(\"All possible keys:\", phi(97) * 97)" ] }, { "cell_type": "markdown", "id": "6291a24b-84af-4976-8d2c-9b15768288b9", "metadata": {}, "source": [ "3. Suppose that modulus p = 97 is public. Malicious Eve intercepts 3-letter ciphertext c = 28 83 43.\n", "Assume that Eve also knows corresponding plaintext m = D O G. Find out the encryption key,\n", "decryption key and use it to decrypt message c\n", "′\n", "= 78 23 33 (The result should be 3-letter airport\n", "code)." ] }, { "cell_type": "code", "execution_count": 29, "id": "776a1fa6-3ae3-40b1-9adb-a00e7f3a0a01", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "28 = a * 3 + b (mod 97)\n", "83 = a * 14 + b (mod 97)\n", "43 = a * 6 + b (mod 97)\n", "\n", "we will subtract the first equation from the second to cancel out b\n", "83 - 28 = a * 14 - (a * 3) (mod 97)\n", "55 = a * 11 (mod 97)\n", "\n", "multiply by the inverse to get a -> 11^-1 (mod 97) == 53\n", "5 = 1 * a (mod 97)\n", "a = 5\n", "\n", "get b from the first equation\n", "28 = 5 * 3 + b (mod 97)\n", "13 = 0 + b (mod 97)\n", "b = 13\n", "\n", "check correctness against third equation\n", "43 = 5 * 6 + 13 (mod 97)\n", "43 = 43 (mod 97)\n", "\n", "we can now decrypt pt2:\n", "Dec(78) = 13 => N\n", "Dec(23) = 2 => C\n", "Dec(33) = 4 => E\n", "Airport is Nice Côte d'Azur Airport in France\n" ] } ], "source": [ "mod = 97\n", "ct1 = [28, 83, 43]\n", "pt1 = [ord(x) - ord('A') for x in ['D', 'O', 'G']] # convert to ints\n", "pt2 = \"\"\n", "ct2 = [78, 23, 33]\n", "\n", "\n", "for p, c in zip(pt1, ct1):\n", " print(f\"{c} = a * {p} + b (mod {mod})\")\n", "\n", "# solve a, b\n", "print(\"\\nwe will subtract the first equation from the second to cancel out b\")\n", "print(f\"{ct1[1]} - {ct1[0]} = a * {pt1[1]} - (a * {pt1[0]}) (mod {mod})\")\n", "\n", "left = ct1[1] - ct1[0]\n", "right = pt1[1] - pt1[0]\n", "print(f\"{left} = a * {right} (mod {mod})\")\n", "\n", "right_inv = inverse_mod97(right)\n", "print(f\"\\nmultiply by the inverse to get a -> {right}^-1 (mod {mod}) == {right_inv}\")\n", "a = (left * right_inv) % mod\n", "print(f\"{a} = {(right * right_inv) % mod} * a (mod {mod})\")\n", "print(f\"a = {a}\")\n", "\n", "print(\"\\nget b from the first equation\")\n", "print(f\"{ct1[0]} = {a} * {pt1[0]} + b (mod {mod})\")\n", "right = a * pt1[0]\n", "b = ct1[0] - right\n", "print(f\"{b} = {a * pt1[0] - right} + b (mod {mod})\")\n", "print(f\"b = {b}\")\n", "\n", "print(\"\\ncheck correctness against third equation\")\n", "print(f\"{ct1[2]} = {a} * {pt1[2]} + {b} (mod {mod})\")\n", "print(f\"{ct1[2]} = {a * pt1[2] + b} (mod {mod})\")\n", "\n", "# decrypt ct2\n", "print(\"\\nwe can now decrypt pt2:\")\n", "for ct in ct2:\n", " pt = decrypt_mod97(ct, a, b)\n", " pt2 += chr(ord('A') + pt)\n", " print(f\"Dec({ct}) = {pt} => {chr(ord('A') + pt)}\")\n", "\n", "# resolve airport code\n", "import requests \n", "response = requests.get(\"https://airport-data.com/api/ap_info.json?iata=\" + pt2)\n", "data = response.json()\n", "if response.status_code == 200:\n", " if data['icao'] is None:\n", " print(\"Airport not found\")\n", " else:\n", " print(f\"Airport is {data['name']} in {data['country']}\")\n", "else:\n", " print(\"api error, cant resolve airport code :(\")" ] }, { "cell_type": "markdown", "id": "a8e5bfda-691c-4c77-bede-76204d72c08a", "metadata": {}, "source": [ "### Task 2\n", "This task is on constructing frequency diagrams:\n", "- Find and write down paragraph of English plaintext. It should be at most 600 letters long." ] }, { "cell_type": "code", "execution_count": 32, "id": "10edb788-996c-49ee-8293-33566738e7e7", "metadata": {}, "outputs": [], "source": [ "plaintext = \"\"\"\n", "According to all known laws of aviation, there is no way a bee should be able to fly.\n", "Its wings are too small to get its fat little body off the ground.\n", "The bee, of course, flies anyway because bees don't care what humans think is impossible.\n", "Yellow, black. Yellow, black. Yellow, black. Yellow, black.\n", "Ooh, black and yellow!\n", "Let's shake it up a little.\n", "Barry! Breakfast is ready!\n", "Coming!\n", "Hang on a second.\n", "Hello?\n", "Barry?\n", "Adam?\n", "Can you believe this is happening?\n", "I can't.\n", "I'll pick you up.\n", "Looking sharp.\n", "Use the stairs, Your father paid good money for those.\n", "Sorry. I'm excited.\n", "Here's the graduate.\n", "\"\"\"" ] }, { "cell_type": "markdown", "id": "ad38acfb-8aa6-469d-b826-b0de46bc1a96", "metadata": {}, "source": [ "- Construct frequency diagram for the chosen plaintext." ] }, { "cell_type": "code", "execution_count": 39, "id": "dff20650-e015-4e1c-b4f9-e172dfd57e43", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0kAAAIPCAYAAACmD5WFAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAN4RJREFUeJzt3XeYVfW5L/DvAMMg0sQCKk1FLDEay1FJTHQQRSVeC0/isURFTpKToEdFj9E0QXMEzVWjEcs5oejNIRpiSaLXioC9YI25il00FCtVGUeY+4cPc9YEMDjOnj3A5/M8+4/123v2+661ZvbMd36rVNTV1dUFAACAJEmrcjcAAADQkghJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVtyll85MiRGTVqVIOx7bbbLi+88EKSZOnSpTnjjDNy/fXXp6amJoMGDcqVV16Zbt26rXGN5cuXZ/bs2enYsWMqKiqatH8AAGDtUVdXl0WLFmWLLbZIq1arny8qa0hKki996Uu555576pfbtPmflk4//fTcdtttmTx5cjp37pyTTz45Rx55ZB588ME1fv/Zs2enZ8+eTdozAACw9nrzzTfTo0eP1T5f9pDUpk2bdO/efaXxBQsWZNy4cZk0aVIGDBiQJJkwYUJ22GGHPPLII9l7773X6P07duyY5NMN0alTp6ZrHAAAWKssXLgwPXv2rM8Iq1P2kPTSSy9liy22SLt27dK/f/+MHj06vXr1yhNPPJHa2toMHDiw/rXbb799evXqlYcffni1IammpiY1NTX1y4sWLUqSbLDBBtlggw1KuzIAAECLVVtbmyT/8DScsoakvfbaKxMnTsx2222XOXPmZNSoUfn617+e5557LnPnzk3btm3TpUuXBl/TrVu3zJ07d7XvOXr06JXOc0qSu+66K+3bt2/qVQAAANYSH3744Rq9rqKurq6uxL2ssfnz56d379655JJLssEGG2To0KENZoWSZM8990x1dXUuvPDCVb7H388krZhSe/fddx1uBwAA67GFCxdmk002yYIFCz4zG5T9cLuiLl26pF+/fnn55ZdzwAEH5OOPP878+fMbzCbNmzdvlecwrVBVVZWqqqqVxisrK1NZWVmKtgEAgLXAmuaBFnWfpMWLF+eVV17J5ptvnt133z2VlZWZ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9rMNLY+ZJAAAgIJGhaRXX321qfsAAABoERoVkvr27Zvq6ur89re/zdKlS5u6JwAAgLJpVEh68skns/POO2fEiBHp3r17vv/97+exxx5r6t4AAACaXaNC0le+8pVcdtllmT17dsaPH585c+Zkn332yU477ZRLLrkk77zzTlP3CQAA0Cy+0IUb2rRpkyOPPDKTJ0/OhRdemJdffjlnnnlmevbsmeOPPz5z5sxpqj4BAACaxRcKSTNmzMgPf/jDbL755rnkkkty5pln5pVXXsndd9+d2bNn57DDDmuqPgEAAJpFo+6TdMkll2TChAmZOXNmDjnkkFx33XU55JBD0qrVp5lrq622ysSJE9OnT5+m7BUAAKDkGhWSrrrqqpx00kk58cQTs/nmm6/yNZtttlnGjRv3hZoDAABobo0KSS+99NI/fE3btm1zwgknNObtAQAAyqZR5yRNmDAhkydPXml88uTJufbaa79wUwAAAOXSqJA0evTobLLJJiuNb7bZZrngggu+cFMAAADl0qiQNGvWrGy11VYrjffu3TuzZs36wk0BAACUS6NC0mabbZZnn312pfFnnnkmG2+88RduCgAAoFwaFZKOPvro/Nu//VumTp2aZcuWZdmyZbn33ntz6qmn5p//+Z+bukcAAIBm06ir251//vl5/fXXs//++6dNm0/fYvny5Tn++OOdkwQAAKzVGhWS2rZtmxtuuCHnn39+nnnmmWywwQb58pe/nN69ezd1fwAAAM2qUSFphX79+qVfv35N1QsAAEDZNSokLVu2LBMnTsyUKVPy9ttvZ/ny5Q2ev/fee5ukOQAAgObWqJB06qmnZuLEiRk8eHB22mmnVFRUNHVfAAAAZdGokHT99dfn97//fQ455JCm7gcAAKCsGnUJ8LZt26Zv375N3QsAAEDZNSoknXHGGbnssstSV1fX1P0AAACUVaMOt3vggQcyderU3H777fnSl76UysrKBs/fdNNNTdIcAABAc2tUSOrSpUuOOOKIpu4FAACg7BoVkiZMmNDUfQAAALQIjTonKUk++eST3HPPPbnmmmuyaNGiJMns2bOzePHiJmsOAACguTVqJumNN97IQQcdlFmzZqWmpiYHHHBAOnbsmAsvvDA1NTW5+uqrm7pPAACAZtGomaRTTz01e+yxRz744INssMEG9eNHHHFEpkyZ0mTNAQAANLdGzSTdf//9eeihh9K2bdsG43369Mnf/va3JmkMAACgHBo1k7R8+fIsW7ZspfG33norHTt2/MJNAQAAlEujQtKBBx6YX/3qV/XLFRUVWbx4cc4999wccsghTdUbAABAs2vU4XYXX3xxBg0alB133DFLly7NMccck5deeimbbLJJfve73zV1jwAAAM2mUSGpR48eeeaZZ3L99dfn2WefzeLFizNs2LAce+yxDS7kAAAAsLZpVEhKkjZt2uS4445ryl4AAADKrlEh6brrrvvM548//vhGNQMAAFBujQpJp556aoPl2trafPjhh2nbtm3at28vJAEAAGutRl3d7oMPPmjwWLx4cWbOnJl99tnHhRsAAIC1WqNC0qpsu+22GTNmzEqzTAAAAGuTJgtJyacXc5g9e3ZTviUAAECzatQ5SX/6058aLNfV1WXOnDm54oor8rWvfa1JGgMAACiHRoWkww8/vMFyRUVFNt100wwYMCAXX3xxU/QFAABQFo0KScuXL2/qPgAAAFqEJj0nCQAAYG3XqJmkESNGrPFrL7nkksaUAAAAKItGhaSnnnoqTz31VGpra7PddtslSV588cW0bt06u+22W/3rKioqmqZLAACAZtKokHTooYemY8eOufbaa7PRRhsl+fQGs0OHDs3Xv/71nHHGGU3aJAAAQHNp1DlJF198cUaPHl0fkJJko402yi9+8QtXtwMAANZqjQpJCxcuzDvvvLPS+DvvvJNFixZ94aYAAADKpVEh6YgjjsjQoUNz00035a233spbb72VG2+8McOGDcuRRx7Z1D0CAAA0m0adk3T11VfnzDPPzDHHHJPa2tpP36hNmwwbNiy//OUvm7RBAACA5tSokNS+fftceeWV+eUvf5lXXnklSbLNNttkww03bNLmAAAAmtsXupnsnDlzMmfOnGy77bbZcMMNU1dX11R9AQAAlEWjQtJ7772X/fffP/369cshhxySOXPmJEmGDRvm8t8AAMBarVEh6fTTT09lZWVmzZqV9u3b148fddRRueOOO5qsOQAAgObWqHOS7rrrrtx5553p0aNHg/Ftt902b7zxRpM0BgAAUA6NmklasmRJgxmkFd5///1UVVV94aYAAADKpVEh6etf/3quu+66+uWKioosX748F110Uaqrq5usOQAAgObWqMPtLrroouy///6ZMWNGPv7445x11ln561//mvfffz8PPvhgU/cIAADQbBo1k7TTTjvlxRdfzD777JPDDjssS5YsyZFHHpmnnnoq22yzTVP3CAAA0Gw+90xSbW1tDjrooFx99dX5yU9+UoqeAAAAyuZzzyRVVlbm2WefLUUvAAAAZdeow+2OO+64jBs3rql7AQAAKLtGXbjhk08+yfjx43PPPfdk9913z4Ybbtjg+UsuuaRJmgOAlqjP2beVvMbrYwaXvAYAq/a5QtKrr76aPn365Lnnnstuu+2WJHnxxRcbvKaioqLpugMAAGhmnyskbbvttpkzZ06mTp2aJDnqqKNy+eWXp1u3biVpDgAAoLl9rnOS6urqGizffvvtWbJkSZM2BAAAUE6NunDDCn8fmgAAANZ2nyskVVRUrHTOkXOQAACAdcnnOieprq4uJ554YqqqqpIkS5cuzb/+67+udHW7m266qek6BAAAaEafKySdcMIJDZaPO+64Jm0GAACg3D5XSJowYUKp+gAAAGgRGnUzWQCA5lTqG/i6eS9Q9IWubgcAALCuEZIAAAAKhCQAAIACIQkAAKCgrCFp9OjR+ad/+qd07Ngxm222WQ4//PDMnDmzwWuWLl2a4cOHZ+ONN06HDh0yZMiQzJs3r0wdAwAA67qyhqTp06dn+PDheeSRR3L33XentrY2Bx54YJYsWVL/mtNPPz1//vOfM3ny5EyfPj2zZ8/OkUceWcauAQCAdVlZLwF+xx13NFieOHFiNttsszzxxBP5xje+kQULFmTcuHGZNGlSBgwYkOTTezXtsMMOeeSRR7L33nuXo20AAGAd1qLuk7RgwYIkSdeuXZMkTzzxRGprazNw4MD612y//fbp1atXHn744VWGpJqamtTU1NQvL1y4MElSW1ub2traUra/Rqpa15W8RktYTz5V6v1tX7cc6+vPtvUundWtt21eGp+1zuWqvb7uayilNf2er6irqyv9T+AaWL58ef7X//pfmT9/fh544IEkyaRJkzJ06NAGoSdJ9txzz1RXV+fCCy9c6X1GjhyZUaNGrTQ+adKktG/fvjTNAwAALd6HH36YY445JgsWLEinTp1W+7oWM5M0fPjwPPfcc/UBqbHOOeecjBgxon554cKF6dmzZw488MDP3BDNZaeRd5a8xnMjB5W8Bmum1Pvbvm451tefbetdOqtbb9u8ND5rnctVe33d11BKK44y+0da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ABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAQZtyNwAAACv0Ofu2ktd4fczgktdg7WYmCQAAoEBIAgAAKBCSAAAACoQkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKCgTbkbAACA9V2fs28reY3XxwwueY11hZkkAACAAiEJAACgQEgCAAAoWCtC0tixY9OnT5+0a9cue+21Vx577LFytwQAAKyjWnxIuuGGGzJixIice+65efLJJ7PLLrtk0KBBefvtt8vdGgAAsA5q8SHpkksuyXe/+90MHTo0O+64Y66++uq0b98+48ePL3drAADAOqhFh6SPP/44TzzxRAYOHFg/1qpVqwwcODAPP/xwGTsDAADWVS36Pknvvvtuli1blm7dujUY79atW1544YVVfk1NTU1qamrqlxcsWJAkef/991NbW1u6ZtdQm0+WlLzGe++9p/Z6Unt1ddfX2uvyvlZb7fWhdkv8XCln7XV5X6utdrksWrQoSVJXV/eZr6uo+0evKKPZs2dnyy23zEMPPZT+/fvXj5911lmZPn16Hn300ZW+ZuTIkRk1alRztgkAAKxF3nzzzfTo0WO1z7fomaRNNtkkrVu3zrx58xqMz5s3L927d1/l15xzzjkZMWJE/fLy5cvz/vvvZ+ONN05FRUVJ+21qCxcuTM+ePfPmm2+mU6dOaqutttpqr2V11VZbbbXXpbrlrt0U6urqsmjRomyxxRaf+boWHZLatm2b3XffPVOmTMnhhx+e5NPQM2XKlJx88smr/JqqqqpUVVU1GOvSpUuJOy2tTp06le2bUG211VZ7Xaq9Pq6z2mqrve7WXh/XuSl07tz5H76mRYekJBkxYkROOOGE7LHHHtlzzz3zq1/9KkuWLMnQoUPL3RoAALAOavEh6aijjso777yTn//855k7d26+8pWv5I477ljpYg4AAABNocWHpCQ5+eSTV3t43bqsqqoq55577kqHD6qtttpqq7121FVbbbXVXpfqlrt2c2rRV7cDAABobi36ZrIAAADNTUgCAAAoEJIAAAAKhCQAAIACIakFe/jhh9O6desMHjy42WqeeOKJqaioqH9svPHGOeigg/Lss882S/25c+fmlFNOydZbb52qqqr07Nkzhx56aKZMmVKymsV1rqysTLdu3XLAAQdk/PjxWb58ecnqrqp+8XHQQQeVrfbLL79c8tpz587Nqaeemr59+6Zdu3bp1q1bvva1r+Wqq67Khx9+WLK6J554Yv3NqYumTZuWioqKzJ8/v2S116SP5qz3hz/8Ie3atcvFF19clvrNUbOioiL/+q//utJzw4cPT0VFRU488cSS1h4zZkyD8VtuuSUVFRUlqfn33nzzzZx00knZYost0rZt2/Tu3Tunnnpq3nvvvZLWLX6utG3bNn379s15552XTz75pKR1/752ZWVlttpqq5x11llZunRpyWu/8847+cEPfpBevXqlqqoq3bt3z6BBg/Lggw+WtO6qPsOLj5EjR5as9n777ZfTTjttpfGJEyemS5cuJat76KGHrvZ35P3335+Kioom/7vl6quvTseOHRt8Hy9evDiVlZXZb7/9Grx2xe+TV155pUl7WLZsWb761a/myCOPbDC+YMGC9OzZMz/5yU+atF5RXV1dBg4cmEGDBq303JVXXpkuXbrkrbfeKln9chCSWrBx48bllFNOyX333ZfZs2c3W92DDjooc+bMyZw5czJlypS0adMm3/zmN0te9/XXX8/uu++ee++9N7/85S/zl7/8JXfccUeqq6szfPjwktZesc6vv/56br/99lRXV+fUU0/NN7/5zWb5xV7c5isev/vd70ped3W1t9pqq5LWfPXVV7PrrrvmrrvuygUXXJCnnnoqDz/8cM4666zceuutueeee0pan+Q3v/lNjj322Fx11VU544wzyt1OyfTs2TPXX399Pvroo/qxpUuXZtKkSenVq1dJa7dr1y4XXnhhPvjgg5LWWZVXX301e+yxR1566aX87ne/y8svv5yrr746U6ZMSf/+/fP++++XtP6Kz5WXXnopZ5xxRkaOHJlf/vKXJa3597VfffXVXHrppbnmmmty7rnnlrzukCFD8tRTT+Xaa6/Niy++mD/96U/Zb7/9Sh5Ki5/dv/rVr9KpU6cGY2eeeWZJ65fDsGHDcvfdd6/yj/IJEyZkjz32yM4779ykNaurq7N48eLMmDGjfuz+++9P9+7d8+ijjzYI4lOnTk2vXr2yzTbbNGkPrVu3zsSJE3PHHXfkv//7v+vHTznllHTt2rWk3+cVFRWZMGFCHn300VxzzTX146+99lrOOuus/PrXv06PHj1KVr8c1or7JK2PFi9enBtuuCEzZszI3LlzM3HixPz4xz9ultor/gOWJN27d8/ZZ5+dr3/963nnnXey6aablqzuD3/4w1RUVOSxxx7LhhtuWD/+pS99KSeddFLJ6iYN13nLLbfMbrvtlr333jv7779/Jk6cmH/5l39ptvrNrRy1f/jDH6ZNmzaZMWNGg3299dZb57DDDos7E5TWRRddlHPPPTfXX399jjjiiHK3U1K77bZbXnnlldx000059thjkyQ33XRTevXqVfJ/BgwcODAvv/xyRo8enYsuuqiktf7e8OHD07Zt29x1113ZYIMNkiS9evXKrrvumm222SY/+clPctVVV5WsfvFz5Qc/+EFuvvnm/OlPf8o555xTspqrqt2zZ88MHDgwd999dy688MKS1Zw/f37uv//+TJs2Lfvuu2+SpHfv3tlzzz1LVnOF4ud3586dU1FRUbbfJ83lm9/8ZjbddNNMnDgxP/3pT+vHFy9enMmTJ5ckkG+33XbZfPPNM23atOy9995JPp0xOuyww3LvvffmkUceqZ9RmjZtWqqrq5u8hyTp169fxowZk1NOOSUDBgzIY489luuvvz6PP/542rZtW5KaK/Ts2TOXXXZZTj755Bx44IHp06dPhg0blgMPPDDf+c53Slq7HMwktVC///3vs/3222e77bbLcccdl/Hjx5flD8fFixfnt7/9bfr27ZuNN964ZHXef//93HHHHRk+fHiDP5pXKOW0/eoMGDAgu+yyS2666aZmr70ue++993LXXXetdl8nabbDkdZHP/rRj3L++efn1ltvXecD0gonnXRSJkyYUL88fvz4DB06tOR1W7dunQsuuCC//vWvm/UwlPfffz933nlnfvjDH9YHpBW6d++eY489NjfccEOz/k7ZYIMN8vHHHzdbvRWee+65PPTQQyX/47FDhw7p0KFDbrnlltTU1JS0FkmbNm1y/PHHZ+LEiQ2+jydPnpxly5bl6KOPLknd6urqTJ06tX556tSp2W+//bLvvvvWj3/00Ud59NFHSxaSkk9njnbZZZd85zvfyfe+9738/Oc/zy677FKyekUnnHBC9t9//5x00km54oor8txzzzWYWVqXCEkt1Lhx43Lccccl+fTQgQULFmT69OnNUvvWW2+t/8Dv2LFj/vSnP+WGG25Iq1al+3Z5+eWXU1dXl+23375kNRpj++23z+uvv17yOsVtvuJxwQUXlLzuqmp/61vfKmm9Fft6u+22azC+ySab1Pfwox/9qKQ9rGp7H3zwwSWt2RLcfvvtueiii/LHP/4x+++/f7nbaTbHHXdcHnjggbzxxht544038uCDD9Z/vpbaEUccka985SvNcrjXCi+99FLq6uqyww47rPL5HXbYIR988EHeeeedkvdSV1eXe+65J3feeWcGDBhQ8nrJ//x8t2vXLl/+8pfz9ttv59///d9LWrNNmzaZOHFirr322nTp0iVf+9rX8uMf/7jZzuddH5100kl55ZVXGvxtNGHChAwZMiSdO3cuSc3q6uo8+OCD+eSTT7Jo0aI89dRT2XffffONb3wj06ZNS/Lp+eQ1NTUlDUkVFRW56qqrMmXKlHTr1i1nn312yWqtyn/+53/mueeey2mnnZb//M//LOlRRuXkcLsWaObMmXnsscdy8803J/n0w/eoo47KuHHjVjo5sBSqq6vrD8P44IMPcuWVV+bggw/OY489lt69e5ekZks9vKqurq5ZZjWK23yFrl27lrzuqmqvbnan1B577LEsX748xx57bMn/E7uq7f3oo4822x/O5bLzzjvn3Xffzbnnnps999wzHTp0KHdLzWLTTTfN4MGD6//rPHjw4GyyySbNVv/CCy/MgAEDmv3ckHJ+rq4IKrW1tVm+fHmOOeaYkl5AoGjFz/eSJUty6aWXpk2bNhkyZEjJ6w4ZMiSDBw/O/fffn0ceeaT+nxK/+c1vSnaBkPXZ9ttvn69+9asZP3589ttvv7z88su5//77c95555Ws5n777ZclS5bk8ccfzwcffJB+/fpl0003zb777puhQ4dm6dKlmTZtWrbeeuuSn/M4fvz4tG/fPq+99lreeuut9OnTp6T1ijbbbLN8//vfzy233NLsF+RpTmaSWqBx48blk08+yRZbbJE2bdqkTZs2ueqqq3LjjTdmwYIFJa+/4YYbpm/fvunbt2/+6Z/+Kb/5zW+yZMmS/Nd//VfJam677bapqKjICy+8ULIajfH888+X/LyFpOE2X/ForpD097U333zzktbr27dvKioqMnPmzAbjW2+9dfr27bvS4UGlsKrtveWWW5a8brltueWWmTZtWv72t7/loIMOyqJFi8rdUrM56aST6v/TX+pzHP/eN77xjQwaNKhZzsdJ/udn7Pnnn1/l888//3w22mijkv73t7q6Ok8//XReeumlfPTRR7n22mub7R8wK36+d9lll4wfPz6PPvpoxo0b1yy127VrlwMOOCA/+9nP8tBDD+XEE09s1lnE5tapU6dV/l0yf/78ks3mFA0bNiw33nhjFi1alAkTJmSbbbapPyesFPr27ZsePXpk6tSpmTp1an2tLbbYIj179sxDDz2UqVOnlnzW9KGHHsqll16aW2+9NXvuuWeGDRvW7P8UWfH36bpMSGphPvnkk1x33XW5+OKL8/TTT9c/nnnmmWyxxRbNdsWzooqKirRq1arB1aGaWteuXTNo0KCMHTs2S5YsWen55rosc9G9996bv/zlL83yH8j1ycYbb5wDDjggV1xxxSr3NaXVu3fvTJ8+PXPnzl2vgtJBBx2Ujz/+OLW1tau8hG2pjRkzJn/+85/z8MMPl7zWip+xK6+8cqXP7blz5+a///u/c9RRR5V0lnxFUOnVq1dZ/5Bq1apVfvzjH+enP/1pSX+Hrc6OO+64Tn/ObbfddnnyySdXGn/yySfTr1+/ktf/9re/nVatWmXSpEm57rrrctJJJ5X86I/q6upMmzYt06ZNa3B0zze+8Y3cfvvteeyxx0p6qN2HH36YE088MT/4wQ9SXV2dcePG5bHHHsvVV19dsprrKyGphbn11lvzwQcfZNiwYdlpp50aPIYMGdIs/w2rqanJ3LlzM3fu3Dz//PM55ZRTsnjx4hx66KElrTt27NgsW7Yse+65Z2688ca89NJLef7553P55Zenf//+Ja29Yp3/9re/5cknn8wFF1yQww47LN/85jdz/PHHl7R2sX7x8e6775a8brlceeWV+eSTT7LHHnvkhhtuyPPPP5+ZM2fmt7/9bV544YW0bt263C2u03r27Jlp06bl7bffzqBBg7Jw4cJmqbtgwYIG//x5+umn8+abbzZL7datW+f555/P//t//68s319f/vKXc+yxx+byyy9vlnpXXHFFampqMmjQoNx333158803c8cdd+SAAw7Illtumf/4j/9olj5agm9961tp3bp1xo4dW7Ia7733XgYMGJDf/va3efbZZ/Paa69l8uTJueiii3LYYYeVrG65/eAHP8iLL76Yf/u3f8uzzz6bmTNn5pJLLsnvfve7Zrm1QIcOHXLUUUflnHPOyZw5c5rlsMbq6uo88MADefrppxvMWu2777655ppr8vHHH5c0JJ1zzjmpq6urvwdbnz598r//9//OWWed1SznUK9PhKQWZty4cRk4cOAqp6mHDBmSGTNmlPxE0DvuuCObb755Nt988+y11155/PHHM3ny5JKfD7X11lvnySefTHV1dc4444zstNNOOeCAAzJlypSSXqo2+Z917tOnTw466KBMnTo1l19+ef74xz82yx9UxW2+4rHPPvuUvG65bLPNNnnqqacycODAnHPOOdlll12yxx575Ne//nXOPPPMnH/++eVucZ3Xo0ePTJs2Le+++26zBaVp06Zl1113bfAYNWpUyeuu0KlTp3Tq1KnZ6v298847r1luUJ18egjzjBkzsvXWW+fb3/52ttlmm3zve99LdXV1Hn744WY7nLclaNOmTU4++eRcdNFFJZvV6dChQ/baa69ceuml+cY3vpGddtopP/vZz/Ld7343V1xxRUlqtgRbb7117rvvvrzwwgsZOHBg9tprr/z+97/P5MmTm+WG6Mmnh9x98MEHGTRoULbYYouS16uurs5HH32Uvn37plu3bvXj++67bxYtWlR/qfBSmD59esaOHZsJEyakffv29ePf//7389WvfrUsh92tyyrqbE0AAIB6ZpIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKBCSAGhRTjzxxBx++OGN+tr99tsvp512WoOxadOmpaKiIvPnz//CvQGwfhCSAGAN1NXV5ZNPPil3GwA0AyEJgLXGc889l4MPPjgdOnRIt27d8p3vfCfvvvtukk9noKZPn57LLrssFRUVqaioyOuvv57q6uokyUYbbZSKioqceOKJSZLly5dn9OjR2WqrrbLBBhtkl112yR/+8If6WitmoG6//fbsvvvuqaqqygMPPJBnnnkm1dXV6dixYzp16pTdd989M2bMaPZtAUDpCEkArBXmz5+fAQMGZNddd82MGTNyxx13ZN68efn2t7+dJLnsssvSv3//fPe7382cOXMyZ86c9OzZMzfeeGOSZObMmZkzZ04uu+yyJMno0aNz3XXX5eqrr85f//rXnH766TnuuOMyffr0BnXPPvvsjBkzJs8//3x23nnnHHvssenRo0cef/zxPPHEEzn77LNTWVnZvBsDgJJqU+4GAGBNXHHFFdl1111zwQUX1I+NHz8+PXv2zIsvvph+/fqlbdu2ad++fbp3717/mq5duyZJNttss3Tp0iVJUlNTkwsuuCD33HNP+vfvnyTZeuut88ADD+Saa67JvvvuW//15513Xg444ID65VmzZuXf//3fs/322ydJtt1225KtMwDlISQBsFZ45plnMnXq1HTo0GGl51555ZX069dvjd/r5Zdfzocfftgg/CTJxx9/nF133bXB2B577NFgecSIEfmXf/mX/J//838ycODAfOtb38o222zzOdYEgJZOSAJgrbB48eIceuihufDCC1d6bvPNN//c75Ukt912W7bccssGz1VVVTVY3nDDDRssjxw5Msccc0xuu+223H777Tn33HNz/fXX54gjjvhcPQDQcglJAKwVdtttt9x4443p06dP2rRZ9a+vtm3bZtmyZSuNJWkwvuOOO6aqqiqzZs1qcGjdmurXr1/69euX008/PUcffXQmTJggJAGsQ1y4AYAWZ8GCBXn66acbPL73ve/l/fffz9FHH53HH388r7zySu68884MHTq0PgD16dMnjz76aF5//fW8++67Wb58eXr37p2Kiorceuuteeedd7J48eJ07NgxZ555Zk4//fRce+21eeWVV/Lkk0/m17/+da699trV9vXRRx/l5JNPzrRp0/LGG2/kwQcfzOOPP54ddtihuTYNAM3ATBIALc60adNWOjdo2LBhefDBB/OjH/0oBx54YGpqatK7d+8cdNBBadXq0//5nXnmmTnhhBOy44475qOPPsprr72WPn36ZNSoUTn77LMzdOjQHH/88Zk4cWLOP//8bLrpphk9enReffXVdOnSJbvttlt+/OMfr7av1q1b57333svxxx+fefPmZZNNNsmRRx6ZUaNGlXR7ANC8Kurq6urK3QQAAEBL4XA7AACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKBCSAAAACv4/NqhgdIG1C/wAAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "from collections import Counter\n", "\n", "# filter just letters and convert them to uppercase\n", "plaintext = ''.join(filter(str.isalpha, plaintext.upper()))\n", "\n", "# plot frequency using matplotlib\n", "def freq_plot(text : str) :\n", " letter_counts = Counter(text)\n", " letters = sorted(letter_counts.keys())\n", " frequencies = [letter_counts[letter] for letter in letters]\n", "\n", " plt.figure(figsize=(10, 6))\n", " plt.bar(letters, frequencies)\n", " plt.xlabel('Letters')\n", " plt.ylabel('Frequency')\n", " plt.grid(axis='y')\n", " plt.show()\n", "\n", "freq_plot(plaintext)" ] }, { "cell_type": "markdown", "id": "5efe6443-4b15-463c-9bbe-475411999c63", "metadata": {}, "source": [ "- Encrypt your plaintext with shift cipher, permutation cipher, Vigenère cipher and construct frequency\n", "diagrams for the corresponding ciphertexts. You may choose any suitable keys for the ciphers." ] }, { "cell_type": "code", "execution_count": 70, "id": "acf75325-dfd3-4a38-bf27-ef3820c498e6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "with shift key: 3\n", "we will get cyphertext: ['D', 'F', 'F', 'R', 'U', 'G', 'L', 'Q', 'J', 'W']...\n", "with frequency diagram:\n" ] }, { "data": { "image/png": "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+d2moTOTBAAAkFCrkPT666/XdR8AAAD1Qq1CUvfu3aO0tDR+/etfx/bt2+u6JwAAgJypVUh69tln4/jjj4/Ro0dHhw4d4p//+Z9j6dKldd0bAABA1tUqJH35y1+OW2+9NdauXRszZsyIdevWxemnnx7HHXdcTJ48Od5+++267hMAACArPteJG/Lz82Pw4MExd+7cmDRpUrz66qtxzTXXRHFxcVx22WWxbt26uuoTAAAgKz5XSFq2bFl8//vfjyOOOCImT54c11xzTbz22mvx6KOPxtq1a2PQoEF11ScAAEBW1Oo6SZMnT46ZM2fGypUr4+yzz4677rorzj777GjU6KPM1a1bt5g1a1Z07dq1LnsFAABIXa1C0tSpU+Pyyy+PYcOGxRFHHLHX5xx++OExffr0z9UcAABAttUqJL3yyiuf+pzCwsIYOnRobRYPAACQM7U6JmnmzJkxd+7cPcbnzp0bd9555+duCgAAIFdqFZImTJgQhx122B7jhx9+eNx4442fuykAAIBcqVVIWrNmTXTr1m2P8S5dusSaNWs+d1MAAAC5UquQdPjhh8cLL7ywx/jzzz8fbdu2/dxNAQAA5EqtQtJFF10U//qv/xrz58+PnTt3xs6dO+Pxxx+PK6+8Mv7hH/6hrnsEAADImlqd3e6GG26I1atXx5lnnhn5+R8tYteuXXHZZZc5JgkAADig1SokFRYWxt133x033HBDPP/889G0adP40pe+FF26dKnr/gAAALKqViFptx49ekSPHj3qqhcAAICcq1VI2rlzZ8yaNSvmzZsXb731VuzatavG448//nidNAcAAJBttQpJV155ZcyaNSvOOeecOO644yIvL6+u+wIAAMiJWoWkOXPmxP/8z//E2WefXdf9AAAA5FStTgFeWFgY3bt3r+teAAAAcq5WIenqq6+OW2+9NTKZTF33AwAAkFO1+rrdU089FfPnz48HH3wwvvjFL0ZBQUGNx3//+9/XSXMAAADZVquQ1Lp167jgggvquhcAAICcq1VImjlzZl33AQAAUC/U6pikiIgPP/wwHnvssbjjjjtiy5YtERGxdu3aqKioqLPmAAAAsq1WM0l/+9vfYuDAgbFmzZqorKyMfv36RYsWLWLSpElRWVkZ06ZNq+s+AQAAsqJWM0lXXnllnHLKKfH+++9H06ZNq8cvuOCCmDdvXp01BwAAkG21mkl68sknY+HChVFYWFhjvGvXrvH3v/+9ThoDAADIhVrNJO3atSt27ty5x/ibb74ZLVq0+NxNAQAA5EqtQlL//v3j5z//efX9vLy8qKioiLFjx8bZZ59dV70BAABkXa2+bnfzzTfHgAED4thjj43t27fHxRdfHK+88kocdthh8dvf/rauewQAAMiaWoWkTp06xfPPPx9z5syJF154ISoqKqKsrCwuueSSGidyAAAAONDUKiRFROTn58ell15al70AAADkXK1C0l133fWJj1922WW1agYAACDXahWSrrzyyhr3q6qqYtu2bVFYWBjNmjUTkgAAgANWrc5u9/7779e4VVRUxMqVK+P000934gYAAOCAVquQtDdHH310TJw4cY9ZJgAAgANJnYWkiI9O5rB27dq6XCQAAEBW1eqYpPvuu6/G/UwmE+vWrYvbbrstvv71r9dJYwAAALlQq5B0/vnn17ifl5cX7dq1iz59+sTNN99cF30BAADkRK1C0q5du+q6DwAAgHqhTo9JAgAAONDVaiZp9OjR+/3cyZMn16YEAABATtQqJD333HPx3HPPRVVVVfTs2TMiIl5++eVo3LhxnHTSSdXPy8vLq5suAQAAsqRWIem8886LFi1axJ133hmHHnpoRHx0gdnhw4fHN77xjbj66qvrtEkAAIBsqdUxSTfffHNMmDChOiBFRBx66KHx05/+1NntAACAA1qtQtLmzZvj7bff3mP87bffji1btnzupgAAAHKlViHpggsuiOHDh8fvf//7ePPNN+PNN9+Me+65J8rKymLw4MF13SMAAEDW1OqYpGnTpsU111wTF198cVRVVX20oPz8KCsri5/97Gd12iAAAEA21SokNWvWLG6//fb42c9+Fq+99lpERBx11FFxyCGH1GlzAAAA2fa5Lia7bt26WLduXRx99NFxyCGHRCaTqau+AAAAcqJWIendd9+NM888M3r06BFnn312rFu3LiIiysrKnP4bAAA4oNUqJI0aNSoKCgpizZo10axZs+rxCy+8MB566KE6aw4AACDbanVM0iOPPBIPP/xwdOrUqcb40UcfHX/729/qpDEAAIBcqNVM0tatW2vMIO323nvvRVFR0eduCgAAIFdqFZK+8Y1vxF133VV9Py8vL3bt2hU33XRTlJaW1llzAAAA2Varr9vddNNNceaZZ8ayZcti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bbXVPpjq5rp2NtXrs9sBAABkW72+mCwAAEC2CUkAAAAJQhIAAECCkAQAAJAgJNVjixYtisaNG8c555yTtZrDhg2LvLy86lvbtm1j4MCB8cILL2StbkFBQbRv3z769esXM2bMiF27dqVa++P1k7eBAwfmrParr76aeu3169fHlVdeGd27d48mTZpE+/bt4+tf/3pMnTo1tm3bllrdYcOGVV8gOqm8vDzy8vJi48aNqdXenz4Oxtp7q/e73/0umjRpEjfffHNO6mfD7t+viRMn1hj/wx/+EHl5eanXf+ONN+Lyyy+Pjh07RmFhYXTp0iWuvPLKePfdd1Otm9yvFBYWRvfu3eMnP/lJfPjhh6nWjcjdOkfs+bekW7duce2118b27dtTr/3222/H9773vejcuXMUFRVFhw4dYsCAAfH000+nWrd3795x1VVX7TE+a9asaN26dWp1zzvvvH3+jXzyyScjLy+vzv93mDZtWrRo0aLG+7iioiIKCgqid+/eNZ67++/Ja6+9Vqc97Ny5M772ta/F4MGDa4xv2rQpiouL44c//GGd1kvKZDLRt2/fGDBgwB6P3X777dG6det48803U6m9+/Xc1620tDSVurkkJNVj06dPj5EjR8YTTzwRa9euzVrdgQMHxrp162LdunUxb968yM/Pj3PPPTdrdVevXh0PPvhglJaWxpVXXhnnnntuVv6wJ9d79+23v/1t6nX3Vbtbt26p1nz99dfjxBNPjEceeSRuvPHGeO6552LRokVx7bXXxv333x+PPfZYqvXJrV/96ldxySWXxNSpU+Pqq6/OdTupatKkSUyaNCnef//9rNZ9/fXX45RTTolXXnklfvvb38arr74a06ZNi3nz5kVJSUm89957qdbfvV955ZVX4uqrr45x48bFz372s1Rr5nqdI/53vV9//fW45ZZb4o477oixY8emXnfIkCHx3HPPxZ133hkvv/xy3HfffdG7d++shMNcKCsri0cffXSv/5TPnDkzTjnllDj++OPrtGZpaWlUVFTEsmXLqseefPLJ6NChQyxZsqRGGJ4/f3507tw5jjrqqDrtoXHjxjFr1qx46KGH4je/+U31+MiRI6NNmzapvtfy8vJi5syZsWTJkrjjjjuqx1etWhXXXntt/PKXv4xOnTqlUvtrX/vaHv+nrFu3Lu64447Iy8uL73//+6nUzaUD4jpJDVFFRUXcfffdsWzZsli/fn3MmjUrrr/++qzU3v0JWEREhw4dYsyYMfGNb3wj3n777WjXrl1W6h555JFx0kknxWmnnRZnnnlmzJo1K/7xH/8xtdofr59tuaj9/e9/P/Lz82PZsmVxyCGHVI9/4QtfiEGDBoWrAxy8brrpphg7dmzMmTMnLrjggly3k7q+ffvGq6++GhMmTIibbropa3VHjBgRhYWF8cgjj0TTpk0jIqJz585x4oknxlFHHRU//OEPY+rUqanVT+5Xvve978W9994b9913X1x33XWp1cz1OkfUXO/i4uLo27dvPProozFp0qTUam7cuDGefPLJKC8vjzPOOCMiIrp06RKnnnpqajVz7dxzz4127drFrFmz4kc/+lH1eEVFRcydOzeVQN6zZ8844ogjory8PE477bSI+GiGY9CgQfH444/H4sWLq2eUysvLU5vd6NGjR0ycODFGjhwZffr0iaVLl8acOXPimWeeicLCwlRq7lZcXBy33nprXHHFFdG/f//o2rVrlJWVRf/+/eM73/lOanULCwv3+D/lpZdeimuuuSauv/76+Na3vpVa7Vwxk1RP/c///E/06tUrevbsGZdeemnMmDEjJ/+0VlRUxK9//evo3r17tG3bNuv1+/TpEyeccEL8/ve/z3rtg9m7774bjzzySIwYMaJGQErKxleRyL4f/OAHccMNN8T999/fIAJSxEef/N54443xy1/+MrWvonzce++9Fw8//HB8//vfrw4Lu3Xo0CEuueSSuPvuu7O6X2/atGns2LEjteXXx3V+8cUXY+HChan/49q8efNo3rx5/OEPf4jKyspUa9UX+fn5cdlll8WsWbNqbNO5c+fGzp0746KLLkqlbmlpacyfP7/6/vz586N3795xxhlnVI9/8MEHsWTJklS/AjZy5Mg44YQT4jvf+U5897vfjR//+MdxwgknpFYvaejQoXHmmWfG5ZdfHrfddlu8+OKLNWaWsmHjxo0xaNCg6N27d9xwww1ZrZ0tQlI9NX369Lj00ksj4qOvDmzatCkWLFiQldr3339/9Q6/RYsWcd9998Xdd98djRrl5u3Sq1evWL16dep1kuu9+3bjjTemXndvtdP+RObVV1+NTCYTPXv2rDF+2GGHVffwgx/8INUe9vZ6n3XWWanWbOgefPDBuOmmm+KPf/xjnHnmmbluJ6suuOCC+PKXv5yVr11FRLzyyiuRyWTimGOO2evjxxxzTLz//vvx9ttvp95LJpOJxx57LB5++OHo06dPanXqyzrv3rc0adIkvvSlL8Vbb70V//Zv/5Zqzfz8/Jg1a1bceeed0bp16/j6178e119/ferH8+ba5ZdfHq+99lqN/09mzpwZQ4YMiVatWqVSs7S0NJ5++un48MMPY8uWLfHcc8/FGWecEd/85jejvLw8Ij46pruysjLVkJSXlxdTp06NefPmRfv27WPMmDGp1dqb//qv/4oXX3wxrrrqqviv//qvVL/p83G7du2Kiy++OPLz8+M3v/nNQfuhqpBUD61cuTKWLl1a/SlMfn5+XHjhhTF9+vSs1C8tLY0VK1bEihUrYunSpTFgwIA466yz4m9/+1tW6n9cJpPJyi9gcr133/7lX/4l9bp7q/2LX/wiK3U/bunSpbFixYr44he/mPqnoXt7vX/1q1+lWrOhO/7446Nr164xduzYqKioyHU7WTdp0qS4884746WXXspazVx+bTUZFs4666y48MILY9y4canX/bR1TntWZ/e+ZcmSJTF06NAYPnx4DBkyJNWaER8dk7R27dq47777YuDAgVFeXh4nnXRSzJo1K/XaudKrV6/42te+FjNmzIiIjz6Ae/LJJ6OsrCy1mr17946tW7fGM888E08++WT06NEj2rVrF2eccUb1cUnl5eXxhS98ITp37pxaHxERM2bMiGbNmsWqVauyNku92+GHHx7//M//HMccc0zWT4pz/fXXx6JFi+KPf/xjtGjRIqu1s0lIqoemT58eH374YXTs2DHy8/MjPz8/pk6dGvfcc09s2rQp9fqHHHJIdO/ePbp37x5f+cpX4le/+lVs3bo1/vu//zv12nvz0ksvpX4Sg4ia67371qZNm9Tr7q32EUcckWq97t27R15eXqxcubLG+Be+8IXo3r37Hl+VScPeXu8jjzwy9boN2ZFHHhnl5eXx97//PQYOHBhbtmzJdUtZ9c1vfjMGDBiQ6jE5u+3+HdtXIHvppZfi0EMPTfXT391h4ZVXXokPPvgg7rzzzn1+vbYu7M86t2vXLtUzrkX8777lhBNOiBkzZsSSJUuy9iFjkyZNol+/fvHv//7vsXDhwhg2bFjqs5ctW7bc6/8GGzduTG02J6msrCzuueee2LJlS8ycOTOOOuqo6uOy0tC9e/fo1KlTzJ8/P+bPn19dq2PHjlFcXBwLFy6M+fPnpzprGhGxcOHCuOWWW+L++++PU089NcrKyrL+ocju/xGzac6cOfGf//mfMWfOnDj66KOzWjvbhKR65sMPP4y77rorbr755hqfsD///PPRsWPHrJ1tLSkvLy8aNWoUH3zwQdZrP/744/HnP/85K58CNiRt27aNfv36xW233RZbt27NdTtkUZcuXWLBggWxfv36BhmUJk6cGH/6059i0aJFqdbZ/Tt2++2377HvXL9+ffzmN7+JCy+8MNVZ8t1hoXPnzln5R2p/1nnYsGGp95HUqFGjuP766+NHP/pRTv6GHXvssanvY3v27BnPPvvsHuPPPvts9OjRI9XaERHf/va3o1GjRjF79uy466674vLLL0/92x+lpaVRXl4e5eXlNU79/c1vfjMefPDBWLp0aapftdu2bVsMGzYsvve970VpaWlMnz49li5dGtOmTUutZn2wYsWKKCsri4kTJ+71NOQHGyGpnrn//vvj/fffj7KysjjuuONq3IYMGZKVT8MqKytj/fr1sX79+njppZdi5MiRUVFREeedd15W6v7973+PZ599Nm688cYYNGhQnHvuuXHZZZelWjtZP3l75513Uq+bK7fffnt8+OGHccopp8Tdd98dL730UqxcuTJ+/etfx1//+tdo3LhxrlskJcXFxVFeXh5vvfVWDBgwIDZv3pyVups2bdrjK5ZvvPFGVmrv9qUvfSkuueSSrHyl9bbbbovKysoYMGBAPPHEE/HGG2/EQw89FP369Ysjjzwy/uM//iP1HrLtk9a5R48e8eMf/zjrPX3rW9+Kxo0bx5QpU1Kr8e6770afPn3i17/+dbzwwguxatWqmDt3btx0000xaNCg1OpGfHTmwpdffjn+9V//NV544YVYuXJlTJ48OX77299m5fT+zZs3jwsvvDCuu+66WLduXVaCcGlpaTz11FOxYsWKGrNWZ5xxRtxxxx2xY8eOVEPSddddF5lMpvr6a127do3//M//jGuvvTYrx1DnwjvvvBPnn39+9O7dOy699NI9/l/KxvGVWZehXjn33HMzZ5999l4fW7JkSSYiMs8//3xq9YcOHZqJiOpbixYtMl/5ylcyv/vd71Kr+fG6+fn5mXbt2mX69u2bmTFjRmbnzp2p1v54/eStZ8+eWak9aNCg1Ovszdq1azNXXHFFplu3bpmCgoJM8+bNM6eeemrmZz/7WWbr1q2p1d3XOs+fPz8TEZn3338/tdr700c2fOc738kMGTIka/X2tq5vvvlm5uijj86cdtppmU2bNqVef2+/Y2VlZanX/fh6r1q1KlNYWJjJxp/A1atXZ4YOHZpp3759pqCgIFNcXJwZOXJk5p133km1bi7f26tWrape57y8vExEZAYPHpzqPmW3fa33hAkTMu3atctUVFSkUnf79u2ZMWPGZE466aRMq1atMs2aNcv07Nkz86Mf/Sizbdu2VGomLV26NNOvX79Mu3btMq1atcp89atfzdx7772p191t4cKFmYjY5/8vdW3VqlWZiMj06tWrxvjq1atT/9tdXl6eady4cebJJ5/c47H+/ftn+vTpk9m1a1dq9ZPGjh2bOeGEE7JSa9asWXvdh+++denSJSt9ZFNeJuNiKADZNnDgwOjevXvcdtttuW4FUjV27NiYPHlyPProo9XXtgGo71xMFiCL3n///Xj66aejvLw8a2dPhFwaP358dO3aNRYvXhynnnpqzi4nAfBZmEkCyKILLrggnnnmmRg6dGj89Kc/PWivLwEABzIhCQAAIMGcNwAAQIKQBAAAkCAkAQAAJAhJAAAACUISAABAgpAEQL0ybNiwOP/882v1s717946rrrqqxlh5eXnk5eXFxo0bP3dvADQMQhIA7IdMJhMffvhhrtsAIAuEJAAOGC+++GKcddZZ0bx582jfvn185zvfiXfeeSciPpqBWrBgQdx6662Rl5cXeXl5sXr16igtLY2IiEMPPTTy8vJi2LBhERGxa9eumDBhQnTr1i2aNm0aJ5xwQvzud7+rrrV7BurBBx+Mk08+OYqKiuKpp56K559/PkpLS6NFixbRsmXLOPnkk2PZsmVZfy0ASI+QBMABYePGjdGnT5848cQTY9myZfHQQw/Fhg0b4tvf/nZERNx6661RUlIS//RP/xTr1q2LdevWRXFxcdxzzz0REbFy5cpYt25d3HrrrRERMWHChLjrrrti2rRp8Ze//CVGjRoVl156aSxYsKBG3TFjxsTEiRPjpZdeiuOPPz4uueSS6NSpUzzzzDOxfPnyGDNmTBQUFGT3xQAgVfm5bgAA9sdtt90WJ554Ytx4443VYzNmzIji4uJ4+eWXo0ePHlFYWBjNmjWLDh06VD+nTZs2ERFx+OGHR+vWrSMiorKyMm688cZ47LHHoqSkJCIivvCFL8RTTz0Vd9xxR5xxxhnVP/+Tn/wk+vXrV31/zZo18W//9m/Rq1eviIg4+uijU1tnAHJDSALggPD888/H/Pnzo3nz5ns89tprr0WPHj32e1mvvvpqbNu2rUb4iYjYsWNHnHjiiTXGTjnllBr3R48eHf/4j/8Y//f//t/o27dvfOtb34qjjjrqM6wJAPWdkATAAaGioiLOO++8mDRp0h6PHXHEEZ95WRERDzzwQBx55JE1HisqKqpx/5BDDqlxf9y4cXHxxRfHAw88EA8++GCMHTs25syZExdccMFn6gGA+ktIAuCAcNJJJ8U999wTXbt2jfz8vf/5KiwsjJ07d+4xFhE1xo899tgoKiqKNWvW1Phq3f7q0aNH9OjRI0aNGhUXXXRRzJw5U0gCOIg4cQMA9c6mTZtixYoVNW7f/e5347333ouLLroonnnmmXjttdfi4YcfjuHDh1cHoK5du8aSJUti9erV8c4778SuXbuiS5cukZeXF/fff3+8/fbbUVFRES1atIhrrrkmRo0aFXfeeWe89tpr8eyzz8Yvf/nLuPPOO/fZ1wcffBBXXHFFlJeXx9/+9rd4+umn45lnnoljjjkmWy8NAFlgJgmAeqe8vHyPY4PKysri6aefjh/84AfRv3//qKysjC5dusTAgQOjUaOPPvO75pprYujQoXHsscfGBx98EKtWrYquXbvG+PHjY8yYMTF8+PC47LLLYtasWXHDDTdEu3btYsKECfH6669H69at46STTorrr79+n301btw43n333bjssstiw4YNcdhhh8XgwYNj/Pjxqb4eAGRXXiaTyeS6CQAAgPrC1+0AAAAShCQAAIAEIQkAACBBSAIAAEgQkgAAABKEJAAAgAQhCQAAIEFIAgAASBCSAAAAEoQkAACABCEJAAAgQUgCAABI+P8sGDmapkTsYgAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "we can clearly see the same patterns just shifted by 3\n", "\n", "with permutation key: [103, 159, 290, 338, 346, 115, 49, 88, 363, 378]...\n", "we will get cyphertext: ['E', 'C', 'T', 'C', 'T', 'R', 'I', 'G', 'D', 'Y']...\n", "with frequency diagram:\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0kAAAINCAYAAADrxzSOAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAANOhJREFUeJzt3WmUVfWZL/5vMRUiIOIECoiKOLTROLRKBrUQQSVeB1ZiR42CdJJO0FbRNpJJ1LSiuWo0otgdBr1poiEak+gVBwScBxxj/gZHHMLgyKiUJdT/hYu6uwIYLOucU8Lns9Z5sX/n1HmevXfVqfrWbw9V9fX19QEAACBJ0qrSDQAAALQkQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFLSpdAOltnLlysydOzedOnVKVVVVpdsBAAAqpL6+PkuWLMnWW2+dVq3WPl+03oekuXPnpmfPnpVuAwAAaCFef/319OjRY63Pr/chqVOnTkk+3hCdO3eucDcAAEClLF68OD179mzICGuz3oekVYfYde7cWUgCAAD+4Wk4LtwAAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVtKt0ArM96n3NbSd9/zpjBJX1/AIANkZkkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKBCSAAAACoQkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKBCSAAAACoQkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKBCSAAAACtpUuoENTe9zbit5jTljBpe8BgAArK/MJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAEBBiwlJY8aMSVVVVU4//fSGseXLl2fEiBHZbLPN0rFjxwwZMiQLFiyoXJMAAMB6r0WEpMceeyzXXnttdt9990bjZ5xxRv70pz9lypQpmTlzZubOnZtjjjmmQl0CAAAbgoqHpKVLl+b444/Pf//3f2fTTTdtGF+0aFHGjx+fyy67LP3798/ee++diRMn5sEHH8zDDz9cwY4BAID1WZtKNzBixIgMHjw4AwYMyM9+9rOG8ccffzx1dXUZMGBAw9jOO++cXr165aGHHsr++++/xverra1NbW1tw/LixYuTJHV1damrqyvRWqy76tb1Ja/REtaTj5V6f9vXAADrbl3/dqpoSLrhhhvyxBNP5LHHHlvtufnz56ddu3bp0qVLo/Gtttoq8+fPX+t7XnTRRTnvvPNWG7/zzjvToUOHz9zzZ3XJvqWv8X//7/8tfRHWSan3t30NALDu3n///XV6XcVC0uuvv57TTjstd911V9q3b99s7ztq1KiMHDmyYXnx4sXp2bNnBg4cmM6dOzdbnababfQdJa/x7OhBJa/Buin1/ravYcPj9whA0606yuwfqVhIevzxx/Pmm29mr732ahhbsWJF7r333lx11VW544478uGHH2bhwoWNZpMWLFiQbt26rfV9q6urU11dvdp427Zt07Zt22Zdh6aoXVFV8hotYT35WKn3t30NGx6/RwCabl0/3yoWkg4++OD8+c9/bjQ2bNiw7LzzzvnBD36Qnj17pm3btpk2bVqGDBmSJJk9e3Zee+219OvXrxItAwAAG4CKhaROnTplt912azS28cYbZ7PNNmsYHz58eEaOHJmuXbumc+fOOfXUU9OvX7+1XrQBAADgs6r41e0+yeWXX55WrVplyJAhqa2tzaBBg3L11VdXui0AAGA91qJC0owZMxott2/fPmPHjs3YsWMr0xAAALDBqfjNZAEAAFoSIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKBCSAAAACoQkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKBCSAAAACoQkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKGhT6QYA+Pzqfc5tJa8xZ8zgktcAgCIzSQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAECBkAQAAFAgJAEAABQISQAAAAVCEgAAQIGQBAAAUCAkAQAAFAhJAAAABUISAABAgZAEAABQICQBAAAUCEkAAAAFQhIAAEBBm0o3AADA6nqfc1vJa8wZM7jkNeDzyEwSAABAgZAEAABQICQBAAAUCEkAAAAFFQ1J11xzTXbfffd07tw5nTt3Tr9+/XL77bc3PL98+fKMGDEim222WTp27JghQ4ZkwYIFFewYAABY31U0JPXo0SNjxozJ448/nlmzZqV///458sgj85e//CVJcsYZZ+RPf/pTpkyZkpkzZ2bu3Lk55phjKtkyAACwnqvoJcCPOOKIRsv/+Z//mWuuuSYPP/xwevTokfHjx2fy5Mnp379/kmTixInZZZdd8vDDD2f//fevRMsAAMB6rsXcJ2nFihWZMmVKli1bln79+uXxxx9PXV1dBgwY0PCanXfeOb169cpDDz201pBUW1ub2trahuXFixcnSerq6lJXV1falVgH1a3rS16jJawnHyv1/ravqTSfaeVnm2847Gtofuv6PV9VX19f+p/AT/DnP/85/fr1y/Lly9OxY8dMnjw5hx9+eCZPnpxhw4Y1CjxJsu+++6ampiYXX3zxGt9v9OjROe+881Ybnzx5cjp06FCSdQAAAFq+999/P8cdd1wWLVqUzp07r/V1FZ9J2mmnnfLUU09l0aJF+d3vfpeTTjopM2fObPL7jRo1KiNHjmxYXrx4cXr27JmBAwd+4oYol91G31HyGs+OHlTyGqybUu9v+5pK85lWfrb5hsO+hua36iizf6TiIaldu3bp06dPkmTvvffOY489liuuuCLHHntsPvzwwyxcuDBdunRpeP2CBQvSrVu3tb5fdXV1qqurVxtv27Zt2rZt2+z9f1q1K6pKXqMlrCcfK/X+tq+pNJ9p5Webbzjsa2h+6/o93+Luk7Ry5crU1tZm7733Ttu2bTNt2rSG52bPnp3XXnst/fr1q2CHAADA+qyiM0mjRo3KYYcdll69emXJkiWZPHlyZsyYkTvuuCObbLJJhg8fnpEjR6Zr167p3LlzTj311PTr18+V7QAAgJKpaEh68803c+KJJ2bevHnZZJNNsvvuu+eOO+7IIYcckiS5/PLL06pVqwwZMiS1tbUZNGhQrr766kq2DAAArOcqGpLGjx//ic+3b98+Y8eOzdixY8vUEQAAsKFrceckAQAAVJKQBAAAUFDxS4ADrA96n3NbyWvMGTO45DWA1ZX659vPNrQ8ZpIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoKBJIenll19u7j4AAABahCaFpD59+qSmpia//vWvs3z58ubuCQAAoGKaFJKeeOKJ7L777hk5cmS6deuW7373u3n00UebuzcAAICya1JI+uIXv5grrrgic+fOzYQJEzJv3rx85StfyW677ZbLLrssb731VnP3CQAAUBaf6cINbdq0yTHHHJMpU6bk4osvzosvvpizzjorPXv2zIknnph58+Y1V58AAABl8ZlC0qxZs/L9738/3bt3z2WXXZazzjorL730Uu66667MnTs3Rx55ZHP1CQAAUBZtmvJFl112WSZOnJjZs2fn8MMPz/XXX5/DDz88rVp9nLm22267TJo0Kb17927OXgEAAEquSSHpmmuuycknn5yhQ4eme/fua3zNlltumfHjx3+m5gAAAMqtSSHphRde+IevadeuXU466aSmvD0AAEDFNOmcpIkTJ2bKlCmrjU+ZMiXXXXfdZ24KAACgUpoUki666KJsvvnmq41vueWWufDCCz9zUwAAAJXSpJD02muvZbvttlttfNttt81rr732mZsCAAColCaFpC233DLPPPPMauNPP/10Nttss8/cFAAAQKU0KSR985vfzL//+79n+vTpWbFiRVasWJF77rknp512Wv7lX/6luXsEAAAomyZd3e6CCy7InDlzcvDBB6dNm4/fYuXKlTnxxBOdkwQAAHyuNSkktWvXLjfeeGMuuOCCPP3009loo43yhS98Idtuu21z9wcAAFBWTQpJq/Tt2zd9+/Ztrl4AAAAqrkkhacWKFZk0aVKmTZuWN998MytXrmz0/D333NMszQEAAJRbk0LSaaedlkmTJmXw4MHZbbfdUlVV1dx9AQAAVESTQtINN9yQ3/72tzn88MObux8AAICKatIlwNu1a5c+ffo0dy8AAAAV16SQdOaZZ+aKK65IfX19c/cDAABQUU063O7+++/P9OnTc/vtt+ef/umf0rZt20bP33zzzc3SHAAAQLk1KSR16dIlRx99dHP3AgAAUHFNCkkTJ05s7j4AAABahCadk5QkH330Ue6+++5ce+21WbJkSZJk7ty5Wbp0abM1BwAAUG5Nmkl69dVXc+ihh+a1115LbW1tDjnkkHTq1CkXX3xxamtrM27cuObuEwAAoCyaNJN02mmnZZ999sl7772XjTbaqGH86KOPzrRp05qtOQAAgHJr0kzSfffdlwcffDDt2rVrNN67d+/87W9/a5bGAAAAKqFJM0krV67MihUrVht/44030qlTp8/cFAAAQKU0KSQNHDgwv/jFLxqWq6qqsnTp0px77rk5/PDDm6s3AACAsmvS4XaXXnppBg0alF133TXLly/PcccdlxdeeCGbb755fvOb3zR3jwAAAGXTpJDUo0ePPP3007nhhhvyzDPPZOnSpRk+fHiOP/74RhdyAAAA+LxpUkhKkjZt2uSEE05ozl4AAAAqrkkh6frrr//E50888cQmNQMAAFBpTQpJp512WqPlurq6vP/++2nXrl06dOggJAEAAJ9bTbq63XvvvdfosXTp0syePTtf+cpXXLgBAAD4XGtSSFqTHXfcMWPGjFltlgkAAODzpNlCUvLxxRzmzp3bnG8JAABQVk06J+mPf/xjo+X6+vrMmzcvV111Vb785S83S2MAAACV0KSQdNRRRzVarqqqyhZbbJH+/fvn0ksvbY6+AAAAKqJJIWnlypXN3QcAAECL0KznJAEAAHzeNWkmaeTIkev82ssuu6wpJQAAACqiSSHpySefzJNPPpm6urrstNNOSZLnn38+rVu3zl577dXwuqqqqubpEgAAoEyaFJKOOOKIdOrUKdddd1023XTTJB/fYHbYsGH56le/mjPPPLNZmwQAACiXJp2TdOmll+aiiy5qCEhJsummm+ZnP/uZq9sBAACfa00KSYsXL85bb7212vhbb72VJUuWfOamAAAAKqVJIenoo4/OsGHDcvPNN+eNN97IG2+8kZtuuinDhw/PMccc09w9AgAAlE2TzkkaN25czjrrrBx33HGpq6v7+I3atMnw4cPz85//vFkbBAAAKKcmhaQOHTrk6quvzs9//vO89NJLSZIddtghG2+8cbM2BwAAUG6f6Way8+bNy7x587Ljjjtm4403Tn19fXP1BQAAUBFNCknvvPNODj744PTt2zeHH3545s2blyQZPny4y38DAACfa00KSWeccUbatm2b1157LR06dGgYP/bYYzN16tRmaw4AAKDcmnRO0p133pk77rgjPXr0aDS+44475tVXX22WxgAAACqhSTNJy5YtazSDtMq7776b6urqz9wUAABApTQpJH31q1/N9ddf37BcVVWVlStX5pJLLklNTU2zNQcAAFBuTTrc7pJLLsnBBx+cWbNm5cMPP8zZZ5+dv/zlL3n33XfzwAMPNHePAAAAZdOkkLTbbrvl+eefz1VXXZVOnTpl6dKlOeaYYzJixIh07969uXsEgBal9zm3lbzGnDGDS14DgDX71CGprq4uhx56aMaNG5cf/ehHpegJAACgYj71OUlt27bNM888U4peAAAAKq5JF2444YQTMn78+ObuBQAAoOKadE7SRx99lAkTJuTuu+/O3nvvnY033rjR85dddlmzNAcAAFBunyokvfzyy+ndu3eeffbZ7LXXXkmS559/vtFrqqqqmq87AACAMvtUIWnHHXfMvHnzMn369CTJsccemyuvvDJbbbVVSZoDAAAot091TlJ9fX2j5dtvvz3Lli1r1oYAAAAqqUkXbljl70MTAADA592nOtyuqqpqtXOOnIMEAJRaqW/g6+a9QNGnCkn19fUZOnRoqqurkyTLly/Pv/3bv612dbubb765+ToEAAAoo08Vkk466aRGyyeccEKzNgMAAFBpnyokTZw4sVR9AAAAtAif6cINAAAA65uKhqSLLroo//zP/5xOnTplyy23zFFHHZXZs2c3es3y5cszYsSIbLbZZunYsWOGDBmSBQsWVKhjAABgfVfRkDRz5syMGDEiDz/8cO66667U1dVl4MCBje69dMYZZ+RPf/pTpkyZkpkzZ2bu3Lk55phjKtg1AACwPvtU5yQ1t6lTpzZanjRpUrbccss8/vjjOeCAA7Jo0aKMHz8+kydPTv/+/ZN8fF7ULrvskocffjj7779/JdoGAADWYxUNSX9v0aJFSZKuXbsmSR5//PHU1dVlwIABDa/Zeeed06tXrzz0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bbXVVvtzVldttdVWe32qW+nazaG+vj5LlizJ1ltv/Ymva9EhafPNN0/r1q2zYMGCRuMLFixIt27d1vg11dXVqa6ubjTWpUuXUrVYFp07d67YN6Haaqut9vpUe0NcZ7XVVnv9rb0hrnNz2GSTTf7ha1r0hRvatWuXvffeO9OmTWsYW7lyZaZNm9bo8DsAAIDm0qJnkpJk5MiROemkk7LPPvtk3333zS9+8YssW7Ysw4YNq3RrAADAeqjFh6Rjjz02b731Vn76059m/vz5+eIXv5ipU6dmq622qnRrJVddXZ1zzz13tcMH1VZbbbXV/nzUVVtttdVen+pWunY5teir2wEAAJRbiz4nCQAAoNyEJAAAgAIhCQAAoEBIAgAAKBCSWrCHHnoorVu3zuDBg8tWc+jQoamqqmp4bLbZZjn00EPzzDPPlKX+/Pnzc+qpp2b77bdPdXV1evbsmSOOOKLRvbKaW3Gd27Ztm6222iqHHHJIJkyYkJUrV5as7prqFx+HHnpoxWq/+OKLJa89f/78nHbaaenTp0/at2+frbbaKl/+8pdzzTXX5P333y9Z3aFDh+aoo45abXzGjBmpqqrKwoULS1Z7XfooZ73f/e53ad++fS699NKK1C9Hzaqqqvzbv/3bas+NGDEiVVVVGTp0aElrjxkzptH4LbfckqqqqpLU/Huvv/56Tj755Gy99dZp165dtt1225x22ml55513Slq3+LnSrl279OnTJ+eff34++uijktb9+9pt27bNdtttl7PPPjvLly8vee233nor3/ve99KrV69UV1enW7duGTRoUB544IGS1l3TZ3jxMXr06JLVPuigg3L66aevNj5p0qR06dKlZHWPOOKItf6OvO+++1JVVdXsf7eMGzcunTp1avR9vHTp0rRt2zYHHXRQo9eu+n3y0ksvNWsPK1asyJe+9KUcc8wxjcYXLVqUnj175kc/+lGz1iuqr6/PgAEDMmjQoNWeu/rqq9OlS5e88cYbJatfCUJSCzZ+/PiceuqpuffeezN37tyy1T300EMzb968zJs3L9OmTUubNm3yta99reR158yZk7333jv33HNPfv7zn+fPf/5zpk6dmpqamowYMaKktVet85w5c3L77benpqYmp512Wr72ta+V5Rd7cZuvevzmN78ped211d5uu+1KWvPll1/OnnvumTvvvDMXXnhhnnzyyTz00EM5++yzc+utt+buu+8uaX2SX/3qVzn++ONzzTXX5Mwzz6x0OyXTs2fP3HDDDfnggw8axpYvX57JkyenV69eJa3dvn37XHzxxXnvvfdKWmdNXn755eyzzz554YUX8pvf/CYvvvhixo0b13Az9nfffbek9Vd9rrzwwgs588wzM3r06Pz85z8vac2/r/3yyy/n8ssvz7XXXptzzz235HWHDBmSJ598Mtddd12ef/75/PGPf8xBBx1U8lBa/Oz+xS9+kc6dOzcaO+uss0pavxKGDx+eu+66a41/lE+cODH77LNPdt9992atWVNTk6VLl2bWrFkNY/fdd1+6deuWRx55pFEQnz59enr16pUddtihWXto3bp1Jk2alKlTp+Z//ud/GsZPPfXUdO3ataTf51VVVZk4cWIeeeSRXHvttQ3jr7zySs4+++z88pe/TI8ePUpWvxJa/H2SNlRLly7NjTfemFmzZmX+/PmZNGlSfvjDH5al9qr/gCVJt27dcs455+SrX/1q3nrrrWyxxRYlq/v9738/VVVVefTRR7Pxxhs3jP/TP/1TTj755JLVTRqv8zbbbJO99tor+++/fw4++OBMmjQp//qv/1q2+uVWidrf//7306ZNm8yaNavRvt5+++1z5JFHxp0JSuuSSy7JueeemxtuuCFHH310pdspqb322isvvfRSbr755hx//PFJkptvvjm9evUq+T8DBgwYkBdffDEXXXRRLrnkkpLW+nsjRoxIu3btcuedd2ajjTZKkvTq1St77rlndthhh/zoRz/KNddcU7L6xc+V733ve/n973+fP/7xjxk1alTJaq6pds+ePTNgwIDcddddufjii0tWc+HChbnvvvsyY8aMHHjggUmSbbfdNvvuu2/Jaq5S/PzeZJNNUlVVVbHfJ+Xyta99LVtssUUmTZqUH//4xw3jS5cuzZQpU0oSyHfaaad07949M2bMyP7775/k4xmjI488Mvfcc08efvjhhhmlGTNmpKamptl7SJK+fftmzJgxOfXUU9O/f/88+uijueGGG/LYY4+lXbt2Jam5Ss+ePXPFFVfklFNOycCBA9O7d+8MHz48AwcOzLe+9a2S1q4EM0kt1G9/+9vsvPPO2WmnnXLCCSdkwoQJFfnDcenSpfn1r3+dPn36ZLPNNitZnXfffTdTp07NiBEjGv3RvEopp+3Xpn///tljjz1y8803l732+uydd97JnXfeudZ9naRshyNtiH7wgx/kggsuyK233rreB6RVTj755EycOLFhecKECRk2bFjJ67Zu3ToXXnhhfvnLX5b1MJR33303d9xxR77//e83BKRVunXrluOPPz433nhjWX+nbLTRRvnwww/LVm+VZ599Ng8++GDJ/3js2LFjOnbsmFtuuSW1tbUlrUXSpk2bnHjiiZk0aVKj7+MpU6ZkxYoV+eY3v1mSujU1NZk+fXrD8vTp03PQQQflwAMPbBj/4IMP8sgjj5QsJCUfzxztscce+da3vpXvfOc7+elPf5o99tijZPWKTjrppBx88ME5+eSTc9VVV+XZZ59tNLO0PhGSWqjx48fnhBNOSPLxoQOLFi3KzJkzy1L71ltvbfjA79SpU/74xz/mxhtvTKtWpft2efHFF1NfX5+dd965ZDWaYuedd86cOXNKXqe4zVc9LrzwwpLXXVPtr3/96yWtt2pf77TTTo3GN99884YefvCDH5S0hzVt78MOO6ykNVuC22+/PZdcckn+8Ic/5OCDD650O2Vzwgkn5P7778+rr76aV199NQ888EDD52upHX300fniF79YlsO9VnnhhRdSX1+fXXbZZY3P77LLLnnvvffy1ltvlbyX+vr63H333bnjjjvSv3//ktdL/t/Pd/v27fOFL3whb775Zv7jP/6jpDXbtGmTSZMm5brrrkuXLl3y5S9/OT/84Q/Ldj7vhujkk0/OSy+91Ohvo4kTJ2bIkCHZZJNNSlKzpqYmDzzwQD766KMsWbIkTz75ZA488MAccMABmTFjRpKPzyevra0taUiqqqrKNddck2nTpmWrrbbKOeecU7Jaa/Jf//VfefbZZ3P66afnv/7rv0p6lFElOdyuBZo9e3YeffTR/P73v0/y8Yfvsccem/Hjx692cmAp1NTUNByG8d577+Xqq6/OYYcdlkcffTTbbrttSWq21MOr6uvryzKrUdzmq3Tt2rXkdddUe22zO6X26KOPZuXKlTn++ONL/p/YNW3vRx55pGx/OFfK7rvvnrfffjvnnntu9t1333Ts2LHSLZXFFltskcGDBzf813nw4MHZfPPNy1b/4osvTv/+/ct+bkglP1dXBZW6urqsXLkyxx13XEkvIFC06ud72bJlufzyy9OmTZsMGTKk5HWHDBmSwYMH57777svDDz/c8E+JX/3qVyW7QMiGbOedd86XvvSlTJgwIQcddFBefPHF3HfffTn//PNLVvOggw7KsmXL8thjj+W9995L3759s8UWW+TAAw/MsGHDsnz58syYMSPbb799yc95nDBhQjp06JBXXnklb7zxRnr37l3SekVbbrllvvvd7+aWW24p+wV5yslMUgs0fvz4fPTRR9l6663Tpk2btGnTJtdcc01uuummLFq0qOT1N9544/Tp0yd9+vTJP//zP+dXv/pVli1blv/+7/8uWc0dd9wxVVVV+etf/1qyGk3x3HPPlfy8haTxNl/1KFdI+vva3bt3L2m9Pn36pKqqKrNnz240vv3226dPnz6rHR5UCmva3ttss03J61baNttskxkzZuRvf/tbDj300CxZsqTSLZXNySef3PCf/lKf4/j3DjjggAwaNKgs5+Mk/+9n7Lnnnlvj888991w23XTTkv73t6amJk899VReeOGFfPDBB7nuuuvK9g+YVT/fe+yxRyZMmJBHHnkk48ePL0vt9u3b55BDDslPfvKTPPjggxk6dGhZZxHLrXPnzmv8u2ThwoUlm80pGj58eG666aYsWbIkEydOzA477NBwTlgp9OnTJz169Mj06dMzffr0hlpbb711evbsmQcffDDTp08v+azpgw8+mMsvvzy33npr9t133wwfPrzs/xRZ9ffp+kxIamE++uijXH/99bn00kvz1FNPNTyefvrpbL311mW74llRVVVVWrVq1ejqUM2ta9euGTRoUMaOHZtly5at9ny5LstcdM899+TPf/5zWf4DuSHZbLPNcsghh+Sqq65a476mtLbddtvMnDkz8+fP36CC0qGHHpoPP/wwdXV1a7yEbamNGTMmf/rTn/LQQw+VvNaqn7Grr756tc/t+fPn53/+539y7LHHlnSWfFVQ6dWrV0X/kGrVqlV++MMf5sc//nFJf4etza677rpef87ttNNOeeKJJ1Ybf+KJJ9K3b9+S1//GN76RVq1aZfLkybn++utz8sknl/zoj5qamsyYMSMzZsxodHTPAQcckNtvvz2PPvpoSQ+1e//99zN06NB873vfS01NTcaPH59HH30048aNK1nNDZWQ1MLceuutee+99zJ8+PDstttujR5Dhgwpy3/DamtrM3/+/MyfPz/PPfdcTj311CxdujRHHHFESeuOHTs2K1asyL777pubbropL7zwQp577rlceeWV6devX0lrr1rnv/3tb3niiSdy4YUX5sgjj8zXvva1nHjiiSWtXaxffLz99tslr1spV199dT766KPss88+ufHGG/Pcc89l9uzZ+fWvf52//vWvad26daVbXK/17NkzM2bMyJtvvplBgwZl8eLFZam7aNGiRv/8eeqpp/L666+XpXbr1q3z3HPP5f/7//6/inx/feELX8jxxx+fK6+8siz1rrrqqtTW1mbQoEG599578/rrr2fq1Kk55JBDss022+Q///M/y9JHS/D1r389rVu3ztixY0tW45133kn//v3z61//Os8880xeeeWVTJkyJZdcckmOPPLIktWttO9973t5/vnn8+///u955plnMnv27Fx22WX5zW9+U5ZbC3Ts2DHHHntsRo0alXnz5pXlsMaamprcf//9eeqppxrNWh144IG59tpr8+GHH5Y0JI0aNSr19fUN92Dr3bt3/vf//t85++yzy3IO9YZESGphxo8fnwEDBqxxmnrIkCGZNWtWyU8EnTp1arp3757u3btnv/32y2OPPZYpU6aU/Hyo7bffPk888URqampy5plnZrfddsshhxySadOmlfRStcn/W+fevXvn0EMPzfTp03PllVfmD3/4Q1n+oCpu81WPr3zlKyWvWyk77LBDnnzyyQwYMCCjRo3KHnvskX322Se//OUvc9ZZZ+WCCy6odIvrvR49emTGjBl5++23yxaUZsyYkT333LPR47zzzit53VU6d+6czp07l63e3zv//PPLcoPq5ONDmGfNmpXtt98+3/jGN7LDDjvkO9/5TmpqavLQQw+V7XDelqBNmzY55ZRTcskll5RsVqdjx47Zb7/9cvnll+eAAw7Ibrvtlp/85Cf59re/nauuuqokNVuC7bffPvfee2/++te/ZsCAAdlvv/3y29/+NlOmTCnLDdGTjw+5e++99zJo0KBsvfXWJa9XU1OTDz74IH369MlWW23VMH7ggQdmyZIlDZcKL4WZM2dm7NixmThxYjp06NAw/t3vfjdf+tKXKnLY3fqsqt7WBAAAaGAmCQAAoEBIAgAAKBCSAAAACoQkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQmAFmXo0KE56qijmvS1Bx10UE4//fRGYzNmzEhVVVUWLlz4mXsDYMMgJAHAOqivr89HH31U6TYAKAMhCYDPjWeffTaHHXZYOnbsmK222irf+ta38vbbbyf5eAZq5syZueKKK1JVVZWqqqrMmTMnNTU1SZJNN900VVVVGTp0aJJk5cqVueiii7Lddttlo402yh577JHf/e53DbVWzUDdfvvt2XvvvVNdXZ37778/Tz/9dGpqatKpU6d07tw5e++9d2bNmlX2bQFA6QhJAHwuLFy4MP3798+ee+6ZWbNmZerUqVmwYEG+8Y1vJEmuuOKK9OvXL9/+9rczb968zJs3Lz179sxNN92UJJk9e3bmzZuXK664Ikly0UUX5frrr8+4cePyl7/8JWeccUZOOOGEzJw5s1Hdc845J2PGjMlzzz2X3XffPccff3x69OiRxx57LI8//njOOeectG3btrwbA4CSalPpBgBgXVx11VXZc889c+GFFzaMTZgwIT179szzzz+fvn37pl27dunQoUO6devW8JquXbsmSbbccst06dIlSVJbW5sLL7wwd999d/r165ck2X777XP//ffn2muvzYEHHtjw9eeff34OOeSQhuXXXnst//Ef/5Gdd945SbLjjjuWbJ0BqAwhCYDPhaeffjrTp09Px44dV3vupZdeSt++fdf5vV588cW8//77jcJPknz44YfZc889G43ts88+jZZHjhyZf/3Xf83/+T//JwMGDMjXv/717LDDDp9iTQBo6YQkAD4Xli5dmiOOOCIXX3zxas917979U79Xktx2223ZZpttGj1XXV3daHnjjTdutDx69Ogcd9xxue2223L77bfn3HPPzQ033JCjjz76U/UAQMslJAHwubDXXnvlpptuSu/evdOmzZp/fbVr1y4rVqxYbSxJo/Fdd9011dXVee211xodWreu+vbtm759++aMM87IN7/5zUycOFFIAliPuHADAC3OokWL8tRTTzV6fOc738m7776bb37zm3nsscfy0ksv5Y477siwYcMaAlDv3r3zyCOPZM6cOXn77bezcuXKbLvttqmqqsqtt96at956K0uXLk2nTp1y1lln5Ywzzsh1112Xl156KU888UR++ctf5rrrrltrXx988EFOOeWUzJgxI6+++moeeOCBPPbYY9lll13KtWkAKAMzSQC0ODNmzFjt3KDhw4fngQceyA9+8IMMHDgwtbW12XbbbXPooYemVauP/+d31lln5aSTTsquu+6aDz74IK+88kp69+6d8847L+ecc06GDRuWE088MZMmTcoFF1yQLbbYIhdddFFefvnldOnSJXvttVd++MMfrrWv1q1b55133smJJ56YBQsWZPPNN88xxxyT8847r6TbA4Dyqqqvr6+vdBMAAAAthcPtAAAACoQkAACAAiEJAACgQEgCAAAoEJIAAAAKhCQAAIACIQkAAKBASAIAACgQkgAAAAqEJAAAgAIhCQAAoEBIAgAAKPj/Adf9dkneZ8JLAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "we can see there is no change compared to the plaintext diagram as permutation does not create any confusion\n", "\n", "with shift key: ['R', 'F', 'I', 'Q', 'S', 'Z', 'K', 'U', 'T', 'S']...\n", "we will get cyphertext: ['R', 'H', 'K', 'E', 'J', 'C', 'S', 'H', 'Z', 'L']...\n", "with frequency diagram:\n" ] }, { "data": { "image/png": "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yHoBYEv8TYOdW7VK0osvvhivvPJK1K5du8ryNm3axL/+9a+0DAYAAJAL1fpM0oYNG2L9+vWbLP/oo4+ifv3633ooAACAXKlWSerRo0fcfvvtledTqVSsXr06rr322vjBD36QrtkAAACyrlpvt7v11lujZ8+esf/++8eXX34Zffr0ifnz50fjxo3jwQcfTPeMAAAAWVOtktSyZct46623YuLEiTF79uxYvXp1DBgwIM4+++zYdddd0z0jAABA1lSrJEVEFBQUxDnnnJPOWQAAAHKuWiXpgQce2Orl5557brWGAQAAyLVqf09SUnl5eaxduzZq164ddevWVZIAAIAdVrWObvf5559XOa1evTrmzZsXxxxzjAM3AAAAO7RqlaTN6dixYwwfPnyTvUwAAAA7krSVpIivD+awePHidK4SAAAgq6r1maS//vWvVc5XVFTEkiVL4u67746jjz46LYMBAADkQrVK0qmnnlrlfCqViiZNmkS3bt3i1ltvTcdcAAAAOVGtkrRhw4Z0zwEAAFAjpPUzSQAAADu6au1JGjRo0DZfd+TIkdWJAAAAyIlqlaQ333wz3nzzzSgvL4999tknIiLeeeedqFWrVhx88MGV10ulUumZEgAAIEuqVZJOPvnkqF+/ftx///2xxx57RMTXXzDbr1+/+P73vx9XXnllWocEAADIlmp9JunWW2+Nm266qbIgRUTsscceccMNNzi6HQAAsEOrVklauXJlfPLJJ5ss/+STT2LVqlXfeigAAIBcqVZJOu2006Jfv37x6KOPxkcffRQfffRRPPLIIzFgwIA4/fTT0z0jAABA1lTrM0mjR4+OwYMHR58+faK8vPzrFRUUxIABA+KWW25J64AAAADZVK2SVLdu3bj33nvjlltuiYULF0ZERPv27WO33XZL63AAAADZ9q2+THbJkiWxZMmS6NixY+y2225RUVGRrrkAAAByolol6dNPP43jjz8+OnXqFD/4wQ9iyZIlERExYMAAh/8GAAB2aNUqSVdccUUUFhbGBx98EHXr1q1cfuaZZ8bkyZPTNhwAAEC2VeszSX//+9/j6aefjpYtW1ZZ3rFjx3j//ffTMhgAAEAuVGtP0po1a6rsQdros88+i6Kiom89FAAAQK5UqyR9//vfjwceeKDyfCqVig0bNsSIESOipKQkbcMBAABkW7XebjdixIg4/vjj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s5KXiYxUKhUXXnjhJpcNHDgwUqlU9O3bN+15w4cPr7L88ccfj1QqlbacpA8//DD69+8fLVq0iNq1a0fr1q3jsssui08//TTtWcnnkNq1a0eHDh3iuuuui3Xr1qU9K1e3q7CwMNq2bRtXXXVVfPnll2nPioj45JNP4qKLLopWrVpFUVFRNGvWLHr27Bkvv/xyWnM293yfPA0dOjRtWV27do3LL798k+Xjx4+Phg0bpi0nIuLkk0/e4t/JF198MVKp1Ld+PTJ69OioX79+lcf26tWro7CwMLp27Vrluhv/3ixcuPBbZUZErF+/Po466qg4/fTTqyxfsWJFFBcXx69+9atvnbFRRUVFdO/ePXr27LnJZffee280bNgwPvroo7TlbdxOWzqVlJSkLSvXlKQaaMyYMXHppZfGCy+8EIsXL85oVq9evWLJkiWxZMmSeO6556KgoCB++MMfZiRr0aJFccghh8Tzzz8ft9xyS/zjH/+IyZMnR0lJSQwcODCtWRtv16JFi2LSpElRUlISl112Wfzwhz/MyAuB5HbceHrwwQfTnrO1vLZt26Y14913342DDjoo/v73v8eNN94Yb775ZkybNi2uuuqqePLJJ+PZZ59Nax6Z8Yc//CHOPvvsGDVqVFx55ZW5HqfaiouLY+LEifHFF19ULvvyyy9jwoQJ0apVq7Tn1alTJ26++eb4/PPP077u//Tuu+/GoYceGvPnz48HH3wwFixYEKNHj6784vTPPvss7Zkbn0Pmz58fV155ZQwdOjRuueWWtGbk8na9++67cdttt8V9990X1157bdpzIiJ69+4db775Ztx///3xzjvvxF//+tfo2rVr2gtg8nn+9ttvjwYNGlRZNnjw4LTmZcuAAQPimWee2ewL+HHjxsWhhx4aBxxwwLfKKCkpidWrV8fMmTMrl7344ovRrFmzmD59epUCPWXKlGjVqlW0b9/+W2VGRNSqVSvGjx8fkydPjj/96U+Vyy+99NJo1KhRWh+TqVQqxo0bF9OnT4/77ruvcvl7770XV111Vdx1113RsmXLtOUdddRRm7z+WLJkSdx3332RSqXi4osvTltWrtX470na2axevToeeuihmDlzZixdujTGjx8f11xzTcbyNv73KyKiWbNmcfXVV8f3v//9+OSTT6JJkyZpzbr44osjlUrFjBkzYrfddqtc/p3vfCf69++f1qzk7dp7773j4IMPju9973tx/PHHx/jx4+OnP/1pxvKyIRt5F198cRQUFMTMmTOr3F/t2rWLU045JXx7QM03YsSIuPbaa2PixIlx2mmn5Xqcb+Xggw+OhQsXxqOPPhpnn312REQ8+uij0apVq7T/gyAionv37rFgwYK46aabYsSIEWlff9LAgQOjdu3a8fe//z123XXXiIho1apVHHTQQdG+ffv41a9+FaNGjUprZvI55KKLLorHHnss/vrXv8aQIUPSlpHr21VcXBzdu3ePZ555Jm6++ea05ixfvjxefPHFKC0tjeOOOy4iIlq3bh2HH354WnMiospz/e677x6pVCqrf28y5Yc//GE0adIkxo8fH7/+9a8rl69evToefvjhtJT2ffbZJ5o3bx6lpaXxve99LyK+3hNyyimnxPPPPx+vvvpq5R6l0tLStO4F6dSpUwwfPjwuvfTS6NatW8yYMSMmTpwYr732WtSuXTttORFfP9bvuOOOuOSSS6JHjx7Rpk2bGDBgQPTo0SN+8pOfpDWrdu3amzz+5s6dG4MHD45rrrkmzjjjjLTm5ZI9STXMn//859h3331jn332iXPOOSfGjh2btRejq1evjj/+8Y/RoUOH2HPPPdO67s8++ywmT54cAwcOrPKCe6N078bfnG7dukWXLl3i0UcfzXjWju7TTz+Nv//971u8vyIiY287Ij1++ctfxvXXXx9PPvnkDl+QNurfv3+MGzeu8vzYsWOjX79+GcmqVatW3HjjjXHXXXel9a0q/+mzzz6Lp59+Oi6++OLKIrFRs2bN4uyzz46HHnoo438Hdt111/jqq6/Str6acLvmzJkTr7zyStpfkEZE1KtXL+rVqxePP/54lJWVpX39O4OCgoI499xzY/z48VUeBw8//HCsX78+zjrrrLTklJSUxJQpUyrPT5kyJbp27RrHHXdc5fIvvvgipk+fnva3il166aXRpUuX+MlPfhIXXHBB/Pa3v40uXbqkNWOj8847L44//vjo379/3H333TFnzpwqe5YyZfny5XHKKadE165d4/rrr894XjYpSTXMmDFj4pxzzomIr982sGLFipg6dWrG8p588snKJ/v69evHX//613jooYdil13S+9BYsGBBVFRUxL777pvW9W6vfffdNxYtWpT29Sa348bTjTfemPacLeWl+z83G++vffbZp8ryxo0bV2b+8pe/TGvm5rbhiSeemNaMncWkSZNixIgR8cQTT8Txxx+f63HS5pxzzomXXnop3n///Xj//ffj5Zdfrny+zITTTjstDjzwwIy9XSsiYv78+VFRURH77bffZi/fb7/94vPPP49PPvkkI/kVFRXx7LPPxtNPPx3dunVL23pzdbs2Po/UqVMnvvvd78a///3v+MUvfpHWjIivX+CPHz8+7r///mjYsGEcffTRcc0112T0M735qH///rFw4cIqr3PGjRsXvXv3jt133z0tGSUlJfHyyy/HunXrYtWqVfHmm2/GcccdF8cee2yUlpZGxNefBS8rK0t7SUqlUjFq1Kh47rnnYq+99oqrr746rev/T7///e9jzpw5cfnll8fvf//7tL8j6D9t2LAh+vTpEwUFBfGnP/0p7/556u12Nci8efNixowZ8dhjj0XE10/CZ555ZowZM2aTDximS0lJSeXbHT7//PO4995748QTT4wZM2ZE69at05ZTU96aVVFRkZFf4uR23KhRo0Zpz9lS3pb29qTbjBkzYsOGDXH22Wen/b+nm9uG06dPz+iL4Hx1wAEHxLJly+Laa6+Nww8/POrVq5frkdKiSZMmcdJJJ1X+5/mkk06Kxo0bZzTz5ptvjm7dumX8cx/Zfo7cWCbKy8srX+ik8wAAG33T7Ur3Xp6NzyNr1qyJ2267LQoKCqJ3795pzdiod+/ecdJJJ8WLL74Yr776auU/J/7whz+k9UAi+WzfffeNo446KsaOHRtdu3aNBQsWxIsvvhjXXXdd2jK6du0aa9asiddeey0+//zz6NSpUzRp0iSOO+646NevX3z55ZdRWloa7dq1y8jnG8eOHRt169aN9957Lz766KNo06ZN2jM2atq0afzsZz+Lxx9/PCsHJLrmmmti2rRpMWPGjKhfv37G87LNnqQaZMyYMbFu3bpo0aJFFBQUREFBQYwaNSoeeeSRWLFiRUYyd9ttt+jQoUN06NAhDjvssPjDH/4Qa9asif/5n/9Ja07Hjh0jlUrF22+/ndb1bq+5c+dm5PMLye248ZTJkvSfec2bN0/r+jt06BCpVCrmzZtXZXm7du2iQ4cOm7x9Jh02tw333nvvtOfsDPbee+8oLS2Nf/3rX9GrV69YtWpVrkdKm/79+1f+Bz/dn2XcnGOPPTZ69uyZ1s/qJG38XZs7d+5mL587d27sscceaf+PcElJScyaNSvmz58fX3zxRdx///1p/WfLttyuJk2apP2t1hufR7p06RJjx46N6dOnx5gxY9KakVSnTp044YQT4je/+U288sor0bdv34zuecy0Bg0abPb1xvLly9O2Z+c/DRgwIB555JFYtWpVjBs3Ltq3b1/5Oa906NChQ7Rs2TKmTJkSU6ZMqVx3ixYtori4OF555ZWYMmVKWvekbvTKK6/EbbfdFk8++WQcfvjhMWDAgIz/Q2Tj68dMmzhxYvzud7+LiRMnRseOHTOelwtKUg2xbt26eOCBB+LWW2+NWbNmVZ7eeuutaNGiRUaPlJaUSqVil112qXIEqXRo1KhR9OzZM+65555Ys2bNJpdn8hDPGz3//PPxj3/8I2P/Vcwne+65Z5xwwglx9913b/b+ouZr3bp1TJ06NZYuXZpXRalXr17x1VdfRXl5+WYPeZsJw4cPj7/97W8xbdq0tK974+/avffeu8nz7tKlS+NPf/pTnHnmmWnfA76xTLRq1SojL6i25XZlem/LLrvsEtdcc038+te/TvvftC3Zf//9d+jnzH322SfeeOONTZa/8cYb0alTp4xk/uhHP4pddtklJkyYEA888ED0798/7Y/3kpKSKC0tjdLS0irvzDn22GNj0qRJMWPGjLS/1W7t2rXRt2/fuOiii6KkpCTGjBkTM2bMiNGjR6c1JxdmzZoVAwYMiOHDh2fteTgXlKQa4sknn4zPP/88BgwYEJ07d65y6t27d8b+E1ZWVhZLly6NpUuXxty5c+PSSy+N1atXx8knn5z2rHvuuSfWr18fhx9+eDzyyCMxf/78mDt3btx5551x5JFHpjVr4+3617/+FW+88UbceOONccopp8QPf/jDOPfcc9OalcxLnpYtW5b2nGy69957Y926dXHooYfGQw89FHPnzo158+bFH//4x3j77bejVq1auR6Rb1BcXBylpaXx73//O3r27BkrV67MSM6KFSuq/HNn1qxZ8eGHH2Ykq1atWjF37tz4f//v/2XtMfjd7343zj777Ljzzjszsv677747ysrKomfPnvHCCy/Ehx9+GJMnT44TTjgh9t577/jv//7vjORm2tZuV6dOneK3v/1txmc444wzolatWnHPPfekdb2ffvppdOvWLf74xz/G7Nmz47333ouHH344RowYEaecckpas7LpoosuinfeeSd+/vOfx+zZs2PevHkxcuTIePDBBzP2FQL16tWLM888M4YMGRJLlizJSHkuKSmJl156KWbNmlVlL9Vxxx0X9913X3z11VdpL0lDhgyJioqKyu9ba9OmTfzud7+Lq666KiOfjc6WZcuWxamnnhpdu3aNc845Z5PXPpn6/GQuKEk1xJgxY6J79+6b3Z3du3fvmDlzZkY+EDp58uRo3rx5NG/ePI444oh47bXX4uGHH87IZ6DatWsXb7zxRpSUlMSVV14ZnTt3jhNOOCGee+65tB8GduPtatOmTfTq1SumTJkSd955ZzzxxBMZeWGV3I4bT8ccc0zac7Kpffv28eabb0b37t1jyJAh0aVLlzj00EPjrrvuisGDB+fdUWyyYcOGDVl5G0RSy5Yto7S0NJYtW5axolRaWhoHHXRQldOwYcPSnrNRgwYNokGDBhlb/+Zcd911Gfky6oiv3448c+bMaNeuXfzoRz+K9u3bxwUXXBAlJSUxbdq0jL51N5M6duwYr732WuXtat26dZx44onRqVOnePnll7PyWbmCgoK45JJLYsSIEWndw1OvXr044ogj4rbbbotjjz02OnfuHL/5zW/i/PPPj7vvvjttOdnWrl27eOGFF+Ltt9+O7t27xxFHHBF//vOf4+GHH87YF6RHfP2Wu88//zx69uwZLVq0SPv6S0pK4osvvogOHTrEXnvtVbn8uOOOi1WrVlUeKjxdpk6dGvfcc0+MGzcu6tatW7n8Zz/7WRx11FFZedtdpjz11FPx/vvvx//93/9t8rqnefPmcdhhh+V6xLRJVeyo9xLADqZXr17RoUOHHfpFFHwb1157bYwcOTKeeeaZyu+tAaiJHN0OIMM+//zzePnll6O0tDQuvPDCXI8DOTNs2LBo06ZNvPrqq3H44Yen/esmANLFniSADDvttNPitddei/POOy9uuOGGvPsuCQDIN0oSAABAgv3cAAAACUoSAABAgpIEAACQoCQBAAAkKEkAAAAJShIANUrfvn3j1FNPrdbPdu3aNS6//PIqy0pLSyOVSsXy5cu/9WwA7ByUJADYBhUVFbFu3bpcjwFAFihJAOww5syZEyeeeGLUq1cv9tprr/jJT34Sy5Yti4iv90BNnTo17rjjjkilUpFKpWLRokVRUlISERF77LFHpFKp6Nu3b0REbNiwIW666aZo27Zt7LrrrtGlS5f4y1/+Upm1cQ/UpEmT4pBDDomioqJ46aWX4q233oqSkpKoX79+NGjQIA455JCYOXNm1rcFAJmjJAGwQ1i+fHl069YtDjrooJg5c2ZMnjw5Pv744/jRj34UERF33HFHHHnkkXH++efHkiVLYsmSJVFcXByPPPJIRETMmzcvlixZEnfccUdERNx0003xwAMPxOjRo+Of//xnXHHFFXHOOefE1KlTq+ReffXVMXz48Jg7d24ccMABcfbZZ0fLli3jtddei9dffz2uvvrqKCwszO7GACCjCnI9AABsi7vvvjsOOuiguPHGGyuXjR07NoqLi+Odd96JTp06Re3ataNu3brRrFmzyus0atQoIiKaNm0aDRs2jIiIsrKyuPHGG+PZZ5+NI488MiIi2rVrFy+99FLcd999cdxxx1X+/HXXXRcnnHBC5fkPPvggfvGLX8S+++4bEREdO3bM2G0GIDeUJAB2CG+99VZMmTIl6tWrt8llCxcujE6dOm3zuhYsWBBr166tUn4iIr766qs46KCDqiw79NBDq5wfNGhQ/PSnP43//d//je7du8cZZ5wR7du3345bAkBNpyQBsENYvXp1nHzyyXHzzTdvclnz5s23e10REU899VTsvffeVS4rKiqqcn633Xarcn7o0KHRp0+feOqpp2LSpElx7bXXxsSJE+O0007brhkAqLmUJAB2CAcffHA88sgj0aZNmygo2Pyfr9q1a8f69es3WRYRVZbvv//+UVRUFB988EGVt9Ztq06dOkWnTp3iiiuuiLPOOivGjRunJAHkEQduAKDGWbFiRcyaNavK6YILLojPPvsszjrrrHjttddi4cKF8fTTT0e/fv0qC1CbNm1i+vTpsWjRoli2bFls2LAhWrduHalUKp588sn45JNPYvXq1VG/fv0YPHhwXHHFFXH//ffHwoUL44033oi77ror7r///i3O9cUXX8Qll1wSpaWl8f7778fLL78cr732Wuy3337Z2jQAZIE9SQDUOKWlpZt8NmjAgAHx8ssvxy9/+cvo0aNHlJWVRevWraNXr16xyy5f/89v8ODBcd5558X+++8fX3zxRbz33nvRpk2bGDZsWFx99dXRr1+/OPfcc2P8+PFx/fXXR5MmTeKmm26Kd999Nxo2bBgHH3xwXHPNNVucq1atWvHpp5/GueeeGx9//HE0btw4Tj/99Bg2bFhGtwcA2ZWqqKioyPUQAAAANYW32wEAACQoSQAAAAlKEgAAQIKSBAAAkKAkAQAAJChJAAAACUoSAABAgpIEAACQoCQBAAAkKEkAAAAJShIAAECCkgQAAJDw/wFZtlzIKRMMtwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "we can see no correlation of ctyphertext diagram to plaintext as vigenere creates great confusion\n", "as plaintext gets longer vigenere with random key converges to uniform distribution among all letters\n" ] } ], "source": [ "import random\n", "import string\n", "\n", "## encryption functions\n", "def shift_enc(pt : str, key : int):\n", " return [chr((ord(letter) - ord('A') + key) % 26 + ord('A') ) for letter in pt]\n", "\n", "def perm_enc(pt : str, key : list[int]):\n", " ret = [\"a\" for i in range(0, len(pt)-1)]\n", " for from_idx, to_idx in enumerate(key):\n", " ret[to_idx] = pt[from_idx]\n", " return ret\n", "\n", "def vigenere_enc(pt : str, key : list[int]):\n", " pt_int = [ord(i) - ord('A') for i in pt]\n", " key_int = [ord(i) - ord('A') for i in key]\n", " \n", " ct_int = [(char + key) % 26 for char, key in zip(pt_int, key_int)]\n", " ct = [chr(i + ord('A')) for i in ct_int]\n", " return ct\n", "\n", "## keygen functions\n", "# generate random shift\n", "def keygen_shift():\n", " return random.randint(1,26)\n", "\n", "# generate random permutation from 0 upto len\n", "def keygen_perm(len : int):\n", " ret = [ i for i in range(0, len-1)]\n", " random.shuffle(ret)\n", " return ret\n", "\n", "# generate len random letters\n", "def keygen_vigenere(len : int):\n", " return [random.choice(string.ascii_uppercase) for i in range(0, len-1)]\n", "\n", "# shift cypher\n", "shift_k = keygen_shift()\n", "shift_ct = shift_enc(plaintext, shift_k)\n", "print(f\"with shift key: {shift_k}\")\n", "print(f\"we will get cyphertext: {shift_ct[:10]}...\")\n", "print(f\"with frequency diagram:\")\n", "freq_plot(shift_ct)\n", "print(f\"we can clearly see the same patterns just shifted by {shift_k}\\n\")\n", "\n", "# permutation cypher\n", "perm_k = keygen_perm(len(plaintext))\n", "perm_ct = perm_enc(plaintext, perm_k)\n", "print(f\"with permutation key: {perm_k[:10]}...\")\n", "print(f\"we will get cyphertext: {perm_ct[:10]}...\")\n", "print(f\"with frequency diagram:\")\n", "freq_plot(perm_ct)\n", "print(f\"we can see there is no change compared to the plaintext diagram as permutation does not create any confusion\\n\")\n", "\n", "# vigenere cypher\n", "vig_k = keygen_vigenere(len(plaintext))\n", "vig_ct = vigenere_enc(plaintext, vig_k)\n", "print(f\"with shift key: {vig_k[:10]}...\")\n", "print(f\"we will get cyphertext: {vig_ct[:10]}...\")\n", "print(f\"with frequency diagram:\")\n", "freq_plot(vig_ct)\n", "print(f\"we can see no correlation of ctyphertext diagram to plaintext as vigenere creates great confusion\")\n", "print(f\"as plaintext gets longer vigenere with random key converges to uniform distribution among all letters\")\n" ] }, { "cell_type": "markdown", "id": "41eda99e-472e-4207-9c9b-ec5516ed6d0a", "metadata": {}, "source": [ "- Analyse constructed diagrams and explain which properties help you to identify which encryption\n", "scheme was used." ] }, { "cell_type": "markdown", "id": "80fa07fa-b128-4466-8b30-27aa505414b2", "metadata": {}, "source": [ "- shift cypher TODO dodat kecy" ] }, { "cell_type": "markdown", "id": "03f965fa-e918-47fe-8706-09f6b6a19a80", "metadata": {}, "source": [ "### Task 3\n", "Assume you have used a time machine and you are back at Julius Caesar’s era. Now, you need\n", "to help Julius Caesar in selecting better ways for sending secret messages to his military units. You may\n", "select among the ones that have been discussed during this course up to Week 3 included (shift cipher,\n", "substitution cipher, permutation cipher, affine cipher, Vigenère cipher, OTP). Provide an explanation for your\n", "choice." ] }, { "cell_type": "markdown", "id": "0f8f2b3b-f8fd-4021-a7b6-4620dc2a5dab", "metadata": {}, "source": [ "### Task 4\n", "Suppose you intercepted the following ciphertext c = 00010010 00000111 11101010. You know\n", "that a 3-letter word was encrypted using one-time pad (to convert letters to binary strings ASCII table was\n", "used). Can you bruteforce possible keys and learn the message that was encrypted?" ] }, { "cell_type": "code", "execution_count": 73, "id": "60fc029e-b140-4d6f-ae7d-c84fc7b4bf94", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[18, 7, 234]\n" ] } ], "source": [ "ct = [0b00010010, 0b00000111, 0b11101010]\n", "\n", "def break_letter(idx : int)" ] }, { "cell_type": "code", "execution_count": null, "id": "fd36e999-99f9-4cc2-b6e4-47282d6c911a", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.6" } }, "nbformat": 4, "nbformat_minor": 5 }