Aller au contenu

Un mot pour Fahmio

Tu écris. Tu continues.

Un problème, une idée — assez pour qu’on comprenne, puis tu retournes à ta copie.

On lit. Tu n’as rien d’autre à faire.

Où veux-tu aller ?

↑ ↓ pour parcourir · Entrée pour ouvrir · Échap pour fermer

Fahmio
Fahmio
Bac Tunisie
FE-GFichiers, enregistrements et matrices

Cryptage d'un fichier texte selon un procédé décrit pas à pas : rang, transformation, lettre, puis décryptage

Idée directrice

Le sujet décrit un procédé de cryptage en étapes numérotées, illustré par un exemple complet. On rejoue d'abord l'exemple à la main, puis on traduit chaque étape en instructions : lettre → rang avec Ord(c) − Ord("A"), transformation du rang (Mod 26, OU exclusif, permutation…), rang → lettre avec Chr. La fonction qui crypte une ligne est appelée dans le parcours standard du fichier texte : Lire_ligne dans le fichier source, Ecrire_nl dans le fichier résultat. Le décryptage applique la transformation inverse ; ses pièges sont la clé qui ne permet pas de revenir et le reste d'un nombre négatif.

Ce qui aide à reconnaître la démarche

« Le cryptage de chaque mot se fait en trois étapes décrites comme suit » ; « Parmi les méthodes de cryptage utilisées pour crypter un texte … » ; « crypter le contenu d'un fichier texte …, ligne par ligne, et enregistrer le résultat dans un 2ᵉ fichier texte » ; « Exemple : … d'où le cryptage du mot … donne le mot … »

Besoin d’un point de départ ? Voir la méthode
  • Rejouer l'exemple de l'énoncé avant d'écrire : il fixe le rang de "A" (0 ou 1), le sort des espaces et l'ordre des étapes.
  • Lettre → rang : Ord(c) − Ord("A") ; rang → lettre : Chr(r + Ord("A")). Aucun tableau de correspondance n'est à déclarer.
  • Trois niveaux de modules : une fonction qui transforme une ligne (chaîne → chaîne), une procédure qui parcourt le fichier (Lire_ligne → fonction → Ecrire_nl), le programme principal qui saisit la clé et appelle.
  • Décrypter, c'est appliquer les étapes inverses dans l'ordre inverse ; ajouter 26 avant de réduire Mod 26 une différence qui peut être négative.
  • Contrôler la clé à la saisie par la condition exacte donnée par l'énoncé.
Les pièges à vérifier dans ta démarche

Crypter aussi les espaces (Ord(" ") − Ord("A") est négatif). Écrire Chr(y) au lieu de Chr(y + Ord("A")). Ouvrir le fichier source en "w" : il est effacé avant d'être lu. Écrire la ligne cryptée avec Ecrire au lieu de Ecrire_nl : toutes les lignes se collent. Décrypter avec (y − b) Mod 26 sans ajouter 26. Accepter une clé a paire ou égale à 13 : deux lettres différentes donnent alors la même lettre cryptée, et le décryptage devient impossible. Appeler Inverse(a) à chaque lettre.

Sujet principal

Problème — cryptage d'un fichier texte (10 points), dans l'esprit des sessions 2017–2021

12 questionsCorrigé masqué

Pour échanger des messages confidentiels, une association crypte le contenu d'un fichier texte nommé "Clair.txt", enregistré dans le dossier D:\Secret. Chaque ligne de ce fichier contient un message formé de mots écrits en lettres majuscules et séparés par un seul espace ; une ligne compte au plus 60 caractères.

Le cryptage utilise une clé formée de deux entiers a et b. Chaque lettre est cryptée en trois étapes :

Étape 1 : remplacer la lettre par son rang X dans l'alphabet : "A" a le rang 0, "B" le rang 1, …, "Z" le rang 25.

Étape 2 : calculer l'entier Y défini par :

Y=(a×X+b) Mod 26Y=(a\times X+b)\ \mathrm{Mod}\ 26

Étape 3 : remplacer Y par la lettre de rang Y.

Les espaces ne sont pas cryptés : chacun reste à sa place.

Exemple : pour la clé a = 7 et b = 3, la lettre "C" a le rang X = 2 ; Y = (7 × 2 + 3) Mod 26 = 17, qui est le rang de la lettre "R". En procédant de même pour chaque lettre, le mot "BAC" devient "KDR".

Pour que le décryptage soit possible, deux lettres différentes ne doivent jamais donner la même lettre cryptée. On admet que c'est le cas si et seulement si a est un entier impair de [1..25], différent de 13. L'entier b est choisi dans [0..25].

Une lettre cryptée de rang Y se décrypte en la lettre de rang X donné par :

X=(a′×(Y−b+26)) Mod 26X=\big(a'\times(Y-b+26)\big)\ \mathrm{Mod}\ 26

où a' est l'inverse de a modulo 26, c'est-à-dire l'unique entier de [1..25] tel que (a × a') Mod 26 = 1. Par exemple, pour a = 7, on a a' = 15.

On se propose d'écrire un programme qui :

  • saisit une clé (a, b) valide ;
  • crée, dans le dossier D:\Secret, le fichier texte "Crypte.txt" dont chaque ligne est le cryptage de la ligne de même rang du fichier "Clair.txt" ;
  • affiche ensuite le décryptage de chaque ligne de "Crypte.txt", afin de vérifier qu'on retrouve le contenu du fichier "Clair.txt".

Travail demandé :

  1. Dans cette question, la clé est a = 7 et b = 3.
    1. Crypter à la main le mot "CODE" en donnant, pour chaque lettre, les valeurs de X et de Y.
    2. Crypter à la main le mot "ZERO".
    3. Vérifier, à l'aide de la formule de décryptage, que la lettre cryptée "R" redonne la lettre "C".
  2. On choisit la clé a = 13 et b = 3. Crypter les lettres "A" et "C", puis expliquer pourquoi cette clé est refusée.
  3. Écrire l'algorithme du programme principal, solution à ce problème, en le décomposant en modules, et dresser le tableau de déclaration des objets globaux.
  4. Écrire l'algorithme d'une procédure Saisir(a, b) qui saisit une clé valide.
  5. Écrire l'algorithme d'une fonction CrypterLigne(ligne, a, b) qui retourne le cryptage d'une ligne du fichier "Clair.txt".
  6. Écrire l'algorithme d'une procédure Codage(ch1, ch2, a, b) qui lit le fichier dont le chemin est ch1 ligne par ligne et écrit chaque ligne cryptée dans le fichier dont le chemin est ch2.
  7. Écrire l'algorithme d'une fonction DecrypterLigne(ligne, a, b) qui retourne le décryptage d'une ligne du fichier "Crypte.txt".
  8. Écrire l'algorithme d'une procédure Verifier(ch2, a, b) qui affiche le décryptage de chaque ligne du fichier dont le chemin est ch2.
  9. Le fichier "Clair.txt" contient les deux lignes BAC INFO et LE CODE SECRET. Donner le contenu du fichier "Crypte.txt" obtenu avec la clé a = 7 et b = 3.

NB : le candidat n'est pas appelé à remplir le fichier "Clair.txt". On dispose de la fonction Inverse(a), qui retourne l'inverse a' de a modulo 26 ; le candidat peut l'utiliser sans la développer. Les tableaux de déclaration des objets locaux accompagnent chaque module.

Voir la correction commentéeAprès avoir posé votre démarche

1.a Idée : on applique les trois étapes lettre par lettre ; seul le reste de la division par 26 demande de l'attention.

LettreX7X + 3YLettre cryptée
"C"21717"R"
"O"1410123"X"
"D"32424"Y"
"E"4315"F"

Le mot "CODE" devient "RXYF"\boxed{\text{"RXYF"}}.

1.b Même calcul. Pour "Z", 7 × 25 + 3 = 178 et 178 = 6 × 26 + 22 : le reste 22 ramène au début de l'alphabet, c'est la lettre "W".

LettreX7X + 3YLettre cryptée
"Z"2517822"W"
"E"4315"F"
"R"1712218"S"
"O"1410123"X"

Le mot "ZERO" devient "WFSX"\boxed{\text{"WFSX"}}.

1.c "R" a le rang Y = 17 et a' = 15 (en effet 7 × 15 = 105 = 4 × 26 + 1). On calcule 15 × (17 − 3 + 26) = 15 × 40 = 600, et 600 = 23 × 26 + 2 : X = 2, c'est bien la lettre "C".

2. Avec a = 13 et b = 3 : "A" donne 13 × 0 + 3 = 3, soit "D" ; "C" donne 13 × 2 + 3 = 29, et 29 Mod 26 = 3, soit encore "D". Deux lettres différentes ont la même lettre cryptée : en lisant "D", on ne peut pas savoir s'il faut revenir à "A" ou à "C". Le décryptage est impossible, d'où le refus de cette clé (13 × X Mod 26 ne prend que les valeurs 0 et 13).

3. Idée : un module par tâche de l'énoncé — saisir la clé, crypter le fichier, vérifier. Les deux fonctions sur une ligne sont appelées à l'intérieur de Codage et de Verifier.

Algorithme Cryptage_affine
DEBUT
    Saisir (a, b)
    Codage ("D:\Secret\Clair.txt", "D:\Secret\Crypte.txt", a, b)
    Verifier ("D:\Secret\Crypte.txt", a, b)
FIN
ObjetType / NatureRôle
a, bEntierClé de cryptage
SaisirProcédureSaisir une clé valide
CodageProcédureCréer "Crypte.txt" à partir de "Clair.txt"
VerifierProcédureAfficher le décryptage de "Crypte.txt"

4. Idée : la condition de l'énoncé se recopie telle quelle dans le Jusqu'à : a impair, entre 1 et 25, différent de 13 ; b entre 0 et 25.

Procédure Saisir (@ a, @ b : Entier)
DEBUT
    Répéter
        Ecrire ("a = ")
        Lire (a)
    Jusqu'à (a ≥ 1) Et (a ≤ 25) Et (a Mod 2 = 1) Et (a ≠ 13)
    Répéter
        Ecrire ("b = ")
        Lire (b)
    Jusqu'à (b ≥ 0) Et (b ≤ 25)
FIN

a et b sont tous deux passés par adresse : chacun porte son propre @ (écrire « @ a, b » passerait b par valeur, et la valeur saisie serait perdue au retour).

5. Idée : un seul parcours de la ligne. Un espace est recopié ; une lettre passe par les trois étapes : Ord pour le rang, le calcul de Y, Chr pour revenir à une lettre.

Fonction CrypterLigne (ligne : Chaîne, a, b : Entier) : Chaîne
DEBUT
    res ← ""
    Pour i de 0 à Long (ligne) - 1 Faire
        Si ligne[i] = " " Alors
            res ← res + " "
        Sinon
            x ← Ord (ligne[i]) - Ord ("A")
            y ← (a * x + b) Mod 26
            res ← res + Chr (y + Ord ("A"))
        Fin Si
    Fin Pour
    Retourner res
FIN
ObjetType / NatureRôle
resChaîneLigne cryptée en construction
iEntierIndice du caractère traité
x, yEntierRang de la lettre, rang de la lettre cryptée

6. Idée : c'est le parcours standard d'un fichier texte ; la transformation est déléguée à CrypterLigne. Le fichier source s'ouvre en lecture ("r"), le fichier résultat en création ("w").

Procédure Codage (ch1, ch2 : Chaîne, a, b : Entier)
DEBUT
    Ouvrir (ch1, Fc, "r")
    Ouvrir (ch2, Fk, "w")
    Tant que Non (Fin_fichier (Fc)) Faire
        Lire_ligne (Fc, ligne)
        Ecrire_nl (Fk, CrypterLigne (ligne, a, b))
    Fin Tant que
    Fermer (Fc)
    Fermer (Fk)
FIN
ObjetType / NatureRôle
Fc, FkFichier texteFichiers "Clair.txt" et "Crypte.txt"
ligneChaîneLigne lue dans "Clair.txt"
CrypterLigneFonctionCrypter une ligne

Ecrire_nl termine chaque ligne écrite : "Crypte.txt" a autant de lignes que "Clair.txt", dans le même ordre.

7. Idée : même parcours que CrypterLigne, avec la formule inverse. On ajoute 26 avant de réduire : y − b est compris entre −25 et 25, donc y − b + 26 est positif et le reste Mod 26 est bien celui attendu.

Fonction DecrypterLigne (ligne : Chaîne, a, b : Entier) : Chaîne
DEBUT
    inv ← Inverse (a)
    res ← ""
    Pour i de 0 à Long (ligne) - 1 Faire
        Si ligne[i] = " " Alors
            res ← res + " "
        Sinon
            y ← Ord (ligne[i]) - Ord ("A")
            x ← (inv * (y - b + 26)) Mod 26
            res ← res + Chr (x + Ord ("A"))
        Fin Si
    Fin Pour
    Retourner res
FIN
ObjetType / NatureRôle
invEntierInverse de a modulo 26
resChaîneLigne décryptée en construction
iEntierIndice du caractère traité
x, yEntierRang de la lettre claire, rang de la lettre cryptée
InverseFonctionFonction disponible (inverse modulo 26)

Inverse(a) est appelée une seule fois, avant la boucle, et non pour chaque lettre.

8. Idée : "Crypte.txt" a été fermé à la fin de Codage ; on le rouvre en lecture et on affiche, ligne par ligne, le résultat de DecrypterLigne.

Procédure Verifier (ch2 : Chaîne, a, b : Entier)
DEBUT
    Ouvrir (ch2, Fk, "r")
    Tant que Non (Fin_fichier (Fk)) Faire
        Lire_ligne (Fk, ligne)
        Ecrire (DecrypterLigne (ligne, a, b))
    Fin Tant que
    Fermer (Fk)
FIN
ObjetType / NatureRôle
FkFichier texteFichier "Crypte.txt"
ligneChaîneLigne lue dans "Crypte.txt"
DecrypterLigneFonctionDécrypter une ligne

9. Les espaces restent en place et les mots "BAC" et "CODE" donnent "KDR" et "RXYF", comme à l'exemple et à la question 1.a :

KDR HQMX
CF RXYF ZFRSFG

Verifier affiche alors BAC INFO puis LE CODE SECRET : on retrouve bien le contenu de "Clair.txt".

Changer d’énoncé, garder le raisonnement

Choisis un seul transfert après le sujet principal. Qu’est-ce qui change ? Quel résultat ou quelle méthode peux-tu réutiliser ? Les autres exercices restent disponibles pour une prochaine séance.

Variantes rencontrées : cryptage de chaque mot d'un fichier texte F par Y = (22 × X) Mod 26, écrit dans un fichier FC (principale 2021) ; OU exclusif bit à bit avec une clef binaire de N bits, message complété par des antislashs puis découpé en blocs, de Initial.txt vers Final.txt (contrôle 2019) ; chiffrement par une matrice 6 × 6 puis par un mot-clé dont on trie les colonnes (principale 2019) ; codes ASCII hexadécimaux par blocs de trois caractères rangés dans une matrice, puis écrits colonne par colonne dans code.txt (contrôle 2017) ; mots de passe cryptés octet par octet, décryptés dans un tableau d'enregistrements (contrôle 2026). Dans les devoirs de lycée : décalage de p positions dans l'alphabet et substitution par un « tableau occupé ».

Exercices d'entraînement — une nuance à la fois

1 Drill FE-G.1 — OU exclusif avec une clef binaire : compléter, découper en blocs, crypter chaque ligne d'un fichier
Entraînement 01 / 04

Drill FE-G.1 — OU exclusif avec une clef binaire : compléter, découper en blocs, crypter chaque ligne d'un fichier

10 questionsCorrigé masqué

On veut crypter le contenu d'un fichier texte nommé "Initial.txt", ligne par ligne, et enregistrer le résultat dans un second fichier texte nommé "Final.txt". Chaque ligne de "Initial.txt" contient un message d'au plus 30 caractères. La clef est une chaîne formée de 0 et de 1 dont la longueur N est un multiple de 7, au plus 21.

Chaque caractère est représenté sur 7 bits par l'écriture en base 2 de son code ASCII. Le cryptage d'une ligne msg se fait ainsi :

  • Étape 1 : ajouter le caractère antislash \ à la fin de msg autant de fois que nécessaire pour que sa longueur soit un multiple de N Div 7 ;
  • Étape 2 : découper msg en blocs de N Div 7 caractères consécutifs ;
  • Étape 3 : remplacer chaque bloc par la concaténation des représentations sur 7 bits de ses caractères ;
  • Étape 4 : appliquer à chaque bloc un OU exclusif bit à bit avec la clef (deux bits égaux donnent 0, deux bits différents donnent 1) ;
  • Étape 5 : concaténer les résultats dans l'ordre des blocs.

On donne les codes ASCII : "B" = 66, "a" = 97, "c" = 99 et 92 pour l'antislash \.

Travail demandé :

  1. La clef est 10110100111001.
    1. Donner le message complété et les blocs obtenus pour la ligne "Bac".
    2. Donner la représentation binaire de chaque bloc, puis la ligne cryptée.
  2. Écrire l'algorithme d'une fonction Bin7(c) qui retourne la représentation sur 7 bits du code ASCII du caractère c.
  3. Écrire l'algorithme d'une fonction OUex(b1, b2) qui retourne le OU exclusif bit à bit de deux chaînes binaires de même longueur.
  4. Écrire l'algorithme d'une procédure Crypter(ch1, ch2, clef) qui crée le fichier "Final.txt" (chemin ch2) à partir du fichier "Initial.txt" (chemin ch1).
  5. Montrer, sur le bloc Ba de la question 1, qu'un second OU exclusif avec la même clef redonne la représentation binaire du bloc. Qu'en déduit-on pour le décryptage ?
Voir la correction commentéeAprès avoir posé votre démarche

1.a Idée : N = 14, donc un bloc contient 14 Div 7 = 2 caractères ; la longueur de la ligne doit devenir paire.

"Bac" a 3 caractères : on ajoute un seul antislash. Le message complété est Bac\ ; les blocs sont Ba et c\.

1.b 66 = 1000010, 97 = 1100001, 99 = 1100011 et 92 = 1011100 en base 2 sur 7 bits.

bloc Ba : 10000101100001
clef    : 10110100111001
OUex    : 00110001011000

bloc c\ : 11000111011100
clef    : 10110100111001
OUex    : 01110011100101

La ligne cryptée est la concaténation des deux résultats : 0011000101100001110011100101 (28 bits).

2. Idée : exactement 7 divisions par 2 ; chaque reste est placé à gauche de ceux déjà obtenus, ce qui garde les zéros de tête.

Fonction Bin7 (c : Caractère) : Chaîne
DEBUT
    n ← Ord (c)
    b ← ""
    Pour j de 1 à 7 Faire
        b ← Chr (Ord ("0") + n Mod 2) + b
        n ← n Div 2
    Fin Pour
    Retourner b
FIN
ObjetType / NatureRôle
nEntierCode ASCII, divisé par 2 à chaque tour
bChaîneReprésentation binaire en construction
jEntierCompteur des 7 bits

3. Idée : on compare les deux chaînes position par position.

Fonction OUex (b1, b2 : Chaîne) : Chaîne
DEBUT
    r ← ""
    Pour i de 0 à Long (b1) - 1 Faire
        Si b1[i] = b2[i] Alors
            r ← r + "0"
        Sinon
            r ← r + "1"
        Fin Si
    Fin Pour
    Retourner r
FIN
ObjetType / NatureRôle
rChaîneRésultat en construction
iEntierPosition du bit comparé

4. Idée : pour chaque ligne lue, l'étape 1 est une boucle Tant que (la ligne peut déjà avoir la bonne longueur), puis une boucle sur les blocs, extraits avec Sous_chaine.

Procédure Crypter (ch1, ch2, clef : Chaîne)
DEBUT
    Ouvrir (ch1, Fi, "r")
    Ouvrir (ch2, Ff, "w")
    nb ← Long (clef) Div 7
    Tant que Non (Fin_fichier (Fi)) Faire
        Lire_ligne (Fi, msg)
        Tant que Long (msg) Mod nb ≠ 0 Faire
            msg ← msg + "\"
        Fin Tant que
        res ← ""
        Pour k de 0 à Long (msg) Div nb - 1 Faire
            bloc ← Sous_chaine (msg, k * nb, (k + 1) * nb)
            bb ← ""
            Pour j de 0 à nb - 1 Faire
                bb ← bb + Bin7 (bloc[j])
            Fin Pour
            res ← res + OUex (bb, clef)
        Fin Pour
        Ecrire_nl (Ff, res)
    Fin Tant que
    Fermer (Fi)
    Fermer (Ff)
FIN
ObjetType / NatureRôle
Fi, FfFichier texteFichiers "Initial.txt" et "Final.txt"
msgChaîneLigne lue, puis complétée
nbEntierNombre de caractères par bloc
k, jEntierNuméro du bloc, position dans le bloc
bloc, bbChaîneBloc de caractères, sa représentation binaire
resChaîneLigne cryptée
Bin7, OUexFonctionReprésentation sur 7 bits, OU exclusif

La borne finale de Sous_chaine est exclue : le bloc k occupe les indices k × nb à (k + 1) × nb − 1.

5. On reprend le résultat obtenu pour le bloc Ba :

OUex    : 00110001011000
clef    : 10110100111001
OUex    : 10000101100001

On retrouve la représentation binaire de "Ba", car deux OU exclusifs avec le même bit s'annulent. Pour décrypter, on applique donc le même OU exclusif avec la même clef à chaque bloc de N bits, puis on relit les caractères 7 bits par 7 bits ; les antislashs ajoutés en fin de ligne sont ensuite retirés.

2 Drill FE-G.2 — mot-clé et lecture par colonnes : remplir une matrice, trier ses colonnes, relire colonne par colonne
Entraînement 02 / 04

Drill FE-G.2 — mot-clé et lecture par colonnes : remplir une matrice, trier ses colonnes, relire colonne par colonne

8 questionsCorrigé masqué

Chaque ligne d'un fichier texte "Messages.txt" contient un message d'au plus 30 caractères, formé de lettres majuscules et d'espaces. On veut crypter chaque ligne à l'aide d'un mot-clé de 5 lettres majuscules distinctes, et écrire le résultat, une ligne par message, dans le fichier texte "Chiffre.txt".

Le cryptage d'un message msg se fait en trois étapes :

  • Étape 1 : remplir une matrice M de caractères à 5 colonnes : la première ligne (ligne 0) reçoit les lettres du mot-clé ; les lignes suivantes reçoivent msg, caractère par caractère, en commençant par la première case de la ligne 1. Les cases restées vides reçoivent un espace.
  • Étape 2 : trier les lettres de la ligne 0 dans l'ordre alphabétique croissant, sachant que tout déplacement d'une lettre entraîne le déplacement de toute sa colonne.
  • Étape 3 : concaténer les caractères de M colonne par colonne, de la première à la dernière, sans la ligne 0 : on obtient le message crypté.

Travail demandé :

  1. Pour le mot-clé "TUNIS" et le message "BAC BLANC DEMAIN", donner la matrice M après l'étape 1, puis après l'étape 2, et le message crypté (on notera ␣ chaque espace).
  2. Écrire l'algorithme d'une procédure Remplir(M, cle, msg, nl) qui réalise l'étape 1 et retourne dans nl le nombre de lignes occupées par le message.
  3. Écrire l'algorithme d'une procédure TrierColonnes(M, nl) qui réalise l'étape 2.
  4. Écrire l'algorithme d'une fonction Lecture(M, nl) qui réalise l'étape 3.
  5. Écrire l'algorithme d'une procédure Chiffrer(ch1, ch2, cle) qui crée le fichier "Chiffre.txt" (chemin ch2) à partir du fichier "Messages.txt" (chemin ch1).

NB : on dispose du type Mat = Tableau de 7 × 5 caractères (lignes 0 à 6, colonnes 0 à 4).

Voir la correction commentéeAprès avoir posé votre démarche

1. Idée : 16 caractères sur 5 colonnes occupent 4 lignes (16 = 3 × 5 + 1) ; les 4 dernières cases reçoivent un espace. Le tri déplace des colonnes entières.

Après l'étape 1 :

col 0col 1col 2col 3col 4
ligne 0TUNIS
ligne 1BAC␣B
ligne 2LANC␣
ligne 3DEMAI
ligne 4N␣␣␣␣

Après l'étape 2 (ordre I, N, S, T, U) :

col 0col 1col 2col 3col 4
ligne 0INSTU
ligne 1␣CBBA
ligne 2CN␣LA
ligne 3AMIDE
ligne 4␣␣␣N␣

En lisant les colonnes de haut en bas sans la ligne 0, le message crypté est "␣CA␣CNM␣B␣I␣BLDNAAE␣" (20 caractères).

2. Idée : le k-ième caractère de msg (k à partir de 0) va dans la case (1 + k Div 5, k Mod 5). On initialise d'abord toutes les cases utiles par un espace.

Procédure Remplir (@ M : Mat, cle, msg : Chaîne, @ nl : Entier)
DEBUT
    nl ← (Long (msg) + 4) Div 5
    Pour j de 0 à 4 Faire
        M[0, j] ← cle[j]
    Fin Pour
    Pour i de 1 à nl Faire
        Pour j de 0 à 4 Faire
            M[i, j] ← " "
        Fin Pour
    Fin Pour
    Pour k de 0 à Long (msg) - 1 Faire
        M[1 + k Div 5, k Mod 5] ← msg[k]
    Fin Pour
FIN
ObjetType / NatureRôle
i, j, kEntierLigne, colonne, position dans msg

3. Idée : un tri à bulles sur les lettres de la ligne 0 ; chaque échange porte sur les nl + 1 cases de deux colonnes voisines.

Procédure TrierColonnes (@ M : Mat, nl : Entier)
DEBUT
    Répéter
        echange ← Faux
        Pour j de 0 à 3 Faire
            Si M[0, j] > M[0, j + 1] Alors
                Pour i de 0 à nl Faire
                    aux ← M[i, j]
                    M[i, j] ← M[i, j + 1]
                    M[i, j + 1] ← aux
                Fin Pour
                echange ← Vrai
            Fin Si
        Fin Pour
    Jusqu'à Non (echange)
FIN
ObjetType / NatureRôle
i, jEntierLigne, colonne
auxCaractèreVariable d'échange
echangeBooléenVrai si un échange a eu lieu pendant le passage

4.

Fonction Lecture (M : Mat, nl : Entier) : Chaîne
DEBUT
    res ← ""
    Pour j de 0 à 4 Faire
        Pour i de 1 à nl Faire
            res ← res + M[i, j]
        Fin Pour
    Fin Pour
    Retourner res
FIN
ObjetType / NatureRôle
resChaîneMessage crypté
i, jEntierLigne, colonne

La boucle sur les colonnes est la boucle extérieure : c'est ce qui fait lire la matrice colonne par colonne.

5. Idée : le parcours standard du fichier texte, les trois étapes étant appelées pour chaque ligne lue.

Procédure Chiffrer (ch1, ch2, cle : Chaîne)
DEBUT
    Ouvrir (ch1, Fm, "r")
    Ouvrir (ch2, Fc, "w")
    Tant que Non (Fin_fichier (Fm)) Faire
        Lire_ligne (Fm, msg)
        Remplir (M, cle, msg, nl)
        TrierColonnes (M, nl)
        Ecrire_nl (Fc, Lecture (M, nl))
    Fin Tant que
    Fermer (Fm)
    Fermer (Fc)
FIN
ObjetType / NatureRôle
Fm, FcFichier texteFichiers "Messages.txt" et "Chiffre.txt"
msgChaîneMessage lu
MMatMatrice du cryptage
nlEntierNombre de lignes occupées par le message
Remplir, TrierColonnesProcédureÉtapes 1 et 2
LectureFonctionÉtape 3
3 Drill FE-G.3 — décrypter des mots de passe octet par octet et les charger dans un tableau d'enregistrements
Entraînement 03 / 04

Drill FE-G.3 — décrypter des mots de passe octet par octet et les charger dans un tableau d'enregistrements

8 questionsCorrigé masqué

Les accès des abonnés d'une médiathèque sont stockés dans un fichier texte nommé "Acces.txt", enregistré dans le dossier D:\Media. Le fichier contient au plus 500 lignes. Chaque ligne contient un login formé exactement de huit chiffres, le caractère "#", puis un mot de passe crypté : une séquence de 0 et de 1 où chaque caractère du mot de passe occupe un octet (8 bits).

Pour chaque octet, le décryptage se fait en trois étapes :

  • Étape 1 : inverser chaque bit de l'octet (0 devient 1 et 1 devient 0) ;
  • Étape 2 : convertir l'octet obtenu de la base 2 vers la base 10 ;
  • Étape 3 : déterminer le caractère ayant ce code ASCII.

Exemple : la ligne 20417356#10101100100100001001001111001011 contient le login 20417356 ; le premier octet 10101100 devient 01010011, soit 83, code ASCII de "S". Les trois autres octets donnent "o", "l" et "4" : le mot de passe décrypté est "Sol4".

Travail demandé :

  1. Décrypter à la main le mot de passe de la ligne 58312047#10111101100001111100100010001110 en détaillant les trois étapes pour chaque octet.
  2. Déclarer le type enregistrement Abonne, formé des champs Login et Pwd (chaînes), et le type TabA, tableau de 500 abonnés.
  3. Écrire l'algorithme d'une fonction DecrypterOctet(oct) qui retourne le caractère correspondant à une chaîne oct de 8 bits.
  4. Écrire l'algorithme d'une procédure Charger(T, NE) qui lit le contenu du fichier "Acces.txt" ligne par ligne et remplit le tableau T par les logins et les mots de passe décryptés, puis retourne dans NE le nombre d'abonnés.
  5. Écrire l'algorithme d'une fonction Autoriser(T, NE, lg, mp) qui retourne Vrai si le couple (lg, mp), saisi en clair, figure dans T, et Faux sinon.

NB : les chaînes et les tableaux sont indexés à partir de 0 ; la borne finale de Sous_chaine est exclue.

Voir la correction commentéeAprès avoir posé votre démarche

1. Idée : on découpe la partie qui suit "#" en octets de 8 bits, puis on applique les trois étapes à chacun.

OctetÉtape 1Étape 2Étape 3
101111010100001066"B"
1000011101111000120"x"
110010000011011155"7"
1000111001110001113"q"

Le mot de passe décrypté est "Bx7q"\boxed{\text{"Bx7q"}}.

2.

Nouveaux types
Abonne = Enregistrement
Login : Chaîne
Pwd : Chaîne
Fin
TabA = Tableau de 500 Abonne

Le login reste une chaîne : un entier perdrait les zéros de tête d'un login comme "04512873".

3. Idée : on n'écrit pas l'octet inversé ; on lit les bits de gauche à droite et on accumule la valeur, en comptant 1 pour un bit "0" et 0 pour un bit "1" : l'inversion et la conversion se font dans la même boucle.

Fonction DecrypterOctet (oct : Chaîne) : Caractère
DEBUT
    code ← 0
    Pour j de 0 à 7 Faire
        Si oct[j] = "0" Alors
            code ← 2 * code + 1
        Sinon
            code ← 2 * code
        Fin Si
    Fin Pour
    Retourner Chr (code)
FIN
ObjetType / NatureRôle
codeEntierCode ASCII en construction
jEntierPosition du bit lu

4. Idée : le login occupe les indices 0 à 7, "#" l'indice 8 ; les octets commencent à l'indice 9 et se suivent de 8 en 8.

Procédure Charger (@ T : TabA, @ NE : Entier)
DEBUT
    Ouvrir ("D:\Media\Acces.txt", F, "r")
    NE ← 0
    Tant que Non (Fin_fichier (F)) Faire
        Lire_ligne (F, ligne)
        T[NE].Login ← Sous_chaine (ligne, 0, 8)
        T[NE].Pwd ← ""
        p ← 9
        Tant que p < Long (ligne) Faire
            T[NE].Pwd ← T[NE].Pwd + DecrypterOctet (Sous_chaine (ligne, p, p + 8))
            p ← p + 8
        Fin Tant que
        NE ← NE + 1
    Fin Tant que
    Fermer (F)
FIN
ObjetType / NatureRôle
FFichier texteFichier "Acces.txt"
ligneChaîneLigne lue
pEntierIndice du début de l'octet courant
DecrypterOctetFonctionDécrypter un octet

NE est incrémenté après le remplissage de T[NE] : à la fin, il vaut le nombre de lignes lues.

5. Idée : recherche séquentielle avec arrêt dès que le couple est trouvé ; le login et le mot de passe doivent correspondre dans le même enregistrement.

Fonction Autoriser (T : TabA, NE : Entier, lg, mp : Chaîne) : Booléen
DEBUT
    i ← 0
    Tant que (i < NE) Et Non ((T[i].Login = lg) Et (T[i].Pwd = mp)) Faire
        i ← i + 1
    Fin Tant que
    Retourner i < NE
FIN
ObjetType / NatureRôle
iEntierIndice de parcours de T
4 Drill FE-G.4 — substitution par un « tableau occupé » : crypter chaque mot d'un fichier, décrypter par lecture directe (devoirs)
Entraînement 04 / 04

Drill FE-G.4 — substitution par un « tableau occupé » : crypter chaque mot d'un fichier, décrypter par lecture directe (devoirs)

6 questionsCorrigé masqué

Exercice des devoirs de lycée (substitution par une table) : ce procédé n'a pas été relevé tel quel dans les sujets nationaux.

Un tableau T de N lettres majuscules (5 < N < 27), d'indices 0 à N − 1, est dit occupé si T contient exactement les N premières lettres de l'alphabet et si aucune case ne contient la lettre de même rang que son indice (T[k] ≠ Chr(k + Ord("A"))).

On crypte un mot en remplaçant chacune de ses lettres par la lettre de rang k, où k est l'indice de la case de T qui contient cette lettre. Si une lettre du mot ne figure pas dans T, le mot ne peut pas être crypté.

On donne N = 8 et le tableau T suivant, où la colonne du milieu rappelle la lettre de rang égal à l'indice :

Indice kLettre de rang kT[k]
0AE
1BH
2CA
3DG
4EB
5FC
6GF
7HD

Chaque ligne du fichier texte "Mots.txt" contient un mot en lettres majuscules. On veut créer le fichier texte "Codes.txt", à raison d'une ligne par mot : le mot crypté, ou le texte impossible si le mot ne peut pas être crypté.

Travail demandé :

  1. Justifier que T est occupé. Le tableau (E, B, A, G, H, C, F, D) l'est-il ?
  2. Crypter les mots "CAFE" et "BAIE" à l'aide de T, puis décrypter le mot "GCHA".
  3. Écrire l'algorithme d'une fonction Occupe(T, N) qui vérifie si T est occupé.
  4. Écrire l'algorithme d'une fonction Crypter(mot, T, N) qui retourne le mot crypté, ou la chaîne vide s'il ne peut pas être crypté.
  5. Écrire l'algorithme d'une fonction Decrypter(mot, T) qui retourne le mot clair.
  6. Écrire l'algorithme d'une procédure Coder(ch1, ch2, T, N) qui lit le fichier "Mots.txt" (chemin ch1) ligne par ligne et crée le fichier "Codes.txt" (chemin ch2).

NB : on dispose du type Tab = Tableau de 26 caractères.

Voir la correction commentéeAprès avoir posé votre démarche

1. Idée : deux conditions à vérifier, les N premières lettres présentes une seule fois, et aucune lettre à la place de même rang.

T contient E, H, A, G, B, C, F, D : ce sont les lettres A à H, chacune une fois. Et aucune case ne contient la lettre de son rang (T[0] = "E" ≠ "A", T[1] = "H" ≠ "B", …, T[7] = "D" ≠ "H"). T est donc occupé. Le tableau (E, B, A, G, H, C, F, D) ne l'est pas : sa case d'indice 1 contient "B", la lettre de rang 1.

2. Idée : crypter, c'est chercher la case qui contient la lettre ; décrypter, c'est lire la case dont l'indice est le rang de la lettre.

"C" est dans la case 5, de rang "F" ; "A" dans la case 2 ("C") ; "F" dans la case 6 ("G") ; "E" dans la case 0 ("A"). Donc "CAFE" devient "FCGA"\boxed{\text{"FCGA"}}. "BAIE" contient "I", qui n'est pas dans T : ce mot ne peut pas être crypté.

Pour "GCHA" : T[6] = "F", T[2] = "A", T[7] = "D", T[0] = "E". Le mot clair est "FADE"\boxed{\text{"FADE"}}.

3. Idée : compter les apparitions de chaque lettre de rang k ; T est occupé si chacune apparaît exactement une fois et si T[k] ne la contient pas.

Fonction Occupe (T : Tab, N : Entier) : Booléen
DEBUT
    ok ← Vrai
    k ← 0
    Tant que ok Et (k < N) Faire
        c ← Chr (k + Ord ("A"))
        nb ← 0
        Pour i de 0 à N - 1 Faire
            Si T[i] = c Alors
                nb ← nb + 1
            Fin Si
        Fin Pour
        ok ← (nb = 1) Et (T[k] ≠ c)
        k ← k + 1
    Fin Tant que
    Retourner ok
FIN
ObjetType / NatureRôle
okBooléenVrai tant qu'aucune condition n'est violée
k, iEntierRang de la lettre testée, indice de parcours
cCaractèreLettre de rang k
nbEntierNombre d'apparitions de c dans T

N lettres présentes une fois chacune parmi N cases : T contient donc exactement les N premières lettres.

4. Idée : une recherche séquentielle par lettre ; si la recherche échoue, on s'arrête et on retourne la chaîne vide.

Fonction Crypter (mot : Chaîne, T : Tab, N : Entier) : Chaîne
DEBUT
    res ← ""
    i ← 0
    possible ← Vrai
    Tant que possible Et (i < Long (mot)) Faire
        k ← 0
        Tant que (k < N) Et (T[k] ≠ mot[i]) Faire
            k ← k + 1
        Fin Tant que
        Si k < N Alors
            res ← res + Chr (k + Ord ("A"))
            i ← i + 1
        Sinon
            possible ← Faux
        Fin Si
    Fin Tant que
    Si possible Alors
        Retourner res
    Sinon
        Retourner ""
    Fin Si
FIN
ObjetType / NatureRôle
resChaîneMot crypté en construction
i, kEntierPosition dans le mot, indice de recherche dans T
possibleBooléenFaux dès qu'une lettre est absente de T

5. Idée : aucune recherche ; le rang de la lettre cryptée est l'indice de la case à lire.

Fonction Decrypter (mot : Chaîne, T : Tab) : Chaîne
DEBUT
    res ← ""
    Pour i de 0 à Long (mot) - 1 Faire
        res ← res + T[Ord (mot[i]) - Ord ("A")]
    Fin Pour
    Retourner res
FIN
ObjetType / NatureRôle
resChaîneMot clair en construction
iEntierPosition dans le mot

6.

Procédure Coder (ch1, ch2 : Chaîne, T : Tab, N : Entier)
DEBUT
    Ouvrir (ch1, Fm, "r")
    Ouvrir (ch2, Fc, "w")
    Tant que Non (Fin_fichier (Fm)) Faire
        Lire_ligne (Fm, mot)
        code ← Crypter (mot, T, N)
        Si code = "" Alors
            Ecrire_nl (Fc, "impossible")
        Sinon
            Ecrire_nl (Fc, code)
        Fin Si
    Fin Tant que
    Fermer (Fm)
    Fermer (Fc)
FIN
ObjetType / NatureRôle
Fm, FcFichier texteFichiers "Mots.txt" et "Codes.txt"
mot, codeChaîneMot lu, mot crypté
CrypterFonctionCrypter un mot

Crypter est appelée une seule fois par mot et son résultat est gardé dans code, au lieu de l'appeler une fois pour le test et une fois pour l'écriture.

Relier ce raisonnement au bac

Choisis une filière pour voir les sujets qui étayent ce scénario.