• STATISTIQUES
  • Il y a eu un total de 0 membres et 50728 visiteurs sur le site dans les dernières 24h pour un total de 50 728 personnes!
    Membres: 2 605
    Discussions: 3 579
    Messages: 32 816
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [EN] xda-developers
    Très bon site pour les gros bidouilleurs de smartphone de windows à androïd et de Apple jusqu'...
    Phreaking
    [FR] Root-me
    Script: 5, Système: 20, Cracking: 16, Cryptanalyse: 17, Programmation: 8, Réaliste: 11, Réseau: 10, Stéganog...
    Challenges
    [FR] PHP Débutant
    Apprendre le PHP par l'exemple, facilement et simplement. Réservé d'abord aux débutants....
    Programmation
    [FR] NewbieContest
    Nous vous proposons une série de challenges regroupant plusieurs domaines allant de l'exploitation de fail...
    Hacking
    [EN] This is legal
    Basic: 10, Realistic: 5, Programming: 1, Bonus: 11, SQL: 2, Encryption: 6, Application: 4, User Contributed: 3
    Challenges
    [EN] Hack This Site
    Hack This Site est considéré comme un réel terrain d'entraînement légal pour le...
    Hacking
    [FR] Newbie Contest
    Crackme: 35, Cryptographie: 49, Hacking: 27, Javascript/Java: 17, Logique: 31, Programmation: 23, Stéganographie: 53
    Challenges

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
[PHP] _password_hash
10-06-2014, 15h00 (Modification du message : 10-06-2014, 15h01 par Ekroz.)
Message : #1
Ekroz Hors ligne
Membre actif
*



Messages : 77
Sujets : 13
Points: 43
Inscription : May 2013
[PHP] _password_hash
Salut à tous,

Voilà en bidouillant PHP Server Monitor je n'ai pas trouvé la manière de gérer les hash très sécurisée.
J'ai donc pondu ma propre fonction _password_hash :

Code PHP :
<?php
function _password_hash($password$algorithm NULL$salt NULL$position NULL)
{
    if (
$algorithm == NULL) {
        
/* Return a list of registered hashing algorithms. */
        
$hash_algos hash_algos();
        
$best_mb_strlen 0;

        foreach (
$hash_algos as $algo) {
            
/* Generate a hash value. */
            
$str hash($algoNULLFALSE);
            
            
/* Get string length. */
            
$mb_strlen mb_strlen($str);
            
            if (
$mb_strlen === FALSE) {
                continue;
            }
            
            if (
$mb_strlen $best_mb_strlen) {
                
$algorithm $algo;
                
$best_mb_strlen $mb_strlen;
            }
        }
    }

    if (
$salt == NULL) {
        
$i 0;
        
        
/* Generate a random integer. */
        
$max rand();

        
/* Generate a better random value. */
        
$length mt_rand(0$max);

        if (
$length === FALSE) {
            return 
FALSE;
        }
        
        
$crypto_strong TRUE;
        
$prefix NULL;

        while (
$i $length) {
            
/* Generate a pseudo-random string of bytes. */
            
$subject openssl_random_pseudo_bytes(1$crypto_strong);
            
            
/* Detect character encoding. */
            
$retval preg_match("/[^\x20-\x7f]/"$subject);
            
            if (
$retval == 1) {
                continue;
            } else if (
$retval === FALSE) {
                continue;
            }
            
            
$prefix .= $subject;
            
$i++;
        }

        
/* Generate a unique ID. */
        
$salt uniqid($prefixTRUE);
    }
    
    if (
$position === NULL) {
        
$max mb_strlen($password);
        
        if (
$max === FALSE) {
            return 
FALSE;
        }
        
        
$position mt_rand(0$max);
        
        if (
$position === FALSE) {
            return 
FALSE;
        }
    }

    
/* Return part of a string. */
    
$data  mb_substr($password0$position) . $salt mb_substr($password$position);
    
$password hash($algorithm$dataFALSE);

    return array(
        
"password" => $password,
        
"algorithm" => $algorithm,
        
"salt" => $salt,
        
"position" => $position
    
);
}

var_dump(_password_hash("foo"));
?>

- Récupère la liste des hashs supportés par votre serveur et sélectionne celui qui génère le plus long hash (SHA-512 dans mon cas).
- Créé un salt ASCII basé sur la fonction openssl_random_pseudo_bytes d'une taille aléatoirement choisie par mt_rand.
- Positionne le salt de manière aléatoire avec mt_rand dans le mot de passe.
- Retourne le résultat sous forme de tableau, à enregistrer dans la BDD.
- Si un hash plus long venait à être supporté par PHP, celui-ci sera automatiquement choisi par la fonction pour les nouveaux utilisateurs et les changements de mots de passe.
+1 (2) -1 (0) Répondre
10-06-2014, 15h42
Message : #2
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
RE: [PHP] _password_hash
Yop,

merci du partage =)

(10-06-2014, 15h00)Ekroz a écrit : Voilà en bidouillant PHP Server Monitor je n'ai pas trouvé la manière de gérer les hash très sécurisée.

En quoi? Par rapport a la génération du salt ?
+1 (0) -1 (0) Répondre
10-06-2014, 16h20
Message : #3
gruik Hors ligne
gouteur de savon
*



Messages : 757
Sujets : 44
Points: 482
Inscription : Oct 2012
RE: [PHP] _password_hash
yop,

(10-06-2014, 15h00)Ekroz a écrit : - Récupère la liste des hashs supportés par votre serveur et sélectionne celui qui génère le plus long hash (SHA-512 dans mon cas).
(...)
- Si un hash plus long venait à être supporté par PHP, celui-ci sera automatiquement choisi par la fonction pour les nouveaux utilisateurs et les changements de mots de passe.

je ne trouve pas que ça soit une si bonne idée que ça en fait, bon ok on peut explicitement spécifier l'algorithme à utiliser, mais dans le cas où on laisse $algorithm = NULL d'une part on génère pour chaque appel autant de hash qu'il y a d'algorithmes (donc ça peut être considéré comme "lent" selon le traitement et la cadence derrière), mais aussi c'est un coup à se retrouver avec une db remplie de hash mixtes, en somme c'est une feature qui tendrait à induire le développeur en erreur à mon avis
une possibilité serait de fournir également la fonction de vérification automatique elle même basée sur la longueur du hash
Avant donc que d'écrire, apprenez à penser.
Selon que notre idée est plus ou moins obscure, l'expression la suit, ou moins nette, ou plus pure.
Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément.
(Nicolas Boileau, L'Art poétique)
+1 (0) -1 (0) Répondre
10-06-2014, 16h42
Message : #4
b0fh Hors ligne
Membre actif
*



Messages : 210
Sujets : 17
Points: 309
Inscription : Jul 2012
RE: [PHP] _password_hash
Hello,

Je suis curieux de savoir d'ou vient l'idée d'insérer un sel à une position aléatoire dans le mot de passe. ça ne me semble pas une fameusement bonne idée.

La manière standard serait d'utiliser l'algorithme hmac, ou au minimum de faire ($password . $salt . $password).
+1 (0) -1 (0) Répondre
10-06-2014, 16h42
Message : #5
Ekroz Hors ligne
Membre actif
*



Messages : 77
Sujets : 13
Points: 43
Inscription : May 2013
RE: [PHP] _password_hash
Citation :En quoi? Par rapport a la génération du salt ?

Yep, c'est un password_hash recodé à la va-vite et basé sur du mcrypt façon deprecated.

Citation :une possibilité serait de fournir également la fonction de vérification automatique elle même basée sur la longueur du hash

Il existe plusieurs hashs de même longueur (par ex SHA-512 et Whirlpool).
+1 (0) -1 (0) Répondre
10-06-2014, 16h49
Message : #6
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
RE: [PHP] _password_hash
(10-06-2014, 16h42)b0fh a écrit : Hello,

Je suis curieux de savoir d'ou vient l'idée d'insérer un sel à une position aléatoire dans le mot de passe. ça ne me semble pas une fameusement bonne idée.

La manière standard serait d'utiliser l'algorithme hmac, ou au minimum de faire ($password . $salt . $password).

J'imagine que ca vient du fait que "comme ca c'est plus dur a deviner". Cependant, pour ma part, je ne vois pas en quoi ce n'est pas une fameusement bonne idée... Si tu peux m'éclairer...?
+1 (0) -1 (0) Répondre
10-06-2014, 17h22
Message : #7
b0fh Hors ligne
Membre actif
*



Messages : 210
Sujets : 17
Points: 309
Inscription : Jul 2012
RE: [PHP] _password_hash
D'abord parce que ça force à stocker la position, dont le choix dépend de la longueur du mot de passe, donc ça leak de l'information sur la longueur du pass, et dans les cas dégénérés (position très a droite ou très a gauche) c'est vulnérable aux attaques par extension si le hash sous-jacent l'est.

En faisant ($password . $salt . $password) c'est au moins aussi robuste, y'a pas besoin de stocker la position, et si le sel est suffisamment long on n'y perd rien a prendre un truc standard.
+1 (2) -1 (0) Répondre
11-06-2014, 18h48
Message : #8
Ekroz Hors ligne
Membre actif
*



Messages : 77
Sujets : 13
Points: 43
Inscription : May 2013
RE: [PHP] _password_hash
Ah oui je n'y avais pas pensé, après on peut toujours répartir le grain de sel avec une boucle for pour bien embrouiller le merdier, pas besoin de connaître la taille.
+1 (0) -1 (0) Répondre
13-06-2014, 15h18
Message : #9
Ekroz Hors ligne
Membre actif
*



Messages : 77
Sujets : 13
Points: 43
Inscription : May 2013
RE: [PHP] _password_hash
Alors voilà je me suis documenté un peu au niveau des fonctions de hachage et nous sommes tous dans le faux. Big Grin
hash ( $password . $salt ) et même hash_hmac ( $password , $salt ) ne sont pas considérés comme sûrs pour stocker des mots de passe.
Apparemment la raison viendrait des Rainbow Tables couplés à la puissance des GPU.

En réalité les fonctions de hachage ne sont pas faites pour être coûteuses en ressources et donc longues à bruteforcer, mais bel et bien pour faire une "signature" rapide avec le moins de risque de collisions possibles.

La librairie PHPASS ainsi que l'algorithme PBKDF2 par exemple, effectuent environ 1000 passes afin d'augmenter le coup en ressource et l'entropie du résultat.

Quand on sait que le SHA-512 utilise maximum 256 octets de mémoire pour générer un hash et qu'aujourd'hui le publique a accès à des cartes graphiques de 12 Go à 7 GHz et 5760 coeurs à 876 MHz, imaginez bien ce dont dispose la NSA, en faite on se rend compte que les NIST approvals and co signifient "vous pouvez vous en servir, on sait déjà le casser Big Grin".

A l'heure actuelle, c'est la librairie scrypt qui produit les hashs de meilleure qualité, avec une consommation de 20 à 40 Mo par mot de passe.
Malheureusement elle n'est pas encore pour l'instant disponible pour PHP, il est donc conseillé de se rabattre sur bcrypt.
Du coup j'ai pondu la fonction suivante :

Code PHP :
<?php
function _password_hash($password)
{
    
/* Vérifie l'existence d'une constante. */
    
$password_bcrypt defined "PASSWORD_BCRYPT" ) ;
    
$algo = (PHP_VERSION_ID 50500 && $password_bcrypt == TRUE) ? PASSWORD_BCRYPT PASSWORD_DEFAULT;

    
/* Retourne les informations sur le système d'exploitation. */
    
$php_uname php_uname "s" ) ;

    
/* Retourne un segment de chaîne. */
    
$substr substr $php_uname ) ;

    if (
$substr === FALSE)
    {
        return 
FALSE;
    }

    
/* Renvoie une chaîne en majuscules. */
    
$strtoupper strtoupper $substr ) ;
    
$source = (PHP_VERSION_ID 50300 && $strtoupper == "WIN") ? MCRYPT_RAND MCRYPT_DEV_URANDOM;

    
/* Crée un vecteur d'initialisation (IV) à partir d'une source aléatoire. */
    
$mcrypt_iv mcrypt_create_iv 217 $source ) ;

    if (
$mcrypt_iv == FALSE)
    {
        return 
FALSE;
    }

    
$timeTarget 0.5;
    
$options = array
    (
        
"salt" => $mcrypt_iv,
        
"cost" => 9
    
);

    do
    {
        
$options["cost"]++;
        
        
/* Retourne le timestamp UNIX actuel avec les microsecondes. */
        
$start microtime TRUE ) ;
        
        
/* Crée une clé de hachage pour un mot de passe. */
        
$password_hash password_hash $password $algo $options ) ;
        
$end microtime TRUE ) ;
    } while ((
$end $start) < $timeTarget);

    if (
$password_hash == FALSE)
    {
        return 
FALSE;
    }
    
    return 
$password_hash;
}

printf(_password_hash("rasmuslerdorf"));
?>

- Compatible avec les versions de PHP antérieures à la 5.3.0
- Calcule le cost algorithmique le plus optimisé pour le serveur. Bon on va encore me dire que je fais un calcul inutile comme pour le coup du hash_algos ( ) mais c'est juste un exemple, à vous d'adapter le code pour stocker le résultat dans la configuration de votre site web et de le recalculer à chaque mise à jour de PHP et/ou migration du site sur une autre plateforme.
+1 (0) -1 (0) Répondre
13-06-2014, 16h37
Message : #10
ark Hors ligne
Psyckomodo!
*****



Messages : 1,033
Sujets : 48
Points: 317
Inscription : Sep 2011
RE: [PHP] _password_hash
Yop,

j'voudrais juste ajouter quelques précisions

(13-06-2014, 15h18)Ekroz a écrit : des fonctions de hachage

C'est des fonctions de haShage ;) on génère un hash, on ne détruit pas l'input a coup de hache tel un boucher sanguinaire !

Citation :hash ( $password . $salt )

Ce genre de truc va etre (et c'est aussi le cas pour hash($salt . $password)) a une attaque de type 'length extension', si la fonction de hashage y est vulnérable.
Le cas du hash_hmac($password, $salt) ne le sera en revanche pas.
+1 (0) -1 (0) Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)
N-PN
Accueil | Challenges | Tutoriels | Téléchargements | Forum | Retourner en haut