Python & Cryptographie niveau lycée : Chiffrement par substitution

# Substitution simple

def subSimple(phrase:str, decalage:int):
    phrase = phrase.upper()
    chiffrement = ''
    for c in phrase:
        if 'A' <= c <= 'Z':
            position = (ord(c) - 65 + decalage) % 26
            chiffrement += chr(65 + position)
        else:
            chiffrement += c
    return chiffrement

# Substitution double (avec clé numérique)

def subDouble(phrase:str, decalage):
    phrase = phrase.upper()
    chiffrement = ''
    longueur = len(decalage)
    for i,c in enumerate(phrase):
        if 'A' <= c <= 'Z':
            position = (ord(c) - 65 + decalage[i % longueur]) % 26
            chiffrement += chr(65 + position)
        else:
            chiffrement += c
    return chiffrement            

# Substitution avec mot-clé

def fabriqueAlphabet(cle:str):
    lettres = list(cle.upper()) + [chr(v) for v in range(65, 91)]
    alphabet = ''
    for c in lettres:
        if c not in alphabet: alphabet += c
    tailleCle = len(set(cle))
    alphabetFinal = ''
    for col in range(tailleCle):
        suiv = col
        while suiv < 26:
         alphabetFinal += alphabet[suiv]
         suiv += tailleCle       
    return alphabetFinal

def subCleSimple(phrase:str,cle:str):
    alphabet = fabriqueAlphabet(cle)
    phrase = phrase.upper()
    chiffrement = ''
    for c in phrase:
        if 'A' <= c <= 'Z':
            chiffrement += alphabet[ord(c) - 65]
        else:
            chiffrement += c
    return chiffrement 

Python & Cryptographie niveau lycée : Déchiffrement des substitutions

def decryptSimple(phrase:str):
    freq = [0] * 26
    for c in phrase:
     if 'A' <= c <= 'Z':
         freq[ord(c) - 65] += 1
    decal = 4 - freq.index(max(freq))
    return subSimple(phrase, decal)

def decryptDouble(phrase:str, taille:int):
    clair = ''
    res = []
    for i in range(taille):
     res.append(decryptSimple(phrase[i::taille]))
    return ''.join(''.join(v) for v in zip(*res))

def inverseAlphabet(chiffre:str, clair:str):
    alphabetDecode = ''
    for i in range(65, 91):
      c = chr(i)
      if c in chiffre: code = clair[chiffre.index(c)]
      else: code = '?'
      alphabetDecode += code     
    return alphabetDecode 

def decryptEnPartie(phrase:str,alphabet:str):
    alphabet = alphabet.upper()
    phrase = phrase.upper()
    chiffrement = ''
    for c in phrase:
        if 'A' <= c <= 'Z':
            chiffrement += chr(65 + alphabet.index(c))
        else:
            chiffrement += c
    return chiffrement 

Exemples de textes :

clair = 'CHOISISSEZUNTRAVAILQUEVOUSAIMEZETVOUSNAUREZPASATRAVAILLERUNSEULJOURDEVOTREVIE'
# Clé numérique [3, 2, 1, 0]
crypte = 'FJPIVKTSHBVNWTBVDKMQXGWOXUBIPGAEWXPUVPBUUGAPDUBTUCWALNMEUWOSHWMJRWSDHXPTUGWIH'

# Extrait du livre "Le petit Prince"

princeClair = 'LESGRANDESPERSONNESMONTCONSEILLEDELAISSERDECOTELESDESSINSDESERPENTSBOASOUVERTSOUFERMESETDEMINTERESSERPLUTOTALAGEOGRAPHIEALHISTOIREAUCALCULETALAGRAMMAIRECESTAINSIQUEJAIABANDONNEALAGEDESIXANSUNEMAGNIFIQUECARRIEREDEPEINTREJAVAISETEDECOURAGEPARLINSUCCESDEMONDESSINNUMERO1ETDEMONDESSINNUMEROLESGRANDESPERSONNESNECOMPRENNENTJAMAISRIENTOUTESSEULESETCESTFATIGANTPOURLESENFANTSDETOUJOURSETTOUJOURSLEURDONNERDESEXPLICATIONSJAIDONCDUCHOISIRUNAUTREMETIERETJAIAPPRISAPILOTERDESAVIONSJAIVOLEUNPEUPARTOUTDANSLEMONDEETLAGEOGRAPHIECESTEXACTMABEAUCOUPSERVIJESAVAISRECONNAITREDUPREMIERCOUPDŒILLACHINEDELARIZONACESTTRESUTILESILONESTEGAREPENDANTLANUITJAIAINSIEUAUCOURSDEMAVIEDESTASDECONTACTSAVECDESTASDEGENSSERIEUXJAIBEAUCOUPVECUCHEZLESGRANDESPERSONNESJELESAIVUESDETRESPRESCANAPASTROPAMELIOREMONOPINIONQUANDJENRENCONTRAISUNEQUIMEPARAISSAITUNPEULUCIDEJEFAISAISLEXPERIENCESURELLEDEMONDESSINNUMERO1QUEJAITOUJOURSCONSERVEJEVOULAISSAVOIRSIELLEETAITVRAIMENTCOMPREHENSIVEMAISTOUJOURSELLEMEREPONDAITCESTUNCHAPEAUALORSJENELUIPARLAISNIDESERPENTSBOASNIDEFORETSVIERGESNIDETOILESJEMEMETTAISASAPORTEEJELUIPARLAISDEBRIDGEDEGOLFDEPOLITIQUEETDECRAVATESETLAGRANDEPERSONNEETAITBIENCONTENTEDECONNAITREUNHOMMEAUSSIRAISONNABLE'

princeChiffre = 'OGTGUCODHUQEUUPNQGTMRPUCRPTELNMEGGMALUTEUFFCRVFLHUEEVUJNVFFSHTQEQVTBRCTOXXFRWUPUIGSMHUFTGGNIQVFRHUTEURMUWQUAOCHERISASJJEDNIIVVPIUGBUFCMCXNFTDNBGUCNMDKSEFGTTDKOSLSVEMCJAECODRPOEDNBGHFFSLZBNVWOEPCHNLHJQXGDAUTJEUGEESGJNWTFJDXBIVGUEGGDOXTBGHRBROKOSXEDEVFFMRPEEVUJNQWNEUQ1EWFFMRPEEVUJNQWNEUQMEVISAQFFSSGSSRPOEVPFCROQRHPOEQVKAPCJSUKFNWQVTHUTEXNFSHVDEVVGAWKHAQVQOXTMEVGOFDPUSGGUOXLPUUUFTWQVJRWSSOGVRGQONHTEEVGYPOKDAWKPNVLBIGQOCGWDHRKTIUWOAXVSEPGUIHTFTMCJASRSIVCQIOQUEUFFSDXJOQUKALXPLHWOPHWQAUVPUWFBNVNFMRPEEHVMAJGPGUCQHLGDEVVFXDEUMDDFAXEPUSUFRYKKEVCWALUSEFQONDKURHFVPUGNIHTDOXREŒLNMAFJJNHFFLDTJZRPBCHUUTUGTUWKMEVKMOQGTTHIBRHRFNGCOTOCOULVKALCJNVKFUDWDOXTTDHOBVLGEEVVBSGGDOQVBCWUBVHEEEVVBSGGHEQUTEUKFUALBIEGBUFQVPYGDUFJFZOGTGUCODHUQEUUPNQGTJHNFSDKWUHUEEWTFSSTFSFCOASCTTUQQAPGMIRTFMRPPPLPJOQSVAQFKEQTFNFQOTUCJSXPFQXKNESCSALUTALVVNSGVLXEJDHLFFDKTALUMEARFRLGOCHUVRHNMEGGNOQFFSVKONXOFRR1RUHLBIWQVJRWSSFQOSHTWEMGWOXNBIVUBVRKSSLGMLHGUALVWRDKNEQVDOPRSEKGOSLXFMDKTTRWKOXTTEONFMHTFPRPEALVDEVVVNFJBPHCVAOQSSMGOEOWJPDTMALUOIGGTEURFNWUCODUOIGGGOUGUSYKFRJGTNLFFTRKMEVLFMHOFTWCJSDUBPRTUEHLFLXKQAUNBIVFFBUKEGHFFGRNGDHRPLLVJQXGFTGGDRDXBTHUFTOCHRDPEESGSSRPOEHVBIWDJEQEPNWGOTHFFCRPOALVSEXPIOPOFAXUTIUCJSRPOAENF'