Add Miller-Rabin
This commit is contained in:
parent
2f78cfe3f1
commit
abe2ae2f80
111
TTM4135.ipynb
111
TTM4135.ipynb
|
@ -46,7 +46,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -245,14 +245,14 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"1105 is composite\n"
|
||||
"1105 is probable prime\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
@ -283,21 +283,93 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Miller-Rabin\n",
|
||||
"n = 137\n",
|
||||
"k = 20\n",
|
||||
"## Miller-Rabin\n",
|
||||
"From https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test \n",
|
||||
"This test is not fooled by Charmichael numbers.\n",
|
||||
"\n",
|
||||
"To test `n`, you choose different `a` values, and test if \n",
|
||||
"\n",
|
||||
"> $a^{d*2^i} \\equiv 1 \\pmod{n}$ for $i = (0, 1, 2, ... r)$\n",
|
||||
"\n",
|
||||
"If this happens, look at the congruence on the calculation just before you got `1`. If that value is not -1 (aka n-1), the value is composite aka not prime."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"168 = 21*2^3 = 168\n",
|
||||
"65536 = 1*2^16 = 65536\n",
|
||||
"\n",
|
||||
"16127 is probably prime.\n",
|
||||
"561 is composite.\n",
|
||||
"2465 is composite.\n",
|
||||
"65537 is probably prime.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Miller-Rabin primality test\n",
|
||||
"# This test is not fooled by Charmichael numbers.\n",
|
||||
"\n",
|
||||
"from math import log2, floor\n",
|
||||
"from random import randint\n",
|
||||
"def miller_rabin(n):\n",
|
||||
" for O in range(k):\n",
|
||||
" d = n-1\n",
|
||||
" a = randint(2,n-2)\n",
|
||||
" x = (a**d) % "
|
||||
"\n",
|
||||
"def decompose_even_number(n):\n",
|
||||
" '''Find the values r and d such that n == d * 2**r.'''\n",
|
||||
" r = 0\n",
|
||||
" d = n\n",
|
||||
" for i in range(1, floor(log2(n)) + 1):\n",
|
||||
" if (d/2).is_integer():\n",
|
||||
" d = d/2\n",
|
||||
" r += 1\n",
|
||||
" else:\n",
|
||||
" break\n",
|
||||
" return (r, int(d))\n",
|
||||
"\n",
|
||||
"verbose = False # Print during execution\n",
|
||||
"\n",
|
||||
"def miller_rabin_prime(n):\n",
|
||||
" ''':param n: should be odd, and n>3. No primes can be even, for obvious reasons.'''\n",
|
||||
" accuracy = 3 # How many different `a` to test\n",
|
||||
" r, d = decompose_even_number(n-1) # n is odd, thus n-1 is even\n",
|
||||
" verbose and print(f\"Testing {n} a maximum of {accuracy} times...\")\n",
|
||||
" \n",
|
||||
" for _ in range(accuracy):\n",
|
||||
" try:\n",
|
||||
" a = randint(2, n-2) # The \"witness\". TODO: don't reuse a witness.\n",
|
||||
" verbose and print(f\"\\tTesting {n} with a={a}\")\n",
|
||||
"\n",
|
||||
" x = (a**d) % n\n",
|
||||
" if x == 1 or x == n-1:\n",
|
||||
" verbose and print(f\"\\t({a}**{d})%{n} was 1 or -1 already!\")\n",
|
||||
" continue # This witness was immediately 1 or -1 (aka n-1), so it can't help us any more.\n",
|
||||
" for squaring in range(r-1):\n",
|
||||
" x = (x**2) % n\n",
|
||||
" verbose and print(f\"\\tx={x}\")\n",
|
||||
" if x == n-1:\n",
|
||||
" raise Exception(\"Try next witness\") # This witness can't help any more.\n",
|
||||
" return \"composite\" # The witness didnt uphold the criteria for a prime, so n is composite!\n",
|
||||
" except Exception as tryNext:\n",
|
||||
" continue\n",
|
||||
" return \"probably prime\"\n",
|
||||
" \n",
|
||||
"s, d = decompose_even_number(168)\n",
|
||||
"print(f\"168 = {d}*2^{s} = {d*(2**s)}\")\n",
|
||||
"s, d = decompose_even_number(65536)\n",
|
||||
"print(f\"65536 = {d}*2^{s} = {d*(2**s)}\")\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"for value in [16127, 561, 2465, 65537]:\n",
|
||||
" print(f\"{value} is {miller_rabin_prime(value)}.\")\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -371,7 +443,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"execution_count": 35,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
@ -446,13 +518,6 @@
|
|||
"- `P = D(C, K)`: Decryption function"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
|
@ -501,5 +566,5 @@
|
|||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue