PHP Generate an unique hash from an IPADDRESS

I have a board and i want to disable registrations instead i want the users to be able to post freely with an unique ID based on their IPAddress

for example:

if “Joe” IP is 200.100.15.117, “Joe” nickname will become the hash function of 200.100.15.117

if “Joe” IP changes he will get another ID, that doesn’t matter, i only want one unique ID per IPAddress

There are also two important things :

  • unique ID must be 8 characters long
  • hash should be secure, i don’t want hackers be abble to crack my users IPaddresses

I thought in using an MD5 function and then trim it to 8 chars, but how unique is that ? is there a better way ?

Answer

EDIT According to OP comment on this answer.

Code below uses BC Math library to translate a MD5 hash into a Base-90 string. This converts a 32 char string into a 20 char one. This is far from desired 8 chars but it is the minimum string length using ASCII range (it is possible to increase the base to Base-94 by using chars ' " [space] but this does not affect to the string length and instead may cause problems while handling data).

$ip      = '200.100.15.117';
$hash    = md5($ip);
$chars16 = array(
    '0' => 0,  '1' => 1,  '2' => 2,  '3' => 3, '4' => 4,  '5' => 5,
    '6' => 6,  '7' => 7,  '8' => 8,  '9' => 9, 'a' => 10, 'b' => 11,
    'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15
);
$base10 = '0';
for ($i = strlen($hash) - 1; $i > 0; $i--) {
    $base10 = bcadd($base10, bcmul($chars16[$hash[$i]], bcpow(16, $i)));
}
$chars   = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,;.:-_+*?!$%&@#~^=/<>[](){}`';
$base    = (string)strlen($chars);
$baseX   = '';
while (bccomp($base10, $base) === 1 || bccomp($base10, $base) === 0) {
    $baseX  = substr($chars, bcmod($base10, $base), 1) . $baseX;
    $base10 = preg_replace('/.d*$/', '', bcdiv($base10, $base));
}
$baseX = substr($chars, $base10, 1) . $baseX;
echo $baseX; // Shows: 1BS[JdZf/7J$J{ud&r5i

Leave a Reply

Your email address will not be published. Required fields are marked *