web-dev-qa-db-fra.com

php: nombre seulement hash?

En php, existe-t-il un moyen de donner un hachage unique à partir d'une chaîne, mais que ce hachage était composé uniquement de chiffres?

exemple:

return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6

mais, j'ai besoin

return numhash(234); // returns 00978902923102372190 
(20 numbers only)

le problème ici est que je veux que le hachage soit court.

edit: OK, laissez-moi vous expliquer le récit en retour ici . J'ai un site qui a un identifiant pour chaque personne enregistrée. pas trop long), jusqu’à présent la numérotation des identifiants était 00001, 00002, 00003 etc ...

  1. cela rend certaines personnes plus importantes
  2. cela révèle des informations d'application que je ne souhaite pas révéler.

Pour corriger les points 1 et 2, je dois "masquer" le nombre tout en le gardant unique.

Edit + SOLUTION:

Fonction de hachage numérique basée sur le code de https://stackoverflow.com/a/23679870/175071

/**
 * Return a number only hash
 * https://stackoverflow.com/a/23679870/175071
 * @param $str
 * @param null $len
 * @return number
 */
public function numHash($str, $len=null)
{
    $binhash = md5($str, true);
    $numhash = unpack('N2', $binhash);
    $hash = $numhash[1] . $numhash[2];
    if($len && is_int($len)) {
        $hash = substr($hash, 0, $len);
    }
    return $hash;
}

// Usage
numHash(234, 20); // always returns 6814430791721596451
34
Timo Huovinen

Il y a quelques bonnes réponses mais pour moi les approches semblent stupides.
Ils ont d'abord forcé php à créer un nombre hexadécimal, puis l'ont reconverti (hexdec) en un BigInteger, puis l'ont réduit à un nombre de lettres ... c'est beaucoup de travail!

Pourquoi pas

Lire le hachage en binaire:

$binhash = md5('[input value]', true);

puis en utilisant 

$numhash = unpack('N2', $binhash); //- or 'V2' for little endian

pour convertir ceci en deux INTs ($numhash est un tableau de deux éléments). Vous pouvez maintenant réduire le nombre de bits dans le nombre en utilisant simplement une opération AND. par exemple:

$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575

Mais soyez prévenu des collisions! Réduire le nombre signifie augmenter la probabilité de deux [valeur d'entrée] différentes avec la même sortie. 

Je pense que le meilleur moyen serait d'utiliser "Cryptage ID" avec une fonction Bijectiv. Donc, aucune collision ne peut arriver! Pour les plus simples, utilisez un Affine_cipher

Exemple avec une valeur d'entrée maximale comprise entre 0 et 25:

function numcrypt($a)
{
   return ($a * 15) % 26;
}

function unnumcrypt($a)
{
   return ($a * 7) % 26;
}

Sortie:

numcrypt(1) : 15
numcrypt(2) : 4
numcrypt(3) : 19

unnumcrypt(15) : 1
unnumcrypt(4)  : 2
unnumcrypt(19) : 3

par exemple.

$id = unnumcrypt($_GET('userid'));

... do something with the ID ...

echo '<a href="do.php?userid='. numcrypt($id) . '"> go </a>';

bien sûr, ce n'est pas sécurisé, mais si personne ne connaît la méthode utilisée pour votre cryptage, il n'y a pas de raisons de sécurité, alors cette méthode est plus rapide et sécurisée contre les collisions.

9
Thomas

Un hachage MD5 ou SHA1 dans PHP renvoie un nombre hexadécimal. Il vous suffit donc de convertir les bases. PHP a une fonction qui peut le faire pour vous:

$bignum = hexdec( md5("test") );

ou

$bignum = hexdec( sha1("test") );

PHP Manuel pour hexdec

Puisque vous voulez un nombre de taille limité, vous pouvez utiliser une division modulaire pour le placer dans la plage de votre choix.

$smallnum = $bignum % [put your upper bound here]

MODIFIER

Comme l'a noté Artefacto dans les commentaires, l'utilisation de cette approche donnera un nombre supérieur à la taille maximale d'un entier en PHP et le résultat après la division modulaire sera toujours égal à 0. Toutefois, si vous prenez une sous-chaîne du hachage contenant les 16 premiers les personnages n'ont pas ce problème. Version révisée pour le calcul du grand nombre initial:

$bignum = hexdec( substr(sha1("test"), 0, 15) );
62
derekerdmann

Vous pouvez essayer crc32(). Voir la documentation sur: http://php.net/manual/en/function.crc32.php

$checksum = crc32("The quick brown fox jumped over the lazy dog.");
printf("%u\n", $checksum); // prints 2191738434 

Cela dit, crc devrait uniquement être utilisé pour validate the integrity of data.

14
David Titarenco

Le problème de couper le hash sont les collisions, pour éviter cela essayez:

return  hexdec(crc32("Hello World"));

Le crc32()

Génère le polynôme de somme de contrôle de redondance cyclique de longueurs de 32 bits de la str. Ceci est généralement utilisé pour valider l'intégrité des données en cours de transmission.

Cela nous donne un entier de 32 bits, négatif dans l'installation de 32 bits ou positif dans les 64 bits. Cet entier peut être stocké comme un identifiant dans une base de données. Cela ne pose pas de problème de collision, car il s’intègre dans la variable 32 bits, une fois convertie en décimal avec la fonction hexdec().

7

Tout d’abord, md5 est fondamentalement compromis, vous ne devriez donc pas l’utiliser pour un hachage non critique . PHP5 a la fonction hash(), voir http://www.php.net/manual/en /function.hash.php .

Si vous définissez le dernier paramètre sur true, vous obtiendrez une chaîne de données binaires. Vous pouvez également fractionner le hachage hexadécimal résultant en deux caractères et les convertir en nombres entiers individuellement, mais je suppose que cela sera beaucoup plus lent.

1
tdammers

Utilisez simplement ma méthode de hachage manuelle ci-dessous:

Divisez le nombre (par exemple 6 chiffres) par les valeurs premières, 3,5,7. 

Et obtenez les 6 premières valeurs qui se trouvent dans les décimales comme identifiant à utiliser. Effectuez une vérification de l'unicité avant la création de l'ID. Si une collision existe, augmentez le dernier chiffre de +1 jusqu'à une non-collision.
Par exemple. 123456 vous donne 771428 123457 vous donne 780952 123458 vous donne 790476. 

0
Ben

Essayez hashid .
Il hache un nombre dans un format que vous pouvez définir. Les formats incluent combien de caractère et quel caractère est inclus.
Exemple:
$ hashids-> encoder (1);
.__ retournera "28630" dépend de votre format,

0
Irfandi D. Vendy