Aller au contenu

Chiffrement de César

Indice d'un caractère

Ecrire un corps possible pour la fonction suivante:

def indice(lettre, chaine):
    """
    chaine -- chaine de caractère
    lettre -- caractère
    renvoie -1 si lettre n'est pas un caractère de chaine
    renvoie l'indice de la première occurrence de lettre dans chaine sinon
    """
Solution
def indice(lettre, chaine):
    """
    chaine -- chaine de caractère
    lettre -- caractère
    renvoie -1 si lettre n'est pas un caractère de chaine
    renvoie l'indice de la première occurrence de lettre dans chaine sinon
    """
    for i, c in enumerate(chaine):
        if c == lettre:
            return i
    return -1

Le principe du chiffrement de César

Pour crypter ses messages, Jules César utilisait un principe simple de décalage.

L'idée est exposée ci-dessous. On associe à chaque lettre de l'aphabet un entier naturel de 0 à 25 comme indiqué sur le cercle ci-dessous:

Chiffre de César

Remarque

En langage Python, cette association est simple.

On définit:

alphabet = "abcdefghijklmnopqrstuvwxyz"

Et ainsi:

>>> alphabet[0]
'a'
>>> alphabet[25]
'z'
>>> alphabet[2]
'c'

Et pour coder un message, on décide de décaler cette association. Par exemple, on choisit un décalage de 3 de sorte que:

  • au lieu d'écrire la lettre 'a' qui est associée à 0, on écrira la lettre associée à 0+3 c'est à dire la lettre 'd'.
  • au lieu d'écrire la lettre 'b' qui est associée à 1, on écrira la lettre associée à 1+3 c'est à dire la lettre 'e'.
  • ...
  • au lieu d'écrire la lettre 'w' qui est associée à 22, on écrira la lettre associée à 22+3 c'est à dire la lettre 'z'.
  • au lieu d'écrire la lettre 'x' qui est associée à 23, on écrira la lettre associée à 23+3... zut, comment faire ?

Pour clarifier le cas des lettres x, y, z dans le cas de ce décalage de 3, revenez au cercle représenté plus haut et avancez de trois "pas" sur le cercle:

  • au lieu d'écrire la lettre 'x' qui est associée à 23, on écrira la lettre 'a' associée à 0 = (23+3)%26 (reste de la division euclidienne de 23+3 par 26).
  • au lieu d'écrire la lettre 'y' qui est associée à 24, on écrira la lettre 'b' associée à 1 = (24+3)%26.
  • au lieu d'écrire la lettre 'z' qui est associée à 25, on écrira la lettre 'c' associée à 2 = (25+3)%26.

Chiffre de César

Ainsi "abcz" devient "defc" avec le décalage 3.

Exercice

Ecrire un corps possible pour la fonction suivante:

def substitution(caractere, decalage):
    """
    caractere -- lettre (minuscule, non accentuée) de l'alphabet ou caractère de ponctuation
    decalage -- entier entre 1 et 25
    renvoie la lettre de substitution suivant césar 
    ou le caractère lui-même en cas de caractère de ponctutation
    """
Solution
def indice(lettre, chaine):
    """
    chaine -- chaine de caractère
    lettre -- caractère
    renvoie -1 si lettre n'est pas un caractère de chaine
    renvoie l'indice de la première occurrence de lettre dans chaine sinon
    """
    for i, c in enumerate(chaine):
        if c == lettre:
            return i
    return -1

def substitution(caractere, decalage):
    """
    caractere -- lettre (minuscule, non accentuée) de l'alphabet ou caractère de ponctuation
    decalage -- entier entre 1 et 25
    renvoie la lettre de substitution suivant césar 
    (ou le caractère lui-même en cas de caractère de ponctuation)
    """
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    rang = indice(caractere, alphabet)
    if rang != -1:
         return alphabet[(rang+decalage)%26]
    else:
        return caractere

Exercice

Écrire une fonction

  • prenant en paramètres un message (type chaîne de caractères, on se permettra d'éviter toute lettre accentuée pour simplifier ici le code) et un entier (entre 1 et 25) correspondant au décalage à effectuer.
  • et renvoyant en sortie la version cryptée du message.
xq frgh srvvleoh
def indice(lettre, chaine):
    """
    chaine -- chaine de caractère
    lettre -- caractère
    renvoie -1 si lettre n'est pas un caractère de chaine
    renvoie l'indice de la première occurrence de lettre dans chaine sinon
    """
    for i, c in enumerate(chaine):
        if c == lettre:
            return i
    return -1

def substitution(caractere, decalage):
    """
    caractere -- lettre (minuscule, non accentuée) de l'alphabet ou caractère de ponctuation
    decalage -- entier entre 1 et 25
    renvoie la lettre de substitution suivant césar 
    (ou le caractère lui-même en cas de caractère de ponctuation)
    """
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    rang = indice(caractere, alphabet)
    if rang != -1:
         return alphabet[(rang+decalage)%26]
    else:
        return caractere

def cesar(message, decalage):
    """
    message -- chaîne de caractères constituée de lettres minusucules de l'aphabet sans accent
    decalage -- entier entre 1 et 25
    renvoie la version cryptée du message à la César avec le décalage decalage.
    """
    message_crypte = ''
    for caractere in message:
        message_crypte += substitution(caractere, decalage)     
    return message_crypte

Exercice

Écrire maintenant une fonction de décryptage.

Solution

La fonction de cryptage convient pour le décryptage: il suffit de prendre le décalage opposé !

Exemple (si vous n'avez pas su décrypter le petit message de la solution précédente):

>>> cesar("xq frgh srvvleoh", -3)
'un code possible'