Last active
August 29, 2015 13:59
-
-
Save timoh6/10959950 to your computer and use it in GitHub Desktop.
Suggestions for Laravel Encrypter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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