wh2
This commit is contained in:
parent
a7a984c0d8
commit
e5d8cd6214
|
@ -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, m∣∣m′) = 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, m∣∣m′) = 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, m∣∣m′) = F(k, 0∣∣m) ⊕ F(k, m′∣∣1), where m, m′∈ {0, 1}^(n−1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"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^(n−1)) ⊕ F(k,0^(n−1)||1)) ⊕ (F(k,0||0^(n−1)) ⊕ F(k,1^(n−1||1)) \n",
|
||||
"y_1 ⊕ y_2 = F(k,0||1^(n−1)) ⊕ F(k,1^(n−1||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 n−block message m = m1∣∣m2∣∣. . .∣∣m_n by some block cipher E in\n",
|
||||
"CFB mode. Let use denote ciphertext produced by E as c = c1∣∣c2∣∣. . .∣∣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
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
docker run -p 8888:8888 \
|
||||
-v "$(pwd)":/work \
|
||||
jupyter
|
Loading…
Reference in New Issue