This commit is contained in:
Ondrej Hladuvka 2025-05-21 21:12:35 +03:00
parent e5d8cd6214
commit b8056c084c
4 changed files with 987 additions and 0 deletions

547
hw3/Homework 2.ipynb Normal file
View File

@ -0,0 +1,547 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "421d5e4d-1327-449b-8aae-16cb1c99cb60",
"metadata": {},
"source": [
"Ondřej Hladůvka \n",
"\n",
"If you want to run code in this notebook, you can find it here: https://git.hladu.xyz/hladu357/TalTech_crypt/src/branch/master/hw2"
]
},
{
"cell_type": "markdown",
"id": "0ed8045c-d080-4288-909a-9190433d6a09",
"metadata": {},
"source": [
"## Task 1 Confusion and diffusion\n",
"From the lectures, you learned about importance of confusion and diffusion principles for the block ciphers. Let us examine them in more details. Assume you need to analyse\n",
"properties of Vigenere cipher."
]
},
{
"cell_type": "markdown",
"id": "c8eedd35-16bd-433d-b161-b1e9c7a26c19",
"metadata": {},
"source": [
"1. Encrypt message THEWANDCHOOSESTHEWIZARD with key MAGIC."
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "47aba105-8f9d-40eb-a5ed-5f93bbe63b86",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ciphertext: FHKECZDIPQASKAVTECQBMRJ\n"
]
}
],
"source": [
"def vigenere_enc(pt : str, key : str):\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_int[idx % len(key_int)]) % 26 for idx, char in enumerate(pt_int)]\n",
" ct = [chr(i + ord('A')) for i in ct_int]\n",
" return ct\n",
"\n",
"pt = \"THEWANDCHOOSESTHEWIZARD\"\n",
"key = \"MAGIC\"\n",
"ct = vigenere_enc(pt, key)\n",
"\n",
"print(\"ciphertext: \", \"\".join(ct))"
]
},
{
"cell_type": "markdown",
"id": "60d515f1-5951-4743-8286-4b41018fabc4",
"metadata": {},
"source": [
"2. Suppose we change one letter (W becomes L) in the plaintext to get THEWANDCHOOSESTHE L IZARD.\n",
"How may letters of the ciphertext are changed? Is the diffusion property achieved?"
]
},
{
"cell_type": "code",
"execution_count": 26,
"id": "3c55e9ad-dd9f-48ee-b4fe-064dacb0706a",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Witch changed plaintext at index 17\n",
"New ciphertext is: FHKECZDIPQASKAVTERQBMRJ\n",
"character changes at index 17 C -> R\n",
"diffusion is not achieved, as the plaintext's change effects the ciphertext in structured way exploitable by cryptanalysis\n"
]
}
],
"source": [
"idx = 17\n",
"pt2 = pt[:idx] + \"L\" + pt[(idx + 1):]\n",
"ct2 = \"\".join(vigenere_enc(pt2, key))\n",
"\n",
"print(f\"Witch changed plaintext at index {idx}\")\n",
"print(f\"New ciphertext is: {ct2}\")\n",
"\n",
"for idx, (a, b) in enumerate(zip(ct, ct2)):\n",
" if (a != b):\n",
" print(f\"character changes at index {idx} {a} -> {b}\")\n",
"print(\"diffusion is not achieved, as the plaintext's change effects the ciphertext in structured way exploitable by cryptanalysis\")"
]
},
{
"cell_type": "markdown",
"id": "47b5e048-9f0a-4436-8294-fcba9fca489e",
"metadata": {},
"source": [
"3. Suppose we change one letter in key (G becomes N). How may letters of the ciphertext are changed?\n",
"Is confusion property achieved?"
]
},
{
"cell_type": "code",
"execution_count": 27,
"id": "c89a36d4-6c24-4ca3-84c5-bafea87073c3",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"it would change lower whole part n / k letters where n is length of plaintext and k is length of the key\n",
"floor(n / k) = floor(23 / 5) = 4\n",
"confusion is not achieved, as the key's effect on the ciphertext is structured and exploitable by cryptanalysis\n"
]
}
],
"source": [
"import math\n",
"print(\"it would change lower whole part n / k letters where n is length of plaintext and k is length of the key\")\n",
"n = len(pt)\n",
"k = len(key)\n",
"print(f\"floor(n / k) = floor({n} / {k}) = {math.floor(n/k)}\")\n",
"print(\"confusion is not achieved, as the key's effect on the ciphertext is structured and exploitable by cryptanalysis\")"
]
},
{
"cell_type": "markdown",
"id": "1b4e0abb-fbcb-4019-9c4d-c8486d7c3884",
"metadata": {},
"source": [
"## Task 2. Pseudorandom function \n",
"Let F {0, 1}\n",
"n × {0, 1}\n",
"n → {0, 1}\n",
"n\n",
"be a secure PRF. Do the following\n",
"functions satisfy definition of pseudo-random function?"
]
},
{
"cell_type": "markdown",
"id": "3dc36d9b-46b1-4222-bd16-19b68356dd6a",
"metadata": {},
"source": [
"1. F(k, m) = F(k, m) || 0^n, where 0^n is a zero string of length n"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "bd6cd25a-944c-4844-a82d-601c27a17a80",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Adversary with strategy that guesses its not oraculum if last n bits of the message are all zeros\n",
"can be wrong only if oraculum, was used (1/2 chance) and it generated last last n bits of the message all zeros (2^-n)\n",
"Chance of this is 2 to the power of minus (message length + 1)\n",
"With growing n, this function converges to 0 -> F' is not secure PRF\n",
"\n",
"\n",
"We can simulate this, assumming python random is close enough to random oraculum\n",
"For message 4 characters long, its only a 0.0625 chance\n",
"but only if random oracle is selected so times 0.5 -> 0.03125 chance\n",
"adverasry got response: [1, 1, 1, 1, 0, 0, 0, 0]\n",
"he guessed it is not oraculum - its False\n",
"\n",
"adverasry got response: [0, 1, 0, 0, 0, 0, 0, 0]\n",
"he guessed it is not oraculum - its True\n",
"\n",
"adverasry got response: [0, 0, 1, 0, 0, 0, 0, 0]\n",
"he guessed it is not oraculum - its True\n",
"\n",
"adverasry got response: [1, 1, 1, 0, 0, 0, 0, 0]\n",
"he guessed it is not oraculum - its True\n",
"\n",
"adverasry got response: [0, 0, 0, 1, 0, 0, 0, 0]\n",
"he guessed it is not oraculum - its True\n",
"\n",
"adverasry got response: [1, 1, 0, 0, 0, 1, 0, 0]\n",
"he guessed it is oraculum - its True\n",
"\n",
"we can meassure the prediction:\n",
"adversary passed 971 out of 1000 tests, which is 0.029 chance of failure\n"
]
}
],
"source": [
"# no efficient algorithm can distinguish (with significant advantage)\n",
"# between a function chosen randomly from the PRF family and a random oracle\n",
"import random\n",
"import string\n",
"msg_len = 4\n",
"\n",
"def prf1(input):\n",
" return [random.randint(0, 1) for _ in range(len(input))] + [0] * len(input)\n",
"\n",
"def challenger1(input):\n",
" if (random.choice([True, False])): # random oracle\n",
" return [random.randint(0, 1) for _ in range(len(input) * 2)], True\n",
" else: # tested function\n",
" return prf1(input), False\n",
"\n",
"words = [\"abcd\", \"efgh\", \"ijkl\", \"mnop\", \"qrst\", \"uvwx\"]\n",
"def adversary1(w, verbose=True):\n",
" response = challenger1(w)\n",
" if verbose: print(f\"adverasry got response: {response[0]}\")\n",
" \n",
" if all(x == 0 for x in response[0][len(w):]):\n",
" if verbose: print(f\"he guessed it is not oraculum - its {response[1] == False}\\n\")\n",
" return response[1] == False\n",
" else:\n",
" if verbose: print(f\"he guessed it is oraculum - its {response[1] == True}\\n\")\n",
" return response[1] == True\n",
"\n",
"\n",
"print(\"Adversary with strategy that guesses its not oraculum if last n bits of the message are all zeros\")\n",
"print(\"can be wrong only if oraculum, was used (1/2 chance) and it generated last last n bits of the message all zeros (2^-n)\")\n",
"print(\"Chance of this is 2 to the power of minus (message length + 1)\")\n",
"print(\"With growing n, this function converges to 0 -> F' is not secure PRF\\n\\n\")\n",
"\n",
"chance = pow(2,-msg_len)\n",
"print(f\"We can simulate this, assumming python random is close enough to random oraculum\")\n",
"print(f\"For message {msg_len} characters long, its only a {chance} chance\")\n",
"print(f\"but only if random oracle is selected so times 0.5 -> {chance/2} chance\")\n",
"\n",
"for w in words:\n",
" adversary1(w)\n",
"\n",
"tests = 1000\n",
"passed = 0\n",
"print(f\"we can meassure the prediction:\")\n",
"for i in range(0, tests):\n",
" msg = ''.join(random.choices(string.ascii_lowercase, k=msg_len))\n",
" passed += adversary1(msg, False)\n",
"\n",
"print(f\"adversary passed {passed} out of {tests} tests, which is {round(1 - (passed / tests),5)} chance of failure\")"
]
},
{
"cell_type": "markdown",
"id": "06d4358a-0216-457a-ab08-3662f1999b89",
"metadata": {},
"source": [
"2. F(k, mm) = F(k, m)F(k, m ⊕ 0^n), where 0^n is a zero string of length n"
]
},
{
"cell_type": "markdown",
"id": "f99e71fa-a4e2-4396-8072-9621b40700fc",
"metadata": {},
"source": [
"Since x ⊕ 0 = x, we can simplify\n",
"F' := F(k, mm) = F'(k, m)F'(k, m)\n",
"\n",
"With startegy: \n",
"choose message x\n",
"x = a^n (where n is power of 2)\n",
"\n",
"get message y \n",
"if message is repeating bit => adversary guess its not oraculum \n",
"y = F'(a^(n/2) || F'(a^(n/2)) = F'(a^(n/4)) || F'(a^(n/4)) || F'(a^(n/4)) || F'(a^(n/4)) = ... = F'(a)^n\n",
"\n",
"else => guess its oraculum\n",
"\n",
"Only way adversary could be wrong if oraculum generated n repeating bits, chance of this is 2^(-n) \n",
"With growing n, this function converges to 0 -> F' is not secure PRF"
]
},
{
"cell_type": "markdown",
"id": "fc89bafe-990c-4a05-9bd4-1c86075f4fcd",
"metadata": {},
"source": [
"3. F(k, mm) = F(k, 0m) ⊕ F(k, m1), where m, m∈ {0, 1}^(n1)"
]
},
{
"cell_type": "markdown",
"id": "7fccba29-9283-448a-83e5-0a9e1dca8864",
"metadata": {},
"source": [
"With startegy:\n",
"querying two messages x_1, x_2 \n",
"x_1 = 0^(n-1)||0^(n-1) \n",
"x_2 = 0^(n-1)||1^(n-1) \n",
" \n",
"get messages y_1, y_2 \n",
"\n",
"\n",
"if y_1 ⊕ y_2 == 0^n => adversary guess its not oraculum \n",
"y_1 ⊕ y_2 = (F(k,0||0^(n1)) ⊕ F(k,0^(n1)||1)) ⊕ (F(k,0||0^(n1)) ⊕ F(k,1^(n1||1)) \n",
"y_1 ⊕ y_2 = F(k,0||1^(n1)) ⊕ F(k,1^(n1||1) \n",
" \n",
"else => guess its oraculum \n",
" \n",
"chance of two random oraculum outputs being inverse (y_1 ⊕ y_2 == 0^n) is 2^(-n) \n",
"With growing n, this function converges to 0 -> F' is not secure PRF"
]
},
{
"cell_type": "markdown",
"id": "e62ff1ca-3ea5-4f08-9b2d-286966f45a7e",
"metadata": {},
"source": [
"## Task 3\n",
"Output feedback mode Consider the following permutation cipher instead of permuting plaintext letters to get ciphertext, you are first required to convert plaintext letters to binary form and next you\n",
"permute bits according to the key. Letter H becomes encrypted to T with key (5, 1, 2, 4, 3). Let us view it as\n",
"block cipher with block length 5 bits."
]
},
{
"cell_type": "code",
"execution_count": 29,
"id": "9ca5e5f2-19ae-4d1d-aad1-eecc6b9d07e3",
"metadata": {},
"outputs": [],
"source": [
"def perm_enc(pt: list[int], key: list[int]):\n",
" blocksize = 5\n",
" ct = [0] * blocksize\n",
" for idx in range(0, blocksize):\n",
" ct[idx] = pt[key[idx] - 1]\n",
" return ct\n",
"\n",
"def convert_str(pt: list[int]): # converts to list of binary blocks\n",
" bit_array = []\n",
" for char in pt:\n",
" bits = bin(ord(char) - ord('A'))[2:][-5:].zfill(5)\n",
" bit_array.append([int(bit) for bit in bits])\n",
" return bit_array\n",
"\n",
"def ofb(pt, key, iv, cipher):\n",
" ct = []\n",
" for block in pt:\n",
" iv = cipher(iv, key)\n",
" ct.append([x ^ y for (x,y) in zip(iv, block)]) # encrypted iv into block\n",
" return ct\n",
"\n",
"key = [5, 1, 2, 4, 3]"
]
},
{
"cell_type": "markdown",
"id": "95d3d5f0-26cc-4adf-ba2f-3e19aac52174",
"metadata": {},
"source": [
"1. Encrypt world DOG with key (4, 1, 3, 5, 2) using permutation cipher in OFB mode with iv = 01011. Leave\n",
"result as a binary string."
]
},
{
"cell_type": "code",
"execution_count": 30,
"id": "63f150c4-cefc-4288-9568-6c0ed4963d7b",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"plaintext: [[0, 0, 0, 1, 1], [0, 1, 1, 1, 0], [0, 0, 1, 1, 0]]\n",
"ciphertext: [[1, 0, 0, 0, 0], [1, 0, 1, 0, 0], [1, 1, 1, 1, 1]]\n"
]
}
],
"source": [
"pt = convert_str(['D', 'O', 'G'])\n",
"key = [4, 1, 3, 5, 2]\n",
"iv = [0, 1, 0, 1, 1]\n",
"ct = ofb(pt, key, iv, perm_enc)\n",
"print(f\"plaintext: {pt}\")\n",
"print(f\"ciphertext: {ct}\")"
]
},
{
"cell_type": "markdown",
"id": "2e92ea0e-ccab-4eb7-bb0d-5f325fcd8e77",
"metadata": {},
"source": [
"2. Flip 5-th bit of received ciphertext (0 becomes 1 and vice versa). Now decrypt modified ciphertext. How\n",
"many bits in the plaintext get changed?"
]
},
{
"cell_type": "code",
"execution_count": 31,
"id": "ae47fd93-809c-4e03-b565-3d1ebb8f4b42",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"original ciphertext: [[1, 0, 0, 0, 0], [1, 0, 1, 0, 0], [1, 1, 1, 1, 1]]\n",
"modified ciphertext: [[1, 0, 0, 0, 1], [1, 0, 1, 0, 0], [1, 1, 1, 1, 1]]\n",
"original plaintext: [[0, 0, 0, 1, 1], [0, 1, 1, 1, 0], [0, 0, 1, 1, 0]]\n",
"modified plaintext: [[0, 0, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 1, 1, 0]]\n",
"one bit also flipped -> no diffusion\n"
]
}
],
"source": [
"import copy\n",
"ct2 = copy.deepcopy(ct)\n",
"ct2[0][4] ^= 1\n",
"pt2 = ofb(ct2, key, iv, perm_enc)\n",
"\n",
"print(f\"original ciphertext: {ct}\")\n",
"print(f\"modified ciphertext: {ct2}\")\n",
"print(f\"original plaintext: {pt}\")\n",
"print(f\"modified plaintext: {pt2}\")\n",
"print(f\"one bit also flipped -> no diffusion\")"
]
},
{
"cell_type": "markdown",
"id": "dd8b801d-8bcc-49dc-8ad1-b0d54ce62959",
"metadata": {},
"source": [
"3. Flip the first bit of the IV iv = 11011, decrypt ciphertext from Step 1 with iv\n",
". How many bits in the\n",
"plaintext get changed?"
]
},
{
"cell_type": "code",
"execution_count": 32,
"id": "a358aa91-7e8a-4ada-82f0-58fdb7aa30a9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"original plaintext: [[0, 0, 0, 1, 1], [0, 1, 1, 1, 0], [0, 0, 1, 1, 0]]\n",
"modified plaintext: [[0, 1, 0, 1, 1], [0, 1, 1, 1, 1], [0, 0, 1, 0, 0]]\n",
"one bit per block also flipped\n"
]
}
],
"source": [
"iv[0] ^= 1\n",
"pt3 = ofb(ct, key, iv, perm_enc)\n",
"\n",
"print(f\"original plaintext: {pt}\")\n",
"print(f\"modified plaintext: {pt3}\")\n",
"print(f\"one bit per block also flipped\")"
]
},
{
"cell_type": "markdown",
"id": "fc3e1681-f07b-4546-bc30-688753fcbd53",
"metadata": {},
"source": [
"## Task 4\n",
"Consider the encryption of nblock message m = m1m2. . .m_n by some block cipher E in\n",
"CFB mode. Let use denote ciphertext produced by E as c = c1c2. . .cn. Show which information about\n",
"the plaintext can be extracted if we get a collision: ci = cj\n",
", where i ≠ j."
]
},
{
"cell_type": "markdown",
"id": "7134ee9b-fcc0-4d6e-a240-208707160694",
"metadata": {},
"source": [
"#### In OFB mode: \n",
"Ek(iv)^n := Ek( Ek( ... Ek(iv))) n times\n",
"ct_n = pt_n ⊕ Ek(iv)^n\n",
"\n",
"ct_i == ct_j implies => \n",
"Ek(iv)^i == Ek(iv)^j => \n",
"pt_i ⊕ pt_j == Ek(iv)^(i-1) ⊕ Ek(iv)^(j-1)"
]
},
{
"cell_type": "markdown",
"id": "7e65fe31-62e3-4c6c-a7a8-e29ee8dc9e57",
"metadata": {},
"source": [
"## Task 5\n",
"Show that Pigpen cipher defined below is not IND-OT-CPA secure (where adversary is allowed to\n",
"do only one query to the challenger in the IND-CPA game).\n",
"The pigpen cipher uses graphical symbols assigned according to a key in the diagram below1\n",
"(NOTE: Positions\n",
"of the letters in the diagrams are random and not known to adversary):"
]
},
{
"cell_type": "markdown",
"id": "296118e7-4df4-451f-8b27-9a317c04d362",
"metadata": {},
"source": [
"#### Indistinguishability under One-Time Chosen Plaintext Attack definition:\n",
"1. The challenger generates a secret key K\n",
"2. The adversary submits two distinct plaintexts Pt_0, Pt_1 of equal length to the challenger\n",
"3. The challenger selects a random bit b ∈ {0,1}, resulting in ciphertext Ct = Ek(M_b) being sent to the adversary\n",
"4. Based on the Ct, the adversary guess b ∈ {0,1} for the value of b\n",
"5. Scheme is not secure if no adversary has a non-negligible advantage in guessing over 1/2\n",
"\n",
"#### Adversary strategy:\n",
"We can expoit Pigpen cipher being monoalphabetic\n",
"Adversary will send one message with repeating characters and another with each character unique \n",
"M_0 := \"AA\" \n",
"M_1 := \"AB\" \n",
"\n",
"If Ct is some repeating characters => choose 0 \n",
"Else => choose 1 \n",
"\n",
"This strategy will work every time thanks to monoalphabeticity"
]
}
],
"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
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 KiB

435
hw3/homework 3.ipynb Normal file
View File

@ -0,0 +1,435 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "04af88ae-4585-44f4-8a6b-e54ef1b369fc",
"metadata": {},
"source": [
"Ondřej Hladůvka"
]
},
{
"cell_type": "markdown",
"id": "81c9f10b-5df5-4187-9be5-913c536fdb27",
"metadata": {},
"source": [
"# Task 1\n",
"You are working in the company that uses RSA cryptosystem in their solutions.\n",
"You have been sent the following abstract for the scientific paper. Based on this, would your recommendation to your company and why? \n",
"<img src=\"Screenshot_11-Apr_12-46-16_5589.png\" width=\"400\" height=\"200\">"
]
},
{
"cell_type": "markdown",
"id": "19cec4fd-90ac-4255-9add-9a48879f5b89",
"metadata": {},
"source": [
"RSA key generation: \n",
"let $p,q$ be large primes \n",
"$n := p \\times q$ \n",
"let $e$ be integer $1 < e < \\text{Lcm}(\\varphi(p, q))$ \n",
"$d := e^{-1} \\pmod{\\varphi(n)}$ \n",
"\n",
"Private key := $(d, n)$ \n",
"Public key := $(e, n)$ \n",
"\n",
"------------------------------------\n",
"\n",
"It is correct that $\\varphi(n)$ for public $n$ is used to generate $d$ (using EEA), so attacker able to compute it could break an encryption.\n",
"\n",
"Another thing that attacker could do knowing $n$ and $\\varphi(n)$ is to compute primes $p, q$:\n",
"$$\n",
"\\varphi(n) = \\varphi(p \\times q) = (p-1)(q-1) = p \\times q - p - q + 1 = (n+1)-(p+q)\n",
"$$\n",
"$$\n",
"\\Rightarrow p+q = (n+1)-\\varphi(n)\n",
"\\,\\,\\,\\,\\, \\land \\,\\,\\,\\,\\,\n",
"p \\times q = n\n",
"$$\n",
"$$\n",
"\\Rightarrow p+q -(n+1)+\\varphi(n) = 0\n",
"\\,\\,\\,\\,\\, \\land \\,\\,\\,\\,\\,\n",
"p \\times q - n = 0\n",
"$$\n",
"this forms system of equations, \n",
"lets substitute $p := (n+1)-\\varphi(n) - q$:\n",
"$$\n",
"((n+1)-\\varphi(n) - q) \\times q - n = 0\n",
"$$\n",
"Solving for $q$:\n",
"$$\n",
"q = \\frac{n}{(n+1)-\\varphi(n)-q}\n",
"$$\n",
"$$\n",
"p = \\frac{n}{q} \\text{ (where } p \\text{ and } q \\text{ can be swapped)}\n",
"$$\n",
"\n",
"This proves that factorization of $n$ is trivial when $\\varphi(n)$ is known, thus computing $\\varphi(n)$ has to be at least as difficult as computing factorization of $n$\n",
"\n",
"And when we know primes $p$ and $q$, computing $\\varphi(n)$ is just $(p-1)(q-1)$ $\\Rightarrow$ computing $\\varphi(n)$ is as difficult as computing factorization of $n$ \n",
" \n",
"#### I would not make any change based on this arcicle, as RSA is based on diffclty of computing $\\varphi(n)$"
]
},
{
"cell_type": "markdown",
"id": "5748beac-4e59-4211-aa41-8175b332bef4",
"metadata": {},
"source": [
"# Task 2\n",
"Suppose you are given the following encryption scheme: \n",
"$KeyGen()$\n",
"1. Sample large prime number $p$\n",
"2. Compute modulus as $n := p^2$\n",
"3. Select $e$ to be integer such that \n",
"$Gcd(\\varphi(n), e) = 1 \n",
"\\,\\,\\,\\,\\, \\land \\,\\,\\,\\,\\,\n",
"2 < e < \\varphi(n)$\n",
"4. Calculate $d$ such that $e \\times d ≡ 1 \\, mod \\, \\varphi(n)$\n",
"5. Return private key $Sk := (d, n)$ and \n",
" public key $Pk = (e, n)$ \n",
"\n",
"$Enc(Pk, Pt)$\n",
"1. Compute ciphertext as $Ct = Pt^e \\, (mod \\,\\, n)$\n",
" \n",
"$Dec(Sk, Ct)$\n",
"1. Compute decryption as $Pt = Ct^d \\, (mod \\,\\, n)$\n",
"\n",
"provide an attack that shows that given encryption scheme is not secure with respect to the\n",
"IND-OT-CPA security definition."
]
},
{
"cell_type": "markdown",
"id": "3029803a-82e5-45a9-b5c9-a6373af60ee7",
"metadata": {},
"source": [
"#### Indistinguishability under One-Time Chosen Plaintext Attack:\n",
"1. Challenger generates a key $k$\n",
"1. Adversary submits two equal-length messages $m_0, m_1$\n",
"1. Challenger flips a random bit $b \\gets \\{0,1\\}$ and returns $Enc(k, m_b)$\n",
"1. Adversary guesses $b$ \n",
"The scheme is IND-OT-CPA secure if this advantage is negligible for all adversaries \n",
"-------------------------------------------\n",
"Knowing $n$ is square, adversary can calculate \n",
"$$\n",
"\\varphi(n) = n^2 - n\n",
"$$\n",
"there are $p^2$ total integers from $1$ to $p^2$ \n",
"out of these, the numbers that are not relatively prime to $p^2$ are the multiples of $p, 2p, 3p ... p^2$\n",
"and there are exactly $p$ such multiples. \n",
"\n",
"With $\\varphi(n)$ obtained, adversary can compute $d \\equiv e^{-1} (mod \\,\\, \\varphi(n))$ the same way challanger did. \n",
" \n",
"#### Attack\n",
"Adversary's strategy:\n",
"1. Adversary will sens two distinct messages $m_0, m_1$ and recieves compute $Ct$ and $Pk = (e, n)$\n",
"2. Computes $\\varphi(n) = n^2 - n$\n",
"3. Computes $d = e^{-1} \\, (mod \\,\\, \\varphi(n))$\n",
"4. Decrypts $Pt = Ct^d \\, (mod \\,\\, n)$\n",
"5. Comares $Pt$ against $m_0, m_1$ and select which plaintext was encrypted\n",
"\n",
"##### Adversary will win every time => scheme is not IND-OT-CPA secure"
]
},
{
"cell_type": "markdown",
"id": "b911e6e5-1a14-47d4-8322-4ee26318db8e",
"metadata": {},
"source": [
"# Task 3\n",
"#### Consider the ElGamal cryptosystem with a public key $h$ and a private key $x$ \n",
"\n",
"let cyclic group $G$ of order $q$, with generator $g$ and identity element $e$. And all operation on this group... \n",
"let message $m \\in G$ \n",
"public key $h := g^x$ \n",
"shared secret $s := h^y = (g^x)^y = g^{x \\times y}$ \n",
"$c_1 := g^y$ \n",
"$c_2 := m \\times s$"
]
},
{
"cell_type": "markdown",
"id": "f9d7ddb7-045e-434a-8af3-d3291a57e08c",
"metadata": {},
"source": [
"1. Assume that you are given a ciphertext $(c_1, c_2)$ encrypting an unknown message $m$. Show how you can generate a new ciphertext $(c_1', c_2')$ that encrypts the same $m$, but with different randomness $y'$ (without decrypting the ciphertext)"
]
},
{
"cell_type": "markdown",
"id": "d3202508-ecae-4fa8-af4f-b09b842f2bd3",
"metadata": {},
"source": [
"ElGamal decryption principle:\n",
"$$\n",
"s \\times c_1^{q-x} = g^{x \\times y} \\times {(g^y)}^{q-x} = g^{x \\times y} \\times g^{y(q-x)} = g^{x \\times y + y \\times q - x \\times y} = g^{y \\times q} = {(g^q)}^y = e^y = e\n",
"$$\n",
"$$\n",
"\\Rightarrow s^{-1} = c_1^{q-x}\n",
"$$\n",
"$$\n",
"m = c_2 \\times s^{-1} = m \\times s \\times s^{-1}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "dc716837-53fb-4f8c-92d5-38ccdb49d317",
"metadata": {},
"source": [
"to get the same message from different ct\n",
"$$\n",
"m = c_2{'} \\times s^{-1}{'} = c_2{'} \\times ({c_1'})^{q-x}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "28980583-2777-4a56-a4f4-9c251070eb80",
"metadata": {},
"source": [
"we can modify messages with any pair $k, l$ \n",
"$c_1{'} := c_1 \\times k$ \n",
"$c_2{'} := c_2 \\times l$\n",
"$$\n",
"m = c_2{'} \\times {(c_1{'})}^{q-x} = c_2 \\times l \\times {(c_1 \\times k)}^{q-x} = c_2 \\times l \\times {c_1}^{q-x} \\times {k}^{q-x}\n",
"$$\n",
"with relation $l \\times {k}^{q-x} = e$, but we dont know private exponent $x$\n"
]
},
{
"cell_type": "markdown",
"id": "c38e621f-392c-4b20-8102-8952c7fb2fc3",
"metadata": {},
"source": [
"this can be achived with $k := g^z$ for any choosen $z \\in G$\n",
"$$\n",
"c_1{'} = c_1 \\times g^z = g^y \\times g^z = g^{y+z}\n",
"$$ \n",
"$$\n",
"s{'} = c_1^{x} = {g}^{x(y+z)} = {g}^{xy+xz}\n",
"$$\n",
"$$\n",
"\\frac{c_2{'}}{c_2} = \\frac{m \\times s{'}}{m \\times s} = \\frac{s{'}}{s} = g^{xz} = \\frac{c_2 \\times l}{c_2} = l\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "71d98453-5695-4942-bee9-8441e95051b0",
"metadata": {},
"source": [
"2. Assume you are given ciphertext $c = (c1, c2)$ that you wants to decrypt, but you do not know corresponding private key $sk$. Suppose that you have a friend who provides you with the decryption of any other chosen ciphertext $c{'} \\not= c$ using private key $sk$. Show how can you decrypt $c$."
]
},
{
"cell_type": "markdown",
"id": "67b945b1-553a-405a-8daa-e797a3f9616f",
"metadata": {},
"source": [
"We can choose any $c'$ to decipher $m$\n",
"$$\n",
"\\frac{c_2}{c_2{'}} = \\frac{m \\times s}{m{'} \\times s} = \\frac{m}{m{'}}\n",
"$$\n",
"$$\n",
"\\Rightarrow m = m{'} \\times \\frac{c_2}{c_2{'}}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "cd4f9b24-52d6-407d-a9e2-769b6dba6a54",
"metadata": {},
"source": [
"3. Assume you are given two ciphertexts $ct_1 = (c_{11}, c_{12})$ and $ct_2 = (c_{21}, c_{22})$ that correspond to some\n",
"plaintext messages (not known to you) $m_1$ and $m_2$. What information can you learn about $m_1$ and $m_2$, if you observe that $c_{11} = c_{21}$?"
]
},
{
"cell_type": "markdown",
"id": "b95d2854-1d8c-40f8-a69e-eb35f5d19ee8",
"metadata": {},
"source": [
"$$\n",
"1 = \\frac{c_{11}}{c_{12}} = \\frac{g^{y_1}}{g^{y_2}} = g^{y_1 - y_2}\n",
"$$\n",
"$$\n",
"\\Rightarrow y_1 = y_2\n",
"$$\n",
"$$\n",
"\\Rightarrow h^{y_1} = h^{y_2}\n",
"$$\n",
"$$\n",
"\\frac{c_{12}}{c_{22}} = \\frac{m_1 \\times h^{y_1}}{m_2 \\times h^{y_2}} = \\frac{m_1}{m_2}\n",
"$$"
]
},
{
"cell_type": "markdown",
"id": "44a536aa-8f2a-4234-a88e-ae020f560d94",
"metadata": {},
"source": [
"4. Bring an example of potential application of ElGamal encryption scheme, where homomorphic property is useful and another example, where it violates the desired security of the application. Justify your answer."
]
},
{
"cell_type": "markdown",
"id": "1a8ce5ba-477e-4be8-b6f1-697da610487a",
"metadata": {},
"source": [
"- Desired application could multiply messages from multiple senders and decrypt result to protect privacy of them but get the product of all \n",
"- Undesired applicatio would be for example online auction where adversary could manipulate offers"
]
},
{
"cell_type": "markdown",
"id": "a2238cd4-1944-4139-909c-ae984776d407",
"metadata": {},
"source": [
"# Task 4\n",
"You have intercepted two RSA ciphertexts $c_1 = 7$ and $c_2 = 16$ that correspond to the same plaintext a promo code for the video game. You know that those ciphertexts have been created using corresponding public keys $pk_1 = (e = 3, n = 57)$ and $pk_2 = (e = 5, n = 57)$. What is the promo code m from the intercepted ciphertext? \n",
"Note: for this attack, your task is not to find the private key!"
]
},
{
"cell_type": "markdown",
"id": "a8d3026a-1b29-4339-9548-d889871ad68e",
"metadata": {},
"source": [
"${\\lvert m^{3} \\rvert}_{57} \\equiv 7$ \n",
"${\\lvert m^{5} \\rvert}_{57} \\equiv 16$ "
]
},
{
"cell_type": "markdown",
"id": "e8358104-d161-4617-9f36-761e80cf6d63",
"metadata": {},
"source": [
"${\\lvert m^{3} \\rvert}_{57} \\equiv 16$ \n",
"${\\lvert 7 \\times m^{2} \\rvert}_{57} \\equiv 16$ \n",
"${\\lvert 7^{-1} \\times 7 \\times m^{2} \\rvert}_{57} \\equiv 16 \\times 7^{-1}$ \n",
"${\\lvert m^{2} \\rvert}_{57} \\equiv 43$ \n",
"${\\lvert \\sqrt{m} \\rvert}_{57} \\equiv \\{10, 28, 29, 47\\}$ "
]
},
{
"cell_type": "markdown",
"id": "82b4dbb3-218a-47a2-a623-8961451298cd",
"metadata": {},
"source": [
"${\\lvert {28}^{3} \\rvert}_{57} \\equiv 7$ \n",
"${\\lvert {28}^{5} \\rvert}_{57} \\equiv 16$ \n",
"$ m = 28$"
]
},
{
"cell_type": "markdown",
"id": "682d50fa-6ab4-4f8e-9c25-d11fea9f2b74",
"metadata": {},
"source": [
"# Task 5\n",
"Your company is building a product that heavily relies on\n",
"usage of cryptography. You receive the following list of security requirements for the system"
]
},
{
"cell_type": "markdown",
"id": "6fd52e32-8336-45a9-8f2b-ea7f741603e2",
"metadata": {},
"source": [
"1. System should ensure data confidentiality and integrity in transmission \n",
"**Scheme: TLS 1.3 with AES-256-GCM or ChaCha20-Poly1305 256-bit** \n",
" $\\to$ Both provide confidentiality and integrity in single pass \n",
" $\\to$ ChaCha20 is efficient in software and resistant to timing attacks \n",
" $\\to$ AES-256 ia accelerated on almost every CPU, AES-NI instructions mitigate side-channel risks \n",
" $\\to$ TLS 1.3 removes deprecated ciphers (RC4 etc..), but may not be supported on older platforms (typically embedded devices) \n",
" using TLS 1.2 and whitelisting only secure ciphers may be option too\n",
" \n",
"3. System should ensure data confidentiality and integrity at rest \n",
"**Scheme: AES-256-XTS with HMAC-SHA-256** \n",
" $\\to$ AES-256 is resistant to brute-force attacks (even with quantum computing, Grover's algorithm would require ~$2^128$ operations) \n",
" $\\to$ XTS Encrypts each sector independently to avoids performance penalties for random I/O operations, but keeps diffusion advantage of chaining modes \n",
" $\\to$ HMAC-SHA-256 ensures integrity and can be backupped separately to ensure backup wasnt tampered with\n",
" \n",
"3. System should enforce strong authentication mechanisms for users and services to ensure that only authorized entities can access the data \n",
"**Scheme for user authentication: pow password hashing + Ed25519** \n",
" $\\to$ Argon2id is designed to not be comutable on FPGA and can be configured (iterations, memory, parallelism) to match requrements\n",
" $\\to$ Passwords should be salted before hashing and never stored as plaintext \n",
" $\\to$ Ed25519 signature can be stored on hardware authenticator providing second factor to the password \n",
" **Scheme for service to service authentication: mTLS Ed25519 256bit** \n",
" $\\to$ Mutual certificate based authentication for every two points in infrastructure \n",
" $\\to$ Ed25519 with 256-bit key comparable secure as RSA with 3072-bit key, but much cheaper to compute - saving cost on the infrastrucure \n",
"4. System must be resistant to common attacks, including side-channel attacks and brute force attacks, using strong cryptographic primitives and practices \n",
"**Mitigation of common attacks:** \n",
" $\\to$ AES-NI instructions to resis power analysis with 256-bit key to resis brute force \n",
" $\\to$ TLS 1.3 insted of 1.2 to not even include insecure schemes in the transport protocol \n",
" $\\to$ XTS mode and HMAC to mitigate tampering with data at rest\n",
" $\\to$ Argon2id for password hashing and salting to resist dictionary and bruteforce FPGA attacks in case hashes got leaked \n",
" $\\to$ Ed25519 to resist simple RSA power analysis "
]
},
{
"cell_type": "markdown",
"id": "2226a20b-4e40-4f57-881f-9ba9658ce358",
"metadata": {},
"source": [
"## Bonus Task\n",
"Show that exponential ElGamal (where the ciphertext is constructed as $c = (c_1, c_2) = (g^y, g^m \\times s)$ is not IND-CCA2 secure. You are allowed to make single encryption query and single decryption\n",
"query to the challenger."
]
},
{
"cell_type": "markdown",
"id": "cc53f0ce-b56b-4560-ab2a-ead78a0f80a9",
"metadata": {},
"source": [
"#### Indistinguishability under adaptive chosen-ciphertext attack \n",
"1. The challenger generates a key pair $Pk, Sk$, and publishes $PK$ to the adversary\n",
"2. The adversary may perform any number of calls to the encryptions and decryption oracle based on arbitrary ciphertexts\n",
"3. Eventually, the adversary submits two distinct chosen plaintexts $m_0, m_1$ to the challenger.\n",
"4. The challenger selects a bit $b \\gets \\{0, 1\\}$ uniformly at random, and sends the ciphertext $c = E(Pk, M_b)$ back\n",
"5. The adversary is free to perform any number of additional computations or encryptions and may make further calls to the decryption oracle\n",
"7. Adversary guesses $b$\n",
" \n",
"A scheme is IND-CCA2secure secure if this advantage is negligible for all adversaries"
]
},
{
"cell_type": "markdown",
"id": "b89d823e-919a-4426-a860-9474b55918a5",
"metadata": {},
"source": [
"#### Adversary's startegy\n",
"1. Challenger computes a public key $h := g^x$\n",
"2. Adversary selects two messages $m_0, m_1$\n",
"3. Challenger responds with $Ct = (c_0, c_1) = (g^y, g^{m_b} \\times h^y)$\n",
"4. Adversary chooses $k \\in N$ computes and submits $Ct{'} := (c_0, c_1 \\times g^k)$ for decryption\n",
"5. Oracle returns $D(Ct{'}) = \\frac{c_1 \\times g^k}{{c_0}^x} = \\frac{g^{m_b} \\times h^y \\times g^k}{g^{y \\times x}} = \\frac {g^{m_b} \\times h^y \\times g^k}{h^y} = g^{m_b + k}$\n",
"6. Adversary computes $g^{m_0 + k}$ and $g^{m_1 + k}$, compares them to decrypted $Ct{'}$\n",
"since $m_0, m_1, k$ are known to the Adversary, he will always succeed $\\Rightarrow$ exponential ElGamal is not IND-CCA2 secure"
]
}
],
"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
}

5
hw3/run.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
docker run -p 8888:8888 \
-v "$(pwd)":/work \
jupyter