Skip to content

Instantly share code, notes, and snippets.

@timoh6
Last active August 29, 2015 13:59
Show Gist options
  • Save timoh6/10959950 to your computer and use it in GitHub Desktop.
Save timoh6/10959950 to your computer and use it in GitHub Desktop.
Suggestions for Laravel Encrypter
<?php
// Use a (maybe?) new "Security" namespace for RandomBytes
namespace Illuminate\Security;
class RandomBytes
{
/**
* Generate a random string of bytes suitable for cryptographic use.
*
* @param int $count
* @return string
* @throws \RuntimeException
*/
public function getRandomBytes($count)
{
$count = (int) $count;
if ($count < 1)
{
throw new \RuntimeException('$count must be greater than 0');
}
$bytes = '';
$hasBytes = false;
// Try mcrypt_create_iv at first
if (function_exists('mcrypt_create_iv'))
{
$tmp = mcrypt_create_iv($count, MCRYPT_DEV_URANDOM);
if ($tmp !== false)
{
$bytes = $tmp;
$hasBytes = true;
}
}
// Fall back trying to read straight from urandom
if ($hasBytes === false && file_exists('/dev/urandom') && is_readable('/dev/urandom') && (false !== ($fh = fopen('/dev/urandom', 'rb'))))
{
if (function_exists('stream_set_read_buffer'))
{
stream_set_read_buffer($fh, 0);
}
$tmp = fread($fh, $count);
fclose($fh);
if ($tmp !== false)
{
$bytes = $tmp;
}
}
if (strlen($bytes) === $count)
{
return $bytes;
}
else
{
throw new \RuntimeException('Could not generate random bytes');
}
}
}
// Inject a new RandomBytes instance to Encrypter and call
// getRandomBytes() when random bytes are needed
$iv = $this->RandomBytes->getRandomBytes($this->getIvSize());
// Randomize the MAC to make the timing side-channel unusable
protected function validMac(array $payload)
{
// Fetch 16 random bytes to generate a random $key to
// randomize the to-be-compared byte string
$key = $this->RandomBytes->getRandomBytes(16);
// It would be good to check the length of $payload['mac'],
// but as long as we make sure $this->hash() is called with
// valid parameters it will be OK
// EDIT: maybe it is actually good to check the user supplied
// MAC length (to mitigate maliciously drafted overlong inputs
// being passed to the underlying SHA-256 function). But I'll leave
// this under your consideration
$userSuppliedMac = $payload['mac'];
$userSuppliedMac = hash_hmac('sha256', $userSuppliedMac, $key, true);
$calculatedMac = $this->hash($payload['iv'], $payload['value']);
$calculatedMac = hash_hmac('sha256', $calculatedMac, $key, true);
return ($userSuppliedMac === $calculatedMac);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment