Как создать последовательную хэш-функцию

Я хочу разработать нечто похожее на jsfiddle, где пользователь может вводить некоторые данные, а затем «сохранять» его и получать уникальный случайный URL-адрес, который загружает эти данные.

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

Есть ли функция или метод, который преобразует число в хеш, который имеет 4 символа без каких-либо коллизий до тех пор, пока записи (62 * 62 * 62 * 62 === 14776336) ?

Например, первая запись на сервере будет называться 1 на сервере, но iUew3 – пользователю, следующая запись будет 2 на сервере, но ueGR – пользователю …

EDIT: Я не уверен, что это очевидно, но эта хэш-функция должна быть обратимой, потому что, когда пользователь запрашивает ueGR сервер должен знать серверу, файл 2

Это можно сделать, но я бы предложил использовать 64 символа, так как это сделает его намного проще. 4 6 бит символов = 24 бит.

Используйте комбинацию из следующих:

  • битное переупорядочение
  • xor с числом
  • поместите его в 24-битную максимальную длину LFSR и выполните пару циклов.

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

Когда вы вычисляете «перетасованный» номер, просто упакуйте его в двоичную строку и base64_encode его с помощью base64_encode .

Для декодирования просто выполните обратную операцию.

Образец (2 ^ 24 длинной уникальной последовательности):

 function lfsr($x) { return ($x >> 1) ^ (($x&1) ? 0xe10000 : 0); } function to_4($x) { for($i=0;$i<24;$i++) $x = lfsr($x); $str = pack("CCC", $x >> 16, ($x >> 8) & 0xff, $x & 0xff); return base64_encode($str); } function rev_lfsr($x) { $bit = $x & 0x800000; $x = $x ^ ($bit ? 0xe10000 : 0); return ($x << 1) + ($bit ? 1 : 0); } function from_4($str) { $str = base64_decode($str); $x = unpack("C*", $str); $x = $x[1]*65536 + $x[2] * 256 + $x[3]; for($i=0;$i<24;$i++) $x = rev_lfsr($x); return $x; } for($i=0; $i<256; $i++) { $enc = to_4($i); echo $enc . " " . from_4($enc) . "\n"; } 

Вывод:

 AAAA 0 kgQB 1 5ggD 2 dAwC 3 DhAH 4 nBQG 5 6BgE 6 ehwF 7 HCAO 8 jiQP 9 +igN 10 aCwM 11 EjAJ 12 gDQI 13 9DgK 14 ZjwL 15 OEAc 16 qkQd 17 3kgf 18 TEwe 19 NlAb 20 pFQa 21 0FgY 22 ... 

Примечание: для URL-адреса замените + и / с - и _ .

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

Вот как я его реализовал. Вот файл save.php (может кто-нибудь сказать мне, есть ли в нем какие-то недостатки дизайна):

 <?php $index = file_get_contents('saves/data/placeholder'); $index++; file_put_contents('saves/data/placeholder', $index); $string = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; do { $hash = $string[rand(0, 61)] . $string[rand(0, 61)] . $string[rand(0, 61)] . $string[rand(0, 61)]; } while (file_exists('saves/' . $hash)); file_put_contents('saves/' . $hash, $index); file_put_contents('saves/data/' . $index, $_REQUEST['data']); echo $hash; ?> 

И вот load.php:

 <?php if (!file_exists('saves/' . $_REQUEST['file'])) { file_put_contents('saves/data/log', 'requested saves/' . $_REQUEST['file'] . "\n", FILE_APPEND); die(); } $file_pointer = file_get_contents('saves/' . $_REQUEST['file']); if (!file_exists('saves/data/' . $file_pointer)) { file_put_contents('saves/data/log', 'requested saves/data/' . $file_pointer . 'from ' . $_REQUEST['file'] . "\n", FILE_APPEND); die(); } echo file_get_contents('saves/data/' . $file_pointer); ?> 

Надеюсь, это поможет другим.

На мой взгляд, если вы также сохраняете время save time of entry на сервере, вы можете создать хеш-функцию. hash = func(id, time) но только с hash = func(id) будет легко разрешаться

Это нечетный набор ограничений. Я регулярно использую контрольные суммы MD5 для создания уникальных URL-адресов из данных. Если пользователь еще не имеет данных, они не могут угадать URL-адреса.

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

Я не понимаю ограничения на "хранение вещей последовательно на сервере". Если вам нужно знать порядок, в котором создаются хеши, я бы просто поместил эту информацию в отдельный файл. Вам может потребоваться блокировка файлов или какой-либо другой хак, чтобы вы могли добавить хэш к этому файлу постепенно.

Если вам нужны короткие URL-адреса, вы можете либо взять префикс контрольной суммы MD5, либо взять код CRC-32 и base64. Оба будут давать вам уникальные URL-адреса с достаточно хорошей вероятностью.

Вот обратимая библиотека, которая работает w / bcmath
http://blog.kevburnsjr.com/php-unique-hash

Это не может быть обратимым. Единственный способ (тот, который используется сократителями url и jsfiddle) – хранить созданный хеш (фактически это дайджест) в какой-то структуре таблицы / данных и * искать его при поиске.

Почему это?

Переходя от, например, 128 символов данных → 4 видимых коррелятора, вы теряете много данных .
Вы не можете хранить оставшиеся данные в магических трещинах между этими 4 байтами, их нет.