2

I need to create truly unique token when inserting records in CakePHP. The table can contain millions of rows so I cant just base on some randomly generated strings. I do not want to use a microtime() as well, because there is, though very small probability that two records can be submitted exactly at the same moment. Of course the best solution would be to use String::uuid(), but as from cakephp documentation

The uuid method is used to generate unique identifiers as per RFC 4122. The uuid is a 128bit string in the format of 485fc381-e790-47a3-9794-1337c0a8fe68.

So, as far as I understood it does not use cake's security salt for its generation. So, I decided to hash it by security component's hash function (or Auth Password function), because I need it to be unique and very, really very secure at the same time. But then I found the question, saying that it is not a good idea, but for php uniqid and md5. Why is MD5'ing a UUID not a good idea?

And, also I think the string hashed by security component is much harder to guess - because, for example String::uuid() in for loop has an output like this

for ($i = 0; $i < 30; $i++) {
    echo String::uuid()."<br>";
}       
die;

// outputs
51f3dcda-c4fc-4141-aaaf-1378654d2d93
51f3dcda-d9b0-4c20-8d03-1378654d2d93
51f3dcda-e7c0-4ddf-b808-1378654d2d93
51f3dcda-f508-4482-852d-1378654d2d93
51f3dcda-01ec-4f24-83b1-1378654d2d93
51f3dcda-1060-49d2-adc0-1378654d2d93
51f3dcda-1da8-4cfe-abe4-1378654d2d93
51f3dcda-2af0-42f7-81a0-1378654d2d93
51f3dcda-3838-4879-b2c9-1378654d2d93
51f3dcda-451c-465a-a644-1378654d2d93
51f3dcda-5264-44b0-a883-1378654d2d93

So, after all the some part of the string is similar, but in case of using hash function the results are pretty different

echo Security::hash('stackoverflow1');
echo "<br>";
echo Security::hash('stackoverflow2');

die;
// outputs
e9a3fcb74b9a03c7a7ab8731053ab9fe5d2fe6bd
b1f95bdbef28db16f8d4f912391c22310ba3c2c2

So, the question is, can I after all hash the uuid() in Cake? Or what is the best secure way to get truly unique and hashed (better according to my security salt) secure token.

UPDATE

Saying secure token, I mean how difficult it is for guessing. UUID is really unique, but from the example above, some records have some similarity. But hashed results do not.

Thanks !!

Community
  • 1
  • 1
dav
  • 8,931
  • 15
  • 76
  • 140

4 Answers4

3

I don't think you need to worry about the UUIDs overlapping.

To put these numbers into perspective, the annual risk of someone being hit by a meteorite is estimated to be one chance in 17 billion,[38] which means the probability is about 0.00000000006 (6 × 10−11), equivalent to the odds of creating a few tens of trillions of UUIDs in a year and having one duplicate. In other words, only after generating 1 billion UUIDs every second for the next 100 years, the probability of creating just one duplicate would be about 50%. Or, to put it another way, the probability of one duplicate would be about 50% if every person on earth owns 600 million UUIDs.

http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates

Continue to use String::uuid() and rest easy :)

Tremendus Apps
  • 1,497
  • 12
  • 20
1

A UUID is unique

I need to create truly unique token when inserting records in cakphp

That is exactly what a UUID is. It is normally used in distributed systems to prevent collisions (multiple sources inserting data, possibly out of sync, into a datasource).

A UUID is not a security measure

I need it to be unique and very, really very secure at the same time

Not sure in what way hashing a uuid is supposed to enhance security - it won't. Relying on security by obscurity is more or less guaranteed to fail.

If your need is random tokens of some form - use a hash function (Hashing a uuid is simply hashing a random seed), if you need guaranteed-unique identifiers use UUIDs. They aren't the same thing and a UUID is a very poor mechanism of generating random, non-sequential "un-guessable" (or whatever the purpose is) strings.

Community
  • 1
  • 1
AD7six
  • 63,116
  • 12
  • 91
  • 123
  • Thanks for the answer, as you said `UUID is a very poor mechanism of generating random, nosequencial "unguessable" stings`, so I want the result to be random and unique, so, for uniqueness I want to use `uuid` and for "unguessability" security hash, not not sure if it is ok for cake after the question mentioned in the quetsion. About saying secure I mostly had in mind the level of "unguessability" – dav Jul 27 '13 at 15:09
1

Generating a random string suitable for cryptographic purposes was answered well here:

Secure random number generation in PHP

The code sample fills the string $pr_bits with random binary data, so the characters are unprintable. To use this in a URL, you could convert the binary data to printable characters a couple ways. None of them enhance the security but make them ready for URLs.

  1. convert bytes to hex: bin2hex($pr_bits)
  2. convert bytes to base64: base64_encode($pr_bits)
  3. hash the bytes (because the output is conveniently in hex, not for added security): string hash ('md5' , $pr_bits)

I include the last one because you will see people use hash functions for other reasons, like to guarantee the output is 16bytes/128bits for md5. In PHP people use it to convert a value into HEX.

Community
  • 1
  • 1
Jonathan
  • 5,736
  • 2
  • 24
  • 22
1

I have come up with the following solution

to use a string as a result of concatenating current time in microseconds and random string's hash

$timeStr = str_replace("0.", "", microtime());
$timeStr = str_replace(" ", "", $timeStr);
echo Security::hash('random string').'_'.$timeStr;

// 5ffd3b852ccdd448809abb172e19bbb9c01a43a4_796473001379403705

So, the first part(hash) of the string will contribute for the unguessability of the token, and the second part will guarantee its uniquenes.

Hope, this will help someone.

dav
  • 8,931
  • 15
  • 76
  • 140