Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Hasher un objet Json

1 réponse
Avatar
Julien Arlandis
Bonsoir,

J'ai besoin d'une fonction qui permet de hasher un objet json, bien sûr
le résultat du hash ne doit pas dépendre de l'ordre des listes.
Par exemple, ces deux objets json
$json = <<<EOF
{
"tttt" : ["hdfhdf","jjj", "2"],
"lll" : "ppppppppppppp",
"aaa" :
{
"jjj" :
{
"aaaaaaa" : "oooo",
"sssss" : "llll"
},
"ccc" : "ooo"
},
"bbb" : "xxxxx"
}
EOF;

et

$json = <<<EOF
{
"aaa" :
{
"ccc" : "ooo",
"jjj" :
{
"sssss" : "llll",
"aaaaaaa" : "oooo"
},
},
"lll" : "ppppppppppppp",
"tttt" : ["hdfhdf","jjj", "2"],
"bbb" : "xxxxx"
}
EOF;

sont identiques, ils doivent donc avoir le même hash sha1.

J'ai donc écrit 2 petites fonctions :

// Transforme l'onbjet json en un tableau ordonné
function json2array($json, $prefix = "")
{
static $tab = array();
foreach ($json as $cle => $value)
{

$cle = $prefix."/".str_replace("/", "//", $cle);
if(is_object($value))
{
json2array($value, $cle);
}
elseif(is_array($value))
{
$i = 0;
foreach($value as $val)
{
$tab[$cle."/".$i] = (string) $val;
$i++;
}
}
else
{
$tab[$cle] = (string) $value;
}
}

ksort($tab);
return $tab;
}


// Applique un hash sur chaque clé, valeur du tableau concatène le tout,
et applique un hash.
function getHash($json)
{
$tab = json2array($json);
$long_hash = "";
foreach($tab as $cle => $value)
{
$long_hash .= sha1($cle).sha1($value);
}

return sha1($long_hash);
}


Pour obtenir mon hash j'appele la fonction
$json = json_decode($json);
getHash($json);
et j'obtiens bien "edfeed3410bbc567fdc73154baf3a5d30b4f8bd3" pour les
deux chaines.

Mon soucis c'est que j'ai deux fonctions, et j'aimerais en avoir qu'une
seule. J'aimerais bien faire rentrer json2array() dans getHash() mais à
cause de la récursivité dans la fonction json2array je ne sais pas
comment m'y prendre.
Une astuce, une idée?

PS : crosspost sur fr.comp.securite pour détecter une éventuelle
faiblesse dans la façon de hasher mon objet.

1 réponse

Avatar
Antoine Polatouche
Le 15/04/2013 21:28, Julien Arlandis a écrit :
Pour obtenir mon hash j'appele la fonction
$json = json_decode($json);
getHash($json);
et j'obtiens bien "edfeed3410bbc567fdc73154baf3a5d30b4f8bd3" pour les
deux chaines.

Mon soucis c'est que j'ai deux fonctions, et j'aimerais en avoir qu'une
seule. J'aimerais bien faire rentrer json2array() dans getHash() mais à
cause de la récursivité dans la fonction json2array je ne sais pas
comment m'y prendre.
Une astuce, une idée?



Bonjour,

en utilisant les classes de php, tu peux faire une méthode statique
maClasse::getHash($json), pour avoir ce qui ressemble le plus à une
fonction, ou utiliser des méthodes publiques, genre
$obj = new maClasse($json);
$obj->getHash();

Dans les deux cas, la fonction récursive est encapsulée dans la classe.

Ça va si tu mets le code de la classe dans un fichier séparé, mais si
c'est pour mettre tout le code dans le même fichier, ça n'arrange pas
ton problème: tu as une classe en plus au lieu d'une fonction en plus ;)