Crypto PBKDF2 Grub2

 

Crypto PBKDF2 Grub2

 

Cet algorithme est utilisé pour lutter contre le brute force de mots de passe (ou clefs) . Il augmente considérablement les temps de calculs pour obtenir un hash.

on le retrouve notamment dans :

grub2
wpa
truecrypt

Dans ces 3 exemples, PBKDF2 repose sur l’algorithme cryptographique HMAC que l’on combine dans une fonction (F) itérative à base de xor.

 

Théorie

 

DK = PBKDF2(PRF, Password, Salt, itérations, dkLen)

PRF : PRF est une fonction pseudo-aléatoire composé de deux paramètres.
on utilise généralement HMAC comme PRF

Password : le mot de passe en clair

Salt: le sel

itérations : nombre d’itération

dkLen : la longueur en octets du résultat (DK – Derived Key)

Dk : Le résultat appelé DerivedKey => le hash du mot de passe

 

Formule

 

F( Password, Salt, c, i ) = U1 xor U2 xor... ...xor Uc

c = nombre d’ itération
i = index itération

U1 = PRF(Password, Salt || i)
U2 = PRF(Password, U1)
Uc = PRF(Password, Uc-1)

La fonction F réalise un « xor » entre les différentes chaines U1 à Uc.
c est égale au nombre d’ itérations.

Calcul de U1 (1ere itération)

  • 1er paramètre : password
  • 2ieme paramètre : salt || i ( || signifie concaténation )
  • i est l’ index d’ itération, à la première itération i vaut 1
  • i est codé sur 4 octets (big-endian 32 bits) cela devient : « \x00\x00\x00\x01 »
  • Ces 2 paramètres servent à calculer U1

Calcul de U2…..Uc( itérations suivantes):

  • 1er paramètre : password ( constant, ne change pas jusqu’à la dernière itération)
  • 2ieme paramètre : correspond à U1(calculé précédemment )

et on réalise un xor entre les Ux comme ceci
entre U1 et U2
puis ensuite entre le résultat précédent (U1 xor U2) et U3
et ainsi de suite

 

Exemple pratique – Grub2

 

La suite de cet article est basée sur le protocole de hashage de mots de passe utilisé par GRUB2.

par défaut, grub2 exécute (10 mille) itérations et la longueur du salt est égale à 64 octets.

La commande grub-mkpasswd-pbkdf2 permet de générer un hash pbkdf2
exemple de résultat :

Détaillons chaque champs:

  • Le mot de passe que j’ ai saisi est : 12345678
  • sha512 : pbkdf2 utilise le protocole sha512 comme PRF
  • 10000 : nombre d’ itérations (10 mille)
  • salt : 64 octets
  • le hash du mot de passe : 64 octets

Les champs sont séparés par des points (.).
Par souci de clarté j’ ai découpé chaque chaine en 4 partie , mais en réalité tout est sur une même ligne.

Rappel :

DK = PBKDF2(PRF, Password, Salt, itérations, dkLen)

Dans le cadre de grub2 :

  • la fonction Prf est la fonction cryptographique HMAC-SHA512.
  • Le nombre d’ itérations est fixé à 10000
  • le résultats est sur 64 octets

Donc la formule devient :

DK = PBKDF2(HMAC-SHA512, password, salt, 10000, 64)

calcul de la 1ere itération :
U1 = HMAC-SHA512(« 12345678 », »\0x2D\0xD6…..\0xDE\x08\x00\x00\x00\x01″)
Rappel : l’indice (\x00\x00\x00\x01) est concaténé au salt

calcul 2ieme itération et itérations suivantes :
U2 = HMAC-SHA512(« 12345678 »,U1)


Uc = HMAC-SHA512(« 12345678 »,Uc-1 )

Programme écrit en python qui génère un hash PBKDF2

 

Programme écrit en python qui génère un hash PBKDF2

 

j’ ai testé ce programme sur kali 1.0.3.

Généré un hash avec la commande grub2 ci-dessous , saisir le mot de passe « 12345678 » :

grub-mkpasswd-pbkdf2 -s 3

-s : nombre d’ octets du salt

important:
Dans cet exemple j’ai réduit longueur du salt pour éviter par la suite des saisis au clavier fastidieuses.

Avant de lancer le programme, repérer la ligne 51 (surlignée) pour déclarer les bons paramètres. Vous devriez normalement changer uniquement le salt ( en bleu).
resultat = PBKDF2(« 12345678″, »\xF2\xB0\xF0 »,10000,64)

Pour sélectionner tout le code , double-cliquez dans la fenêtre.

# -*- coding: utf-8 -*-

import struct
import timeit
import hashlib
import hmac
import binascii

# fonctions

def hmacfunc(key,message):
    # key = mot de passe
    # message = salt
    return hmac.new(key,message,hashlib.sha512).digest()

def xor_string(str1, str2):
    # TODO: slow!
    str3 = ''
    for i in xrange(len(str1)):
        str3 += chr(ord(str1[i]) ^ ord(str2[i]))
    return str3

def PBKDF2(password, salt, iterations, derivedlen):

        def F(P, S, c, i):
            U_prev = hmacfunc(P, S + struct.pack('>L', i))
            res = U_prev
            for cc in xrange(2, c+1):
                U_c = hmacfunc(P, U_prev)
                res = xor_string(res, U_c)
                U_prev = U_c
            return res
        tmp = ''
        i = 1
        while True:
            tmp += str(F(password, salt, iterations, i))
            if len(tmp) > derivedlen:
                break
            i += 1

        return tmp[0:(derivedlen)]

# grub-mkpasswd-pbkdf2 -s 3
# pensez à  changer le mot de passe,le salt et le nombre d' iteration
# dans cet exemple
#  le mot de passe est "password"
#  le salt est "\x4D\x06\x01"
#  le nombre d' itération est  : 10000
resultat =  PBKDF2("123", "\xA2\xC8\x73", 10000, 64)

#arg01 : mot de pase
#arg02 : salt
#arg03 : iteration
#arg04 : taille en octets du resultat

# commande a taper en ligner de commande pour timer la durée de la fonction
# pbkdf2 est le nom du programme a timer (sans l' extension .py)

#import timeit
#from pbkdf2 import *
#timeit.Timer(stmt='PBKDF2("password", "\xF2\xB0\xF0", 10000, 64)',setup='from pbkdf2 import PBKDF2,hmacfunc').timeit(1)

print "resultat " + binascii.hexlify(resultat).upper()

Le protocole WPA2 utilise également le protocole PBKDF2. Voici les paramètres utilisés

DK = PBKDF2(HMAC−SHA1, passphrase, ssid, 4096, 256)

la fonction PRF est dans ce cas HMAC-SHA1 le ssid fait office de salt le nombre d’ itération s’élève à 4096 le taille du résultat est égale à 256 octets.

 

Un challenge pour la fin

 

Enoncé : grub-mkpasswd-pbkdf2 -s 3 password : ???

#
# Your PBKDF2 is grub.pbkdf2.sha512.10000.BBD751.AFC96786A477E787381FBB4AE0B42DAA2E56B25C0A285C653C3452D0A8A31FD42E83736E53BE1CA8380E4C90C791AFA80ACE59DCB285E0EB2F9D018B1D55233E
#

le mot de passe à trouver est composé de 3 chiffres (001 à 999)

Laisser un commentaire

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


The reCAPTCHA verification period has expired. Please reload the page.