Generate unique activation keys

Hello everyone,

What is the best way to generate unique activation keys that look like xxxx-xxxx-xxxx-xxxx where x is a hexdecimal number so for example 53e1-fbaf-4230-6c7a. I thought I could use mile md5 but it produces a longer value and then I have to trim it down which feels like it increases the risk of simular values.

-Martin

Marius Karthaus has created a class that returns

A UUID, made up of 32 hex digits and 4 hyphens

http://php.net/manual/en/function.uniqid.php#88400


<?php

function random($length, $chars = '')
{
	if (!$chars) {
		$chars = implode(range('a','f'));
		$chars .= implode(range('0','9'));
	}
	$shuffled = str_shuffle($chars);
	return substr($shuffled, 0, $length);
}
function serialkey()
{
	return random(4).'-'.random(4).'-'.random(4).'-'.random(4);
}

echo serialkey();

?>

Thanks BooBooGotU but there’s a boo-boo in your code.

The request is for hexadecimal values, not alphabetic ones, and there are serious entropy problems with your solution.

You can contact the people in GRC’s Cryptography forum if you would like to learn more about this.

I believe 0-9 and a-f is hex (oh I see edited). Can you explain more about the entropy please?

Boo-boo fixed. Thanks.

lundberg: are you keeping these keys in some place like a database? If so, add unique key on column and this will prevent any repeating values being generated. If that is your main concern, as I read in your post, then this solution provides you with 100% uniqueness.

How many of these keys are going to generate? 1000? 10 thousands? million? or maybe billion? If it’s no too many, then I don’t think there is a need to search for some really advanced solution, str_shuffle works fine.

It is truly difficult for computers generate a true randomness. The less of a pattern that can be discerned, more entropy it contains.

Computer cryptography experts have become well versed with increasing the entropy of their encryptions. Steve Gibson for example has, in conjunction with feedback from the cryptography community, created a way to generate ultra-high security passwords that uses

Rijndael (AES) block encryption of never-repeating counter values in CBC mode

Despite the quote, the page make for a very good read.

Then for more fun there are Perfect Paper Passwords

Is that not a little overboard for something that does not need to be cryptography secure?

I personally would forget about using some special format and just do:


code = hash( username + date( ISO8601 ) )

Perhaps a little, but these are supposed to be for unique activation keys, so introducing weaknesses in the keys is best to be avoided.

If we’re going the easy and mostly effective way, we could just use a couple of uniqid calls.

Here is the script from PHP 5 in Practice for generating a unique 40-character identifer


<?php
// A function to return a unique identifier for the user's browser
function create_unique() {
    // Read the user agent, IP address, current time, and a random number:

    $data = $_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR'] .
            time() . rand();

    // Return this value hashed via sha1
    return sha1($data);
}

// Echo out the hashed data - This will be different every time.
$newhash = create_unique();
echo "<pre>{$newhash}</pre>";
?>

pmw57, very good points indeed, but maybe then add one more layer and use hash_hmac() instead or plain hash?


<?php
// A function to return a unique identifier for the user's browser
function create_unique() {
    // Read the user agent, IP address, current time, and a random number:

    $data = $_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR'] .
            time() . rand();
    $secret_key = 'really secret sequence for this web-applications function only';//change t
    // Return this value HMAC with sha256
    return hash_hmac('sha256',$data,$secret_key);
}

// Echo out the hashed data - This will be different every time.
$newhash = create_unique();
echo "<pre>{$newhash}</pre>";
?>

Yep, if your hosting provider gives you access to it then HMAC is a more secure way to encrypt SHA1.

However, completely unnecessary to use HMAC…

… and that is because… ?

The value only needs to be unique, not secure.

In that case, why not drop hashing at all and use a counter that increments as an activation key. 1,2,3 and so on. :slight_smile: