Travaux Pratiques n°3

chiffrement d'un fichier

Instructions

Ces travaux pratiques sont à effectuer seul.

Les réponses aux exercices sont à envoyer à mon adresse mail avant la séance suivante.

Chiffrement d'un fichier

L'objectif de ces travaux pratiques est de créer une classe Secret qui permet de chiffrer un fichier lu depuis un stockage de masse (disque dur, clef USB, ...) et d'écrire le résultat dans un autre fichier.

Pour commencer, nous allons utiliser un chiffrement à clé symétrique extrêmement simple : XOR2 (OU exclusif), dont le principe est décrit par l'algorithme ci-dessous.

L'algorithme de chiffrement se base sur une clé qui est représentée par une chaine de caractères. Le message original est traité octet par octet et chacun de ces octets subit un XOR avec l'octet correspondant dans la clef. Si la clef est trop courte, on reprend au début de celle-ci pour la suite du message.

En réalité le XOR est fait bit à bit sur chacun des octets. Mais le langage nous permet un raccourci en écrivant un XOR octet par octet. Il s'occupe lui même de descendre au niveau du bit.

données
 - cle  : la chaine de caractères représentant la clé de chiffrement
 - Fin  : le fichier à chiffrer
 - Fout : le fichier chiffré
 - bfi  : tampon de lecture
 - bfo  : tampon d'écriture


N ← taille de cle en octets
tant que il reste des octets dans Fin faire
	bfi ← lire au plus N octets depuis Fin
	pour chaque octet O de bfi faire
		bfo[O] ← bfi[O] XOR cle[O]
	fin pour
	ecrire bfo dans Fout
fin tant que
Algorithme de chiffrement d'un fichier.

La table logique du OU exclusif est la suivante :

^01
001
110

Par exemple, si l'un des octets de la clef est 01000010 et que l'octet correspondant, dans le message à coder est 01011000, nous obtenons l'octet du chiffre suivant :

  0100001066 (code ASCII de 'B')
^0101100088 (code ASCII de 'X')
= 0001101026 (code ASCII de 'sup')

On remarque dans l'exemple précédent que le caractère correspondant au code obtenu n'est pas un caractère affichable. Le fichier chiffré ne sera donc pas forcément affichable à l'écran.

Mais ce chiffrement est réversible, c'est à dire qu'il est possible de retrouver le message original à partir du message chiffré. Dans notre cas, le déchiffrement se fait à l'aide du même procédé en utilisant la même clef.

Réalisation

Vous réaliserez une classe qui aura un attribut qui sera la clef de chiffrement. Cette clef devra impérativement être précisée au moment de l'instanciation d'un objet de la classe, mais pourra être modifiée plus tard via une méthode publique dédiée.

Enfin, la classe devra proposer au moins deux méthodes :

  1. int chiffrer(char *, char *) ; qui chiffrera le fichier dont le nom est le premier argument et écrira le résultat dans le fichier dont le nom est le second argument.
  2. int decriffrer(char *, char *) ; qui déchiffrera le fichier dont le nom est le premier argument et écrira le résultat dans le fichier dont le nom est le second argument.

Ces deux méthodes retourneront 0 si tout s'est bien passé ou un code différent de 0 s'il y a eu un problème.

Les opérations de lecture et d'écriture dans un fichier se font à l'aide de la classe fstream. Cette classe fait partie de l'IOstream Library et hérite de la classe ios. Vous aurez donc sans doute besoin de lire les descriptions de certaines méthodes de ces classes.

Nous utiliserons plus particulièrement ici les méthodes de lecture et d'écriture non formatée (méthodes read() et write()). Ceci pour nous abstraire de toute contrainte relative à l'encodage des caractères et à la gestion des caractères spéciaux tels que les espaces ou les fins de lignes. Et de toutes manières, rien ne précise que notre message original devra ressembler de près ou de loin à un texte.

Pour que cela soit possible, il faut que l'ouverture des fichiers, en lecture et en écriture, se fasse en mode binaire. Il sera donc nécessaire de passer ios::binary aux différentes méthodes open().

Vous prendrez également soin de bien vérifier la validité de vos opérations sur les fichiers : l'ouverture s'est bien passée alors je peux continuer ; la lecture se fait correctement à chaque étape ; je pense à fermer mes fichiers une fois les opérations de lecture et d'écriture terminées.

Vous pourrez également vous intéresser aux méthodes fail() et gcount() de la classe ios (et donc disponibles dans fstream), qui permettent respectivement de savoir s'il y a eu un problème pendant la lecture et combien d'octets ont été lus si tous n'ont pas pû être lus (cas de la fin du fichier).

En C++, le XOR est représenté par l'opérateur ^. C'est un XOR qui est réalisé bit à bit sur ses opérandes. Par exemple :

int main(int argc, char *argv[])
{
int a, b, c ;  // entiers codés sur 32 bits

a = 31 ;       // 00000000 00000000 00000000 00011111
b = 248 ;      // 00000000 00000000 00000000 11111000
c = a ^ b ;    // 00000000 00000000 00000000 11100111 soit 231

cout << a << " ^ " << b << " = " << c << endl ;

return 0 ;
}

Exercice

Écrivez une classe Secret qui réponde aux caractéristiques décrites ci-dessus. Procédez par étape, n'essayez pas de tout écrire d'un coup.

Écrivez un programme d'exemple qui utilise votre classe Secret et qui chiffre un fichier passé comme premier paramètre au programme et qui écrit le résultat dans un autre fichier passé comme second paramètre au programme (il faudra utiliser les arguments de la fonction main).

Pour aller plus loin

Cette partie n'est pas à réaliser dans le cadre des travaux pratiques. Cependant, si vous avez aimé programmer cette classe et que vous désirez en savoir un peu plus sur les méthodes de chiffrement à clé symétrique, faire ce qui suit sera instructif.

Les algorithmes de chiffrement à clef symétrique sont nombreux. Vous pouvez modifier le code de votre méthode chiffrer() pour que l'algorithme soit différent (et par la même occasion, plus robuste) sans que l'interface de votre classe ne change.

Pour information vous pouvez vous intéresser aux méthodes de chiffrement DES et AES. Attention, ces méthodes ne sont pas simples à mettre en œuvre. Si vous vous lancez dedans, soyez patients.


  1. [↑] http://fr.wikipedia.org/wiki/Chiffrement
  2. [↑] http://fr.wikipedia.org/wiki/OU_exclusif
  3. [↑] pour les classes et méthodes associées, reportez vous au site http://www.cplusplus.com/
  4. [↑] http://fr.wikipedia.org/wiki/Data_Encryption_Standard
  5. [↑] http://fr.wikipedia.org/wiki/Advanced_Encryption_Standard