Exercices
Exercice 1
Utilisation des bibliothèques cryptographiques du module sympy.
Documentation : https://docs.sympy.org/latest/modules/crypto.html
Décoder la phrase RYTVJKGCLJWRTZCVRMVTLEDFULCVHLZWRZKKFLKRMFKIVGCRTV, sachant qu'elle a été chiffrée par décalage (shift en anglais...)
Correction
1 2 3 4 5 6 7 | |
Exercice 2
Chiffrage affine
Principe du chiffrage affine :
- Chaque lettre est codée par son rang, en commençant à 0 (A->0, B->1, ..., Z->25)
- On applique à chaque rang la transformation affine \(f(x) = (ax+b)\, \%26\)
où \(a\) et \(b\) sont deux nombres entiers. Attention, \(a\) doit être premier avec 26.
Rappel sur les nombres premiers entre eux
Deux nombres sont dits premiers entre eux si leur PGCD vaut 1.
Exemples :
- 8 et 15 sont premiers entre eux (ils n'ont aucun diviseur commun autre que 1)
- 8 et 12 ne sont pas premiers entre eux (leur PGCD vaut 4).
Q1. Codez votre fonction affine(msg, a, b).
Pour tester votre fonction :
>>> affine("BONJOUR", 3, 5)
'IVSGVNE'
Correction
1 2 3 4 5 6 7 8 9 10 11 | |
Q2. Comparez vos résultats avec ceux obtenus par la fonction encipher_affine() de sympy.
Q3. Décodez la phrase UCGXLODCMOXPMFMSRJCFQOGTCRSUSXC, sachant qu'elle contient le mot TRAVAIL et que \(a\) et \(b\) sont inférieurs à 20.
Aide
L'instruction gcd du module math permet de calculer le PGCD de deux nombres.
Correction
1 2 3 4 5 6 7 8 9 | |
Exercice 3
Exercice 3 (Parties A et B) du sujet Métropole J2 2025
Partie A
alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z']
Correction Q1
On obtient le mot PGRDX.
Correction Q2
def indice(L, element):
for i in range(len(L)):
if L[i] == element:
return i
Correction Q3
def lettres_vers_indices(txt):
lst = []
for c in txt:
lst.append(indice(alphabet,c))
return lst
def indices_vers_lettres(lst):
s = ''
for c in lst:
s += alphabet[c]
return s
def chiffrement(msg, cle):
assert len(cle) >= len(msg), 'impossible'
indices_msg = lettres_vers_indices(msg)
indices_cle = lettres_vers_indices(cle)
n = len(msg)
indices_msg_chiffre = []
for k in range(n):
ind = ...
if ind >= 26:
ind = ...
indices_msg_chiffre.append(ind)
msg_chiffre = indices_vers_lettres(...)
return msg_chiffre
Correction Q4
def chiffrement(msg, cle):
assert len(cle) >= len(msg), 'impossible'
indices_msg = lettres_vers_indices(msg)
indices_cle = lettres_vers_indices(cle)
n = len(msg)
indices_msg_chiffre = []
for k in range(n):
ind = indices_msg[k] + indices_cle[k]
if ind >= 26:
ind = ind - 26
indices_msg_chiffre.append(ind)
msg_chiffre = indices_vers_lettres(indices_msg_chiffre)
return msg_chiffre
Correction Q5
On obtient AssertionError 'impossible' car la longueur de la clé est inférieure à la longueur du message.
Correction Q6
On obtient le mot BRAVO.
Correction Q7
Pour chaque caractère du message chiffré, on effectue la soustraction entre sa position dans l’alphabet et la position du caractère associé dans le masque. Si la valeur obtenue est strictement négative, on ajoute 26. On obtient finalement la position du caractère en clair dans l’alphabet.
Correction Q8
def dechiffrement(msg, cle):
assert len(cle) >= len(msg), 'impossible'
indices_msg = lettres_vers_indices(msg)
indices_cle = lettres_vers_indices(cle)
n = len(msg)
indices_msg_dechiffre = []
for k in range(n):
ind = indices_msg[k] - indices_cle[k]
if ind < 0:
ind = ind + 26
indices_msg_dechiffre.append(ind)
msg_dechiffre = indices_vers_lettres(indices_msg_dechiffre)
return msg_dechiffre
Partie B
Correction Q9
Avec un chiffrement symétrique, la connaissance d'une seule et unique clé est requise pour chiffrer et déchiffrer le message. Dans un chiffrement asymétrique, la clé de déchiffrement est connue seulement du destinataire, alors que la clé de chiffrement est publique et distribuée à tous.
Correction Q10
Il suffit à Bob de déchiffer le message avec sa clé privée.
Correction Q11
Tout le monde a la clé publique de Bob, donc tout le monde peut écrire en se faisant passer pour Alice.
Correction Q12
Dans le protocole https, une clé AES est générée par chiffrement asymétrique au tout début de la communication (TLS). Ensuite, le reste du flux est chiffré avec le chiffrement symétrique AES.
Correction Q13
Utiliser un chiffrement asymétrique tout au long de la navigation ralentirait considérablement le trafic car un chiffrement asymétrique consomme beaucoup de ressources de calcul, contrairement au chiffrement symétrique.
Exercice 4
Cryptographie RSA presque à la main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
- Pour générer un grand nombre premier de taille
bits, on utilise la fonctionCrypto.Util.number.getPrime(bits, randfunc=get_random_bytes). - Pour inverser un nombre \(x\) modulo \(n\), on utilise la fonction
pow(x, -1, n). - Pour calculer
aà la puissancebmodulon, on utilisepow(a, b, n).
Correction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
Exercice 5
En vous servant du code précédent, déchiffrez le message 58152918114477529438769495136495430966050302170947748011925859233600631318929939319619808279389222131229963717435870597641010567365311762267359794338657867540621133550787677728203831932548041236152866441194127191404729294628415184239755221703677388875259927092794165578604353985011899152968982365630138088486380827379488939561996226754182 sachant que :
- \(e\) vaut 65537.
- \(p\) et \(q\) sont respectivement les 13èmes et 14èmes nombres de Mersenne.
Correction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
Exercice 6
module RSA dans les règles de l'art
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
import binascii
keyPair = RSA.generate(1024)
pubKey = keyPair.publickey()
pubKeyPEM = pubKey.exportKey()
privKeyPEM = keyPair.exportKey()
msg = b'vive la crypto en NSI !'
encryptor = PKCS1_OAEP.new(pubKey)
encrypted = encryptor.encrypt(msg)
print("Encrypted:", binascii.hexlify(encrypted))
decryptor = PKCS1_OAEP.new(keyPair)
decrypted = decryptor.decrypt(encrypted)
print('Decrypted:', decrypted)