Я использую последовательные идентификаторы в качестве первичных ключей, и есть случаи, когда я не хочу, чтобы эти идентификаторы были видимыми для пользователей, например, я мог бы избежать URL-адресов вроде invoice_id = 1234, которые позволят пользователям угадать, сколько выставляет счета в системе в целом.
Я мог бы добавить поле базы данных с GUID или что-то, вызванное из хеш-функций, случайных строк и/или числовых базовых преобразований, но в схемах такого рода есть три проблемы, которые я нахожу раздражающими:
-
Необходимо выделить дополнительное поле базы данных. Я знаю, что я мог бы использовать GUID в качестве моего основного ключа, но мой auto-increment integer PK является правильным для большинства целей, и я не хочу его изменять.
-
Необходимо подумать о возможности коллизий hash/GUID. Я полностью согласен со всеми аргументами о столкновениях с GUID как вероятное самопроизвольное сжигание или что-то в этом роде, но, не обращая внимания на исключительные случаи, потому что они исключительны, противоречит всему, чему меня учили, и это продолжает беспокоить меня, даже когда я знаю Мне нужно больше беспокоиться о других вещах.
-
Я не знаю, как безопасно обрезать хэш-идентификаторы, поэтому даже если мои личные идентификаторы 16 или 32 бита, я застрял с 128-битными сгенерированными идентификаторами, которые являются неприятностью в URL-адресах.
Мне интересны 1-1 сопоставления диапазона id, растяжимые или сжимаемые, так что, например, 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 о выборе из трех видов ключей - суррогатных (ориентированных), суррогатное (целочисленное), естественное. В этих терминах я пытаюсь скрыть целостный суррогатный ключ от пользователей, но я ищу что-то сжатое, что делает не слишком длинными URL-адреса, которые я не знаю, как сделать со стандартным 128-битным GUID, Иногда, как предлагает нижеприведенная принцесса, проблема может быть устранена естественным ключом.
ИЗМЕНИТЬ 2/РЕЗЮМЕ:
- Учитывая ограничения на вопрос, который я задал (растяжимость, обратимость, легкость реализации), наиболее подходящим решением до сих пор является обфускация на основе XOR, предложенная кем-то и Бретоном.
- Было бы безответственно, если бы я предположил, что я могу добиться чего-то большего, чем запутывание/безопасность от неясности. Знание того, что это целая последовательность, вероятно, является кроваткой, которую мог бы использовать любой компетентный злоумышленник.
- Я еще немного подумал над идеей дополнительного поля базы данных. Одним из преимуществ дополнительного поля является то, что он делает его более простым для будущих программистов, которые пытаются ознакомиться с системой, просматривая базу данных. В противном случае им придется прорыть исходный код (или документацию, г-н), чтобы выяснить, как запрос на заданный URL-адрес разрешен для данной записи в базе данных.
- Если я разрешаю дополнительное поле базы данных, то некоторые из других предположений в вопросе становятся несущественными (например, преобразование не должно быть обратимым). Это становится другим вопросом, поэтому я оставлю его там. Спасибо всем за то, что поделились своими знаниями.