Adloun

Corrigé bac NSI 2025 Métropole jour 2 — Exercice 3 : Masque jetable : chiffrement symétrique, HTTPS et découpage en sous-réseaux IPv4

Sujet officiel du baccalauréat, spécialité numérique et sciences informatiques, session 2025. Corrigé rédigé par Ibrahim Alame.

Travailler ce sujet sur Adloun Sujet officiel (PDF) Corrigé complet (PDF)

Énoncé

Cet exercice porte sur la programmation de base en Python, la sécurisation des communications et les réseaux.

Partie A – La méthode du masque jetable

Dans cette partie, on s'intéresse à une méthode de chiffrement dite du masque jetable. Voici ce que l'on peut lire sur le site Wikipédia :

Le chiffrement par la méthode du masque jetable consiste à combiner le message en clair avec une clé présentant les caractéristiques très particulières suivantes :

Illustrons cette méthode par un exemple : on souhaite chiffrer le message HELLO avec la clé aléatoire, ou « masque », WMCKL.

Pour cela, on attribue un nombre à chaque lettre, par exemple le rang dans l'alphabet, de 0 à 25.

Tableau de correspondance

LettreABCDEFGHIJKLM
Rang0123456789101112

Tableau de correspondance

LettreNOPQRSTUVWXYZ
Rang13141516171819202122232425

Ensuite, on additionne la valeur du rang de chaque lettre du message avec la valeur du rang correspondante dans le masque.

Enfin, si le résultat est supérieur à 25 on soustrait 26 (calcul dit « modulo 26 »).

Ainsi, le chiffrement du message HELLO avec la clé WMCKL donne le message chiffré DQNVZ comme le montre l'illustration suivante.


     7 (H)   4 (E)  11 (L)  11 (L)  14 (O) message
+   22 (W)  12 (M)   2 (C)  10 (K)  11 (L) masque
=   29      16      13      21      25     masque + message
=    3 (D)  16 (Q)  13 (N)  21 (V)  25 (Z) masque + message  modulo 26

Figure 1. Exemple de chiffrement par la méthode du masque jetable

Source : d'après l'article Masque jetable de Wikipédia en français (https\string://fr.wikipedia.org/wiki/Masque_jetable)

Dans cet exercice, on ne travaillera que sur des chaînes de caractères écrites en majuscules non accentuées (les 26 caractères allant de 'A' à 'Z').

1. Chiffrer, par la méthode du masque jetable, le message LIBRE à l'aide de la clé EYQMT.

En Python, on crée une fois pour toute la variable alphabet qui sera accessible et utilisable dans toutes les fonctions. Celle-ci contient la liste des 26 lettres de l'alphabet rangées dans l'ordre alphabétique :


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']

2. Écrire une fonction Python indice qui prend pour paramètre une liste L et renvoie l'indice de element dans la liste L.

On supposera que chaque élément de la liste L n'y apparaît qu'une seule fois et que element est bien présent dans la liste L.

Par exemple, l'appel indice(alphabet, 'K') renvoie l'entier 10.

3. Écrire une fonction Python lettres_vers_indices qui prend pour paramètre une chaîne de caractères et renvoie, dans l'ordre, la liste des indices de ces caractères dans l'alphabet.

Par exemple, l'appel lettres_vers_indices('HELLO') renvoie la liste d'entiers [7, 4, 11, 11, 14].

On dispose également d'une fonction indices_vers_lettres, qu'on ne demande pas d'écrire, permettant de convertir une liste d'entiers, compris entre 0 et 25, en une chaîne de caractères.

Par exemple, l'appel indices_vers_lettres([3, 16, 13, 21, 25]) renvoie la chaîne de caractères 'DQNVZ'.

Ci-après, on donne une fonction Python chiffrement incomplète, qui, à partir d'un message msg et d'une clé cle entrés en paramètres, renvoie la chaîne de caractères représentant le message chiffré par la méthode du masque jetable.


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

4. Recopier et compléter les lignes 7 à 13 de la fonction chiffrement.

5. Indiquer, en justifiant, ce que l'on observe lors de l'appel chiffrement('RESEAU', 'GFTZ').

On s'intéresse maintenant au déchiffrement d'un message chiffré par la méthode du masque jetable.

Par exemple, le déchiffrement du message DQNVZ avec la clé WMCKL donne le message HELLO.

6. Déchiffrer le message GMEDH avec la clé FVEIT.

7. Expliquer comment procéder pour déchiffrer un message lorsqu'on connaît la clé.

On souhaite maintenant écrire, en Python, une fonction dechiffrement qui permet de déchiffrer un message chiffré par la méthode du masque jetable.

Pour cela, on s'inspire de la fonction chiffrement dans laquelle les paramètres ainsi que les lignes 2 à 5 sont inchangées. On décide cependant de remplacer, ligne 6, le nom de la variable indices_msg_chiffre par le nom plus explicite indices_msg_dechiffre.

8. Adapter les lignes 6 à 13 de la fonction chiffrement pour obtenir la nouvelle fonction dechiffrement.

Partie B – Sécurisation des communications

9. Expliquer la différence entre un algorithme de chiffrement symétrique et un algorithme de chiffrement asymétrique.

Alice souhaite envoyer un message à Bob par l'intermédiaire d'un réseau informatique en utilisant un algorithme de chiffrement asymétrique.

Pour cela, Bob envoie à Alice sa clé publique. Alice chiffre ensuite le message à l'aide de la clé publique de Bob qu'elle vient de recevoir, puis elle envoie ce message chiffré à Bob.

10. Indiquer comment Bob peut déchiffrer le message que lui envoie Alice.

11. Expliquer comment une tierce personne pourrait se faire passer pour Alice sans que Bob ne s'en aperçoive.

12. Expliquer brièvement le fonctionnement du protocole HTTPS.

13. Expliquer pourquoi, pour sécuriser intégralement les communications sur Internet, on utilise le protocole HTTPS plutôt qu'un chiffrement asymétrique.

Partie C – Réseaux

Bob et Marc travaillent pour une petite compagnie d'assurances.

Leurs postes de travail font partie d'un même réseau local géré par l'administratrice système qui dispose du bloc d'adresses IPv4 192.168.110.0/24.

La notation /24 situé à la suite de l'adresse 192.168.110.0 signifie que le masque de sous-réseau du réseau de cette entreprise est 255.255.255.0 : les trois premiers octets d'une adresse IP sur ce réseau permettent donc d'identifier la partie réseau de l'adresse, alors que le dernier octet permet d'identifier la partie hôte et est propre à chaque machine sur le réseau. Ce sous-réseau permet donc d'attribuer 256 adresses IPv4 différentes.

L'administratrice choisit alors d'attribuer, en représentation décimale, l'identifiant 115 pour la partie hôte du poste de travail de Bob et l'identifiant 153 pour celui de Marc.

Depuis son poste de travail, Marc souhaite tester la communication avec celui de Bob. Pour cela, il exécute la commande ping 192.168.100.115 et obtient l'affichage suivant :


--- 192.168.100.115 ping statistics ---

4 packets transmitted, 0 received, 100% packet loss, time
3060ms

14. Expliquer l'affichage obtenu et corriger l'erreur de Marc.

Afin d'améliorer les performances et la sécurité du réseau de l'entreprise, l'administratrice système décide de séparer le réseau local en plusieurs sous-réseaux et de les relier entre eux par des routeurs. Pour cela, elle modifie le masque de sous-réseau qui devient 11111111.11111111.11111111.11100000, donné ici en représentation binaire.

15. Donner la représentation décimale de ce masque de sous-réseau.

Pour obtenir l'adresse IPv4 du sous-réseau auquel appartient une machine, il suffit d'appliquer l'opérateur binaire ET, bit à bit, entre le masque de sous-réseau et l'adresse IPv4 de la machine.

Par exemple, prenons le dernier octet de l'adresse IPv4 de Bob dont la représentation binaire est 01110011 : en appliquant bit à bit l'opérateur binaire ET entre cet octet et l'octet correspondant dans le masque, on obtient le dernier octet de l'adresse du sous-réseau, soit 01100000.


   1 1 1 0 0 0 0 0 (224)
ET 0 1 1 1 0 0 1 1 (115)
------------------
   0 1 1 0 0 0 0 0 (96)

Le poste de travail de Bob est donc sur le sous-réseau d'adresse 192.168.110.96.

16. Indiquer le nombre total d'adresses IPv4 pouvant être attribuées sur le sous-réseau d'adresse 192.168.110.96 sur lequel se trouve Bob.

L'administratrice système attribue maintenant l'adresse IPv4 192.168.110.134 au poste de travail de Zoé, nouvelle employée de la compagnie d'assurances.

17. Donner la représentation binaire du nombre 134.

Depuis son poste de travail, Zoé exécute les deux commandes suivantes :

18. Indiquer, en justifiant, laquelle de ces deux commandes a produit l'affichage :


4 packets transmitted, 4 received, 0% packet loss, time
3002ms

Corrigé

Partie A – La méthode du masque jetable

1. On additionne rang par rang, puis on retranche 26 dès que la somme dépasse 25 :

messageL (11)I (8)B (1)R (17)E (4)
masqueE (4)Y (24)Q (16)M (12)T (19)
somme1532172923
modulo 2615617323
lettrePGRDX

Le message chiffré est PGRDX. Seules les colonnes I et R ont nécessité la soustraction (, ).

2. La fonction prend deux paramètres, la liste L et l'élément cherché, comme le montre l'appel indice(alphabet, 'K'). On parcourt la liste jusqu'à trouver l'élément ; l'hypothèse de présence garantit que la boucle s'arrête :


def indice(L, element):
    """renvoie l'indice de element dans la liste L
    (element y est présent, une seule fois)"""
    i = 0
    while L[i] != element:
        i = i + 1
    return i

indice(alphabet, 'K') renvoie 10, indice(alphabet, 'A') renvoie 0 et indice(alphabet, 'Z') renvoie 25. Une variante avec for i in range(len(L)): et return i dès que L[i] == element est tout aussi correcte. Dans le pire cas (dernier élément), on fait len(L) comparaisons : recherche séquentielle, coût linéaire.

3. On applique indice à chaque caractère de la chaîne et l'on ajoute le résultat à une liste, dans l'ordre de lecture :


def lettres_vers_indices(chaine):
    """renvoie la liste des indices dans alphabet
    des caractères de chaine, dans l'ordre"""
    indices = []
    for lettre in chaine:
        indices.append(indice(alphabet, lettre))
    return indices

lettres_vers_indices('HELLO') renvoie [7, 4, 11, 11, 14] ; sur la chaîne vide elle renvoie []. La variable globale alphabet est lue directement dans la fonction, comme l'énoncé l'autorise.

4. À chaque position k, on additionne l'indice de la lettre du message et celui de la lettre de la clé, on ramène la somme entre 0 et 25, puis on reconvertit la liste des indices chiffrés en chaîne :


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

Test : chiffrement('HELLO', 'WMCKL') renvoie 'DQNVZ' (l'exemple de la Figure 1) et chiffrement('LIBRE', 'EYQMT') renvoie 'PGRDX' (question 1). Une seule soustraction suffit à la ligne 10 car la somme de deux rangs est au plus ; écrire ind = ind % 26 serait aussi accepté. Si la clé est plus longue que le message, seuls ses n premiers caractères servent, puisque la boucle s'arrête à n = len(msg).

5. Le message 'RESEAU' compte caractères et la clé 'GFTZ' seulement : la condition len(cle) >= len(msg) de la ligne 2 est fausse. L'instruction assert interrompt alors l'exécution en levant une exception AssertionError accompagnée du message 'impossible' ; rien n'est chiffré et la fonction ne renvoie aucune valeur. C'est conforme à la première caractéristique du masque jetable : la clé doit être au moins aussi longue que le message, faute de quoi indices_cle[k] n'existerait pas pour k = 4 et k = 5.

6. Déchiffrer, c'est retrancher le rang de la lettre de la clé à celui de la lettre chiffrée, en ajoutant 26 si le résultat est négatif :

chiffréG (6)M (12)E (4)D (3)H (7)
masqueF (5)V (21)E (4)I (8)T (19)
différence10
si négatif11702114
lettreBRAVO

Le message clair est BRAVO.

7. Le chiffrement ajoute, modulo 26, le rang de la lettre du masque au rang de la lettre du message ; pour l'annuler, on effectue l'opération inverse : pour chaque position, on soustrait le rang de la lettre de la clé au rang de la lettre chiffrée ; si le résultat est strictement négatif, on lui ajoute 26 pour revenir dans l'intervalle de 0 à 25 ; on convertit enfin les rangs obtenus en lettres. La clé sert donc dans les deux sens : c'est un chiffrement symétrique. On vérifie sur l'exemple du sujet : DQNVZ avec WMCKL donne (H), (E), (L), (L), (O), soit HELLO.

8. Seules changent l'opération (soustraction), le test (résultat négatif) et la correction () :


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

Tests : dechiffrement('DQNVZ', 'WMCKL') renvoie 'HELLO', dechiffrement('GMEDH', 'FVEIT') renvoie 'BRAVO' (question 6), et pour tout message m et toute clé c assez longue, dechiffrement(chiffrement(m, c), c) redonne m (vérifié sur 200 couples tirés au hasard).

Ce que le correcteur attend : la différence de deux rangs est comprise entre et : le test est ind &lt; 0 et non ind &gt;= 26, et l'on ajoute 26. Un candidat qui recopie ind &gt;= 26 sans changer le test a une fonction qui ne corrige jamais rien et renvoie des indices négatifs.

Partie B – Sécurisation des communications

9. Dans un chiffrement symétrique, une même clé secrète sert à chiffrer et à déchiffrer (le masque jetable de la Partie A, ou AES) : les deux correspondants doivent posséder cette clé, ce qui pose le problème de son échange sur un canal non sûr. Dans un chiffrement asymétrique (RSA), chaque participant possède une paire de clés : une clé publique, diffusée librement, et une clé privée, jamais transmise ; ce qui est chiffré avec la clé publique ne peut être déchiffré qu'avec la clé privée correspondante. Il n'y a plus de secret à échanger, mais les calculs sont beaucoup plus lents.

10. Le message a été chiffré avec la clé publique de Bob : seul le possesseur de la clé privée associée peut le déchiffrer. Bob déchiffre donc avec sa clé privée, qu'il n'a jamais communiquée à personne ; même un espion qui aurait capté la clé publique et le message chiffré n'en tire rien.

11. La clé publique de Bob est, par définition, publique : elle a circulé en clair sur le réseau et n'importe qui peut l'intercepter ou l'obtenir. Une tierce personne, Ève, peut donc rédiger un message de son choix, le chiffrer avec la clé publique de Bob et l'envoyer en prétendant être Alice (par exemple en signant « Alice » ou en usurpant son adresse). Bob le déchiffre normalement avec sa clé privée et n'a aucun moyen de savoir qui l'a écrit : le chiffrement asymétrique garantit la confidentialité (seul Bob peut lire), pas l'authentification de l'expéditeur. Pour s'en prémunir, Alice devrait signer son message avec sa propre clé privée, signature que Bob vérifierait avec la clé publique d'Alice.

12. HTTPS est le protocole HTTP encapsulé dans le protocole TLS (port 443 au lieu de 80). Lors de la connexion, le serveur envoie au navigateur son certificat, qui contient sa clé publique et est signé par une autorité de certification de confiance ; le navigateur vérifie ce certificat (authentification du serveur), génère une clé de session symétrique et la transmet au serveur chiffrée avec la clé publique de celui-ci (chiffrement asymétrique) ; la suite des échanges HTTP est ensuite chiffrée avec cette clé de session (chiffrement symétrique, rapide). HTTPS apporte ainsi la confidentialité, l'authentification du serveur et l'intégrité des données (toute altération est détectée).

13. Un chiffrement asymétrique seul présente deux défauts. D'abord il est lent : ses calculs sur de grands nombres sont beaucoup plus coûteux que ceux d'un algorithme symétrique, et chiffrer ainsi tout le trafic d'une page web ou d'une vidéo serait prohibitif ; HTTPS ne l'emploie que pour échanger la clé de session, puis chiffre le reste en symétrique. Ensuite, comme l'a montré la question 11, il n'authentifie pas l'interlocuteur : rien n'empêche un pirate de se faire passer pour le serveur (ou pour Alice) ; HTTPS règle ce point avec le certificat délivré par une autorité de confiance, et garantit en plus l'intégrité des échanges. HTTPS combine donc le meilleur des deux méthodes : la sécurité de l'échange de clé asymétrique, la vitesse du chiffrement symétrique et l'authentification par certificat.

Partie C – Réseaux

14. Marc a fait une faute de frappe dans le troisième octet : il a tapé 192.168.<strong>100.115 au lieu de 192.168.<strong>110.115. Avec le masque 255.255.255.0, les trois premiers octets identifient le réseau : l'adresse tapée appartient au réseau 192.168.100.0/24, qui n'est pas le réseau local de l'entreprise. Aucune machine ne répond à cette adresse (ou les paquets ne sont même pas routés) : les quatre requêtes ICMP envoyées par ping restent sans réponse, d'où « 4 packets transmitted, 0 received, 100 % packet loss ». La commande correcte, avec l'identifiant d'hôte 115 de Bob, est ping 192.168.110.115.

15. On convertit chaque octet : 11111111 vaut et 11100000 vaut . Le masque s'écrit 255.255.255.224, soit /27 (27 bits à 1).

16. Le masque laisse bits à 0 pour la partie hôte : il y a combinaisons, soit 32 adresses sur le sous-réseau 192.168.110.96, de 192.168.110.96 à 192.168.110.127 (c'est la convention du sujet, qui compte 256 adresses pour le /24). En pratique deux d'entre elles sont réservées, l'adresse du sous-réseau .96 (bits hôte tous à 0) et l'adresse de diffusion .127 (bits hôte tous à 1), si bien que machines au plus peuvent recevoir une adresse. Le réseau initial est ainsi découpé en sous-réseaux de 32 adresses.

17. , d'où l'écriture binaire 10000110 (on vérifie : ).

18. On calcule le sous-réseau de chaque poste par un ET bit à bit du dernier octet avec 11100000 :

postedernier octetbinaireET `11100000`sous-réseau
Zoé134`10000110``10000000` `192.168.110.128`
Bob115`01110011``01100000` `192.168.110.96`
Marc153`10011001``10000000` `192.168.110.128`

Zoé et Marc sont sur le même sous-réseau 192.168.110.128 (adresses de .128 à .159) : les paquets circulent directement entre leurs postes et les quatre réponses reviennent. Bob est sur un autre sous-réseau (192.168.110.96), désormais séparé par un routeur, mis en place précisément pour la sécurité : la communication n'est plus directe et peut être filtrée. C'est donc la commande n°2, ping 192.168.110.153 vers le poste de Marc, qui a produit l'affichage « 4 received, 0 % packet loss ».

Ce que le correcteur attend : le calcul du ET pour les trois adresses, qui montre que 134 et 153 partagent les trois premiers bits 100 de leur dernier octet alors que 115 commence par 011 ; répondre « la n°2 » sans ce calcul ne justifie rien.

Poser une question au tuteur sur ce sujet