Mis à jour le mercredi 8 mars 2017
  • 4 heures
  • Facile

Protégez les données

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Comme promis, je fais une petite partie à part sur la protection des données. Je suis conscient que si votre site web est bien protégé, théoriquement personne ne pourra avoir accès à ces données. Mais on n'est jamais à l'abri d'une fuite, même pour les plus grands sites web. C'est pourquoi je pense qu'il est essentiel de maîtriser certaines notions de chiffrement. Je vais donc vous présenter quelques options.

Le hashage

Introduction à la notion de hash

Je pense que vous avez au moins une vague idée de ce qu'est un hash. C'est en fait un algorithme qui va, à partir d'une donnée de départ, proposer une empreinte irréversible. Une fois une donnée hashée, il est  impossible de la "décrypter", et c'est là la plus grande différence avec un cryptage. Il existe de très nombreux algorithmes de hashage. En PHP les deux plus utilisés sont :

  • SHA1() propose un hash en 160 bits (40 caractères)

  • MD5() propose un hash en 128 bits (32 caractères)

Il existe évidemment beaucoup d'autres algorithmes (il est même possible de créer le sien) mais bon, leur fonctionnement est sensiblement le même, il est donc inutile de tous les aborder. Voilà comment les utiliser avec PHP :

<?php

    $texte = "NeedCoffee";
    $retour = "</br>"; // pour faire un retour à la ligne
    
    echo sha1($texte);
    echo $retour;
    echo md5($texte);

?>

Essayez chez vous, vous devriez obtenir :

f586c6e965e011689dfd25da4c6a57157423b360
e541a547ddd667352cf267f4287673b4

Mais si le hashage est irréversible, ça veut dire que les données ne sont plus exploitables. Alors à quoi ça sert ?

Effectivement le hashage permet d'encoder dans un seul sens. Et c'est bien là son plus grand avantage ! Un hashage est irréversible, une personne mal intentionnée n'aura donc (théoriquement) aucun moyen de savoir ce qui se cache derrière. Mais ce n'est pas pour autant que les données hashées deviennent complètement inutiles, bien au contraire ! Par exemple dans un système de connexion/inscription, il sera très simple de sécuriser un mot de passe. Je m'explique :

Lors de l'inscription :

<?php

// On réceptionne le password envoyé par le formulaire
$password = $_POST['password'];

// On hash le password
$password = sha1($password);

// On enregistre dans la bdd
// ...

?>

Lors de la connexion :

<?php

// On imagine que l'on a récupéré le hash dans la bdd
// ce hash est contenu dans la variable $hash

// On réceptionne le password entré par l'utilisateur
$password = $_POST['password'];

// On hash ce password
$password = sha1($password);

// On compare le hash du pseudo entré par l'utilisateur 
// avec le hash enregistré dans la bdd
if ($password == $hash) {
 
 echo "Connexion réussie !";
 
}

else {
    echo "Mauvais password !";
}

?>

Et voilà, le tour est joué ! On a réussi à identifier la personne sans jamais avoir utilisé son mot de passe en clair !

Bon il va donc falloir corser un peu les choses. Sur Internet, beaucoup de théories circulent sur la question. Certains préconisent de hasher plusieurs fois le mot :

<?php $password = sha1(md5(sha1(md5($password)))); ?>

Cette technique est plus que controversée. D'une part, si le hacker n'a aucune idée du code PHP, on peut supposer que l'attaque par force brute s'avèrera plus complexe puisqu'il ne sait pas quels algorithmes vous avez utilisé et dans quel ordre. Mais d'un autre côté, hasher plusieurs fois la même chaîne augmente grandement le risque de collisions, et rend donc votre hash beaucoup moins solide. En effet, les algorithmes de hash ont été mis au point et optimisés mathématiquement pour éviter ces collisions. En hashant plusieurs fois à la suite la même chaine, vous ne faites qu'affaiblir la fonction de hash en décuplant les risques de collisions. C'est pourquoi il ne faut jamais hasher plusieurs fois une chaine de la sorte.

Pas très professionnel tout ça, vous l'avouerez. On préfèrera donc des algorithmes de hash plus complexes, avec un temps d'exécution beaucoup plus élevé. Ils produiront un hash plus "lourd" qui sera maintes fois plus sécurisé qu'un simple sha1. Vous pouvez ainsi utiliser :

  • SHA-256 : Produit un hash en 256 bits

  • SHA-512 : Produit un hash de 512 bits

Ces deux algorithmes sont apparus en mêmes temps, et ont pour seule différence la taille des blocs de données traitées. Quand SHA-512 traitera des blocs de 1024 bits (mots de 64 bits), SHA-256 se contentera de traiter des blocs de 512 bits. Ces deux algorithmes sont considérés comme réellement sûrs. Vous pouvez les utiliser sans limite, le risque d'attaque par force brut est presque nul. Pour les utiliser, rien de bien sorcier Jami :

<?php

$password = "MOT_DE_PASSE";

// Pour sha256
$password = hash('sha256', $password);

// Pour sha512
$password = hash('sha512', $password);

?>

Le sel

Un notion intéressante que je me dois d'évoquer, est celle du sel. Saler une chaine consiste à ajouter des caractères à cette chaine avant de la hasher, pour la rendre plus complexe. Exemple :

<?php

$password = "MOT_DE_PASSE";

// On sale la chaîne
$password = "Need" . $password . "Coffee";

// Puis on hash
$password = hash('sha512', $password);

?>

Je vous ai présenté ici la version la plus basique possible du sel qui consiste à ajouter des chaines de caractères statiques à la chaine entrée par l'utilisateur. Mais il peut être intéressant de songer à mettre en place des sels dynamiques, c'est à dire des sels qui varieront en fonction de la chaine entrée par l'utilisateur. L'exemple le plus simple est celui de la longueur de la chaine :

<?php

// On choppe la longueur de la chaîne
$long = strlen($password);

// On sale et on hash
$password = $long . $password;
$password = hash('sha512', $password);

?>
<?php

$long = strlen($password);
$password = "&=@+" . $long . $password . "#1%";
$password = hash('sha512', $password);

?>

Bonus

On pourrait également s'amuser à créer notre propre fonction, produisant un hash complètement inconnu du pirate :

<?php

// On récupère le pass entré par l'utilisateur
$mdp = $_POST['texte'];
// On prends la longueur de la chaine
$code = strlen($mdp);
// On fait quelques opérations
$code = ($code * 4)*($code/3);
// Le premier sel correspond à la longueur du mot de passe
$sel = strlen($mdp);
// Le deuxième sel est égal à la longueur des chaines $code et $mdp
$sel2 = strlen($code.$mdp);
// On termine en beauté avec quelques hashs
$texte_hash = sha1($sel.$mdp.$sel2);
$texte_hash_2 = md5($texte_hash.$sel2);

// On assemble tout ça pour obtenir une chaine de 82 caractères
$final = $texte_hash.$texte_hash_2;
// On supprime 2 caractère pour brouiller les pistes (ici 7 et 8)
substr($final , 7, 8);
// On finit par tout mettre en majuscule
$final = strtoupper($final);

?>

395F8E71F95ABFB32AE73B64AF58361F4E0B58F66AEC5EE90D4D7DCE818CC21DE472AA10

Le pirate qui tombera devant ça ne pourra pas savoir comment ce hash a été produit, à moins d'avoir accès au code source (éternel problème). Vous pouvez également vous amuser à créer voter propre fonction de hash, sans utiliser d'algorithme existant. Bien que ce genre de pratique ne soit pas conseillées,  cela peut vous permettre dans un premier temps de bien assimiler le principe de fonctionnement des hash. Vous pouvez également vous amuser à ce reprendre ce code tout en corrigeant les erreurs évoquées précédemment. Il ne vous reste plus qu'à redoubler d'imagination pour créer un algorithme qui vous correspond :)

Le chiffrement (cryptage)

Le cryptage est une notion très vaste. Il existe des milliers de possibilités pour crypter et décrypter des données. Je vais donc vous expliquer rapidement le principe du chiffrage et vous présenter une méthode. Contrairement au hashage, le cryptage est réversible. Il est donc possible de récupérer ce qui a été crypté, si on connait l'algorithme utilisé ainsi que la clé de chiffrement.

Je vous propose un algorithme de chiffrement très facile à utiliser en PHP. Je ne prétends pas que cet algorithme est le meilleur (car ce n'est pas le meilleur), mais il est relativement simple et efficace. Pour cela on va utiliser la fonction mcrypt_encrypt() qui prend en compte 5 paramètres :

  • l'algorithme de chiffrement utilisé

  • La clé de chiffrement

  • La chaîne à crypter

  • Le mode de chiffrement

  • Le vecteur d'initialisation

Comme je l'ai dit précédemment, je ne peux pas détailler toutes les possibilités de chiffrement, même en ne parlant que de mcrypt_encrypt(). C'est pourquoi je vais vous proposer un algorithme tout fait dans lequel vous n'aurez qu'à modifier la chaîne à crypter et la clé de chiffrement. Plus la clé est compliquée, meilleur sera votre chiffrement (personnellement j'utilise des hash) ! Si le cryptage vous intéresse, je  vous encourage vivement à faire des recherches complémentaires !

Voilà le fameux algorithme :

<?php

class Chiffrement {

// Algorithme utilisé pour le cryptage des blocs
private static $cipher  = MCRYPT_RIJNDAEL_128;

// Clé de cryptage         
private static $key = "your_key";

// Mode opératoire (traitement des blocs)
private static $mode    = 'cbc';
 
public static function crypt($data){
    $keyHash = md5(self::$key);
    $key = substr($keyHash, 0, mcrypt_get_key_size(self::$cipher, self::$mode));
    $iv  = substr($keyHash, 0, mcrypt_get_block_size(self::$cipher, self::$mode));
 
    $data = mcrypt_encrypt(self::$cipher, $key, $data, self::$mode, $iv);
    
    return base64_encode($data);
}
 
public static function decrypt($data){
    $keyHash = md5(self::$key);
    $key = substr($keyHash, 0,   mcrypt_get_key_size(self::$cipher, self::$mode) );
    $iv  = substr($keyHash, 0, mcrypt_get_block_size(self::$cipher, self::$mode) );

    $data = base64_decode($data);
    $data = mcrypt_decrypt(self::$cipher, $key, $data, self::$mode, $iv);

    return rtrim($data);
}}

?>

Pour l’appeler rien de plus simple :

<?php
    // Pour crypter
    $crypt   = Chiffrement::crypt($var);

    //pour décrypter
    $decrypt = Chiffrement::decrypt($var);
?>

Normalement vous devriez obtenir quelque chose qui ressemble à  :

R5reBJdm23DhpNbU/F0I2Q==

N'hésitez pas à le tester chez vous, et à faire quelques tests pour mieux cerner son fonctionnement ! 

Exemple de certificat de réussite
Exemple de certificat de réussite