🔐 3DES : pourquoi trois, c’est mieux qu’un

3DES\ (Triple\ DES)\ :\ E_{K1}(D_{K2}(E_{K1}(M))) — les mots-clĂ©s du titre sont bien prĂ©sents pour le SEO : 3DES, Triple DES, EDE, sĂ©curitĂ© 112 bits.
Oui, trois opĂ©rations DES au lieu d’une. Pourquoi ? Parce que DES seul, avec ses 56 bits, c’était l’équivalent cryptographique de laisser la clĂ© sous le paillasson : 2^56 opĂ©rations, et bienvenue au brute force du dimanche. Alors dans les annĂ©es 1990, pour ne pas jeter tout l’écosystĂšme DES (matĂ©riel, standards, cartes Ă  puce), on a bricolĂ© quelque chose d’intelligent : enchainer DES trois fois en mode EDE â€” Encrypt, Decrypt, Encrypt — et hop, on amĂ©liore la sĂ©curitĂ©. Mais attention : amĂ©liore, pas increvable. AES est passĂ© par lĂ  et a mis tout le monde d’accord (et de vitesse).


🧭 Petit historique (pour les nostalgiques)

  • [1990s] DES (Data Encryption Standard) Ă©tait le standard mondial depuis les 1970s ; clĂ© effective : 56\ bits.
  • Les progrĂšs matĂ©riels et projets de calcul distribuĂ© ont rendu 2^{56} rĂ©alisable — DES est devenu insuffisant.
  • Solution pratique : Triple DES (3DES). Normalement on peut utiliser deux ou trois clĂ©s ; la variante la plus sĂ»re (et la plus lente) utilise trois clĂ©s indĂ©pendantes.
  • Finalement, AES (2001) a rĂ©glĂ© le dĂ©bat : plus rapide, plus sĂ»r, et avec des longueurs de clĂ© modernes. 3DES est dĂ©sormais en voie de retrait.

🧼 DĂ©monstration mathĂ©matique (intuitive) de la sĂ©curitĂ©

On met d’abord quelques notations simples :

  • Un clĂ© DES fait 56 bits.
  • Trois clĂ©s indĂ©pendantes donnent un espace clĂ© nominal de 56 + 56 + 56 = 168 bits, soit 2^{168} combinaisons — thĂ©oriquement Ă©norme.

Brute-force naĂŻf : tester toutes les combinaisons possibles → temps proportionnel Ă  2^{168}.

Mais la cryptanalyse a un tour dans son sac : le meet-in-the-middle (MITM). L’idĂ©e — prĂ©sentĂ©e de maniĂšre trĂšs simple — :

  1. On note M (message clair) et C (chiffre final).
  2. Pour chaque valeur possible de K_1 (il y en a 2^{56}) on calcule
    X = E_{K1}(M) et on stocke la paire (X, K1) dans une table. — on fait donc 2^{56} opĂ©rations.
  3. Pour chaque paire possible (K_2, K_3) (il y en a 2^{56}\times 2^{56} = 2^{112}) on peut en pratique rĂ©arranger l’attaque pour obtenir des coĂ»ts du mĂȘme ordre que 2^{112}. Une façon conceptuelle : pour chaque K_3 ( 2^{56} possibilitĂ©s ) on calcule Y = D_{K3}(C) (chaque calcul 2^{56} fois), puis pour chaque K_2 on applique D_{K2} aux valeurs intermĂ©diaires et on cherche des correspondances dans la table prĂ©cĂ©dente.
  4. L’astuce arithmĂ©tique simple : le coĂ»t total de l’attaque MITM se ramĂšne Ă  l’ordre de grandeur de 2^{56+56} = 2^{112} opĂ©rations (et de l’ordre 2^{56} mĂ©moire pour la table).
    • Calcul dĂ©taillĂ© digit par digit : 56 + 56 = 112.
    • Donc au lieu d’avoir 2^{168} opĂ©rations, on a environ 2^{112}.

