Solution de s-celles pour À l'aise

intro crypto

5 décembre 2024

Le chiffrement de Vigenère

C’est un chiffrement par substitution polyalphabétique inventé par Blaise de Vigenère au XVIe siècle.

Principe :

  1. On prend une clé (ici “FCSC”)
  2. On la répète pour couvrir tout le message à chiffrer
  3. Pour chaque lettre du message :
    • On décale la lettre du message selon la position de la lettre correspondante dans la clé
    • A=0, B=1, C=2, etc.

Exemple :

Message : HELLO
Clé     : FCSCF  (FCSC répété)
Résultat : MELLQ  (H+F, E+C, L+S, L+C, O+F)

Pour chiffrer : (lettre_message + lettre_clé) modulo 26

Pour déchiffrer : (lettre_chiffrée - lettre_clé + 26) modulo 26

Le déchiffrement dans notre cas

  1. Nous avions :

    • Le message chiffré
    • La clé “FCSC”
  2. Notre implémentation :

    function decipher(cipher_char::Char, key_char::Char)
        c = Int(cipher_char) - Int('A')  # Convertit la lettre en nombre (0-25)
        k = Int(key_char) - Int('A')     # Convertit la lettre de clé en nombre
        return Char(((c - k + 26) % 26) + Int('A'))  # Déchiffre et reconvertit en lettre
    end
    
  3. Étapes du déchiffrement :

    • Nettoyage du texte (garder A-Z)
    • Extension de la clé “FCSC” à la longueur du message
    • Application de la formule de déchiffrement sur chaque lettre
    • Reconstruction du message

Cette méthode historique reste un excellent exemple pédagogique de cryptographie, même si elle n’est plus utilisée pour la sécurité moderne. Plus d’informations sur https://fr.wikipedia.org/wiki/Chiffre_de_Vigen%C3%A8re

Créons pour cela dans un éditeur de texte le code Julia suivant (decipher.jl)

"""
Nettoie le texte en gardant uniquement les lettres majuscules A-Z
"""
function clean_text(text::String)
    return join(filter(c -> c in 'A':'Z', uppercase(text)))
end

"""
Ajuste la longueur de la clé pour correspondre à la longueur du message
"""
function adjust_key_length(keyword::String, message_length::Int)
    cleaned_key = clean_text(keyword)
    return repeat(cleaned_key, ceil(Int, message_length/length(cleaned_key)))[1:message_length]
end

"""
Chiffre un caractère unique (dispatch sur Char)
"""
function cipher(message_char::Char, key_char::Char)
    m = Int(message_char) - Int('A')
    k = Int(key_char) - Int('A')
    return Char(((m + k) % 26) + Int('A'))
end

"""
Déchiffre un caractère unique (dispatch sur Char)
"""
function decipher(cipher_char::Char, key_char::Char)
    c = Int(cipher_char) - Int('A')
    k = Int(key_char) - Int('A')
    return Char(((c - k + 26) % 26) + Int('A'))
end

"""
Chiffre un message complet (dispatch sur String)
"""
function cipher(message::String, keyword::String)
    cleaned_message = clean_text(message)
    key = adjust_key_length(keyword, length(cleaned_message))
    return join([cipher(m, k) for (m, k) in zip(cleaned_message, key)])
end

"""
Déchiffre un message complet (dispatch sur String)
"""
function decipher(ciphertext::String, keyword::String)
    cleaned_cipher = clean_text(ciphertext)
    key = adjust_key_length(keyword, length(cleaned_cipher))
    return join([decipher(c, k) for (c, k) in zip(cleaned_cipher, key)])
end

# Message chiffré (ciphertext)
c = "Gqfltwj emgj clgfv ! Aqltj rjqhjsksg ekxuaqs, ua xtwk n'feuguvwb gkwp xwj, ujts f'npxkqvjgw nw tjuwcz ugwygjtfkf qz uw efezg sqk gspwonu. Jgsfwb-aqmu f Pspygk nj 29 cntnn hqzt dg igtwy fw xtvjg rkkunqf."

# Clé donnée
k = "FCSC"

# Déchiffrement
p = decipher(c, k)

println("Message chiffré : ", c)
println("Message en clair : ", p)

Utilisation :

$ julia decipher.jl

Il apparaît dans la console

Message chiffré : Gqfltwj emgj clgfv ! Aqltj rjqhjsksg ekxuaqs, ua xtwk n'feuguvwb gkwp xwj, ujts f'npxkqvjgw nw tjuwcz ugwygjtfkf qz uw efezg sqk gspwonu. Jgsfwb-aqmu f Pspygk nj 29 cntnn hqzt dg igtwy fw xtvjg rkkunqf.
Message en clair : BONJOURCHERAGENTVOTREPROCHAINEMISSIONSIVOUSLACCEPTEZBIENSURSERADINFILTRERLERESEAUSOUTERRAINOUSECACHENOSENNEMISRENDEZVOUSANANTESLEAVRILPOURLEDEBUTDEVOTREMISSION

Le flag est donc FCSC{NANTES}.