Skip to content

Instantly share code, notes, and snippets.

@timkuijsten
Created August 10, 2011 19:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save timkuijsten/1137905 to your computer and use it in GitHub Desktop.
Save timkuijsten/1137905 to your computer and use it in GitHub Desktop.
random_key base 62
<?php
/*
* Copyright 2011, Tim Kuijsten
* Released under the MIT license.
* http://creativecommons.org/licenses/MIT/
*/
/**
* Generate a random string of base 62 characters [a-zA-Z0-9].
*
* @param int $str_length minimum of 2
* @return string base 62 string of length $str_length
*/
function random_key($str_length = 24)
{
// base 62 map
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// get enough random bits for base 64 encoding (and prevent '=' padding)
// note: +1 is faster than ceil()
$bytes = openssl_random_pseudo_bytes(3*$str_length/4+1);
// convert base 64 to base 62 by mapping + and / to something from the base 62 map
// use the first 2 random bytes for the new characters
$repl = unpack('C2', $bytes);
$first = $chars[$repl[1]%62];
$second = $chars[$repl[2]%62];
return strtr(substr(base64_encode($bytes), 0, $str_length), '+/', "$first$second");
}
@Synchro
Copy link

Synchro commented Aug 10, 2011

I can see what that's doing, but it's not base-62 as the two replacement chars you generate are each in two different base-26s and all the others are in base-64. I can't see it being that useful for URL shortening as it's not based on the URL, so you'd end up storing different hashes for the same URL. I'd have thought something like this would be more useful:

function random_hash($url, $key_length = 22) {
  return substr(gmp_strval(gmp_init(md5('my salt'.strlen($url).$url), 16), 62), 0, $key_length);
}```

This way any given URL will always map to the same thing, but it's a true hash (not just a random value) salted with fixed and variable data, so is pretty secure.

If you do want a purely random value, you need a bit more entropy in there - those two calls to mt_rand are going to get you at most 62 bits, which you're diluting into your 128-bit hash; may as well fill it up. Alternatively look at crypt() which does much of this anyway.

@timkuijsten
Copy link
Author

tnx for your insights!

@timkuijsten
Copy link
Author

You were completely right about the entropy and replacement shortcomings. Furthermore it definitely isn't an url hashing function. I use it to create unique url's, sorry if I mislead you.

I updated the code to use more entropy and from a better source. The new function is about 8% to 9% slower but scales really well to large truly random base 62 keys (a lot more than the original 11 character keys that were padded to at most 22 characters ;-).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment