commit e19faa6cd91977416188929911138044fecdb08a Author: c01rowe Date: Thu Jun 26 22:56:24 2025 +0200 Initial Commit diff --git a/Mahdavi_OT_MP_PSI.ipynb b/Mahdavi_OT_MP_PSI.ipynb new file mode 100644 index 0000000..e22c7b9 --- /dev/null +++ b/Mahdavi_OT_MP_PSI.ipynb @@ -0,0 +1,323 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d172899c", + "metadata": {}, + "source": [ + "# Mahdavi et al.'s OT-MP-PSI Protocol\n", + "## An implementation in SageMath for research purposes\n", + "\n", + "We implement the OT-MP-PSI protocol of Mahdavi et al. It is based on Shamir's Secret Sharing and the homomorphic Paillier encryption scheme.\n", + "\n", + "### Mathematical Preamble\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "42670e84", + "metadata": {}, + "outputs": [], + "source": [ + "import hashlib\n", + "import random\n", + "\n", + "# Prime order of the finite field\n", + "q = 11\n", + "p = 2*q + 1 # 23 is prime!\n", + "# Threshold value\n", + "t = 4\n", + "# Number of participants (holders of a dataset)\n", + "m = 7\n", + "# Secret to reconstruct\n", + "S = 0\n", + "\n", + "Fp = GF(p)\n", + "R = PolynomialRing(Fp,\"x\")\n", + "\n", + "G = Integers(q)\n", + "\n", + "# Paillier Cryptosystem\n", + "p2 = 13\n", + "q2 = 17\n", + "assert(p2.is_prime())\n", + "assert(q2.is_prime())\n", + "N = p2 * q2\n", + "\n", + "alpha = 0\n", + "\n", + "#FN2 = FiniteField(N^2, 'g')\n", + "ZN2 = Zmod(N^2)\n", + "FN2 = [a for a in ZN2 if gcd(a,N^2) == 1]\n", + "\n", + "g = random.choice(FN2)" + ] + }, + { + "cell_type": "markdown", + "id": "8c2c98e4", + "metadata": {}, + "source": [ + "### Paillier Encryption" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "a264ea15", + "metadata": {}, + "outputs": [], + "source": [ + "def paillier_encrypt(element):\n", + " r = random.randint(0, N-1)\n", + " return pow(g, element) * pow(r, N)" + ] + }, + { + "cell_type": "markdown", + "id": "d76a9195", + "metadata": {}, + "source": [ + "### Initialize Shamir's Secret Sharing" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "695e93bf", + "metadata": {}, + "outputs": [], + "source": [ + "def sample_coefficients(t):\n", + " coefficients = []\n", + " coefficients.append(S)\n", + " for i in range(0, t-1):\n", + " coefficients.append(Fp.random_element())\n", + " print(coefficients)\n", + " return coefficients" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "7c2565c5", + "metadata": {}, + "outputs": [], + "source": [ + "# Construct Polynomial\n", + "def poly(coefficients):\n", + " return R(coefficients)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "b61c1603", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 6, 6, 0]\n" + ] + }, + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "f_x = poly(sample_coefficients(t))\n", + "f_x(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "4c8c5660", + "metadata": {}, + "outputs": [], + "source": [ + "def H(element):\n", + " h = hashlib.new('sha256')\n", + " h.update(bytes(element))\n", + " return int(h.hexdigest(), 16) % q" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "54e8a4bf", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "7" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "H(0b10011101)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "b9bada7f", + "metadata": {}, + "outputs": [], + "source": [ + "def keyholder_init():\n", + " coefficients = sample_coefficients(t)\n", + " \n", + "def participant_init(element):\n", + " global alpha \n", + " alpha = random.randint(1,p)\n", + " print(alpha)\n", + " return (pow(H(element), alpha), pow(g, alpha))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d43f845", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "fd75b745", + "metadata": {}, + "outputs": [], + "source": [ + "def keyholder_processing(part_init_res):\n", + " hash_element, g_power_alpha = part_init_res\n", + " print(hash_element)\n", + " random_numbers = []\n", + " for i in range(0, t-1):\n", + " random_numbers.append(Fp.random_element())\n", + " \n", + " return_values = []\n", + " print(random_numbers)\n", + " for j in range(0, t-1):\n", + " return_values.append(pow(g_power_alpha, random_numbers[j]) * pow(hash_element, coefficients[j+1]))\n", + " \n", + " return return_values" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "8395e9bd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 8, 14, 12]\n", + "[0, 8, 14, 12]\n", + "3\n", + "3\n", + "(64, 16102)\n", + "64\n", + "[21, 21, 3]\n", + "3\n", + "64\n", + "[6, 9, 6]\n" + ] + }, + { + "data": { + "text/plain": [ + "[5806, 32072, 38726]" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "coefficients = sample_coefficients(t)\n", + "print(coefficients)\n", + "res = participant_init(10)\n", + "print(alpha)\n", + "print(res)\n", + "keyholder_processing(res)\n", + "\n", + "def participant_2(keyholder_values):\n", + " intermediate_results = []\n", + " for i in keyholder_values:\n", + " intermediate_results.append(pow(i, alpha))\n", + " \n", + " # Paillier Encryption\n", + " encrypted_values = []\n", + " for i in intermediate_results:\n", + " encrypted_values.append(paillier_encrypt(i))\n", + " \n", + " return encrypted_values\n", + " \n", + " \n", + "participant_2(keyholder_processing(participant_init(10)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cc33c78", + "metadata": {}, + "outputs": [], + "source": [ + "def keyholder_2(encrypted_values):\n", + " intermediate_values = []\n", + " for i in encrypted_values:\n", + " intermediate_values.append(i * )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dcb3185e", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "SageMath 9.5", + "language": "sage", + "name": "sagemath" + }, + "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.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Shamir_Secret_Sharing.ipynb b/Shamir_Secret_Sharing.ipynb new file mode 100644 index 0000000..c4daf57 --- /dev/null +++ b/Shamir_Secret_Sharing.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "id": "8a105f7c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 15, 12, 18]\n", + "18*x^3 + 12*x^2 + 15*x\n", + "share 1: 7\n", + "share 2: 13\n", + "share 3: 12\n", + "share 4: 17\n", + "share 5: 3\n", + "share 6: 2\n", + "[(1, 7), (2, 13), (3, 12), (4, 17), (5, 3), (6, 2)]\n", + "0\n", + "[0, 15, 12, 18]\n", + "0\n", + "0\n" + ] + } + ], + "source": [ + "import hashlib\n", + "import random\n", + "\n", + "# Prime order of the finite field\n", + "q = 19\n", + "\n", + "Fq = GF(q)\n", + "R = PolynomialRing(Fq,\"x\")\n", + "\n", + "t = 4\n", + "m = 7\n", + "S = 0\n", + "\n", + "coefficients = []\n", + "coefficients.append(S)\n", + "for i in range(1, t):\n", + " coefficients.append(Fq.random_element())\n", + "\n", + "print(coefficients)\n", + "\n", + "f_x = R(coefficients)\n", + "print(f_x)\n", + "shares = []\n", + "for i in range(1, m):\n", + " print(f\"share {i}: {f_x(i)}\")\n", + " shares.append((i, f_x(i)))\n", + "\n", + "def secret_recovery(shares): \n", + " return sum([i[1] * prod([(0-j[0] * pow(i[0] - j[0], -1, q)) for j in shares[:t] if i[0] != j[0]]) for i in shares[:t]])\n", + "\n", + "S_man = 0\n", + "for i in shares[:t]:\n", + " im_prod = i[1]\n", + " for j in shares[:t]:\n", + " if j[0] != i[0]:\n", + " im_prod *= ((-j[0]) * pow(i[0] - j[0], -1, q)) % q\n", + " S_man += im_prod\n", + " \n", + "\n", + "print(shares)\n", + "S_sage = R.lagrange_polynomial(shares[:t])\n", + "print(S_sage[0])\n", + "print(coefficients)\n", + "print(S_man % q)\n", + "print(secret_recovery(shares[:t]))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e5c47c9d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Information Word a: \t[0, 15, 10, 13, 13, 17, 5, 2, 8, 12, 7]\n", + "Code Word D: \t\t[7, 9, 5, 9, 0, 2, 9, 1, 7, 16, 17, 12, 18, 6, 12, 11, 8, 3]\n", + "a_0: \t\t\t0\n", + "Manipulated Codeword: \t[6, 9, 5, 9, 0, 2, 9, 1, 7, 16, 16, 12, 18, 6, 12, 11, 8, 3]\n", + "a_0: \t\t\t2\n" + ] + } + ], + "source": [ + "non_zero_elem_of_Fq = [x for x in Fq if x != 0]\n", + "k = 11\n", + "\n", + "information_word = []\n", + "information_word.append(S)\n", + "for _ in range(0, k-1):\n", + " information_word.append(Fq.random_element())\n", + "\n", + "print(f\"Information Word a: \\t{information_word}\")\n", + "\n", + "code_word = []\n", + "for i in range(0, q-1):\n", + " code_word.append(sum([information_word[j] * pow(non_zero_elem_of_Fq[i], j) for j in range(0, k)]))\n", + "\n", + "print(f\"Code Word D: \\t\\t{code_word}\")\n", + "\n", + "secret = -sum([code_word[d] for d in range(0, q-1)])\n", + "print(f\"a_0: \\t\\t\\t{secret}\")\n", + "\n", + "assert(secret == information_word[0] == S)\n", + "\n", + "manipulated_codeword = []\n", + "for i in range(0, len(code_word)):\n", + " if i % 10 == 0:\n", + " manipulated_codeword.append(code_word[i]-1 % q)\n", + " else:\n", + " manipulated_codeword.append(code_word[i])\n", + "\n", + "print(f\"Manipulated Codeword: \\t{manipulated_codeword}\")\n", + "\n", + "secret_man = -sum([manipulated_codeword[d] for d in range(0, q-1)])\n", + "print(f\"a_0: \\t\\t\\t{secret_man}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cff95199", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "152ae6a0", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "SageMath 10.6", + "language": "sage", + "name": "sagemath" + }, + "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.12.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}