ROT13

Où l'on code des messages pour les rendre (un peu) secrets…

IPT Sup

Introduction

Le ROT13 (de l'anglais « rotate by 13 places ») est un cas particulier du chiffre de César, un algorithme simpliste de chiffrement de texte. Comme son nom l'indique, il s'agit de décaler chaque lettre du texte à chiffrer de 13 places. Son principal aspect pratique est que le codage et le décodage se font exactement de la même manière. En effet, puisque l'alphabet comporte 26 lettres, il suffit de décaler deux fois de 13 caractères pour revenir à la lettre de départ.

Cependant, contrairement à d'autres méthodes de cryptographie (où l'intérêt réside dans le fait qu'il est difficile voire impossible de lire le message si l'on n'a pas le code pour le décoder), il s'agit plus ici de faire en sorte que le message ne soit pas lisible directement mais qu'il soit néanmoins possible de l'obtenir sans grosses difficultés.

Démonstration :

Qu'est-ce qui fait nioc nioc ?
Ha pnaneq dhv antr n y'rairef.

Nous allons programmer cette méthode, ainsi que quelques variantes.

Caractères et code ASCII

Les caractères usuels sont, dans la version la plus simple, codés par un entier compris en 32 et 126. Ce codage, qui date de 1963, s'appelle le code ASCII (pour American Standard Code for Information Interchange). Avec ce code, la virgule est le caractère numéro 44, le A est le caractère 65.

En Python, deux fonctions permettent de manipuler ces codes. La fonction ord permet d'obtenir le numéro d'un caractère donné, alors que chr permet d'avoir le caractère correspondant à un numéro donné.

Question Essayez les commandes suivantes, pour vérifier que vous avez bien compris.

>>> chr(63)
>>> ord('A')
>>> chr(ord('A') + 4)

Question Quel est le code ASCII du caractère : ? Quel est le caractère de code 48 ?

Question Écrire une suite d'instruction pour que la variable ascii, de type str, contienne tous les caractères ASCII dans l'ordre.

Remarque Le code ASCII comporte un gros inconvénient : Mis au point par les américains, il ne code pas les accents et plus généralement, les lettres avec signes diacritiques (comme les accents, trémas, cédilles, etc.). C'est d'ailleurs compréhensible, car rien que pour les langues latines, le nombre de lettres avec signe diacritique est trop important pour qu'il soit possible de coder un caractères sur un octet.

Cela a eu pour conséquence facheuse qu'afin d'inclure les diacritiques, de nombreux codages ont été mis au point, incompatibles entre eux. La conséquence a été que pendant longtemps, à cause de ces problèmes de codage, il était fréquent de croiser des choses comme :

« La vie n'est bonne qu'àétudier et àenseigner les mathématiques. »
— Blaise Pascal

La situation s'améliore maintenant avec la création du code Unicode. En Python 3, les chaînes de caractères sont codées en utf-8, la version usuelle de l'Unicode. Les caractères du code ASCII se retrouvent avec le même code en utf-8.

Remarque En utf-8, les caractères accentués y sont codés sur deux octets. On peut le voir en Python 2, qui n'est pas configuré par défaut pour utiliser l'utf-8, en tapant les instructions suivantes :

>>> len("e")
>>> len("é")

Mais Python 3, plus habitué à l'utf-8, sait comment découper les chaînes de caractères, et donc voit "é" comme un unique caractère.

Pour la suite du TP, on commencera par ne traîter que des chaînes de caractères non accentués.

L'implémentation du ROT13

À partir de maintenant, nous allons écrire un ensemble de fonctions pour implémenter le codage ROT13. Les fonctions suivantes sont donc à écrire dans un ficher plutôt que dans la console.

Commençons par les majuscules.

Question Quels sont les lettres majuscules dont le chiffrage par ROT13 revient à ajouter 13 au code ASCII ? Et celles pour lesquelles on retranche 13 ? Quels sont les codes ASCII correspondants ?

Question Écrire une fonction carrot13 (qui applique rot13 aux caractères, ou car) qui prends en entrée un caractère c, et retourne un caractère qui est :

  • soit c si ce n'est pas une lettre majuscule
  • le caractère obtenu à partir de c après chiffrage par ROT13 si c'est une lettre majuscule.

On veut par exemple avoir :

>>> carrot13('i')
'i'
>>> carrot13('B')
'O'
>>> carrot13(',')
','

Question Modifier la fonction précédente pour que le chiffrage ROT13 s'applique aussi aux lettres minuscules.

Question Écrire une fonction rot13 qui prends en entrée une chaîne de caractères et retourne la chaîne de caractères où toutes les lettres ont subi un chiffrage ROT13.

Question Trouver la réponse à la question du début.

Une variante, le ROT47

Une variante du chiffrage ROT13 et le ROT47, qui utilise tous les caractères du code ASCII excepté l'espace. Cela correspond donc aux caractères allant du code 33 au code 126 (en particulier, on laisse inchangé le caractère numéro 32, qui est l'espace). Cela représente donc 12633+1=94=2×47{`126 - 33 + 1 = 94 = 2 \\times 47`} caractères. On décale donc tous les codes de 47, et deux décalages ramènent au caractère de départ.

Question pour les PTSI1 Programmez la méthode de chiffrage ROT47, et déchiffrez la phrase suivante :

Attention Le caractère ` est un accent grave et non une apostrophe. Son code ASCII est 96.

Question pour les PTSI2 Programmez la méthode de chiffrage ROT47, et déchiffrez la phrase suivante :

Comment supprimer les accents et autres

Jusqu'à présent, nous avons supposé que les textes à chiffrer ne contenaient aucun signe diacritique. Pour traiter des textes généraux, il faut tout d'abord les supprimer. Pour ne pas surcharger les fonctions qui suivent, on ne traîtera que les minuscules. L'ajout du traîtement des majuscules ne complique pas les fonctions, il ne fait que les allonger.

Question Écrire une fonction desaccente qui, étant donné une chaîne de caractères, la retourne après avoir supprimé les accents et autres signes diacritiques.

On rappelle qu'en français, les lettres diacritées usuelles sont

à â ä ç é è ê ë î ï ô ö ù û ü

Question Modifiez la fonction desaccente pour qu'elle transforme les ligatures æ et œ en ae et oe respectivement.

Remarque Sous Windows, on entrera les caractères æ et œ en tapant respectivement alt + 0 2 3 0 et alt + 0 1 5 6. Sous MacOS X, on utilisera alt + a et alt + o et, sous Linux, altGr + a et altGr + o.

Le code de César

Le chiffrage ROT13 consiste donc, si vous avez bien suivi, à décaler les lettres de 13 rangs, éventuellement en bouclant. Une telle méthode de chiffrage est appelée code de César, en mémoire de Jules César qui en utilisait un version, comme le montre la citation suivante :

« Il y employait, pour les choses tout à fait secrètes, une espèce de chiffre qui en rendait le sens inintelligible (les lettres étant disposées de manière à ne pouvoir jamais former un mot), et qui consistait, je le dis pour ceux qui voudront les déchiffrer, à changer le rang des lettres dans l'alphabet, en écrivant la quatrième pour la première, c'est-à-dire le d pour le a, et ainsi de suite. »
— Suétone, Vie des douze Césars, Livre I, paragraphe 56.

César utilisait donc un décalage de 4, et le ROT13 un décalage de 13. On peut en fait utiliser pour effectuer le décalage tout entier compris entre 1 et 25.

Question Écrire une fonction cesar qui prends en argument un tel entier n et une chaîne de caractère, et retourne le texte codé par un décalage des lettres de n places.