{
"cells": [
{
"cell_type": "markdown",
"id": "7870e6da",
"metadata": {},
"source": [
"## RSA kriptosistem"
]
},
{
"cell_type": "markdown",
"id": "201873d5",
"metadata": {},
"source": [
"RSA kriptosistem bomo predstavili v Pythonovskem zvezku. Seveda potrebujemo nekaj dodatnih orodij."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "edcc71c7",
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from sympy import prime\n",
"from sympy.ntheory import ecm\n",
"from sympy.ntheory import totient\n",
"from random import randint"
]
},
{
"cell_type": "markdown",
"id": "eb499fff",
"metadata": {},
"source": [
"_prime_? praštevilo\n",
"\n",
"_ecm_? praštevilski razcep \n",
"\n",
"_totient_? Eulerjeva funkcija, alternativno ime\n",
"\n",
"_randint_? slučajno število"
]
},
{
"cell_type": "markdown",
"id": "0d4ff21e",
"metadata": {},
"source": [
"### Dve veliki praštevili"
]
},
{
"cell_type": "markdown",
"id": "aeca405b",
"metadata": {},
"source": [
"Radi bi poiskati dve primerljivo veliki praštevili.\n",
"Primerljivo veliki? Skoraj isto število binarnih/decimalnih mest."
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "ac6b78cb",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"22801763489\n",
"18054236957\n"
]
}
],
"source": [
"p = prime(1000000000)\n",
"q = prime(800000000)\n",
"print(p)\n",
"print(q)"
]
},
{
"cell_type": "markdown",
"id": "bbfadfae",
"metadata": {},
"source": [
"Produkt praštevil *p* in *q* označimo z *n*."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "010fdab5",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"411668441067877062973\n"
]
}
],
"source": [
"n = p*q\n",
"print(n)"
]
},
{
"cell_type": "markdown",
"id": "d613f26f",
"metadata": {},
"source": [
"### Eulerjeva funkcija"
]
},
{
"cell_type": "markdown",
"id": "df4c0906",
"metadata": {},
"source": [
"S *phi* označimo Eulerjevo funkcijo števila *n = p q*.\n",
"Ker poznamo praštevilski razcep števila *n* je naloga otročje lahka."
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "45be81fe",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"411668441027021062528\n"
]
}
],
"source": [
"phi = (p-1)*(q-1)\n",
"print(phi)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "c909a79f",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{18054236957, 22801763489}"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ecm(n)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "a598df95",
"metadata": {},
"outputs": [
{
"data": {
"text/latex": [
"$\\displaystyle 411668441027021062528$"
],
"text/plain": [
"411668441027021062528"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"totient(n)"
]
},
{
"cell_type": "markdown",
"id": "f2a0bb48",
"metadata": {},
"source": [
"Naše število je dovolj majhno, da zna njegov razcep oziroma Eulerjevo funkcijo izračunati tudi Python. To pomeni, da naši ključi v tem zgledu nikakor niso varni!"
]
},
{
"cell_type": "markdown",
"id": "ea5df9bd",
"metadata": {},
"source": [
"### Konstrukcija javnega in privatnega ključa"
]
},
{
"cell_type": "markdown",
"id": "eb6ec424",
"metadata": {},
"source": [
" Izberimo si poljubno število *d*, manjše od *phi*, ki je **tuje** *phi*. Poskusimo s slučajnim številom."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "7458e708",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"88859890694783175795\n",
"1\n"
]
}
],
"source": [
"d = randint(1,n)\n",
"print(d)\n",
"print(math.gcd(d, phi))"
]
},
{
"cell_type": "markdown",
"id": "9102d0cb",
"metadata": {},
"source": [
"\n",
"Par *(n,d)* je Borutov privatni ključ."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "a04fcb3d",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(411668441067877062973, 88859890694783175795)"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(n,d)"
]
},
{
"cell_type": "markdown",
"id": "1b4968b5",
"metadata": {},
"source": [
"Določimo naravno število *e*, ki reši diofansko enačbo: *e d = 1 + k phi*. Ker sta _d_ in _phi_ tuji števili, je ta LDE rešljiva.\n",
"\n",
"Z drugimi besedami, produkt *e d* je po modulu *phi* kongruenten *1*. "
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "babcf65a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"275253687879854124347\n"
]
}
],
"source": [
"e = pow(d, -1, phi)\n",
"print(e)"
]
},
{
"cell_type": "markdown",
"id": "1fff66c1",
"metadata": {},
"source": [
"Tole zgoraj je trik. Iskali smo _inverz_ k _d_ za množenje po modulu _phi_. \n",
"\n",
"Preverimo."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "5aa7be22",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"e * d % phi"
]
},
{
"cell_type": "markdown",
"id": "322ffdcc",
"metadata": {},
"source": [
"Par (n,e) je Borutov javni ključ."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "8b152963",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(411668441067877062973, 275253687879854124347)"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"(n,e)"
]
},
{
"cell_type": "markdown",
"id": "4746a426",
"metadata": {},
"source": [
"Zelo pomembno se je znebiti števila *phi*.\n",
"Ravno tako moramo paziti, da nihče ne more do privatnega ključa."
]
},
{
"cell_type": "markdown",
"id": "4d1f05f2",
"metadata": {},
"source": [
"### Prenos kriptiranih podatkov"
]
},
{
"cell_type": "markdown",
"id": "9d16bc77",
"metadata": {},
"source": [
"\n",
"Ančka bi rada Borutu poslala sporočilo."
]
},
{
"cell_type": "markdown",
"id": "d52aa250",
"metadata": {},
"source": [
"Sporočilo, ki ga Ančka počilja Borutu mora biti kratko. Manjše od *n*. To ne predstavlja nobenega problema. Če je sporočilo daljše, ga Ančka lahko razseka na ustrezno kratke dele."
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "8586a54c",
"metadata": {},
"outputs": [],
"source": [
"sporocilo = 12345678987654321"
]
},
{
"cell_type": "markdown",
"id": "0377d625",
"metadata": {},
"source": [
" Sporočilo Ančka zaklene z Borutovim javnim ključem.\n",
" Potencira ga na potenco *e* in določi ostanek pri deljenju z *n*."
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "054a4091",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"362266224501015323438\n"
]
}
],
"source": [
"zaklenjenosporocilo = pow(sporocilo,e,n)\n",
"print(zaklenjenosporocilo)"
]
},
{
"cell_type": "markdown",
"id": "9c01b100",
"metadata": {},
"source": [
" Zaklenjeno sporočilo lahko pošlje Borutu po nezavarovanem kanalu. Odklene ga lahko samo Borut."
]
},
{
"cell_type": "markdown",
"id": "0d4c1df4",
"metadata": {},
"source": [
" Borut sporočilo odklene s svojim privatnim ključem. Potencira ga na potenco *d* in določi ostanek pri deljenju z *n*."
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "d603e600",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"12345678987654321\n"
]
}
],
"source": [
"odklenjenosporocilo = pow(zaklenjenosporocilo,d,n)\n",
"print(odklenjenosporocilo)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "9f752937",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sporocilo == odklenjenosporocilo"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4f3e2610",
"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.8.15"
}
},
"nbformat": 4,
"nbformat_minor": 5
}