Вам понадобится что-то правильное по построению, то есть функция перестановки: это функция, которая выполняет обратимое взаимно однозначное отображение одного целого числа (вашего последовательного счетчика) в другое.
Некоторые примеры (любая комбинация из них также должна работать):
- инвертирование некоторых битов (например, с использованием XOR, ^ в PHP)
- поменять местами биты (($ i & 0xc) >> 2 | ($ i & 0x3) << 2) или просто поменять местами все биты </li>
- добавление постоянного значения по модулю вашего максимального диапазона (должно быть в два раза, если вы комбинируете это с вышеупомянутыми)
Пример: эта функция преобразует 0, 1, 2, 3, 5, .. в 13, 4, 12, 7, 15, .. для чисел до 15:
$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;
EDIT
Более простой способ - использовать линейный конгруэнтный генератор (LCG, который обычно используется для генерации случайных чисел), который определяется формулой вида:
X_n+1 = (a * X_n + c) mod m
Для хороших значений для a, c и m последовательность X_0, X_1 .. X_m-1 будет содержать все числа от 0 до m-1 ровно один раз. Теперь вы можете начать с линейно увеличивающегося индекса и использовать значение next в последовательности LCG в качестве «секретного» ключа.
EDIT2
Реализация:
Вы можете создать свои собственные параметры LCG , но если вы ошибетесь, он не будет охватывать весь диапазон (и, следовательно, иметь дубликаты), поэтому я буду использовать здесь опубликованный и опробованный набор параметров из этот документ :
a = 16807, c = 0, m = 2147483647
Это дает вам диапазон 2 ** 31. С pack () вы можете получить результирующее целое число в виде строки, base64_encode () делает его читаемой строкой (до 6 значащих символов, 6 бит на байт), так что это может быть вашей функцией:
substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)