You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

415 lines
13 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"id": "e4a99103-1fbd-43a9-9464-bb220e226097",
"metadata": {},
"source": [
"# TP 3 : Chiffrement asymétrique El Gamal\n",
"## Chiffrement dEl Gamal\n",
"Le chiffrement dEl Gamal est un protocole de cryptographie asymétrique inventé par Taher El Gamal\n",
"en 1984 et qui repose sur le problème du logarithme discret.\n",
"## Génération des clefs.\n",
"La première étape du schéma de chiffrement consiste à produire une paire de clefs : la clef publique,\n",
"et la clef secrète (ou clé privée). La première servira à chiffrer les messages et la deuxième à les\n",
"déchiffrer.\n",
"Pour générer sa paire de clefs, il faut dabord choisir un nombre premier p et un générateur g pour\n",
"Z/pZ.\n",
"Ensuite il faut choisir un élément s de Z/pZ qui constituera la clef privée, et calculer h = g\n",
"s mod p.\n",
"Pour terminer, la clé publique est (p, g, h).\n",
"## Chiffrement\n",
"Pour chiffrer un message M encodé comme un entier de Z/pZ avec la clé publique (p, g, h), il faut\n",
"tirer au hasard un aléa r dans Z/pZ et calculer C1 = g\n",
"r mod p et C2 = (M ·(h\n",
"r mod p)) mod p.\n",
"Ainsi le chiffré C est composé de ces deux nombres : C = (C1, C2).\n",
"## Déchiffrement\n",
"Ayant accès à C = (C1, C2) et à la clé privée s, pour déchiffrer il suffit de calculer :\n",
"\u0010\n",
"C2 × ((C1)\n",
"s mod p)\n",
"1 mod p\n",
"\u0011\n",
"mod p\n",
"pour retrouver le message M"
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "c5b14247-bb01-4d53-bfe9-a6794e1d083a",
"metadata": {},
"outputs": [],
"source": [
"from sympy import randprime\n",
"from sympy import mod_inverse\n",
"from random import randint"
]
},
{
"cell_type": "markdown",
"id": "da5acb5b-c88f-4cf8-b77f-5730a2fb8b8b",
"metadata": {},
"source": [
"# Exercice 1"
]
},
{
"cell_type": "markdown",
"id": "cb40eddd-9d83-4866-a2fb-596c936b6c96",
"metadata": {},
"source": [
"## (Génération des clefs). \n",
"Écrivez une fonction Python3 Clefs(k) qui permet de générer\n",
"une paire de clefs El Gamal, avec un module compris entre 2k et 2k+1 1.\n",
"La taille compte ! Plus vos clés seront de grands nombres, plus elles seront sûres. Le « paramètre de\n",
"sécurité » est donc le nombre de bits du module p, autrement dit son logarithme binaire k.\n",
"Vous aurez peut-être lusage de la fonction randprime de la bibliothèque sympy (éventuellement à\n",
"installer en tapant pip install sympy dans un terminal) et de la fonction randint de la bibliothèque random. Pour calculer x\n",
"n mod p vous devrez utiliser pow(x, n, mod=p) car (x**n)%p ne\n",
"marche pas pour les grands nombres. Attention, ce nest pas une fonction de la bibliothèque math ! !\n",
"### 1. Choisissez comme module un nombre premier p au hasard compris entre 2k et 2k+1 1.\n",
"### 2. Choisissez comme générateur un nombre g au hasard compris entre 2 et p 1.\n",
"Remarque : Votre « générateur » nen est peut-être pas un. Pour gagner du temps, on ne\n",
"vous demande pas de le vérifier : la procédure de chiffrement/déchiffrement marche encore,\n",
"mais votre clé sera plus facile à casser, car il y aura plusieurs valeurs possibles pour s, en plus\n",
"de celle qui sera vraiment votre clé secrète.\n",
"### 3. Choisissez comme secret un nombre s au hasard compris entre 2 et p 1.\n",
"### 4. Calculez h."
]
},
{
"cell_type": "code",
"execution_count": 33,
"id": "fc076bdc-53b4-4c7a-947e-93545a63cb81",
"metadata": {},
"outputs": [],
"source": [
"def Clef(k):\n",
" p = randprime(2**k, 2**(k+1) - 1)\n",
" g = randint(2, p)\n",
" s = randint(2, p)\n",
" h = pow(g, s, mod=p)\n",
" return (p, g, h), s"
]
},
{
"cell_type": "code",
"execution_count": 34,
"id": "ccddb73a-53f9-45dc-9d0f-12ea0b7bc880",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"((59, 59, 0), 2)\n"
]
}
],
"source": [
"print(Clef(5))"
]
},
{
"cell_type": "markdown",
"id": "dca8a06b-a782-42ef-ac24-bb7b448b2d39",
"metadata": {},
"source": [
"# Exercice 2. \n",
"## Écrivez une fonction Python3 Chiffrer(...) qui permet de chiffrer un nombre M avec le chiffrement dEl Gamal."
]
},
{
"cell_type": "code",
"execution_count": 35,
"id": "9bcdf40f-6aa0-47f3-aee7-efcd5b6bf1a5",
"metadata": {},
"outputs": [],
"source": [
"def Chiffrer(M, p, g, h):\n",
" r = randint(0, p)\n",
" C1 = pow(g, r, mod=p)\n",
" C2 = (M * pow(h, r, mod=p))%p\n",
" return C1, C2"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "e5abbe34-905f-4651-8744-952376af16b2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Génération de clef : \n",
"Clef public : (1871, 1240, 1473)\n",
"Clef privé : 1063\n",
"Chiffrement de 1200 Soit un chiffré c = (973, 292)\n"
]
}
],
"source": [
"print(\"Génération de clef : \")\n",
"public, prive = Clef(10)\n",
"print(\"Clef public : \", public)\n",
"print(\"Clef privé : \", prive)\n",
"M = 1200\n",
"C = Chiffrer(M, public[0], public[1], public[2])\n",
"print(\"Chiffrement de \", M, \"Soit un chiffré c = \", C)"
]
},
{
"cell_type": "markdown",
"id": "606ffacb-eb0d-4023-8c5f-86a885f5fc3f",
"metadata": {},
"source": [
"# Exercice 3. \n",
"## Écrivez une fonction Python3 Dechiffrer(...) qui permet de déchiffrer un chiffré (C1, C2) avec le chiffrement dEl Gamal.\n",
"Vous pouvez calculer linverse de x modulo p (sil existe) par pow(x, -1, p)."
]
},
{
"cell_type": "code",
"execution_count": 58,
"id": "1827a062-4875-411e-820b-6c040bd42a9f",
"metadata": {},
"outputs": [],
"source": [
"def Dechiffrer(C1, C2, s, p):\n",
" M = (C2 * mod_inverse(pow(C1, s, mod=p), p))%p\n",
" return M"
]
},
{
"cell_type": "code",
"execution_count": 59,
"id": "9d49814a-be2f-4875-815d-296d08e74a1c",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Message à déchiffrer : (973, 292)\n",
"Resultat après déchiffrement : 1200\n"
]
}
],
"source": [
"print(\"Message à déchiffrer : \", C)\n",
"Md = Dechiffrer(C[0], C[1], prive, public[0])\n",
"print(\"Resultat après déchiffrement : \", Md)"
]
},
{
"cell_type": "markdown",
"id": "ca4ddadd-1181-4b1d-a6a8-f50f4c53dc84",
"metadata": {},
"source": [
"# Exercice 4. \n",
"Fondamentalement, le chiffrement dEl Gamal sapplique à des nombres. Mais très souvent, les messages quon souhaite chiffrer sont plutôt des textes ! Pour chiffrer des textes, il faut donc passer par une étape préalable de numérisation des caractères qui le composent.\n",
"### 1. Écrivez une fonction Python3 Encode(texte) qui convertit une chaîne de caractères texte en un nombre entier. Il y a plusieurs manières de faire cela, voici celle que nous proposons ici :\n",
"(a) Chaque caractère est encodé par son code ASCII décimal, composé de 1, 2 ou 3 chiffres. Étant donné un caractère c, le code ASCII correspondant est obtenu par ord(c). \n",
"(b) Les codes ASCII des caractères sont transformés en str, puis ramenés sur 3 chiffres en ajoutant si nécessaire des 0 à gauche. \n",
"(c) Les chaînes représentant les codes ASCII sur 3 chiffres sont concaténées les unes à la suite des autres pour obtenir une seule (grande) chaîne, ensuite transformée en int. \n",
"### 2. Écrivez une fonction Python3 Decode(nombre) effectuant lopération réciproque : étant donné un nombre entier nombre, retrouver la chaîne de caractères texte quil représente.\n",
"Pour cela, utilisez la fonction chr. Étant un code ASCII donné num, le caractère associé est\n",
"obtenu par chr(num).\n",
"Pour récupérer les codes ASCII des différents caractères, vous voudrez peut-être utiliser le\n",
"reste (%) et le quotient (//) de la division par 1000.\n",
"### 3. Testez vos fonctions dencodage/décodage. On doit avoir, pour tout message M :\n",
"M=Decode(Encode(M))"
]
},
{
"cell_type": "code",
"execution_count": 171,
"id": "bcbf166a-3b1f-4610-91ad-f34c4489e53f",
"metadata": {},
"outputs": [],
"source": [
"def Encode(texte):\n",
" newTexte = \"\"\n",
" for i in range(len(texte)):\n",
" newTexte = newTexte + str(ord(texte[i])).zfill(3)\n",
" intTexte = int(newTexte)\n",
" return intTexte"
]
},
{
"cell_type": "code",
"execution_count": 168,
"id": "6aac494a-7bae-4bff-a054-9e8832bde008",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"69115115097105"
]
},
"execution_count": 168,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Encode(\"Essai\")"
]
},
{
"cell_type": "code",
"execution_count": 184,
"id": "4986d5be-89c1-441c-8cfc-87e265998d16",
"metadata": {},
"outputs": [],
"source": [
"def Decode(nb):\n",
" res = \"\"\n",
" while nb > 0 :\n",
" res = chr(nb % 1000) + res\n",
" nb = nb // 1000\n",
" return res"
]
},
{
"cell_type": "code",
"execution_count": 185,
"id": "30aa336c-5959-49d6-90b1-b57b5ed9fa92",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Essai'"
]
},
"execution_count": 185,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Decode(69115115097105)"
]
},
{
"cell_type": "code",
"execution_count": 179,
"id": "9f2678f3-8180-46c9-aba0-f9a975775a12",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(1443295143187065358570471830895, 895427499536852088675129942696)"
]
},
"execution_count": 179,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Chiffrer(Encode(\"Yoloyolo boys\"), 2300342751692871968900072455807, 1945803074531676481815246424499, 150618869292435473863944805702)"
]
},
{
"cell_type": "markdown",
"id": "e02cb23c-4b07-4d2f-a086-693fa11c5245",
"metadata": {},
"source": [
"# Exercice 7 \n",
"(Exponentielle).\n",
"### 1. Écrire une fonction exp_basique(x,n,p) qui, pour trois entiers positifs x, n, p donnés en entrée, calcule de manière basique (sans utiliser la bibliothèque math) lexponentielle modulaire x n mod p\n",
"### 2. Lalgorithme dexponentielle rapide permet également de calculer le nombre x n mod p mais en utilisant lalgorithme récursif suivant :\n",
"puissance(x, n) =\n",
"\n",
"\n",
"\n",
"x, si n = 1\n",
"puissance(x\n",
"2\n",
", n/2), si n est pair\n",
"x × puissance(x\n",
"2\n",
", (n 1)/2), si n est impair \n",
"Écrire une fonction exp_rapide(x,n,p) implémentant cet algorithme.\n",
"### 3. Calculer le nombre suivant, avec les deux méthodes :\n",
"123456789123456789 (mod 987654321) = 598987215\n",
"Que constatez-vous ?"
]
},
{
"cell_type": "code",
"execution_count": 188,
"id": "5e226a8c-c067-4f5e-8ab6-3e698d540a7d",
"metadata": {},
"outputs": [],
"source": [
"def exp_basique(x, n, p):\n",
" return (x**n)%p"
]
},
{
"cell_type": "code",
"execution_count": 192,
"id": "7bf34597-1e83-4ba2-9a79-5d0b95aac962",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"3\n",
"3\n"
]
}
],
"source": [
"print(exp_basique(973, 2, 1871))\n",
"print(pow(973, 2, 1871))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "74960463-b5c5-4bc2-951e-4f4de37a93a8",
"metadata": {},
"outputs": [],
"source": [
"def exp_rapide(x, n, p):\n",
" if(n = 1):\n",
" return x\n",
" if(n%2 = 0):\n",
" return puissance(x, n, p)"
]
}
],
"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.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}