Generate OAuth Consumer Key and Shared Secrets using PHP

Multithreaded JavaScript has been published with O'Reilly!

While looking into creating an OAuth 1.0a provider using PHP, I came across this article by Rasmus Lerdorf on using the PECL OAuth extension. He had some code in place for generating a consumer key and private key pair, and it would chop up a sha1 hash and use those, which works fine and provides plenty of randomness.

I've personally never been a big fan of passing a bunch of hexadecimal hashes around, as it involves a lot of wasted entropy. Since hashes like this can only convey 16 different characters, they aren't that efficient. Something like Base64 is much nicer, as it has 64 possible characters, and in theory the same data could be described in one fourth the number of characters. It's really just a personal choice though.

Anyway, I took Rasmus's code, and modified it a bit. Instead of generating a SHA1 (40 hex chars) and hacking that up, I generate a SHA512 (64 hex chars), and base62 encode that (which is 0-9, a-z, A-Z, leaving out the / and + and trailing = characters of base64). This way, I still get extra entropy, and don't have the hard-to-encode characters of base64.

The code looks like this, and one pair can be generated in about 0.0006 seconds.

<?php
function gen_oauth_creds() {
  // Get a whole bunch of random characters from the OS
  $fp = fopen('/dev/urandom','rb');
  $entropy = fread($fp, 32);
  fclose($fp);

  // Takes our binary entropy, and concatenates a string which represents the current time to the microsecond
  $entropy .= uniqid(mt_rand(), true);

  // Hash the binary entropy
  $hash = hash('sha512', $entropy);

  // Base62 Encode the hash, resulting in an 86 or 85 character string
  $hash = gmp_strval(gmp_init($hash, 16), 62);

  // Chop and send the first 80 characters back to the client
  return array(
    'consumer_key' => substr($hash, 0, 32),
    'shared_secret' =>; substr($hash, 32, 48)
  );
}

Here are some example pairs of Consumer Keys and Shared Secrets generated using this code:

lInXLgx6HbF9FFq1ZQN8iSEnhzO3JVuf : 6kvwVhDGUQGXFawmulAhvORRV8HpZy5OMqMVH7xqwkLcvTbo
uFKE99LWQ8PDdBFQiO6fUhRRLoagFcDT : RGa8MqS4NZtAbWM8Voloi9kSVPg5AoKc5kySZxoYtpkOFgHU
NZqgHW5oOkxHxc5OgVXkJGQ0Kus3rOjz : QQsfDh5Q7S1BB8UHiB0Ni3okKn8lEEbeDx1k4k2OjT2jWuzr

Let me know if you see any security issues with the above code, I admit that I don't fully understand the gmp_ functions.

Thomas Hunter II Avatar

Thomas has contributed to dozens of enterprise Node.js services and has worked for a company dedicated to securing Node.js. He has spoken at several conferences on Node.js and JavaScript and is an O'Reilly published author.