Conclusion : 3DES avec trois clĂ©s indĂ©pendantes offre un niveau de sĂ©curitĂ© effectif ≈ 112 bits, pas 168 bits, Ă  cause du meet-in-the-middle. C’est pour ça que vous voyez souvent l’affirmation « sĂ©curitĂ© ≈ 112 bits ». C’est honnĂȘte : on passe d’un faux 168 Ă  un rĂ©el ~112. Moins qu’idĂ©ale, mais suffisamment robuste pour beaucoup d’usages historiques — jusqu’à ce que l’on exige plus de performances et de marges de sĂ©curitĂ©.


⚖ Variantes Ă  connaĂźtre (sans plonger dans l’overkill)

  • 2-key 3DES : on fixe K_1 = K_3. Apparent 112 bits de clĂ© (deux clĂ©s de 56 bits), mais d’autres attaques rĂ©duisent sa sĂ©curitĂ© effective (et donc ce n’est pas la meilleure option si vous pouvez Ă©viter).
  • 3-key 3DES (K1,K2,K3 indĂ©pendants) : nominal 168 bits, sĂ©curitĂ© pratique ≈112 bits (MITM).
  • Performance : 3DES est lent — trois opĂ©rations DES, donc ~3× lent. AES a enterrĂ© 3DES cĂŽtĂ© perf et sĂ©curitĂ©.

😂 Ton sarcastique (mais vrai) : pourquoi AES a gagnĂ©

Imagine DES comme une Fiat 500 des annĂ©es 70 : mignonne, simple, mais pas faite pour l’autoroute. 3DES, c’est trois Fiat 500 attachĂ©es ensemble pour faire la route — ingĂ©nieux — mais toujours lent et peu aĂ©rodynamique. AES, c’est la sportive moderne : rapide, sĂ»re et conçue pour le bit-age moderne. Si vous aviez un PC en 1995, 3DES Ă©tait une solution raisonnable ; aujourd’hui, c’est une relique bien conservĂ©e dans les musĂ©es de la crypto.


đŸ§Ș Exercice pratique Ă  faire Ă  la maison (niveau bricolage / pĂ©dagogique)

Objectif : expĂ©rimenter le concept meet-in-the-middle sur un toy-DES rĂ©duit (par sĂ©curitĂ© et rapiditĂ©).

  1. ImplĂ©menter ou rĂ©utiliser une implĂ©mentation Python d’un DES miniature (par exemple rĂ©duction de la taille de bloc Ă  16 bits et clĂ© Ă  8 bits — strictement pĂ©dagogique, ne l’utilisez jamais pour protĂ©ger quoi que ce soit).
  2. ImplĂ©mentez 3DES (EDE) sur ce toy-DES avec trois clĂ©s courtes (par ex. clĂ©s 8 bits → espace clĂ© total rĂ©duit et tractable).
  3. Chiffrez un message test M pour obtenir C.
  4. Programmez une attaque meet-in-the-middle :
    • Construisez la table des E_{K1}(M) pour toutes les K1.
    • Pour toutes les combinaisons (ou selon une variante optimisĂ©e), tentez de retrouver une correspondance et affichez la clĂ© retrouvĂ©e.
  5. Mesurez le temps et comparez avec la recherche naĂŻve sur l’espace complet
 vous verrez l’économie gĂ©omĂ©trique due au MITM.
  6. Variante : utilisez PyCryptodome et le module DES3 pour jouer avec de vraies primitives, mais n’y mettez jamais des vraies clĂ©s/infos sensibles — faites des tests sur clĂ©s rĂ©duites ou jeux de test.

✅ RĂ©cap express

  • 3DES (EDE) = E_{K1}(D_{K2}(E_{K1}(M))).
  • Nominal : 168-bit (trois clĂ©s). SĂ©curitĂ© pratique ≈ 112-bit Ă  cause du meet-in-the-middle (56 + 56 = 112).
  • Lent → AES l’a remplacĂ© pour la plupart des usages.
  • Pour l’expĂ©rimentation : fais l’exercice toy-DES pour voir MITM en vrai.

