Aller au contenu

Le chiffre de César en Python

La fonction tient en dix lignes. Copiez-la, ou saisissez votre texte pour voir ce que le code fait de chaque lettre.

Python 3
def caesar(text, shift):    result = ""    for char in text:        if char.isascii() and char.isalpha():            base = ord("A") if char.isupper() else ord("a")            index = (ord(char) - base + shift) % 26            result += chr(index + base)        else:            result += char    return result print(caesar("Bonjour à tous !", 3))# Erqmrxu à wrxv !
publicité

Comment fonctionne le code

La boucle lit le texte caractère par caractère. ord() transforme une lettre en nombre : ord("A") vaut 65 et ord("a") vaut 97. En retirant cette base, on obtient le rang de la lettre dans l’alphabet, de 0 à 25.

Une fois le décalage ajouté, % 26 revient au début de l’alphabet : avec un décalage de 3, le Z tombe sur le C. chr() repasse ensuite du nombre à la lettre. Si le chiffre lui-même est nouveau pour vous, le guide l’explique sans code.

Les espaces, la ponctuation et les chiffres passent par la branche else sans changer. Il en va de même pour les lettres accentuées, grâce à isascii(). Sans ce test, é compte comme une lettre et, avec un décalage de 3, devient j : impossible ensuite de retrouver le é d’origine.

Déchiffrer en Python

Inutile d’écrire une seconde fonction. Déchiffrer revient à décaler dans l’autre sens : il suffit de passer un nombre négatif.

Python
print(caesar("Erqmrxu à wrxv !", -3))# Bonjour à tous !

Cela fonctionne parce que le % de Python ne donne jamais de négatif ici : (0 - 3) % 26 vaut 23, et le A revient au X. En C, Java et JavaScript, on obtiendrait -3, d’où une étape de plus dans la version JavaScript.

Un programme avec saisie utilisateur

Beaucoup d’exercices demandent un programme qui lit le texte et le décalage au clavier. Ajoutez ceci sous la fonction :

Python
text = input("Texte : ")shift = int(input("Décalage : "))mode = input("Chiffrer ou déchiffrer ? (c/d) : ") if mode == "d":    shift = -shift print(caesar(text, shift))

input() renvoie toujours une chaîne : le décalage doit donc passer par int(). Si l’on tape un mot à la place d’un nombre, Python s’arrête sur une ValueError.

Casser le code par force brute

Avec 26 lettres, il n’y a que 25 décalages à essayer, et une courte boucle suffit pour lire un message sans la clé. Cherchez dans la sortie la ligne qui a du sens :

Python
def crack(text):    for shift in range(1, 26):        print(shift, caesar(text, -shift)) crack("Erqmrxu à wrxv !")# 1 Dqplqwt à vqwu !# 2 Cpokpvs à upvt !# 3 Bonjour à tous !# ...

L’article sur l’attaque par force brute va plus loin, et le casseur en ligne fait la même chose dans votre navigateur.

Une version plus courte avec str.translate

Une fois la boucle comprise, vous pouvez la remplacer par une table de traduction. str.maketrans() associe chaque lettre à sa version décalée, et translate() applique la table à tout le texte. Ici non plus, les accents ne bougent pas.

Python
from string import ascii_lowercase as lower, ascii_uppercase as upper def caesar(text, shift):    shift %= 26    table = str.maketrans(        lower + upper,        lower[shift:] + lower[:shift] + upper[shift:] + upper[:shift],    )    return text.translate(table)

Le résultat est identique, et c’est souvent plus rapide sur un long texte, car la table n’est construite qu’une fois. Pour un premier exercice, la boucle reste plus facile à expliquer.

Autres alphabets et chiffres

Pour décaler autre chose que A à Z, gardez l’alphabet dans une chaîne et cherchez chaque caractère avec index(). Ici, l’alphabet comprend aussi les chiffres :

Python
ALPHABET = "abcdefghijklmnopqrstuvwxyz0123456789" def caesar_alphabet(text, shift):    result = ""    for char in text:        letter = char.lower()        if letter in ALPHABET:            index = (ALPHABET.index(letter) + shift) % len(ALPHABET)            new = ALPHABET[index]            result += new.upper() if char.isupper() else new        else:            result += char    return result print(caesar_alphabet("Salle 101", 3))# Vdooh 434

Le retour au début dépend désormais de len(ALPHABET), et il suffit de modifier la chaîne pour y ajouter é, è ou ç. Notre outil de chiffre de César propose aussi des alphabets tout prêts pour comparer les résultats.

Chiffrer un fichier texte

Lisez le fichier, passez son contenu à la fonction et écrivez le résultat dans un nouveau fichier. Avec encoding="utf-8", les accents restent intacts sur tous les systèmes.

Python
with open("message.txt", encoding="utf-8") as source:    text = source.read() with open("encrypted.txt", "w", encoding="utf-8") as target:    target.write(caesar(text, 3))

Le même chiffre sous forme de classe

Une classe devient utile si vous réutilisez souvent la même clé, ou si un cours exige du code orienté objet. Elle garde le décalage et s’appuie sur la fonction du haut de la page :

Python
class CaesarCipher:    def __init__(self, shift=3):        self.shift = shift     def encrypt(self, text):        return caesar(text, self.shift)     def decrypt(self, text):        return caesar(text, -self.shift) cipher = CaesarCipher(5)print(cipher.encrypt("Bonjour à tous !"))# Gtsotzw à ytzx !

Tester votre code

Quelques lignes assert repèrent la plupart des bugs : dépassement du Z, respect de la casse, ponctuation conservée et retour au texte d’origine. Si tout va bien, le programme affiche OK.

Python
assert caesar("ABC", 3) == "DEF"assert caesar("xyz", 3) == "abc"assert caesar("Hello, World!", 5) == "Mjqqt, Btwqi!"assert caesar(caesar("Python", 7), -7) == "Python"assert caesar("A", 26) == "A"assert caesar("é", 3) == "é"print("OK")

Erreurs fréquentes

Le grand classique consiste à écrire chr(ord(char) + shift) sans modulo : avec un décalage de 3, le Z devient alors le symbole ]. Autre erreur courante, la base 65 appliquée à toutes les lettres, qui abîme les minuscules. Et sans int() autour de input(), Python s’arrête sur une TypeError au moment d’ajouter le décalage.

Questions fréquentes

Quelle version de Python faut-il ?

Python 3.7 ou plus récent, puisque isascii() date de cette version. Nous avons exécuté le code de cette page sous Python 3.9. Aucun paquet supplémentaire n’est nécessaire.

Puis-je protéger de vraies données avec ce code ?

Non. La boucle ci-dessus le casse en quelques secondes. Gardez-le pour apprendre et pour les énigmes, et protégez mots de passe et données privées avec le chiffrement moderne d’une librairie maintenue.

Comment vérifier mon résultat ?

Saisissez le même texte et le même décalage dans notre outil de chiffre de César et comparez. Vous pouvez aussi appeler l’API REST gratuite depuis vos tests.

Pour aller plus loin