commit
e19faa6cd9
2 changed files with 491 additions and 0 deletions
@ -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 |
||||
|
} |
@ -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 |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue