PHP explication fonction pack()

PHP explication fonction pack() - PHP - Programmation

Marsh Posté le 07-02-2009 à 14:46:54    

Bonjour, j'aurai besoin d'une explication de ces quelques lignes lignes.
 
Ces lignes de codes doivent completer (d'une certaine facon) une chaine pour que sa longueur soit un multiple de 512 bits
 

Citation :

//PARTIE 1
$M = strlen($str);      //    number of bytes  
$L1 = ($M >> 28) & 0x0000000F;  //        top order bits  
$L2 = $M << 3;  //        number of bits  
$l = pack('N*', $L1, $L2);
               
 
//PARTIE 2
//      64 = 64 bits needed for the size mark. 1 = the 1 bit added to the  
//      end. 511 = 511 bits to get the number to be at least large enough  
//      to require one block. 512 is the block size.  
$k = $L2 + 64 + 1 + 511;  
$k -= $k % 512 + $L2 + 64 + 1;  
$k >>= 3;       //     convert to byte count

 
//PARTIE 3
$str .= chr(0x80) . str_repeat(chr(0), $k) . $l;  


 
PARTIE 1
D'apres l'algorithme suivit on devrait retrouver dans $l le nombre de bits contenus dans $str sur 64 bits mais je ne comprends pas bien la fonction pack donc j'aimerai des explication.
 
d'abord dans $M on recupere le nombre de caractères de $str.
Ensuite dans $L1 on recupere les bits n° 28 29 30 31 de $M ($M pouvant etre sur 32 ou 64 bits, d'ou le  & 0x0000000F; ) Je pense qu'on fait ca a cause des bits perdus a la ligne d'apres mais je ne sais pas pourquoi
Dans $L2 on décale de 3 bits a gauche, soit une multiplication par 8 ce qui nous donne le nombre de bits dans $str. Cela ne tient pas compte d'un eventuel dépassement je pense

 
 

PARTIE 2
D'apres l'algorithme, on est sensé avoir dans k une valeur telle que : (nombre de bits dans $str)+$k1+64 soit un multiple de 512. et $k = $k1/8 pour le convertir en nombre de caractères

 
PARTIE 3
a la chaine de bits de $str on concatène : un 1 puis plein de 0 et enfin la longueur de bits de $str sur les 64 derniers bits
 
 
Donc j'ai 3 principales questions :
 
je comprends pas la fonction pack meme apres avoir lu sur internet. Et je comprends pas pourquoi elle nous donne le résultat attendu.
 
Dans $L2 qu'est ce qui se passe si on a un dépassement (cad : imaginons qu'il y avait un 1 dans les 3 bits de poids fort de $M celui ci est perdu)
 
je comprends pas bien les opérations effectuées pour $k
 
 
Merci pour l'aide


---------------
Toinou87 ;-p May the force be with you!!
Reply

Marsh Posté le 07-02-2009 à 14:46:54   

Reply

Marsh Posté le 07-02-2009 à 17:11:27    

ben alors?
personne sur ce forum n'est capable de m'aider?


---------------
Toinou87 ;-p May the force be with you!!
Reply

Marsh Posté le 07-02-2009 à 17:37:49    

c'est surement en partie du au fait que peu de personnes à ma connaissance utilisent PHP pour manipuler des données binaires :D

Reply

Marsh Posté le 07-02-2009 à 17:43:13    

ca change pas le fait que des gens peuvent connaitre la fonction pack() (qui en soit n'est pas forcement faites pour de la manipulation de binaires).
 
Y a deux points qui me genent ici et seulement l'un des deux est lié au binaire


---------------
Toinou87 ;-p May the force be with you!!
Reply

Marsh Posté le 09-02-2009 à 23:38:04    

Tu ne trouveras pas plus clair que la documentation : http://php.net/pack
Autre conseil, utilise hash('sha256',$s)

Reply

Marsh Posté le 09-02-2009 à 23:47:08    

ben j'ai lu la doc mais j'ai du mal a me représenter ce que ca donne.
Sinon, l'idée est de refaire l'algorithme, comme je l'ai dit plusieurs fois


---------------
Toinou87 ;-p May the force be with you!!
Reply

Marsh Posté le 10-02-2009 à 00:17:13    

Je ne vois pas où tu l'as dit, et de toute façon c'est une mauvaise idée si tu n'as pas les compétences nécessaires.
 
En tout cas, pack('N*', ...) va formater les arguments que tu lui donnes sous forme de mots 32 bits big endian (bit de poids fort à droite) mis dans une chaîne de caractères binaire. Ce n'est rien d'autre que ce qu'il est indiqué dans la documentation PHP.
 
Tu as bien compris à quoi servent L1 et L2. Si L2 dépasse, les 4 bits perdus sont récupérés dans L1 (attention, PHP est little endian et le résultat est mis sous forme big endian). Remarque au passage que le script est mal fait, car il ne gère que les chaînes ayant au plus 2^24 caractères alors que SHA1 en supporte jusqu'à 2^56.
 
$k n'est rien d'autre que le nombre de 0 qu'il faut insérer entre le 1 après la fin du message à hacher et les 64 bits de taille à la fin du bloc de 512.

Reply

Marsh Posté le 10-02-2009 à 09:27:33    


Je kiffe les malades qui connaissent ce genre de truc  [:cerveau lent]

Reply

Marsh Posté le 10-02-2009 à 11:20:48    

Bouchon2 a écrit :

Je ne vois pas où tu l'as dit, et de toute façon c'est une mauvaise idée si tu n'as pas les compétences nécessaires.
 
En tout cas, pack('N*', ...) va formater les arguments que tu lui donnes sous forme de mots 32 bits big endian (bit de poids fort à droite) mis dans une chaîne de caractères binaire. Ce n'est rien d'autre que ce qu'il est indiqué dans la documentation PHP.
 
Tu as bien compris à quoi servent L1 et L2. Si L2 dépasse, les 4 bits perdus sont récupérés dans L1 (attention, PHP est little endian et le résultat est mis sous forme big endian). Remarque au passage que le script est mal fait, car il ne gère que les chaînes ayant au plus 2^24 caractères alors que SHA1 en supporte jusqu'à 2^56.
 
$k n'est rien d'autre que le nombre de 0 qu'il faut insérer entre le 1 après la fin du message à hacher et les 64 bits de taille à la fin du bloc de 512.


plusieurs choses: a confirmer mais il me semble que le big endian c'est poid fort a gauche, mais bon c'est pas l'important.
 
sinon pour L2 etant donner qu'il y a un decalage de 3 bits, il ne peut y avoir que 3 bits de perdu d'ou le fait que je comprend pas pourquoi on a un bit en double dans L1 et L2.
 
le probleme des chaines trop longue je l'avais remarqué d'ou le fait que je comprends pas pourquoi il utilise $L2 et pas $l dans son algorithme (car SHA-256 doit pouvoir aller a 2^64 caracteres)
 
pour $k, je sais ce qu'il fait, je comprends pas bien comment il le fait.
 
Merci en tout cas pour ta reponse plus complete que les précédentes


---------------
Toinou87 ;-p May the force be with you!!
Reply

Marsh Posté le 11-02-2009 à 00:15:36    

Toinou87 a écrit :

plusieurs choses: a confirmer mais il me semble que le big endian c'est poid fort a gauche, mais bon c'est pas l'important.


 
Très bonne remarque
 

Toinou87 a écrit :

sinon pour L2 etant donner qu'il y a un decalage de 3 bits, il ne peut y avoir que 3 bits de perdu d'ou le fait que je comprend pas pourquoi on a un bit en double dans L1 et L2.


 
Encore une fois très bonne remarque, le code est clairement faux pour l > 2^31 (l'auteur ne doit pas s'attendre à une chaîne de plus de 2 Go). Tu peux utiliser (l>>28) & 0x7 si tes chaînes font moins de 16 Go. Au delà tu auras des problèmes avec PHP qui ne gère que les entiers 32 bits signés.
 

Citation :

le probleme des chaines trop longue je l'avais remarqué d'ou le fait que je comprends pas pourquoi il utilise $L2 et pas $l dans son algorithme (car SHA-256 doit pouvoir aller a 2^64 caracteres)


C'est parce que PHP considère comme flottant un entier plus grand que ~2 milliards, et on ne peut plus utiliser l'arithmétique binaire au delà.
 

Citation :

pour $k, je sais ce qu'il fait, je comprends pas bien comment il le fait.


C'est normal, le calcul de $k est vraiment fait de manière immonde, mais à première vu il a l'air correct.


Message édité par Bouchon2 le 11-02-2009 à 01:01:15
Reply

Marsh Posté le 11-02-2009 à 00:15:36   

Reply

Marsh Posté le 11-02-2009 à 11:30:01    

ce qui est bizarre c'est que toutes ces "erreurs" (peut etre seulement notre incomprehension) etaient dans un fichier de classe pour PHP4 a priori fait par zend


---------------
Toinou87 ;-p May the force be with you!!
Reply

Marsh Posté le 11-02-2009 à 21:47:59    

Il peut très bien s'agir d'une erreur volontaire mais en tout cas il ne fait aucun doute qu'avec une chaîne de plus de 2Go le résultat sera faux. Les erreurs existent aussi chez Zend, et ce d'autant plus qu'ils ne sont pas spécialistes en cryptologie.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed