{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {
        "id": "PGUXEUMHxzQV"
      },
      "outputs": [],
      "source": [
        "import random\n",
        "import numpy"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "thBdACa4xzQT"
      },
      "source": [
        "# <center></center>\n",
        "# <center>TP1 - Simulation du protocole de sécurité WEP</center>\n",
        "\n",
        "<center>Siham Bouchelaghem</center>\n",
        "\n",
        "<center> R4.B.10 Cryptographie et sécurité </center>\n",
        "    \n",
        "<center>IUT de Vannes - BUT2 Informatique - 2025/2026</center>\n",
        "\n",
        "**Usage de l'IA générative : interdit**\n",
        "\n",
        "WEP (*Wired Equivalent Privacy*) est un protocole de sécurité pour les réseaux sans fil de type Wi-Fi. L'objectif de ce TP est de simuler son fonctionnement et d'expérimenter certaines de ses failles afin de mieux comprendre pourquoi il n'est plus considéré comme sûr."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rbYocWQE1qvI"
      },
      "source": [
        "## 1. Chiffrement RC4\n",
        "RC4 est un algorithme de chiffrement **symétrique par flot** utilisé par le protocole WEP pour chiffrer les données transmises sur les réseaux Wi-Fi 802.11. Par convention, nous appellerons :\n",
        "\n",
        "* `IV` : le vecteur d'initialisation de 24 bits\n",
        "* `WEP_key` : la clé WEP secrète partagée de 40 bits (WEP-64) ou 104 bits (WEP-128)\n",
        "* `keystream` : la clé RC4 réelle\n",
        "* `message` : le message en clair\n",
        "* `encrypted_message` : le message chiffré"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "g5eoqIJ8DFsJ"
      },
      "source": [
        "#### a) Chiffrement/déchiffrement\n",
        "\n",
        "Les trois fonctions données ci-dessous correspondent à une **version simplifiée** de l'algorithme de chiffrement RC4 sur lequel se base le protocole WEP telles que :\n",
        "\n",
        "* La fonction `generate_keystream()` permet de retourner une clé RC4 de taille fixe.\n",
        "* La fonction `encrypt()` permet de chiffrer un message donné.\n",
        "* La fonction `decrypt()` permet de déchiffrer un message avec un procédé similaire au chiffrement.\n",
        "\n",
        "> **Question 1 :** Étudiez le comportement de ces trois fonctions, puis expliquez le fonctionnement du protocole WEP en commentant le code de chaque fonction."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "id": "8fk_kdAfxzQW"
      },
      "outputs": [],
      "source": [
        "def generate_keystream(k, WEP_key, IV):\n",
        "    random.seed(IV+WEP_key)\n",
        "    # suite binaire aléatoire de longueur k\n",
        "    return ''.join(random.choice('01') for _ in range(k))\n",
        "\n",
        "def encrypt(message, keystream):\n",
        "    encrypted_message = ''\n",
        "    for i in range(len(message)):\n",
        "        # pour chaque charactère du message m et de la keystream k de façon circulaire on a c = m XOR k\n",
        "        encrypted_message += chr(ord(message[i]) ^ ord(keystream[i % len(keystream)]))\n",
        "    return encrypted_message\n",
        "\n",
        "def decrypt(encrypted_message, keystream):\n",
        "    decrypted_message = ''\n",
        "    for i in range(len(encrypted_message)):\n",
        "        # identique au chiffrement\n",
        "        decrypted_message += chr(ord(encrypted_message[i]) ^ ord(keystream[i % len(keystream)]))\n",
        "    return decrypted_message"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "hcmtGdgC4xoe"
      },
      "source": [
        "#### b) Communication WEP\n",
        "\n",
        "On souhaite simuler une communication WEP en générant un trafic réseau composé d'une liste de $n$ couples [[IV$_1$, message$_1$], [IV$_2$, message$_2$], $\\cdots$, [IV$_n$, message$_n$]] où :\n",
        "\n",
        "* IV$_i$ est un vecteur d'initialisation de 8 bits aléatoires;\n",
        "* message$_i$ est une chaîne aléatoire de 12 caractères ASCII dont les quatre premiers sont \"IPv4\".\n",
        "\n",
        "> **Question 2 :** Implémentez la fonction `generate_traffic(n)` qui permet de générer un trafic réseau en retournant une liste de $n$ couples [IV$_i$, message$_i$]."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "id": "_J6sW2HwxzQW"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[['10011100', 'IPv4shCR\\\\^Z`'], ['01000110', 'IPv4maYPcJhj'], ['00000000', 'IPv4KwPIZlAi'], ['00011100', 'IPv4[ue{KZGS'], ['11000111', 'IPv4oyA^]AS{'], ['01110101', 'IPv4vAaQNIMD'], ['00011100', 'IPv4yPsLxRXw'], ['01011001', 'IPv4Z{RWG_Yh']]\n",
            "[['10011100', 'IPv4shCR\\\\^Z`'], ['01000110', 'IPv4maYPcJhj'], ['00000000', 'IPv4KwPIZlAi'], ['00011100', 'IPv4[ue{KZGS'], ['11000111', 'IPv4oyA^]AS{'], ['01110101', 'IPv4vAaQNIMD'], ['00011100', 'IPv4yPsLxRXw'], ['01011001', 'IPv4Z{RWG_Yh']]\n"
          ]
        }
      ],
      "source": [
        "def generate_traffic(n):\n",
        "    l = []\n",
        "    for i in range(n):\n",
        "        IV = ''.join(random.choice('01') for _ in range(8))\n",
        "        message = 'IPv4'+''.join(chr(random.randint(65, 123)) for _ in range(8))\n",
        "        l.append([IV, message])\n",
        "    print(l)\n",
        "    return l\n",
        "\n",
        "print (generate_traffic(8))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KG3Z_FjUB1GK"
      },
      "source": [
        "## 2. Sécurité du protocole WEP\n",
        "\n",
        "Dans une communication WEP avec un message en clair $m$ à transmettre, le vecteur d'initialisation est transmis **en clair** avec le résultat du chiffrement du message $m$.\n",
        "#### a) Écoute réseau\n",
        "On souhaite simuler l'interception d'un trafic WEP par un attaquant lui permettant de récupérer $n$ couples [IV$_i$, encrypted\\_message$_i$].\n",
        "\n",
        "> **Question 3 :** Implémentez la fonction `sniffing(n, WEP_key)` qui, étant donné $n$ messages en clair et une clé secrète WEP définie, retourne une liste de $n$ couples [IV$_i$, encrypted\\_message$_i$].\n",
        "\n",
        "**Contrainte :** La fonction `sniffing()` doit faire appel à la fonction `generate_traffic()` pour générer $n$ messages en clair avec `IV`, puis chiffrer chaque message avec une `keystream`, **unique pour chaque message**, générée à partir de la clé `WEP_key`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "id": "VN7guyJTxzQX"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[['11010111', 'IPv4OHv[splK'], ['00110100', 'IPv4c\\\\htWD^I'], ['01101001', 'IPv4\\\\nUevcVl'], ['10011100', 'IPv4ST{Rwg_o'], ['01101101', 'IPv4cUiz[fJq'], ['11011101', 'IPv4PMGV_t\\\\b'], ['01011101', 'IPv4_WHuAw`f'], ['10101001', 'IPv4DZExjfbU']]\n",
            "[['11010111', 'y`G\\x05~xFkC@]{'], ['00110100', 'xaF\\x05SmXEftnx'], ['01101001', 'yaG\\x05l_eUFRg\\\\'], ['10011100', 'xaF\\x04cdJcGWo^'], ['01101101', 'yaG\\x04SdXKkW{A'], ['11011101', 'y`F\\x04`|vfoDmR'], ['01011101', 'yaG\\x04ngyDpFQV'], ['10101001', 'y`F\\x04ujtIZWSd']]\n"
          ]
        }
      ],
      "source": [
        "def sniffing(n, WEP_key):\n",
        "    l=[]\n",
        "    traffic = generate_traffic(n)\n",
        "    for packet in traffic:\n",
        "        IV, message = packet\n",
        "        keystream = generate_keystream(len(message), WEP_key, IV)\n",
        "        encrypted_message = encrypt(message, keystream)\n",
        "        l.append([IV, encrypted_message])\n",
        "    return l\n",
        "print (sniffing(8, 'SECRET'))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "EyjJv-mWEM8Z"
      },
      "source": [
        "#### b) Attaque par collision d'IV\n",
        "Une première faille du protocole WEP réside dans le fait qu'une partie de la clé de chiffrement RC4, à savoir le **vecteur d'initialisation IV**, est transmise en clair. Cet IV est censé permettre la génération d'un flot de chiffrement `keystream` différent pour chaque paquet transmis sur le réseau, rendant ainsi le déchiffrement plus difficile. Cependant, même pour un IV de 8 bits (2$^8$ possibilités), un même IV peut être **réutilisé**. Dans ce cas, la même `keystream` est générée, et plusieurs messages peuvent alors être chiffrés avec **le même flot RC4**, ce qui compromet la confidentialité des communications.   \n",
        "\n",
        "> **Question 4 :** Implémentez la fonction `collisions(intercepted_traffic)` qui, étant donné un trafic intercepté contenant [[IV$_1$, encrypted_message$_1$], [IV$_2$, encrypted_message$_2$], $\\cdots$, [IV$_n$, encrypted_message$_n$]] avec $n$ assez grand, permet de retourner les couples [IV$_i$, encrypted_message$_i$] ayant le même IV."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {
        "id": "7qYXh2hoxzQX"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[['00110010', 'IPv4Q{DtM^IX'], ['00111110', 'IPv4c`fs[^ci'], ['01011010', 'IPv4XFVhvY^x'], ['01110111', 'IPv4]NEhAzlT'], ['10001010', 'IPv4FgPcG^Dz'], ['10100011', 'IPv4zdhoPVXt'], ['01111011', 'IPv4EOWJYyGK'], ['00010001', 'IPv4NeXS]IlF'], ['01101110', 'IPv4[OKV\\\\gcg'], ['11101110', 'IPv4NQgHdfTA'], ['11011111', 'IPv4kLvxO{VU'], ['01001111', 'IPv4WGTz_H^Q'], ['01110011', 'IPv4[mKovkOv'], ['01111011', 'IPv4_sCCqLsS'], ['11101001', 'IPv4xRuf\\\\B{N'], ['00111001', 'IPv4onBSDoDx'], ['00110001', 'IPv4WAJehASL'], ['01000001', 'IPv4Yf{oCAHE'], ['10000001', 'IPv4zSPxmKA`'], ['10101000', 'IPv4lfaFEqdu']]\n",
            "[['01111011', ['xaF\\x04t~fziIv{', 'xaF\\x04nBrsA|Bc']], ['01111011', ['xaF\\x04t~fziIv{', 'xaF\\x04nBrsA|Bc']]]\n"
          ]
        }
      ],
      "source": [
        "def collisions(intercepted_traffic):\n",
        "\n",
        "    IVs = [packet[0] for packet in intercepted_traffic]\n",
        "    res = []\n",
        "    for iv in IVs:\n",
        "        l=[j[1] for j in intercepted_traffic if j[0] == iv]\n",
        "        if len(l)>1:\n",
        "            res.append([iv,l])\n",
        "    return res\n",
        "print (collisions(sniffing(20, 'SECRET')))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "\n",
        "> **Question 5 :** Expliquez en quoi une collision d'IV constitue une faille majeure du protocole WEP.\n",
        "\n",
        "**Indication :** Considérez le cas où un attaquant intercepte deux messages c$_1$ et c$_2$ chiffrés avec le même IV, et où il connaît partiellement le message en clair associé à l'un d'eux.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gieNoJxGXGhJ"
      },
      "source": [
        "---\n",
        "### Réponse\n",
        "Dans WEP, une collision d’IV entraîne la réutilisation du même flot de clés RC4.\n",
        "\n",
        "Si deux messages sont chiffrés avec le même IV :\n",
        "c1 = m1 XOR k et c2 = m2 XOR k  \n",
        "alors :\n",
        "c1 XOR c2 = m1 XOR m2\n",
        "\n",
        "Si l’attaquant connaît partiellement m1, il peut retrouver le flot de clés k et déchiffrer m2. Comme l’IV est court, ces collisions sont fréquentes.\n",
        "\n",
        "---"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Cette faille du protocole WEP permet à un attaquant de récupérer la `keystream`, s'il connaît la **structure du message en clair** transmis - par exemple, le fait qu'ici chaque message commence par la chaîne \"IPv4\" - et qu'il intercepte le message chiffré correspondant.\n",
        "\n",
        "En effet, les trames Wi-Fi ont une structure très privisible (en-têtes connus, formats standards comme IPv4, ARP, etc.). Une fois la `keystream` récupérée pour un `IV` donné, l'attaquant peut déchiffrer d'autres paquets chiffrés avec le **même IV**, ou modifier voire **forger** des paquets valides.\n",
        "\n",
        "> **Question 6 :** Implémentez la fonction `find_partial_keystream(known_plaintext, encrypted_message)` qui permet, pour un message chiffré intercepté, de récupérer la portion de la `keystream` correspondant à la partie du message en clair connue de l'attaquant."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "id": "EDaB03MDxzQX"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "010111001001\n",
            "0101\n"
          ]
        }
      ],
      "source": [
        "def find_partial_keystream(known_plaintext, encrypted_message):\n",
        "\n",
        "    partial_keystream = ''\n",
        "    for i in range(len(known_plaintext)):\n",
        "        partial_keystream += chr(ord(known_plaintext[i]) ^ ord(encrypted_message[i]))\n",
        "\n",
        "    return partial_keystream\n",
        "g=generate_keystream(12, 'SECRET', '10101010')\n",
        "print(g)\n",
        "print (find_partial_keystream('IPv4', encrypt('IPv4TESTDATA', g)))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8Bkaunf33v2x"
      },
      "source": [
        "\n",
        "\n",
        "> **Question 7 :** Utilisez la portion de `keystream` récupérée pour déchiffrer partiellement un autre message chiffré dans le cas d'une attaque par réutilisation d'IV.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 36,
      "metadata": {
        "id": "KSeWD_U5CTWC"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "[['10101110', 'IPv4nKIYBFdD'], ['01111011', 'IPv4^_YKRIPw'], ['11011001', 'IPv4vWXCLo`y'], ['00011011', 'IPv4fqO^hzLg'], ['01010001', 'IPv4UqPvGzcW'], ['10011101', 'IPv4GEs{QzMo'], ['10010000', 'IPv4I{C{TujV'], ['10010011', 'IPv4Lo^EfLnh'], ['01000001', 'IPv4llxzLuRi'], ['00010101', 'IPv4EnylkQea'], ['11111010', 'IPv4ziMEfPnO'], ['01111010', 'IPv4uMtuLWvT'], ['00110111', 'IPv4MsG]MsBa'], ['00010100', 'IPv4xewZyrDw'], ['11101111', 'IPv4lY{aDEXj'], ['11101100', 'IPv4T^s]pSQP'], ['10111001', 'IPv4R\\\\Q^wtTY'], ['10111111', 'IPv4hsNpLVuq'], ['01011111', 'IPv4dA{LFDQS'], ['00111101', 'IPv4Im{XcIZW'], ['01010111', 'IPv4Ff]X`RIf'], ['01011100', 'IPv4KXY]gwas'], ['01111000', 'IPv4L_twCsfd'], ['11000101', 'IPv4Ij\\\\PxglM'], ['01000101', 'IPv4t^JCrWj`'], ['10000101', 'IPv4avrULdNK'], ['11000100', 'IPv4[^WiLK`['], ['11110101', 'IPv4mwZF`_t^'], ['00111101', 'IPv4hLKKZgBY'], ['10100000', 'IPv4bop]npCG'], ['01001110', 'IPv4vVYbHv\\\\C'], ['00010110', 'IPv4BA`dlTVv'], ['10111100', 'IPv4\\\\yhB[OlU'], ['01001101', 'IPv4VPXyGdAW'], ['10110100', 'IPv4pIahm]JG'], ['11101000', 'IPv4qsYgf_vr'], ['00000101', 'IPv4QBvSITpw'], ['11000011', 'IPv4jUCOakCV'], ['10010001', 'IPv4OlC`cb_L'], ['00110001', 'IPv4YUVXJNO`'], ['01000011', 'IPv4[nNJpnDI'], ['01111001', 'IPv4vAxQbHOB'], ['01111101', 'IPv4FUuOxH]c'], ['11010000', 'IPv4rPy[iR_I'], ['01000101', 'IPv4CFM^t\\\\jP'], ['01000100', 'IPv4]RqvAA[T'], ['00001110', 'IPv4T]MvcP{`'], ['11111001', 'IPv4XlFfboTM'], ['11101101', 'IPv4IJDiibC`'], ['01001110', 'IPv4IUjafeiX']]\n",
            "Found message: IPv4GDs{QzMn\n",
            "Found message: IPv4LrF\\MrBa\n",
            "Found message: IPv4IlzXbHZW\n",
            "Found message: IPv4u^JBsVka\n",
            "Found message: IPv4hMJK[fBY\n",
            "Found message: IPv4YUVYJNO`\n",
            "Found message: IPv4ZnOKqoEH\n",
            "Found message: IPv4BFM_u]kQ\n"
          ]
        }
      ],
      "source": [
        "s=sniffing(50, 'SECRET')\n",
        "c=collisions(s)\n",
        "f=find_partial_keystream('IPv4', c[0][1][0])\n",
        "for e in s:\n",
        "    res = encrypt(e[1], f)\n",
        "    if res.startswith('IPv4'):\n",
        "        print('Found message:', res)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qwCY_c6PWS5o"
      },
      "source": [
        "#### c) Attaque par fragmentation"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SFSf-O-XETlp"
      },
      "source": [
        "La dernière faille du protocole WEP que nous allons étudier provient d'une spécification de la norme IEEE 802.11, qui constitue la base des réseaux Wi-Fi : **la fragmentation des paquets**. En effet, il est prévu que l'on puisse découper un message en plusieurs fragments de plus petite taille, transmis indépendamment.\n",
        "\n",
        "> **Question 8 :** Implémentez les fonctions `fragment_packet(message, fragment_size)` et `encrypt_fragments(fragments, key)` permettant respectivement de fragmenter un message en clair en fragments de taille fixe et de chiffrer séparément chaque fragment à l'aide d'une clé de même taille.\n",
        "    \n",
        "**Hypothèse :** La clé utilisée pour chiffrer chaque fragment correspond à une **même portion** de la `keystream` générée à partir de la clé WEP partagée et de l'IV.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 38,
      "metadata": {
        "id": "ZGsQKUbXxzQX"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']"
            ]
          },
          "execution_count": 38,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "def fragment_packet(message, fragment_size=4):\n",
        "    l = []\n",
        "    for i in range(0, len(message), fragment_size):\n",
        "        l.append(message[i:i+fragment_size])\n",
        "\n",
        "    return l\n",
        "fragment_packet('Hello World', 1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "T_iubDTyxzQX"
      },
      "outputs": [],
      "source": [
        "def encrypt_fragments(fragments, key):\n",
        "\n",
        "    l = []\n",
        "    for packet in fragments:\n",
        "        encrypted = encrypt(packet, key)\n",
        "        l.append(encrypted)\n",
        "    return l"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "DVSnPWnRHNNd"
      },
      "source": [
        "À la réception de ces fragments, le point d'accès Wi-Fi les déchiffre fragment par fragment, reconstitue le message en clair, puis le rechiffre avant de l'acheminer vers la destination. La fonction `AP(encrypted_fragments, key, keystream)` donnée ci-dessous formalise ce comportement."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 40,
      "metadata": {
        "id": "DGc3xWhwxzQX"
      },
      "outputs": [],
      "source": [
        "def AP(encrypted_fragments, key, keystream):\n",
        "    decrypted_fragments=[decrypt(fragment, key) for fragment in encrypted_fragments]\n",
        "    reconstructed_message = ''.join(decrypted_fragments)\n",
        "    encrypted_message = encrypt(reconstructed_message, keystream)\n",
        "    return encrypted_message"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3n1EzIXNHQzR"
      },
      "source": [
        "En exploitant ce comportement, un attaquant peut récupérer la **keystream complète** à partir des fragments chiffrés interceptés et du **premier fragment en clair**, supposé connu.\n",
        "\n",
        "> **Question 9 :** Implémentez la fonction `find_keystream_from_fragments(encrypted_fragments, fragment_size)` qui permet, dans un premier temps, de récupérer la portion de keystream utilisée pour chiffrer le premier fragment (ainsi que les autres), puis d'en déduire la `keystream` complète utilisée par le point d'accès.\n",
        "\n",
        "**Indication :** Pensez à réutiliser la fonction `find_partial_keystream()` implémentée à la question 6."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 71,
      "metadata": {
        "id": "jrZDFPk1xzQY"
      },
      "outputs": [],
      "source": [
        "def find_keystream_from_fragments(encrypted_fragments, encrypted_message, fragment_size=4):\n",
        "\n",
        "    known_plaintext = 'IPv4'\n",
        "    \n",
        "    key = find_partial_keystream(known_plaintext, encrypted_fragments[0])\n",
        "\n",
        "    message = decrypt(''.join(encrypted_fragments),key)\n",
        "\n",
        "    res = find_partial_keystream(message, encrypted_message)\n",
        "    \n",
        "    return res"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "arPmnDPdTsJH"
      },
      "source": [
        "\n",
        "\n",
        "> **Question 10 :** Déroulez un exemple d'utilisation permettant d'illustrer l'attaque par fragmentation.\n",
        "\n",
        "\n",
        "\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 72,
      "metadata": {
        "id": "pK4NfywhxzQY"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "execution_count": 72,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "### Déroulement d'un exemple illustrant l'attaque par fragmentation ###\n",
        "message = 'IPv4nKIYBFdD'\n",
        "key='0101'\n",
        "keystream = '010101010101'\n",
        "\n",
        "fragments = fragment_packet(message, 4)\n",
        "encrypted_fragments = encrypt_fragments(fragments, key)\n",
        "encrypted_wifi_message = AP(encrypted_fragments, key, keystream)\n",
        "\n",
        "res = find_keystream_from_fragments(encrypted_fragments, encrypted_wifi_message)\n",
        "res==keystream"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "B1pmqFc6J98W"
      },
      "source": [
        "\n",
        "## Pour aller plus loin...\n",
        "\n",
        "WPA (*Wi-Fi Protected Access*) est un protocole de sécurité pour les réseaux sans fil de type Wi-Fi qui a été introduit pour pallier les faiblesses du protocole WEP.\n",
        "\n",
        "Dans ce TP, vous avez implémenté une simulation du protocole WEP avec une **keystream** générée par concaténation d'une **clé WEP** secrète fixe et d'un **vecteur d'initialisation** de 8 bits aléatoires fournie\n",
        "en entrée d'un générateur de nombres pseudo-aléatoires. Un chiffrement par **XOR** est ensuite réalisé entre les bits du message en clair et de la keystream pour produire le message chiffré à transmettre.\n",
        "\n",
        "L'objectif de cette partie supplémentaire est de simuler une **version simplifiée** du protocole **WPA**, en vous basant sur les fonctions déjà implémentées pour le protocole WEP."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PmkU84arasqz"
      },
      "source": [
        "\n",
        "\n",
        "Le protocole WPA utilise un **IV étendu**, appelé nonce WPA, de 16 bits générés aléatoirement à chaque message.\n",
        "\n",
        "> **Question 1 :**  Implémentez une fonction `generate_nonce()` qui permet de générer un tel IV.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "26h4sLpObH7n"
      },
      "outputs": [],
      "source": [
        "def generate_nonce():\n",
        "\n",
        "   # TODO #\n",
        "\n",
        "   return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2qwRIUfLbTu7"
      },
      "source": [
        "La `keystream` utilisée pour le chiffrement est ensuite dérivée d'un **hachage cryptographique** (SHA-256) qui prend en entrée :\n",
        "\n",
        "* Une passphrase de 12 caractères ASCII, élément secret partagé entre le client et le point d'accès;\n",
        "* Un IV de 16 bits générés aléatoirement;\n",
        "* L'adresse MAC du client.\n",
        "\n",
        "> **Question 2 :** Implémentez la fonction `generate_wpa_keystream(passphrase, IV, MAC_address, k)` permettant de générer la keystream.\n",
        "\n",
        "**Indication :** Vous pouvez utiliser le module `hashlib` qui prend en charge plusieurs fonctions de hachage courantes.\n",
        "\n",
        "**Exemple d'utilisation :** hash = hashlib.sha256(message.encode()).hexdigest()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "R81-FW4IdKmh"
      },
      "outputs": [],
      "source": [
        "def generate_wpa_keystream(passphrase, IV, MAC_address, k):\n",
        "\n",
        "  # TODO #\n",
        "\n",
        "  return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xH_7GlcydeqK"
      },
      "source": [
        "Tout comme avec le protocole WEP, un message en clair est chiffré en effectuant un **XOR** avec la keystream.\n",
        "\n",
        "Pour assurer l'intégrité et l'authenticité du message transmis, le protocole WPA ajoute un MIC (*Message Integrity Code*) calculé à l'aide d'une fonction de hachage cryptographique.\n",
        "\n",
        "> **Question 3 :** Implémentez une fonction `compute_mic(message, integrity_key)` qui retourne le hash SHA-256 du message en clair concaténé à une clé secrète partagée `integrity_key` de valeur fixe.\n",
        "\n",
        "**Remarque :** Le MIC correspond au **16 premiers bits** de ce hash et est ajouté à la fin du message avant d'être chiffré."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "J53K5Gumem_u"
      },
      "outputs": [],
      "source": [
        "def compute_mic(message, integrity_key):\n",
        "\n",
        "  # TODO #\n",
        "\n",
        "  return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-hgpQAPefNpm"
      },
      "source": [
        "> **Question 4 :** Implémentez la fonction `wpa_encrypt(message, keystream, MIC)` permettant de chiffrer un message."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "j33rBOZ0fV6t"
      },
      "outputs": [],
      "source": [
        "def wpa_encrypt(message, keystream, MIC):\n",
        "\n",
        "  # TODO #\n",
        "\n",
        "  return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xkf5ofZxetRD"
      },
      "source": [
        "> **Question 5 :** Implémentez une fonction `verify_mic(encrypted_message, keystream, integrity_key)` qui vérifie l'intégrité d'un message chiffré en comparant, après déchiffrement, le MIC reçu avec un MIC recalculé localement à l'aide de la clé `integrity_key`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RCW2-AxgfOLC"
      },
      "outputs": [],
      "source": [
        "def verify_mic(encrypted_message, keystream, integrity_key):\n",
        "\n",
        "  # TODO #\n",
        "\n",
        "  return"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.9.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
