{ "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 }