Edit: I have since found and published an efficient and elegant solution that transforms IDs like
3141592
to strings such asvJST
and backwards. It's available for PHP here:https://github.com/delight-im/PHP-IDs
Providing some background, it uses Knuth's multiplicative hashing followed by a base conversion to generate unique, reversible, non-sequential IDs.
Problem:
I have dynamic pages in PHP where the content is shown according to the given id. The id is always submitted via a GET parameter: page.php?id=X This causes a problem: Site visitors can enumerate the ids and simply walk through all the different content pages. This shouldn't be possible, of course.
How could this be solved?
My approach is to encode all ids in links and forms which are used as a GET parameter later. At the beginning of every page, the given id is decoded into the "real" id which is used in the database. Is this a good approach? Would you choose another way?
Possible solution of my approach:
I would convert the integer id to a base 38 integer and replace the digits by characters of a given list. I would use these characters for the encoded string id:
a-z 0-9 - _
Would you use other characters as well? For these characters my script would be this:
function id2secure($old_number) {
$alphabet_en = array(0=>'1', 1=>'3', 2=>'5', 3=>'7', 4=>'9', 5=>'0', 6=>'2', 7=>'4', 8=>'6', 9=>'8', 10=>'a', 11=>'c', 12=>'e', 13=>'g', 14=>'i', 15=>'k', 16=>'m', 17=>'o', 18=>'q', 19=>'s', 20=>'u', 21=>'w', 22=>'y', 23=>'b', 24=>'d', 25=>'f', 26=>'h', 27=>'j', 28=>'l', 29=>'n', 30=>'p', 31=>'r', 32=>'t', 33=>'v', 34=>'x', 35=>'z', 36=>'-', 37=>'_');
$new_number = '';
while ($old_number > 0) {
$rest = $old_number%38;
if (!isset($alphabet_en[$rest])) { return FALSE; }
$new_number .= $alphabet_en[$rest];
$old_number = floor($old_number/38);
}
$new_number = strrev($new_number);
return $new_number;
}
Additional question:
What would be the reverse function for my function?
I hope you can help me. Thank you!