Я использую последовательные идентификаторы в качестве первичных ключей, и есть случаи, когда я не хочу, чтобы эти идентификаторы были видны пользователям, например, я мог бы хотеть избегать URL-адресов вроде? Invoice_id = 1234, которые позволяют пользователям угадывать, сколько Счета системы в целом выдают.
Я мог бы добавить поле базы данных с GUID или чем-то подобным из хэш-функций, случайных строк и / или числовых базовых преобразований, но схемы такого рода имеют три проблемы, которые меня раздражают:
Необходимо выделить дополнительное поле базы данных. Я знаю, что мог бы использовать GUID в качестве своего первичного ключа, но мои целочисленные PK с автоинкрементом подходят для большинства целей, и я не хочу их менять.
Необходимо подумать о возможности коллизий хеша / GUID. Я полностью согласен со всеми доводами о том, что коллизии GUID столь же вероятны, как и самовозгорание, или что-то в этом роде, но не обращая внимания на исключительные случаи, потому что они исключительные, идут против всего, чему меня учили, и продолжают беспокоить меня, даже когда я знаю, Я должен быть более обеспокоен другими вещами.
Я не знаю, как безопасно обрезать идентификаторы на основе хеш-функции, поэтому даже если мои личные идентификаторы имеют размер 16 или 32 бита, я застрял с сгенерированными 128-битными идентификаторами, которые создают неудобства в URL-адресах.
Я заинтересован в отображении 1-1 диапазона идентификаторов, растягиваемых или сжимаемых, чтобы, например, 16-разрядные идентификаторы были сопоставлены с 16-разрядными идентификаторами, 32-разрядные идентификаторы сопоставлены с 32-разрядными идентификаторами и т. Д., И это остановит кто-то попытался угадать общее количество выделенных идентификаторов или скорость распределения идентификаторов за период.
Например, если мои идентификаторы пользователя являются 16-битными целыми числами (0..65535), то примером преобразования, которое несколько запутывает распределение идентификаторов, является функция f (x) = (x mult 1001) mod 65536. внутренняя последовательность идентификаторов 1, 2, 3 становится общедоступной последовательностью идентификаторов 1001, 2002, 3003. С дополнительным уровнем запутывания от преобразования базы, например, к базе 36, последовательность становится 'rt', '1jm', '2bf ». Когда система получает запрос к url? Userid = 2bf, она конвертируется из базы 36 в 3003 и применяет обратное преобразование g (x) = (x mult 1113) mod 65536, чтобы вернуться к внутреннему id = 3.
Подобной схемы достаточно, чтобы остановить случайное наблюдение случайными пользователями, но ее легко решить кто-то, кто достаточно заинтересован, чтобы попытаться разгадать ее. Кто-нибудь может предложить что-то более сильное, но легко реализуемое в PHP без специальных библиотек? Это приближается к схеме шифрования по принципу «сворачивай свой собственный», так что, может быть, существует подходящий алгоритм шифрования, который широко доступен и имеет свойство растягиваемости, упомянутое выше?
РЕДАКТИРОВАТЬ: Отступив немного назад, некоторые обсуждения в codinghorror о выборе из трех видов ключей - суррогат (основанный на guid), суррогат (основанный на целых числах), натуральный. В этих терминах я пытаюсь скрыть целочисленный суррогатный ключ от пользователей, но я ищу что-то сжатое, что делает URL-адреса не слишком длинными, что я не знаю, как сделать со стандартным 128-битным GUID , Иногда, как рекомендует принцесса-комментатор ниже, проблему можно обойти естественным ключом.
РЕДАКТИРОВАТЬ 2 / РЕЗЮМЕ:
- Учитывая ограничения вопроса, который я задал (растяжимость, обратимость, простота реализации), наиболее подходящим решением на данный момент представляется запутывание на основе XOR, предложенное Someone и Breton.
- С моей стороны было бы безответственно предполагать, что я могу достичь чего-то большего, чем запутывание / безопасность за счет безвестности. Знание того, что это целочисленная последовательность, - это, вероятно, шпаргалка, которой любой компетентный злоумышленник сможет воспользоваться.
- Я еще немного подумал над идеей дополнительного поля базы данных. Одним из преимуществ дополнительного поля является то, что оно делает его более простым для будущих программистов, которые пытаются ознакомиться с системой, просматривая базу данных. В противном случае им пришлось бы копаться в исходном коде (или документации, хм), чтобы выяснить, как запрос к заданному URL-адресу разрешается для данной записи в базе данных.
- Если я разрешу дополнительное поле базы данных, то некоторые другие предположения в вопросе станут неактуальными (например, преобразование не должно быть обратимым). Это становится другим вопросом, поэтому я оставлю это там.