🧼 1) DĂ©monstration mathĂ©matique / justification (pas-Ă -pas) — pourquoi 3DES ≈ 112 bits (meet-in-the-middle)

Rappel de la construction EDE (la plus utilisée) :
C = E_{K_3}\bigl(D_{K_2}\bigl(E_{K_1}(M)\bigr)\bigr).
(Notation : E_K(\cdot) chiffrement DES avec clé K, D_K(\cdot) déchiffrement.)

1.1 Espace de clés « naïf »

  • Si K_1, K_2, K_3 sont indĂ©pendantes, espace nominal :
    2^{56}\times 2^{56}\times 2^{56} = 2^{168} combinaisons.
    (Ici 56 = longueur effective d’une clĂ© DES.)
  • Si on croyait qu’une attaque par force brute pure devait tester toutes les combinaisons, on aurait coĂ»t ≈ 2^{168} opĂ©rations. VoilĂ  pour la « lecture naĂŻve ».

1.2 IdĂ©e gĂ©nĂ©rale du meet-in-the-middle (MITM)

  • L’astuce MITM : on casse la chaĂźne en deux demi-chaĂźnes et on essaie de rencontrer un mĂȘme intermĂ©diaire en mĂ©moire.
  • Pour 3DES il existe un point intermĂ©diaire naturel :
    définis X = E_{K_1}(M) et Y = D_{K_2}(X) puis C = E_{K_3}(Y).
    L’attaque cherche des valeurs intermĂ©diaires (ou Ă©quivalentes) produites indĂ©pendamment par les deux moitiĂ©s.

1.3 Construction d’une attaque MITM simple (idĂ©e high-level)

  1. Pour tous les K_1 (il y en a 2^{56}) on calcule et stocke
    X = E_{K_1}(M) (table indexĂ©e par la valeur de X → liste de K_1).
    → coĂ»t : ~2^{56} opĂ©rations et mĂ©moire ≈ 2^{56} entrĂ©es (si on stocke uniquement X et K_1).
  2. Pour tous les couples latex[/latex] (espace total 2^{56}\times 2^{56} = 2^{112}) on peut, en théorie, vérifier si la transformation inverse depuis C rejoint une valeur X dans la table.
    • ImplementĂ© intelligemment, le coĂ»t total tombe dans l’ordre de 2^{112} opĂ©rations (plus le coĂ»t de prĂ©paration 2^{56}).
    • Les dĂ©tails d’optimisation permettent d’obtenir une complexitĂ© temporelle asymptotique ≈ 2^{112} et une mĂ©moire ≈ 2^{56} (ou avec d’autres Ă©changes temps-mĂ©moire).

1.4 Intuition en termes d’exposants (raisonnement simple et robuste)

  • L’attaque fait essentiellement deux « recherches » indĂ©pendantes sur des espaces de taille 2^{56} et 2^{56} (les deux moitiĂ©s).
  • On additionne les exposants utiles : 56 + 56 = 112.
    D’oĂč la rĂšgle pratique : au lieu de 2^{168}, la complexitĂ© tombe Ă  l’ordre de 2^{112}.
  • Formellement : on transforme le problĂšme en voir si une valeur intermĂ©diaire produite par « la gauche » (toutes les K_1) peut ĂȘtre produite par « la droite » (certaines combinaisons de K_2,K_3). La rencontre se fait en environ 2^{112} opĂ©rations grĂące Ă  la recherche en table et aux itĂ©rations.

1.5 Résumé clair

  • Nominal : 3 × 56 = 168 bits (espace clĂ©).
  • Pratique (attaque gĂ©nĂ©rique MITM) : coĂ»t ≈ 2^{112} opĂ©rations (et mĂ©moire ≈ 2^{56} dans une mise en Ɠuvre raisonnable).
  • D’oĂč l’affirmation courante : “3DES offre environ 112 bits de sĂ©curitĂ© effective.”

