Solution de JosephLerouxBook pour À l'aise

intro crypto

2 janvier 2025

Introduction et théorie

Avant toute chose, il faut se renseigner concrètement sur le chiffrement de Vigenere. C’est un chiffrement par clé dans lequel on va soustraire la valeur du caractère de la clé à la valeur de la lettre à déchiffrer.

Par exemple : A chiffrer : C = 3 Clé : B = 1 En le chiffrant, on va ajouter B à C, ou, 3 + 1 = 4, la 4ème lettre de l’alphabet étant D, on a alors D. pour le déchiffrer, on va faire l’inverse : D - B = 4 - 1 = 3, on retrouve notre C

Malheureusement, en langage machine, les lettres de l’alphabet ne sont pas numérotées de 0 à 25, mais elles sont représentées par un ensemble de valeurs numériques correspondant à leurs valeurs ASCII. Ces valeurs sont différentes entre majuscule et minuscule, chose qui n’est pas prise en compte dans l’algorithme de Vigenere. Tout comme les caractères spéciaux, dans ce type de chiffrement nous gardons les caractères spéciaux tels quels.

On va donc chercher à appliquer cet algorithme à la chaîne donnée.

Mise en place - Powershell

Tout d’abord, on va convertir notre phrase chiffrée pour n’avoir que des caractères majuscules (ou minuscules, l’essentiel est d’avoir un seul type de lettre)

$ciphered = "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."

$ciphered = $ciphered.ToUpper()

Ensuite on va parcourir caractère par caractère le texte chiffré tout en vérifiant si le caractère en cours est bien une simple lettre :

for($i = 0; $i -ne $ciphered.Length; $i++){ #Parcours la chaines chiffrer
    $isSpecial = isSpecial -toTest $ciphered[$i]
    if ($isSpecial -eq $true){ #Vérification : si le charactère est spécial, 
        $unciphered += $ciphered[$i] #Alors on le copie sans chiffrer (et donc sans incrémenter la clé
    }
    else{ #Pas Charactere spécial

Pour assurer la vérification du caractère spécial, on va créer une fonction isSpecial() :

function isSpecial {
    Param([Char] $toTest)
    if ($toTest -notmatch '[A-Za-z]'){
       return $true
    } else {
        return $false
    }
}

Puis on va pouvoir appliquer notre conversion en sachant qu’en ASCII l’intervalle A-Z est 65-90.

        $char = $ciphered[$i]
        $asciChar = [int][char]$ciphered[$i] #Conversion du charactere en valeur ASCII
        $asciKey = [int][char]$key[$keyIndex] #Conversion du charactere de la clé en valeur ASCII
        
        $newChar = (($asciChar - $asciKey + 26) % 26) + 65 #Conversion, on ajoute 26 pour eviter de gerer les nombre négatif avec %. puis on ajoute 65 pour retourner dans l'interval "A-Z"
        $unciphered += [char]$newChar #On ajoute le charactere dechiffrer
        $keyIndex = ($keyIndex + 1) % $key.Length #Incrementation de la clé

Comme on le voit ici :

 $newChar = (($asciChar - $asciKey + 26) % 26) + 65

Lors de la conversion, le chiffre récupéré peut être négatif si le caractère de la clé est supérieur au caractère chiffré. Pour remédier à cela, on va ajouter 26, puis récupérer le reste par 26 afin d’obtenir une valeur correspondant à la position dans l’alphabet de la lettre (0-25). À cette valeur, on va ajouter 65 pour retourner dans notre intervalle A-Z

Code complet

#Fonctions verifiant si le charactere envoyer est un charactere spécial.
function isSpecial {
    Param([Char] $toTest)
    if ($toTest -notmatch '[A-Za-z]'){
       return $true
    } else {
        return $false
    }
}

#Programme principal
$ciphered = "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."
#Le chiffrement de Vigenere ne prend pas en compte : la casse et les charactere spéciaux, donc on passe tout en majuscule
$ciphered = $ciphered.ToUpper()

$key = "FCSC"
$unciphered = " "
$keyIndex = 0
for($i = 0; $i -ne $ciphered.Length; $i++){ #Parcours la chaines chiffrer
    $isSpecial = isSpecial -toTest $ciphered[$i]
    if ($isSpecial -eq $true){ #Vérification : si le charactère est spécial, 
        $unciphered += $ciphered[$i] #Alors on le copie sans chiffrer (et donc sans incrémenter la clé
    }
    else{ #Pas Charactere spécial
        $char = $ciphered[$i]
        $asciChar = [int][char]$ciphered[$i] #Conversion du charactere en valeur ASCII
        $asciKey = [int][char]$key[$keyIndex] #Conversion du charactere de la clé en valeur ASCII
        
        $newChar = (($asciChar - $asciKey + 26) % 26) + 65 #Conversion, on ajoute 26 pour eviter de gerer les nombre négatif avec %. puis on ajoute 65 pour retourner dans l'interval "A-Z"
        $unciphered += [char]$newChar #On ajoute le charactere dechiffrer
        $keyIndex = ($keyIndex + 1) % $key.Length #Incrementation de la clé
    }

    <# #Troubleshoot
    Write-Host "Current char = " $ciphered[$i]
    Write-Host "Current key = "$key[$keyIndex]
    Write-Host "Unciphered = $($unciphered[$i])"
    Write-Host "Return of IsSpecial = $isSpecial"
    Write-Host ""
    #>
}

$unciphered

PS : il existe de nombreux autres langages plus adaptés à ce genre d’exercice, ici l’idée a été d’utiliser ce langage de script que j’aime tant plutôt que de le faire en 3 lignes dans d’autres langages. Cette méthodologie est l’exemple concret du : “Ce n’est pas parce qu’on est unique qu’on est meilleure.” À bon entendeur.