Você precisará de algo que seja correto por construção, ou seja, uma função de permutação:esta é uma função que faz um mapeamento reversível um para um de um inteiro (seu contador sequencial) para outro. Alguns exemplos (qualquer combinação deles também deve trabalhar):
- invertendo alguns dos bits (f.i. usando um XOR, ^ em PHP)
- trocando os lugares dos bits (($i &0xc)>> 2 | ($i &0x3) <<2), ou apenas invertendo a ordem de todos os bits
- adicionar um módulo de valor constante ao seu alcance máximo (deve ser um fator de dois, se você estiver combinando isso com os acima)
Exemplo:esta função irá converter 0, 1, 2, 3, 5, .. em 13, 4, 12, 7, 15, .. para números até 15:
$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;
EDITAR
Uma maneira mais fácil seria usar um gerador congruencial linear (LCG, que geralmente é usado para gerar números aleatórios), que é definido por uma fórmula da forma:
X_n+1 = (a * X_n + c) mod m
Para bons valores de a, c e m, a sequência de X_0, X_1 .. X_m-1 conterá todos os números entre 0 e m-1 exatamente uma vez. Agora você pode começar com um índice crescente linearmente e usar o próximo valor na seqüência LCG como sua chave "secreta".
EDIT2
Implementação:Você pode projetar seus próprios parâmetros LCG , mas se você errar, não cobrirá todo o intervalo (e, portanto, terá duplicatas), então usarei um conjunto de parâmetros publicado e testado aqui de este artigo :
a = 16807, c = 0, m = 2147483647
Isto dá-lhe um intervalo de 2**31. Com pack() você pode obter o inteiro resultante como uma string, base64_encode() torna uma string legível (de até 6 caracteres significativos, 6 bits por byte) então esta pode ser sua função:
substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)