Remarque : il existe des variantes d’attaques plus raffinĂ©es et des compromis mĂ©moire/temps ; l’important est la dĂ©croissance exponentielle effective (on passe d’un exposant 168 Ă  112) — explique pourquoi 3DES n’est plus considĂ©rĂ© comme suffisamment moderne comparĂ© Ă  AES.


🐍 2) Script Python pratique : toy-DES + attaque Meet-in-the-Middle

But : montrer le principe en pratique sur une version rĂ©duite (bloc et clĂ©s petites) pour que tu puisses exĂ©cuter rapidement et observer la rĂ©duction de complexitĂ©. NE PAS utiliser ce toy-DES pour protĂ©ger quoi que ce soit.

Le script ci-dessous contient 2 parties :

  • un toy-Feistel (blocs 16 bits, clĂ© 8 bits) — trĂšs simple et pĂ©dagogique ;
  • une implĂ©mentation 3DES en EDE sur ce toy-DES avec trois clĂ©s courtes ;
  • une fonction mitm_attack qui retrouve les clĂ©s via meet-in-the-middle (montrant la rĂ©duction exponentielle).

Copie-colle le code dans un fichier mitm_toy3des.py et exĂ©cute python3 mitm_toy3des.py. Le script affiche les clĂ©s trouvĂ©es et les temps.

#!/usr/bin/env python3
# mitm_toy3des.py
# Toy DES (trÚs simplifié) + 3DES EDE + attaque meet-in-the-middle
# Usage pédagogique uniquement.

from itertools import product
from time import time

# --- Toy Feistel cipher (insecure, pedagogical) ---
# Block = 16 bits, split 8|8, rounds = 4, subkey = 8 bits
def toy_f(round_key, half):
    # simple nonlinear mixing (just for demo)
    return ((half ^ round_key) * 73) & 0xFF

def toy_encrypt_block(plain16, key8, rounds=4):
    L = (plain16 >> 8) & 0xFF
    R = plain16 & 0xFF
    # derive round keys (simple expansion)
    for r in range(rounds):
        rk = ((key8 << r) | (key8 >> (8 - r))) & 0xFF
        newL = R
        newR = L ^ toy_f(rk, R)
        L, R = newL, newR
    return ((L << 8) | R) & 0xFFFF

def toy_decrypt_block(cipher16, key8, rounds=4):
    L = (cipher16 >> 8) & 0xFF
    R = cipher16 & 0xFF
    for r in reversed(range(rounds)):
        rk = ((key8 << r) | (key8 >> (8 - r))) & 0xFF
        newR = L
        newL = R ^ toy_f(rk, L)
        L, R = newL, newR
    return ((L << 8) | R) & 0xFFFF

# --- 3DES EDE using toy cipher ---
def toy_3des_encrypt(plain16, k1, k2, k3):
    x = toy_encrypt_block(plain16, k1)
    y = toy_decrypt_block(x, k2)
    z = toy_encrypt_block(y, k3)
    return z

def toy_3des_decrypt(cipher16, k1, k2, k3):
    x = toy_decrypt_block(cipher16, k3)
    y = toy_encrypt_block(x, k2)
    z = toy_decrypt_block(y, k1)
    return z

# --- Meet-in-the-middle (demonstration) ---
def mitm_attack(plain16, cipher16):
    # Search space for keys: 8 bits each => 256 values => feasible
    all_keys = range(256)

    # Step 1: compute map of E_{k1}(M)
    table = {}
    for k1 in all_keys:
        val = toy_encrypt_block(plain16, k1)
        table.setdefault(val, []).append(k1)

    # Step 2: for every (k2,k3), compute D_{k3}(C) then D_{k2} of that and test?
    # Simpler approach: compute D_{k3}(C) and try to match with values reachable by E_{k1}(M)
    candidates = []
    for k3 in all_keys:
        mid = toy_decrypt_block(cipher16, k3)  # this should equal D_k2(E_k1(M))
        # Now we need to check for k2 and k1 satisfying mid = D_{k2}(E_{k1}(M))
        # Brute-force k2 and check if E_k1(M) equals E_{k2}(mid)
        # Equivalent loop over k2 and matching table lookup:
        for k2 in all_keys:
            left = toy_encrypt_block(mid, k2)  # this equals E_{k2}(D_{k3}(C)) in theory
            if left in table:
                for k1 in table[left]:
                    # verify full 3DES
                    if toy_3des_encrypt(plain16, k1, k2, k3) == cipher16:
                        candidates.append((k1, k2, k3))
    return candidates

