|
|
@ -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" |
|
|
|
] |
|
|
|
} |
|
|
|
], |
|
|
|