diff --git a/TTM4135.ipynb b/TTM4135.ipynb index c4e2178..401bc1f 100644 --- a/TTM4135.ipynb +++ b/TTM4135.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -19,7 +19,7 @@ "5" ] }, - "execution_count": 14, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -92,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -340,8 +340,8 @@ "A generator of $Z_p^∗$ is an element of order $p − 1$\n", "\n", "To find a generator of $Z_p^∗$ we can choose a value g and test it as follows:\n", - "1. compute all the distinct prime factors of $p − 1$ and call them $f_1, f_2, ..., f_r$\n", - "2. then $g$ is a generator as long as $g^{\\frac{p−1}{f_i}} \\neq 1 \\mod(p)$ for $i = 1,2,,...,r$" + "1. Compute all the distinct prime factors of $p − 1$ and call them $f_1, f_2, ..., f_r$\n", + "2. Then $g$ is a generator as long as $g^{\\frac{p−1}{f_i}} \\neq 1 \\mod(p)$ for $i = 1,2,,...,r$" ] }, { @@ -547,7 +547,26 @@ "Sources:\n", "- https://stackoverflow.com/a/1832648/5976426\n", "- https://en.wikipedia.org/wiki/Baby-step_giant-step\n", - "- https://gist.github.com/0xTowel/b4e7233fc86d8bb49698e4f1318a5a73" + "- https://gist.github.com/0xTowel/b4e7233fc86d8bb49698e4f1318a5a73\n", + "\n", + "### Square and multiply\n", + "\n", + "Used to simplify doing large exponentiations. Instead of solving $3^5$ as $3*3*3*3*3$, \n", + "\n", + "1. Convert the exponent to Binary.\n", + "2. For the first $1$, simply list the number\n", + "3. For each ensuing $0$, do Square operation\n", + "4. For each ensuing $1$, do Square and Multiply operations\n", + "\n", + "Example:\n", + "```\n", + "5 = 101 in Binary\n", + "1 First One lists Number 3\n", + "0 Zero calls for Square (3)²\n", + "1 One calls for Square + Multiply ((3)²)²*3\n", + "```\n", + "\n", + "https://www.practicalnetworking.net/stand-alone/square-and-multiply/\n" ] }, { @@ -559,8 +578,74 @@ "name": "stdout", "output_type": "stream", "text": [ - "x = 2570\n", - "y = g^x mod p ==> 34 = 7324^2570 mod 4363\n", + "7894352216^(1) * 7894352216^(2) * 7894352216^(16) * 7894352216^(64) * 7894352216^(1024) * 7894352216^(8192) * 7894352216^(131072) * 7894352216^(2097152) * 7894352216^(33554432) * 7894352216^(67108864)\n", + "squarings: 26\n", + "mults: 9\n", + "\n", + "z = 7894352216^102900819 mod(604604729)\n", + "z = 355407489\n", + "\n", + "7894352216^102900819 mod(604604729) = 355407489\n" + ] + } + ], + "source": [ + "# Square and multiply\n", + "from math import log, floor\n", + "\n", + "def square_and_multiply(y,e,n, verbose=True):\n", + " # prep\n", + " e_bin = bin(e)[:1:-1] # e0, e1, e2, e3, ... , ek\n", + " k = len(e_bin)\n", + " z = 1\n", + " yi = y\n", + " indices = []\n", + " # -------------\n", + "\n", + " for i in range(k):\n", + " ei = int(e_bin[i])\n", + " if ei == 1:\n", + " z = z*yi % n\n", + " if ei < k:\n", + " yi = yi*yi % n\n", + " if ei:\n", + " indices.append(i)\n", + "\n", + " # post calc\n", + " mults = str(e_bin).count(\"1\") - 1\n", + " squarings = floor( log(e, 2) )\n", + " # -------------\n", + "\n", + " if verbose:\n", + " print(f\"{' * '.join([f'{y}^({2**i})' for i in indices])}\")\n", + " print(f\"squarings: {squarings}\")\n", + " print(f\"mults: {mults}\")\n", + " print()\n", + " print(f\"z = {y}^{e} mod({n})\")\n", + " print(f\"z = {z}\\n\")\n", + " return z\n", + "\n", + "# y^e mod(n)\n", + "y = 7894352216\n", + "e = 102900819\n", + "n = 604604729\n", + "\n", + "z = square_and_multiply(y,e,n, True)\n", + "\n", + "print(f\"{y}^{e} mod({n}) = {z}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x = 102900819\n", + "y = g^x mod p ==> 355407489 = 7894352216^102900819 mod 604604729\n", "Test: True\n" ] } @@ -591,16 +676,18 @@ " return None\n", "\n", "def disc_log_test(y, g, x, p):\n", - " return y == (g**x) % p\n", + " #return y == (g**x) % p\n", + " return y == square_and_multiply(g,x,p,False)\n", "\n", - "#y = 355407489\n", - "#g = 7894352216\n", - "#p = 604604729 # Must be prime\n", "\n", "# y = g^x mod p\n", - "y = 34\n", - "g = 7324\n", - "p = 4363 # Must be prime\n", + "y = 355407489\n", + "g = 7894352216\n", + "p = 604604729 # Must be prime\n", + "\n", + "#y = 34\n", + "#g = 7324\n", + "#p = 4363 # Must be prime\n", "\n", "x = bsgs(g, y, p)\n", "\n", @@ -608,8 +695,7 @@ "\n", "print(f\"y = g^x mod p ==> {y} = {g}^{x} mod {p}\")\n", "\n", - "# Don't run the test with big numbers!\n", - "if x<10000: print(f\"Test: {disc_log_test(y,g,x,p)}\")" + "print(f\"Test: {disc_log_test(y,g,x,p)}\")" ] }, { @@ -624,34 +710,8 @@ "- `C`: Ciphertext block (length n bits) \n", "- `K` : Key (length k bits)\n", "- `C = E(P, K)`: Encryption function \n", - "- `P = D(C, K)`: Decryption function" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n", - "54\n" - ] - } - ], - "source": [ - "# Discarded code\n", - "\n", - "def z(n):\n", - " return [i for i in range(n)]\n", - "print(z(10))\n", - "\n", - "n = 81\n", - "zn = z(n)\n", - "rel_primes = list(filter(lambda x: is_relative_prime(x,n), zn))\n", - "print(len(rel_primes))" + "- `P = D(C, K)`: Decryption function\n", + "- `IV`: Initialisation vector" ] } ],