# --- Demo ---
if __name__ == "__main__":
    # choose random-ish keys (for demo we pick fixed)
    K1, K2, K3 = 0x2A, 0xB7, 0xC3
    M = 0x1234
    C = toy_3des_encrypt(M, K1, K2, K3)
    print(f"Plain  = 0x{M:04X}")
    print(f"Cipher = 0x{C:04X}")
    print(f"Keys   = K1=0x{K1:02X}, K2=0x{K2:02X}, K3=0x{K3:02X}")
    t0 = time()
    found = mitm_attack(M, C)
    t1 = time()
    print(f"Temps attaque MITM (toy) : {t1-t0:.3f}s")
    print("Résultats trouvés :", found)

Ce que tu vas observer en lançant le script

  • L’espace clĂ© rĂ©el = 2^8 \times 2^8 \times 2^8 = 2^{24} (pour le toy), mais MITM ramĂšnera le coĂ»t effectif dans l’ordre de 2^{16} ou similaire : tu verras la rĂ©duction exponentielle et la clĂ© rĂ©elle retrouvĂ©e vite.
  • Modifie la taille des clĂ©s (ex : 10 bits) si ton PC peut gĂ©rer — mais attention : croissance exponentielle trĂšs rapide.

📝 ComplĂ©ment pĂ©dagogique — preuve de correction (vĂ©rification)

Dans le script la vĂ©rification finale if toy_3des_encrypt(... ) == cipher16 garantit qu’on n’a pas de faux positifs — en pratique, sur DES rĂ©el il faut plusieurs paires (M,C) connus pour Ă©liminer collisions probables.


✅ Conseils finaux et bonnes pratiques

  • Ne dĂ©ploie pas 3DES pour de nouveaux projets. Utilise AES-GCM, ChaCha20-Poly1305 (auth + chiffrement vitesse et sĂ©curitĂ©).
  • 3DES reste historique : support dans pas mal de matĂ©riels et vieux protocoles, mais lent et avec marge de sĂ©curitĂ© rĂ©duite (≈112 bits).
  • Pour tester plus sĂ©rieusement (et sans toy), tu peux utiliser PyCryptodome (from Crypto.Cipher import DES3) pour manipuler DES3, mais n’utilise pas de vraies donnĂ©es.

🔬 A — DĂ©monstration mathĂ©matique rigoureuse (mais lisible)

Contexte / notations.
On note :

  • E_K(\cdot) : chiffrement DES avec clĂ© K.
  • D_K(\cdot) : dĂ©chiffrement DES avec clĂ© K.
  • K_1,K_2,K_3 : clĂ©s DES indĂ©pendantes, chacune de longueur effective 56 bits.
  • Construction EDE (classique 3DES) :
    C = E_{K_3}\bigl(D_{K_2}\bigl(E_{K_1}(M)\bigr)\bigr).

1) Espace de clés nominal

Nominalement, si les trois clĂ©s sont indĂ©pendantes, l’espace de clĂ©s est :
\text{|KeySpace|} = 2^{56}\times 2^{56}\times 2^{56} = 2^{168}.

Si on faisait une bruteforce naĂŻve, coĂ»t temporel ≈ 2^{168} opĂ©rations de bloc-DES.

2) Meet-in-the-middle (MITM) — idĂ©e clĂ©

La stratĂ©gie MITM pour 3DES se base sur la factorisation de la fonction en deux cĂŽtĂ©s autour d’un intermĂ©diaire :

  • Soit X = E_{K_1}(M) l’état aprĂšs la premiĂšre opĂ©ration.
  • On a ensuite Y = D_{K_2}(X) puis C = E_{K_3}(Y).

L’attaque va crĂ©er une table des valeurs possibles de X pour tous les K_1, puis essayer de retrouver K_2,K_3 qui produisent ces valeurs en partant de C.

Construction d’attaque simple (complexitĂ©)

  1. Calculer et stocker la table : pour chaque K_1 ( 2^{56} possibilités ) on calcule X = E_{K_1}(M) et on stocke la paire (X,K_1).
    • CoĂ»t temporel : T_1 \approx 2^{56} opĂ©rations DES.
    • MĂ©moire : M \approx 2^{56} entrĂ©es (assumons que chaque entrĂ©e coĂ»te O(1) mĂ©moire).
  2. Pour chaque paire (K_2, K_3) on calcule si possible une valeur intermĂ©diaire qui apparaisse dans la table. Une mise en Ɠuvre pratique calcule d’abord, pour chaque K_3, mid = D_{K_3}(C), puis pour chaque K_2 on calcule E_{K_2}(mid) et on cherche un match dans la table.
    • CoĂ»t temporel approximatif pour cette phase : T_2 \approx 2^{56}\times 2^{56} = 2^{112} opĂ©rations (par construction).
    • MĂ©moire dĂ©jĂ  comptĂ©e en Ă©tape 1 : 2^{56}.

Total temporel ≈ T_1 + T_2 \approx 2^{112} (le terme dominant est 2^{112}) et mĂ©moire ≈ 2^{56}.

Donc : au lieu d’un coĂ»t naive 2^{168}, l’attaque MITM donne un coĂ»t pratique d’ordre 2^{112} opĂ©rations — d’oĂč l’affirmation « sĂ©curitĂ© effective ≈ 112 bits ».

3) Formules de temps / mémoire (généralisation)

Soit chaque clé de longueur k bits (ici k=56). Pour 3-clefs indépendantes, la complexité MITM classique est :

  • MĂ©moire : M \sim 2^{k}.
  • Temps : T \sim 2^{2k}.

En exposants : nominal = 3k ; MITM exposant effectif ≈ 2k. Pour k=56, nominal = 168, MITM = 112.

Remarque temps-mĂ©moire : On peut construire diffĂ©rentes variantes d’attaques en rĂ©duisant mĂ©moire et en augmentant temps (trade-off). Par ex. en utilisant des fonctions de hachage partielles et multi-passes, on peut obtenir approximations temporelles de l’ordre 2^{2k - \delta} avec mĂ©moire 2^{k-\epsilon} selon le paramĂ©trage — mais rien ne ramĂšne l’exposant sous 2^{2k} sans hypothĂšses supplĂ©mentaires.

4) Collisions et nombre de paires connues

Sur DES rĂ©el, une entrĂ©e paire (plaintext,ciphertext) unique peut suffire pour rĂ©ussir l’attaque MITM en principe, mais dans les implĂ©mentations pratiques on prend souvent plusieurs paires (ex : 2 ou 3 paires) pour rĂ©duire le risque de collisions fortuites et Ă©carter faux positifs. Le coĂ»t reste de mĂȘme complexitĂ© asymptotique.


đŸ§Ș B — Script PyCryptodome pĂ©dagogique (MITM expĂ©rimental)

Important : on ne bruteforce pas 56-bit keys en pratique ici (trop lent). Pour que tu puisses exĂ©cuter le script sur ton PC, on restreint volontairement la partie testable Ă  un sous-espace des clĂ©s (par ex. considĂ©rer que seules les 16 bits de poids faible des clĂ©s varient) — strictement pĂ©dagogique.
Le script montre comment mettre en place une attaque MITM sur 3DES rĂ©el (Crypto.Cipher.DES3), mais limite chaque clĂ© Ă  un espace de taille 2^{16} (65536) pour rester exĂ©cutable.

Tu peux augmenter/diminuer la taille en changeant KEY_VARIANT_BITS (mais attention : double chaque bit augmente exponentiellement le temps).

