Reputation: 19999
I am currently working on a project which requires closed loop email verification. As part of the process I need to generate a random hash string which can be appended to a link sent to the user. When they click the link they will be directed to my site at which time the app will confirm the hash and complete the registration process. For all my hashing I have been using:
hash('sha256', $string);
But for this process, I need to seed $string
with a random value. I have Zend Framework available and was looking to do something like this:
$crypt = new Zend_Filter_Encrypt_Mcrypt(array());
$hash = hash('sha256', $crypt->getVector());
My question is, is this a viable algorithm for generating random hash codes?
Here is the Zend_Filter_Encrypt_Mcrypt::setVector()
method (generates the value returned via getVector()
:
public function setVector($vector = null)
{
$cipher = $this->_openCipher();
$size = mcrypt_enc_get_iv_size($cipher);
if (empty($vector)) {
$this->_srand();
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) {
$method = MCRYPT_RAND;
} else {
if (file_exists('/dev/urandom') || (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')) {
$method = MCRYPT_DEV_URANDOM;
} elseif (file_exists('/dev/random')) {
$method = MCRYPT_DEV_RANDOM;
} else {
$method = MCRYPT_RAND;
}
}
$vector = mcrypt_create_iv($size, $method);
} else if (strlen($vector) != $size) {
require_once 'Zend/Filter/Exception.php';
throw new Zend_Filter_Exception('The given vector has a wrong size for the set algorithm');
}
$this->_encryption['vector'] = $vector;
$this->_closeCipher($cipher);
return $this;
}
Upvotes: 2
Views: 524
Reputation: 173642
I'm not very familiar with ZF, but something that has the word Encrypt
in it just sounds like the wrong approach.
The ->getVector()
sounds similar to what the Initialization Vector does in symmetric encryption; the problem is that such a vector doesn't need to be cryptographically safe, just random. For instance, it may well be just implemented as uniqid(mt_rand())
or something.
->getVector()
uses mcrypt
to first initialize the encryption cipher to know how big the IV should be; this is typically 8 bytes, but it largely depends on the block size of the used cipher. The thing is, you're not encrypting anything; you just want a random sequence.
The better way to get a random sequence is by using openssl_random_pseudo_bytes()
with a size of 8 bytes.
In its absence, you could also read from an entropy file such as /dev/random
or /dev/urandom
. Afterwards you can run it through binh2hex()
to generate a hexadecimal string.
Something like this is pretty rudimentary but should work on Linux'y systems:
$rnd = bin2hex(file_get_contents('/dev/urandom', false, null, 0, 8));
As a fallback for Windows, you can still use something like:
$rnd = hash('sha256', uniqid(mt_rand(), true));
Upvotes: 3
Reputation: 11132
You may want to look into ircmaxell's CryptLib which has a fairly comprehensive suite of random generation features. If you use the medium strength random string generator, like so:
$generator = ( new CryptLib\Random\Factory() )->getMediumStrengthGenerator();
$string = $generator->generateString(LENGTH);
The library will use multiple cryptographically secure sources and run them through a mixer to generate a string. It's worth checking into if you just want a simple solution and don't want to recompile PHP with openssl.
See the readme on secure string generation.
Upvotes: 0