unknown
2013-04-15 19:28:38 UTC
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.
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.