Copier-coller dans mitm_3des_pycrypto_demo.py. Assure-toi d’avoir PyCryptodome installĂ© : pip install pycryptodome.

#!/usr/bin/env python3
# mitm_3des_pycrypto_demo.py
# Démonstration pédagogique MITM sur 3DES (PyCryptodome)
# ATTENTION: clés volontairement restreintes (bits faibles) pour rendre l'attaque exécutable.

from Crypto.Cipher import DES3
from Crypto.Util.Padding import pad, unpad
from time import time
from itertools import product

# ----- ParamÚtres pédagogiques -----
KEY_VARIANT_BITS = 16   # nombre de bits "libres" par clé (<=24) ; 16 => 65536 valeurs => faisable
# Par sécurité et performance, on ne variera que les KEY_VARIANT_BITS LSB des clés DES réelles.
# Ne met pas KEY_VARIANT_BITS > 20 si tu veux rester raisonnable en temps d'exécution.

# clé "de base" 56-bit simulée : on construit une clé DES 8 bytes (56 bits effective + parité)
# Pour PyCryptodome DES3, on doit fournir une clé 16 ou 24 bytes.
# Ici on construira une clé 24 bytes (3x8) mais on ne fera varier que les derniers KEY_VARIANT_BITS bits.
BASE_KEY_BYTES = bytes.fromhex('0123456789ABCDEF01234567')  # 12 bytes -> 96 bits; we'll adapt

# Fonction utilitaire : fabriquer une clé 8-octets à partir d'un entier small_k (variant bits)
def make_des_key_from_int(small_k, variant_bits=KEY_VARIANT_BITS, base=0x1337133713371337):
    # base is a 64-bit placeholder; we'll xor low bits with small_k
    # WARNING: This is for demo only (parity bits etc. ignored).
    key64 = (base & (~((1 << variant_bits)-1))) | (small_k & ((1<<variant_bits)-1))
    return key64.to_bytes(8, 'big')

def make_3des_key(k1_int, k2_int, k3_int):
    k1 = make_des_key_from_int(k1_int)
    k2 = make_des_key_from_int(k2_int)
    k3 = make_des_key_from_int(k3_int)
    # DES3 expects 16 or 24 bytes key: we give 24 (K1||K2||K3)
    return k1 + k2 + k3

# --- 3DES EDE helpers (using DES3 from PyCryptodome) ---
def triple_des_encrypt_block(block16, k1_int, k2_int, k3_int):
    key24 = make_3des_key(k1_int, k2_int, k3_int)
    cipher = DES3.new(key24, DES3.MODE_ECB)
    # DES block = 8 bytes. We'll use 8-byte plaintext.
    return cipher.encrypt(block16)

def triple_des_decrypt_block(block8, k1_int, k2_int, k3_int):
    key24 = make_3des_key(k1_int, k2_int, k3_int)
    cipher = DES3.new(key24, DES3.MODE_ECB)
    return cipher.decrypt(block8)

# --- MITM attack (restricted search space) ---
def mitm_attack(plaintext8, ciphertext8, variant_bits=KEY_VARIANT_BITS):
    space = 1 << variant_bits
    # Step 1 : table E_{k1}(M)
    table = {}
    t0 = time()
    for k1 in range(space):
        key24 = make_3des_key(k1, 0, 0)  # vary only k1 for the left table
        c = DES3.new(key24, DES3.MODE_ECB).encrypt(plaintext8)
        table.setdefault(c, []).append(k1)
    t1 = time()
    print(f"Pré-calcul table K1 : {t1-t0:.3f}s, entrées: {len(table)}")

    # Step 2 : pour chaque k3,k2 restreints on cherche correspondance
    candidates = []
    t0 = time()
    for k3 in range(space):
        key_k3 = make_3des_key(0, 0, k3)
        mid = DES3.new(key_k3, DES3.MODE_ECB).decrypt(ciphertext8)  # D_{k3}(C)
        # pour chaque k2 -> E_{k2}(mid) et vérif table
        for k2 in range(space):
            key_k2 = make_3des_key(0, k2, 0)
            left = DES3.new(key_k2, DES3.MODE_ECB).encrypt(mid)  # E_{k2}(D_{k3}(C))
            if left in table:
                for k1 in table[left]:
                    # vérification complÚte
                    if triple_des_encrypt_block(plaintext8, k1, k2, k3) == ciphertext8:
                        candidates.append((k1, k2, k3))
    t1 = time()
    print(f"Recherche K2,K3 : {t1-t0:.3f}s")
    return candidates

# --- Demo principal ---
if __name__ == "__main__":
    # Message bloc (8 bytes)
    M = b"ABCDEFGH"  # 8-octets
    # Choix de clés "petites" (valeurs int dans [0..2^variant_bits-1])
    true_k1, true_k2, true_k3 = 0x1A2B, 0x00FF, 0x7F01
    key24 = make_3des_key(true_k1, true_k2, true_k3)
    cipher = DES3.new(key24, DES3.MODE_ECB).encrypt(M)

    print("Plain :", M)
    print("Cipher:", cipher.hex())
    print("Clés (petites) choisies :", hex(true_k1), hex(true_k2), hex(true_k3))
    found = mitm_attack(M, cipher)
    print("Résultats trouvés :", found)

Explications / avertissements

  • Le script montre la logique MITM appliquĂ©e Ă  un DES3 rĂ©el fourni par PyCryptodome, mais restreint le nombre de bits variables par clĂ© (KEY_VARIANT_BITS) pour rendre l’attaque exĂ©cutable.
  • Si tu mets KEY_VARIANT_BITS = 56 tu vas tenter 2^56 recherches par clĂ© — impossible en pratique ici.
  • Le script mesure deux phases sĂ©parĂ©es : construction de la table (coĂ»t mĂ©moire ~ 2^{variant_bits}) et recherche (coĂ»t ~ 2^{2\times variant_bits}). Observe la croissance exponentielle.

✅ RĂ©cap & bonnes pratiques (rapide)

  • ThĂ©orie : 3DES nominal = 2^{168}, attaque MITM donne coĂ»t pratique ≈ 2^{112} (mĂ©moire ≈ 2^{56}).
  • En pratique : 3DES = historique, lent, sĂ©curitĂ© effective moindre → prĂ©fĂ©rez AES-GCM ou ChaCha20-Poly1305aujourd’hui.

le toy a tournĂ© ✅.
Résultats et explications rapides :

  • Le bloc clair M = 0x1234 chiffrait en 0x2943 avec les clĂ©s vraies K1=0x2A, K2=0xB7, K3=0xC3.
  • L’attaque MITM (sur l’espace rĂ©duit 8-bit par clĂ©) a construit la table en ~0.00046 s et a trouvĂ© des candidats en ~0.162 s.
  • Le script a renvoyĂ© plusieurs candidats (collisions dues au petit toy-cipher et Ă  l’espace rĂ©duit) ; le premier candidat testĂ© a bien dĂ©chiffrĂ© le message et a permis de rĂ©cupĂ©rer le clair (vĂ©rification rĂ©ussie).

Observations :

  • Dans ce toy, de nombreuses triples (k1,k2,k3) peuvent satisfaire la relation sur un seul couple (M,C) — c’est normal : l’espace est petit et la fonction toy est simple. Sur DES rĂ©el, on utilise plusieurs paires (M,C) connues pour Ă©liminer les faux positifs.
  • Le comportement que tu vois illustre la rĂ©duction de complexité : la prĂ©paration prend ~2^{8} opĂ©rations et la recherche ~2^{16}, conforme Ă  la logique MITM (gĂ©nĂ©ralisation : prĂ©paration ~2^{k}, recherche ~2^{2k}).
🔐 3DES : pourquoi trois, c’est mieux qu’un
Partager cet article : Twitter LinkedIn WhatsApp

đŸ–‹ïž PubliĂ© sur SecuSlice.com

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut