|
|
@ -0,0 +1,414 @@
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
"cells": [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
|
|
|
"id": "e4a99103-1fbd-43a9-9464-bb220e226097",
|
|
|
|
|
|
|
|
"metadata": {},
|
|
|
|
|
|
|
|
"source": [
|
|
|
|
|
|
|
|
"# TP 3 : Chiffrement asymétrique El Gamal\n",
|
|
|
|
|
|
|
|
"## Chiffrement d’El Gamal\n",
|
|
|
|
|
|
|
|
"Le chiffrement d’El 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 d’abord 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 l’usage 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 n’est 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 » n’en 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 d’El 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 d’El Gamal.\n",
|
|
|
|
|
|
|
|
"Vous pouvez calculer l’inverse de x modulo p (s’il 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 d’El Gamal s’applique à des nombres. Mais très souvent, les messages qu’on 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 l’opération réciproque : étant donné un nombre entier nombre, retrouver la chaîne de caractères texte qu’il 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 d’encodage/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) l’exponentielle modulaire x n mod p\n",
|
|
|
|
|
|
|
|
"### 2. L’algorithme d’exponentielle rapide permet également de calculer le nombre x n mod p mais en utilisant l’algorithme 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
|
|
|
|
|
|
|
|
}
|