php: номер только хэш? - PullRequest
35 голосов
/ 31 июля 2010

В php есть способ дать уникальный хеш из строки, но чтобы хеш состоял только из чисел?

пример:

return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6

но мне нужно

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

проблема здесь в том, что я хочу, чтобы хеширование было коротким.

редактирование: Хорошо, позвольте мне объяснить историю здесь. У меня есть сайт, на котором есть идентификатор для каждого зарегистрированного человека, а также мне нужен идентификатор для того, чтобы человек мог использовать и обмениваться (следовательно, он не может быть слишком длинным), пока нумерация идентификаторов была 00001, 00002, 00003 и т. Д. ..

  1. это делает некоторых людей более важными
  2. это показывает информацию о приложении, которую я не хочу раскрывать.

Чтобы исправить точки 1 и 2, мне нужно «спрятать» номер, сохраняя его уникальным.

Редактировать + РЕШЕНИЕ:

Числовая хеш-функция на основе кода 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

Ответы [ 7 ]

62 голосов
/ 31 июля 2010

Хэш MD5 или SHA1 в PHP возвращает шестнадцатеричное число, поэтому все, что вам нужно сделать, - это преобразовать базы.PHP имеет функцию, которая может сделать это для вас:

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

или

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

Руководство по PHP для hexdec

Поскольку вы хотитеограниченный размер, вы можете затем использовать модульное деление, чтобы поместить его в нужный вам диапазон.

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

РЕДАКТИРОВАТЬ

Как отмечено Артефакто в комментариях, используяпри таком подходе число, превышающее максимальный размер целого числа в PHP, получится, а результат после модульного деления всегда будет равен 0. Однако, взятие подстроки хэша, содержащей первые 16 символов, не имеет этой проблемы.Пересмотренная версия для расчета начального большого числа:

$bignum = hexdec( substr(sha1("test"), 0, 15) );
15 голосов
/ 31 июля 2010

Вы можете попробовать crc32(). См. Документацию по адресу: 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 

С учетом сказанного, crc должен только использоваться для validate the integrity of data.

10 голосов
/ 15 мая 2014

Есть несколько хороших ответов, но для меня подходы кажутся глупыми.
Сначала они заставляют php создать шестнадцатеричное число, затем конвертируют его обратно (hexdec) в BigInteger и затем сокращают его до количества букв ... это большая работа!

Вместо этого, почему бы не

Считать хеш в двоичном виде:

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

затем используя

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

для приведения этого к двум INT с ($numhash - это массив из двух элементов). Теперь вы можете уменьшить количество бит в числе, просто используя операцию AND. например:

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

Но предупреждаем о столкновениях! Уменьшение числа означает увеличение вероятности двух разных [входных значений] с одинаковым выходом.

Я думаю, что гораздо лучшим способом было бы использование "ID-Crypting" с функцией Bijectiv. Так что никаких столкновений не может произойти! Для простейшего вида просто используйте Affine_cipher

Пример с максимальным диапазоном входных значений от 0 до 25:

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

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

Выход:

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

unnumcrypt(15) : 1
unnumcrypt(4)  : 2
unnumcrypt(19) : 3
* * +1032 например,
$id = unnumcrypt($_GET('userid'));

... do something with the ID ...

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

конечно, это небезопасно, но если никто не знает метод, используемый для вашего шифрования, то нет никаких причин безопасности, тогда этот путь быстрее и безопаснее при столкновении.

7 голосов
/ 19 августа 2015

Проблема обрезания хэша заключается в коллизиях, чтобы избежать этого, попробуйте:

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

crc32():

Генерирует полином из контрольной суммы циклической избыточности 32длина бита ул.Это обычно используется для проверки целостности передаваемых данных.

Это дает нам целое число 32 бита, отрицательное в 32-битной установке или положительное в 64-битном.Это целое число может храниться как идентификатор в базе данных.У этого нет проблем столкновения, потому что он вписывается в 32-битную переменную, как только вы преобразуете ее в десятичную с помощью функции hexdec().

1 голос
/ 31 июля 2010

Прежде всего, md5 в основном скомпрометирован, поэтому вы не должны использовать его ни для чего, кроме некритического хеширования. PHP5 имеет функцию hash(), см. http://www.php.net/manual/en/function.hash.php.

Если установить для последнего параметра значение true, вы получите строку двоичных данных. Кроме того, вы можете разбить получившийся шестнадцатеричный хеш на куски по 2 символа и преобразовать их в целые числа по отдельности, но я ожидаю, что это будет намного медленнее.

0 голосов
/ 26 сентября 2018

Просто используйте мой ручной метод хеширования ниже:

Разделите число (например, 6 цифр) на простые значения, 3,5,7.

И получите первые 6 значений в десятичных разрядах в качестве идентификатора, который будет использоваться.Проверяйте уникальность перед фактическим созданием идентификатора, если существует коллизия, увеличивайте последнюю цифру на +1 до тех пор, пока не произойдет коллизия.
Например, 123456 дает вам 771428, 123457 дает 780952, 123458 дает 790476.

0 голосов
/ 05 апреля 2016

Попробуйте hashid .
Он хеширует число в формате, который вы можете определить.Форматы включают в себя, сколько символов и какой символ включены.
Пример:
$ hashids-> encode (1);
Возвращает «28630» в зависимости от вашего формата,

...