Затемнение идентификатора базы данных

У меня есть таблица с первичным ключом, который является автоматическим инкрементом. Я хочу связать изображение с первичным ключом, но я не хочу, чтобы первичный ключ был показан. Был бы, называя изображения чем-то как:

$filename = md5($primarykey + $secret_string) . '.jpg';

быть хорошим решением?

Я волнуюсь, что могла быть коллизия и файл быть по записанному.

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

Другая опция является логическим преобразованием стиль URL YouTube, например, 1=a 2=b, но с рандомизированным порядком, например, 1=x 2=m..., но затем существует шанс его декодируемый... плюс md5, вероятно, было бы легче, чем какая-либо функция URL YouTube.

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

7
задан JimBo 3 March 2010 в 21:48
поделиться

10 ответов

На самом деле у вас есть два варианта:

  • Создать что-то и проверить отсутствие столкновений
  • Создать что-то и надеяться на отсутствие столкновений

Обычно вы можете используйте следующие параметры: - Хеш - случайно сгенерированная строка - UUID

Хеш Если вы выбираете хеш, выберите что-нибудь с низкой частотой столкновений. Кроме того, при хешировании подумайте, почему вы хотите скрыть идентификаторы БД. Кто-то не займет много времени, чтобы вычислить ваши хэши, если вы хешируете простые числа, вам абсолютно необходимо это солить. Преимущества соленого хэша - быстрая генерация и низкая вероятность коллизий (в небольших случаях совершенно не нужно проверять это, поэтому более быстрые вставки). Обратной стороной является то, что любая правильная реализация будет SHA256 или лучше, а это значит, что она длинная. Вы можете сделать несколько шестнадцатеричных преобразований, если хотите сэкономить место в базе данных / индексе, это может быть больше, чем вы хотите.

Случайная строка Вы можете сгенерировать ее любой длины, которая вам подходит, любого набора символов или чисел a-Z0-9. Это также означает «больше» данных в более короткой строке, которая используется в URI, данных REQUEST и т. Д. Обратной стороной является то, что вам нужно проверить, есть ли они в базе данных.

UUID Как хэш, быстро генерируется, довольно низкая вероятность коллизий и может быть изменен, чтобы он был «менее» уродливым, чем чистые выходные данные.

Мое предложение Не делай этого.Мне приходилось иметь дело с этим раньше в очень большой реализации, которая выросла из очень маленькой реализации. В конце концов вы начинаете делать «умные» вещи, такие как создание полностью уникальных идентификаторов (например, тип контента + ваш идентификатор) и начинаете видеть в нем какое-то значение, но затем вам приходится иметь дело с масштабом. Масштабировать это очень сложно. БД оптимизированы для идентификаторов в качестве первичных ключей, и вам нужно подумать над этим, если вы хотите масштабировать его по вертикали. Если необходимо, используйте его только для взаимодействия с внешними клиентами.

0
ответ дан 7 December 2019 в 14:31
поделиться

Я полагаю, что имею дело с более чем двумя миллионами записей, так какова вероятность столкновения?

Согласно Wikipedia, вам потребуется более 2*10^19 записей, чтобы получить 50% вероятность хотя бы одного столкновения, так что я бы сказал, что вам не стоит беспокоиться.

2
ответ дан 7 December 2019 в 14:31
поделиться

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

Вы захотите преобразовать зашифрованные данные в ASCII, используя base64 или шестнадцатеричное кодирование, например:

base64_encode(encrypt(id, secret_key))

И декодирование:

decrypt(base64_decode(id), secret_key)

(выше псевдокод, вам нужно будет найти соответствующие функции в PHP)

Для шифрования ничего особенного не нужно. Достаточно простого блочного шифра, такого как DES.

0
ответ дан 7 December 2019 в 14:31
поделиться

Алгоритм хеширования, такой как MD5, не является хорошим решением для этого, поскольку хеши по определению не гарантируют уникальность (они создают хеши, которые имеют конечное число значения).

Вам нужно шифрование. Взгляните на javax.crypto.Cipher.

0
ответ дан 7 December 2019 в 14:31
поделиться

Если вы можете добавить колонку, добавьте GUID как UNIQUE колонку в таблице и используйте .jpg в качестве ключевого имени. Алгоритмы GUID в обозримом будущем не должны создавать дубликаты, но на всякий случай ограничение UNIQUE может это уловить.

0
ответ дан 7 December 2019 в 14:31
поделиться

Если хотите использовать идентификатор, но не хотят раскрывать идентификатор и хотят иметь низкий риск столкновений; один из вариантов - использовать хэш идентификатора. Хэш будет согласованным, необратимым и (за исключением огромных наборов данных - 2 32 иш в зависимости от используемого хеша) уникальным для каждой фотографии. Вы, кажется, имеете основную идею в своем вопросе:

$filename = md5($primarykey + $secret_string) . '.jpg';

Вы заменяете MD5 на лучший алгоритм хеширования по вашему выбору. Желательно что-нибудь с большей мощностью. Судя по множеству статей в ответ на комментарии, может показаться, что SHA512 или что-то подобное было бы лучше.

0
ответ дан 7 December 2019 в 14:31
поделиться

Используйте линейный конгруэнтный генератор . Если правильно подобрать значения, то получится псевдослучайная последовательность с очень большим периодом. Никаких коллизий, но учтите, что это всего лишь метод обфускации и не обеспечит никакой реальной безопасности (но я предполагаю, что это не то, что вы ищете).

2
ответ дан 7 December 2019 в 14:31
поделиться

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

Если вы хотите быть действительно уверенными: вот небольшой тестовый скрипт ;)

<?php
for($i = 0; $i < 1000000; ++$i) {
    $hash = md5($i);
    if(isset($x[$hash])) { die("COLLISION!"); }
    $x[$hash] = true;
}        }
echo "All is well";

Более сложное решение кажется пустой тратой времени, но в случае, если вам нужны более короткие идентификаторы, вы можете дать короткий случайно сгенерированный идентификатор каждой фотографии (и проверить, использовался ли он уже во время генерации и сгенерировать другой, если это так)

1
ответ дан 7 December 2019 в 14:31
поделиться

Просто используйте хэш первичного ключа. Шансы на столкновение очень низки.

-1
ответ дан 7 December 2019 в 14:31
поделиться

Я согласен с использованием Base64. Вы также можете использовать Guid. Или просто сохраните имя файла в таблице, что я и сделал.

Кроме того, будьте осторожны, чтобы не потерять файлы.

0
ответ дан 7 December 2019 в 14:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: