Related
I'm trying to build a simple password generating function using openssl_random_pseudo_bytes and want to know if it is cryptographically strong.
function randomPassword($length = 12) {
mt_srand( hexdec( bin2hex( openssl_random_pseudo_bytes(256) ) ) );
$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$&*-_=+.?';
$pass = '';
$alphaLength = strlen($alphabet) - 1;
for ($i = 0; $i < $length; $i++) {
$n = mt_rand(0, $alphaLength);
$pass .= $alphabet[$n];
}
return $pass;
}
I would assume that if there is a weakness that is is till in the mt_rand function regardless of seeding it with openssl_random_pseudo_bytes. However, I have been unable to find any discussion on the topic.
According to the documentation
openssl_random_pseudo_bytes is not guaranteed to produce cryptographically strong random data. However, in the improbable case that it was not able to use a cryptographically strong RNG, it will at least tell you. That's what openssl_random_pseudo_bytes's second parameter is for:
It also indicates if a cryptographically strong algorithm was used to produce the pseudo-random bytes, and does this via the optional crypto_strong parameter. It's rare for this to be FALSE, but some systems may be broken or old.
You can pass this parameter and then check its value:
$bytes = openssl_random_pseudo_bytes(256, $strong);
if (!$strong) {
// handle error as necessary.
}
However, opposed to openssl_random_pseudo_bytes, mt_rand is explicitly stated to not produce cryptographically secure values.
This function does not generate cryptographically secure values, and should not be used for cryptographic purposes.
I'm no expert, but I doubt that seeding a Mersenne Twister with secure random data would make the generated data any more secure (if at all, probably just the first byte):
Counter-suggestion
You did not state which version of PHP you're using. If you are using PHP 7, random_int might make a good alternative for you (it's also explicitly stated to be cryptographically secure):
for ($i = 0; $i < $length; $i++) {
$n = random_int(0, $alphaLength);
$pass .= $alphabet[$n];
}
Alternatively, this answer provides a secure, PHP-based implementation for a rand function that uses OpenSSL as an CSPRNG that you could use in place of random_int.
Here's the function I'm using to generate random salts:
function generateRandomString($nbLetters){
$randString="";
$charUniverse="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for($i=0; $i<$nbLetters; $i++){
$randInt=rand(0,61);
$randChar=$charUniverse[$randInt];
$randString=$randomString.$randChar;
}
return $randomString;
}
This is for a non commercial website. It's only used to generate the salt (to be stored in the db and used along with the user submitted pw for hashing).
Is this appropriate? Should I use a larger subset of characters, and if so is there an easy way to do that in PHP?
If you are hashing passwords, you should use a modern hashing algorithm that does not require you to generate your own salt. Using weak hashing algorithms presents a danger to both you and your users. My original answer was written eight years ago. Times have changed, and password hashing is a lot easier now.
You should always use built in functions to hash/check passwords. Using your own algorithms at any point introduces a huge amount of unnecessary risk.
For PHP, consider using password_hash(), with the PASSWORD_BCRYPT algorithm. There is no need to provide your own salt.
Below is my original answer, for posterity:
Warning: The following implementation does not produce an unpredictable salt, as per the documentation for uniqid.
From the php sha1 page:
$salt = uniqid(mt_rand(), true);
This looks simpler, and more effective (since each is unique) than what you have proposed.
If you're on Linux, /dev/urandom is probably your best source of randomness. It's supplied by the OS itself, so it's guaranteed to be much more reliable than any PHP built-in function.
$fp = fopen('/dev/urandom', 'r');
$randomString = fread($fp, 32);
fclose($fp);
This will give you 32 bytes of random blob. You'll probably want to pass this through something like base64_encode() to make it legible. No need to juggle characters yourself.
Edit 2014: In PHP 5.3 and above, openssl_random_pseudo_bytes() is the easiest way to get a bunch of random bytes. On *nix systems, it uses /dev/urandom behind the scenes. On Windows systems, it uses a different algorithm that is built into the OpenSSL library.
Related: https://security.stackexchange.com/questions/26206
Related: should i use urandom or openssl_random_pseudo_bytes?
password_hash() is availble in PHP 5.5 and newer. I am surprised to learn it is not mentioned here.
With password_hash() there is no need to generate a salt as the salt is automatically being generated using the bcrypt algorithm -- and therefore no need to make up a set of characters.
Instead, the user-submitted password is compared to the unique password hash stored in the database using password_verify(). Just store Username and Password hash in the user database table, you will then be able to compare it to a user-submitted password using password_verify().
How password hash()'ing works:
The password_hash() function outputs a unique password hash, when storing the string in a database -- it is recommended that the column allows up to 255 characters.
$password = "goat";
echo password_hash($password, PASSWORD_DEFAULT);
echo password_hash($password, PASSWORD_DEFAULT);
echo password_hash($password, PASSWORD_DEFAULT);
// Output example (store this in the database)
$2y$10$GBIQaf6gEeU9im8RTKhIgOZ5q5haDA.A5GzocSr5CR.sU8OUsCUwq <- This hash changes.
$2y$10$7.y.lLyEHKfpxTRnT4HmweDKWojTLo1Ra0hXXlAC4ra1pfneAbj0K
$2y$10$5m8sFNEpJLBfMt/3A0BI5uH4CKep2hiNI1/BnDIG0PpLXpQzIHG8y
To verify a hashed password, you use password_verify():
$password_enc = password_hash("goat", PASSWORD_DEFAULT);
dump(password_verify('goat', $password_enc)); // TRUE
dump(password_verify('fish', $password_enc)); // FALSE
If you prefer, salt can be added manually as an option, like so:
$password = 'MyPassword';
$salt = 'MySaltThatUsesALongAndImpossibleToRememberSentence+NumbersSuch#7913';
$hash = password_hash($password, PASSWORD_DEFAULT, ['salt'=>$salt]);
// Output: $2y$10$TXlTYWx0VGhhdFVzZXNBT.ApoIjIiwyhEvKC9Ok5qzVcSal7T8CTu <- This password hash not change.
Replace rand(0,61) with mt_rand(0, 61) and you should be fine (Since mt_rand is better at producing random numbers)...
But more important than strength of the salt is the way you hash it. If you have a great salt routine, but only do md5($pass.$salt), you're throwing away the salt. I personally recommend stretching the hash... For example:
function getSaltedHash($password, $salt) {
$hash = $password . $salt;
for ($i = 0; $i < 50; $i++) {
$hash = hash('sha512', $password . $hash . $salt);
}
return $hash;
}
For more information on hash stretching, check out this SO answer...
I would take advice from another answer and use mt_rand(0, 61), because the Mersenne Twister produces better entropy.
Additionally, your function is really two parts: generating random $nbLetters digits and encoding that in base62. This will make things much clearer to a maintenance programmer (maybe you!) who stumbles across it a few years down the road:
// In a class somewhere
private $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private function getBase62Char($num) {
return $chars[$num];
}
public function generateRandomString($nbLetters){
$randString="";
for($i=0; $i < $nbLetters; $i++){
$randChar = getBase62Char(mt_rand(0,61));
$randString .= $randChar;
}
return $randomString;
}
This is my method, It uses truly random numbers from atmospheric noise. It is all mixed in with pseudo-random values and strings. Shuffled and hashed. Here is my code: I call it overkill.
<?php
function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
function get_true_random_number($min = 1, $max = 100) {
$max = ((int) $max >= 1) ? (int) $max : 100;
$min = ((int) $min < $max) ? (int) $min : 1;
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => '',
CURLOPT_USERAGENT => 'PHP',
CURLOPT_AUTOREFERER => true,
CURLOPT_CONNECTTIMEOUT => 120,
CURLOPT_TIMEOUT => 120,
CURLOPT_MAXREDIRS => 10,
);
$ch = curl_init('http://www.random.org/integers/?num=1&min='
. $min . '&max=' . $max . '&col=1&base=10&format=plain&rnd=new');
curl_setopt_array($ch, $options);
$content = curl_exec($ch);
curl_close($ch);
if(is_numeric($content)) {
return trim($content);
} else {
return rand(-10,127);
}
}
function generateSalt() {
$string = generateRandomString(10);
$int = get_true_random_number(-2,123);
$shuffled_mixture = str_shuffle(Time().$int.$string);
return $salt = md5($shuffled_mixture);
}
echo generateSalt();
?>
The atmospheric noise is provided by random.org. I have also seen truly random generation from images of lava lamps that are interpreted via hue and location. (Hue is location)
Here is a much better way if you have windows and cant do /dev/random.
//Key generator
$salt = base64_encode(openssl_random_pseudo_bytes(128, $secure));
//The variable $secure is given by openssl_random_ps... and it will give a true or false if its tru then it means that the salt is secure for cryptologic.
while(!$secure){
$salt = base64_encode(openssl_random_pseudo_bytes(128, $secure));
}
I think that a very good salt for example is the user name (if you are talking about pw hashing and the user name doesn't change.)
You don't need to generate anything and don't need to store further data.
A fairly simple technique:
$a = array('a', 'b', ...., 'A', 'B', ..., '9');
shuffle($a);
$salt = substr(implode($a), 0, 2); // or whatever sized salt is wanted
Unlike uniqid() it generates a random result.
I use this:
$salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
If you want ultimate unique salt you should use a unique value entered and required by the user such as the email or the username, then hashing it using sha1 and then merge it - concatenate - with the salt value generated by your code.
Another, you have to extend $charUniverse by the mean of some special characters such as #,!#- etc.
I am working on Yii. I want to generate 20 digit random keys. I had written a function as -
public function GenerateKey()
{
//for generating random confirm key
$length = 20;
$chars = array_merge(range(0,9), range('a','z'), range('A','Z'));
shuffle($chars);
$password = implode(array_slice($chars, 0, $length));
return $password;
}
This function is generating 20 digit key correctly. But I want the key in a format like
"g12a-Gh45-gjk7-nbj8-lhk8". i.e. separated by hypen. So what changes do I need to do?
You can use chunk_split() to add the hyphens. substr() is used to remove the trailing hyphen it adds, leaving only those hyphens that actually separate groups.
return substr(chunk_split($password, 4, '-'), 0, 24);
However, note that shuffle() not only uses a relatively poor PRNG but also will not allow the same character to be used twice. Instead, use mt_rand() in a for loop, and then using chunk_split() is easy to avoid:
$password = '';
for ($i = 0; $i < $length; $i++) {
if ( $i != 0 && $i % 4 == 0 ) { // nonzero and divisible by 4
$password .= '-';
}
$password .= $chars[mt_rand(0, count($chars) - 1)];
}
return $password;
(Even mt_rand() is not a cryptographically secure PRNG. If you need to generate something that must be extremely hard to predict (e.g. an encryption key or password reset token), use openssl_random_pseudo_bytes() to generate bytes and then a separate function such as bin2hex() to encode them into printable characters. I am not familiar with Yii, so I cannot say whether or not it has a function for this.)
You can use this Yii internal function:
Yii::app()->getSecurityManager()->generateRandomString($length);
Quick Question
How does youtube encode theirs urls? take below
http://www.youtube.com/watch?v=MhWyAL2hKlk
what are they doing to get the value MhWyAL2hKlk
are they using some kind of encryption then decrypting at their end
I want to something similar with a website i am working on below looks horrible.
http://localhost:8888/example/account_player/?playlist=drum+and+bass+music
i would like to encode the urls to act like youtubes dont know how they do it tho.
Any advice
Well, technically speaking, YouTube generates video IDs by using an algorithm. Honestly, I have no idea. It could be a hashsum of the entire video file + a salt using the current UNIX time, or it could be a base64 encoding of something unique to the video. But I do know that it's most likely not random, because if it were, the risk of collision would be too high.
For the sake of example, though, we'll assume that YouTube does generate random ID's. Keep in mind that when using randomly generated values to store something, it is generally a good idea to implement collision checking to ensure that a new object doesn't overwrite the existing one. In practice, though, I would recommend using a hashing algorithm, since they are one-way and very effective at preventing collisions.
So, I'm not very familiar with PHP. I had to write it in JavaScript first. Then, I ported it to PHP, which turned out to be relatively simple:
function randch($charset){
return $charset[rand() % strlen($charset)];
}
function randstr($len, $charset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-"){
$out = [];
for($i = 0; $i < $len; $i++){
array_push($out, randch($charset));
}
return join("", $out);
}
What this does is generate a random string len characters long via the given charset.
Here's some sample output:
randstr(5) -> 1EWHd
randstr(30) -> atcUVgfhAmM5bXz-3jgyRoaVnnY2jD
randstr(30, "asdfASDF") -> aFSdSAfsfSdAsSSddFFSSsdasDDaDa
Though it's not a good idea to use such a short charset.
randstr(30, "asdf")
sdadfaafsdsdfsaffsddaaafdddfad
adaaaaaafdfaadsadsdafdsfdfsadd
dfaffafaaddfdddadasaaafsfssssf
randstr(30)
r5BbvJ45HEN6dWtNZc5ZvHGLCg4Qyq
50vKb1rh66WWf9RLZQY2QrMucoNicl
Mklh3zjuRqDOnVYeEY3B0V3Moia9Dn
Now let's say you have told the page to use this function to generate a random id for a video that was just uploaded, now you want to store this key in a table with a link to the relevant data to display the right page. If an id is requested via $_GET (e.g. /watch?v=02R0-1PWdEf), you can tell the page to check this key against the database containing the video ids, and if it finds a match, grab the data from that key, else give a 404.
You can also encode directly to a base 64 string if you don't want it to be random. This can be done with base64_encode() and base64_decode(). For example, say you have the data for the video in one string $str="filename=apples.avi;owner=coolpixlol124", for whatever reason. base64_encode($str) will give you ZmlsZW5hbWU9YXBwbGVzLmF2aTtvd25lcj1jb29scGl4bG9sMTI0.
To decode it later use base64_decode($new_str), which will give back the original string.
Though, as I said before, it's probably a better idea to use a hashing algorithm like SHA.
I hope this helped.
EDIT: I forgot to mention, YouTube's video ids as of now are 11 characters long, so if you want to use the same kind of thing, you would want to use randstr(11) to generate an 11 digit random string, like this sample id I got: 6AMx8N5r6cg
EDIT 2 (2015.12.17): Completely re-wrote answer. Original was crap, I don't know what I was thinking when I wrote it.
Your question is similar to this other SO question which contains some optimised generator functions along with a clear description of the problem you're trying to solve:
php - help improve the efficiency of this youtube style url generator
It will provide you with code, a better understanding of performance issues, and a better understanding of the problem domain all at once.
Dunno how exactly google generates their strings, but the idea is really simple. Create a table like:
+----------+------------------------------+
| code | url |
+----------+------------------------------+
| asdlkasd | playlist=drum+and+bass+music |
+----------+------------------------------+
Now, create your url like:
http://localhost:8888/example/account_player/asdlkasd
After that, just read compare your own made code with the database url and load your image, video or whatever you intend to.
PS: This is just a fast example. It can be done in many other ways also of course.
If you don't want to use decimal numbers, you can encode them into base36:
echo base_convert(123456789, 10, 36); // => "21i3v9"
And decode back:
echo base_convert("21i3v9", 36, 10); // => "123456789"
function alphaID($in, $to_num = false, $pad_up = false, $pass_key = null)
{
$out = '';
$index = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$base = strlen($index);
if ($pass_key !== null) {
for ($n = 0; $n < strlen($index); $n++) {
$i[] = substr($index, $n, 1);
}
$pass_hash = hash('sha256',$pass_key);
$pass_hash = (strlen($pass_hash) < strlen($index) ? hash('sha512', $pass_key) : $pass_hash);
for ($n = 0; $n < strlen($index); $n++) {
$p[] = substr($pass_hash, $n, 1);
}
array_multisort($p, SORT_DESC, $i);
$index = implode($i);
}
if ($to_num) {
// Digital number <<-- alphabet letter code
$len = strlen($in) - 1;
for ($t = $len; $t >= 0; $t--) {
$bcp = bcpow($base, $len - $t);
$out = $out + strpos($index, substr($in, $t, 1)) * $bcp;
}
if (is_numeric($pad_up)) {
$pad_up--;
if ($pad_up > 0) {
$out -= pow($base, $pad_up);
}
}
} else {
// Digital number -->> alphabet letter code
if (is_numeric($pad_up)) {
$pad_up--;
if ($pad_up > 0) {
$in += pow($base, $pad_up);
}
}
for ($t = ($in != 0 ? floor(log($in, $base)) : 0); $t >= 0; $t--) {
$bcp = bcpow($base, $t);
$a = floor($in / $bcp) % $base;
$out = $out . substr($index, $a, 1);
$in = $in - ($a * $bcp);
}
}
return $out;
}
?>
you can encypt or decrypt using this function.
<?php
$random_id=57256;
$encode=alphaID($random_id);
$decode=alphaID($encode,true); //where boolean true reverse the string back to original
echo "Encode : {$encode} <br> Decode : {$decode}";
?>
Just visit the below for more info :
http://kvz.io/blog/2009/06/10/create-short-ids-with-php-like-youtube-or-tinyurl/
Just use an auto-increment ID value (from a database). Although I personally like the long URLs.
Here's the function I'm using to generate random salts:
function generateRandomString($nbLetters){
$randString="";
$charUniverse="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for($i=0; $i<$nbLetters; $i++){
$randInt=rand(0,61);
$randChar=$charUniverse[$randInt];
$randString=$randomString.$randChar;
}
return $randomString;
}
This is for a non commercial website. It's only used to generate the salt (to be stored in the db and used along with the user submitted pw for hashing).
Is this appropriate? Should I use a larger subset of characters, and if so is there an easy way to do that in PHP?
If you are hashing passwords, you should use a modern hashing algorithm that does not require you to generate your own salt. Using weak hashing algorithms presents a danger to both you and your users. My original answer was written eight years ago. Times have changed, and password hashing is a lot easier now.
You should always use built in functions to hash/check passwords. Using your own algorithms at any point introduces a huge amount of unnecessary risk.
For PHP, consider using password_hash(), with the PASSWORD_BCRYPT algorithm. There is no need to provide your own salt.
Below is my original answer, for posterity:
Warning: The following implementation does not produce an unpredictable salt, as per the documentation for uniqid.
From the php sha1 page:
$salt = uniqid(mt_rand(), true);
This looks simpler, and more effective (since each is unique) than what you have proposed.
If you're on Linux, /dev/urandom is probably your best source of randomness. It's supplied by the OS itself, so it's guaranteed to be much more reliable than any PHP built-in function.
$fp = fopen('/dev/urandom', 'r');
$randomString = fread($fp, 32);
fclose($fp);
This will give you 32 bytes of random blob. You'll probably want to pass this through something like base64_encode() to make it legible. No need to juggle characters yourself.
Edit 2014: In PHP 5.3 and above, openssl_random_pseudo_bytes() is the easiest way to get a bunch of random bytes. On *nix systems, it uses /dev/urandom behind the scenes. On Windows systems, it uses a different algorithm that is built into the OpenSSL library.
Related: https://security.stackexchange.com/questions/26206
Related: should i use urandom or openssl_random_pseudo_bytes?
password_hash() is availble in PHP 5.5 and newer. I am surprised to learn it is not mentioned here.
With password_hash() there is no need to generate a salt as the salt is automatically being generated using the bcrypt algorithm -- and therefore no need to make up a set of characters.
Instead, the user-submitted password is compared to the unique password hash stored in the database using password_verify(). Just store Username and Password hash in the user database table, you will then be able to compare it to a user-submitted password using password_verify().
How password hash()'ing works:
The password_hash() function outputs a unique password hash, when storing the string in a database -- it is recommended that the column allows up to 255 characters.
$password = "goat";
echo password_hash($password, PASSWORD_DEFAULT);
echo password_hash($password, PASSWORD_DEFAULT);
echo password_hash($password, PASSWORD_DEFAULT);
// Output example (store this in the database)
$2y$10$GBIQaf6gEeU9im8RTKhIgOZ5q5haDA.A5GzocSr5CR.sU8OUsCUwq <- This hash changes.
$2y$10$7.y.lLyEHKfpxTRnT4HmweDKWojTLo1Ra0hXXlAC4ra1pfneAbj0K
$2y$10$5m8sFNEpJLBfMt/3A0BI5uH4CKep2hiNI1/BnDIG0PpLXpQzIHG8y
To verify a hashed password, you use password_verify():
$password_enc = password_hash("goat", PASSWORD_DEFAULT);
dump(password_verify('goat', $password_enc)); // TRUE
dump(password_verify('fish', $password_enc)); // FALSE
If you prefer, salt can be added manually as an option, like so:
$password = 'MyPassword';
$salt = 'MySaltThatUsesALongAndImpossibleToRememberSentence+NumbersSuch#7913';
$hash = password_hash($password, PASSWORD_DEFAULT, ['salt'=>$salt]);
// Output: $2y$10$TXlTYWx0VGhhdFVzZXNBT.ApoIjIiwyhEvKC9Ok5qzVcSal7T8CTu <- This password hash not change.
Replace rand(0,61) with mt_rand(0, 61) and you should be fine (Since mt_rand is better at producing random numbers)...
But more important than strength of the salt is the way you hash it. If you have a great salt routine, but only do md5($pass.$salt), you're throwing away the salt. I personally recommend stretching the hash... For example:
function getSaltedHash($password, $salt) {
$hash = $password . $salt;
for ($i = 0; $i < 50; $i++) {
$hash = hash('sha512', $password . $hash . $salt);
}
return $hash;
}
For more information on hash stretching, check out this SO answer...
I would take advice from another answer and use mt_rand(0, 61), because the Mersenne Twister produces better entropy.
Additionally, your function is really two parts: generating random $nbLetters digits and encoding that in base62. This will make things much clearer to a maintenance programmer (maybe you!) who stumbles across it a few years down the road:
// In a class somewhere
private $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private function getBase62Char($num) {
return $chars[$num];
}
public function generateRandomString($nbLetters){
$randString="";
for($i=0; $i < $nbLetters; $i++){
$randChar = getBase62Char(mt_rand(0,61));
$randString .= $randChar;
}
return $randomString;
}
This is my method, It uses truly random numbers from atmospheric noise. It is all mixed in with pseudo-random values and strings. Shuffled and hashed. Here is my code: I call it overkill.
<?php
function generateRandomString($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters[rand(0, strlen($characters) - 1)];
}
return $randomString;
}
function get_true_random_number($min = 1, $max = 100) {
$max = ((int) $max >= 1) ? (int) $max : 100;
$min = ((int) $min < $max) ? (int) $min : 1;
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => '',
CURLOPT_USERAGENT => 'PHP',
CURLOPT_AUTOREFERER => true,
CURLOPT_CONNECTTIMEOUT => 120,
CURLOPT_TIMEOUT => 120,
CURLOPT_MAXREDIRS => 10,
);
$ch = curl_init('http://www.random.org/integers/?num=1&min='
. $min . '&max=' . $max . '&col=1&base=10&format=plain&rnd=new');
curl_setopt_array($ch, $options);
$content = curl_exec($ch);
curl_close($ch);
if(is_numeric($content)) {
return trim($content);
} else {
return rand(-10,127);
}
}
function generateSalt() {
$string = generateRandomString(10);
$int = get_true_random_number(-2,123);
$shuffled_mixture = str_shuffle(Time().$int.$string);
return $salt = md5($shuffled_mixture);
}
echo generateSalt();
?>
The atmospheric noise is provided by random.org. I have also seen truly random generation from images of lava lamps that are interpreted via hue and location. (Hue is location)
Here is a much better way if you have windows and cant do /dev/random.
//Key generator
$salt = base64_encode(openssl_random_pseudo_bytes(128, $secure));
//The variable $secure is given by openssl_random_ps... and it will give a true or false if its tru then it means that the salt is secure for cryptologic.
while(!$secure){
$salt = base64_encode(openssl_random_pseudo_bytes(128, $secure));
}
I think that a very good salt for example is the user name (if you are talking about pw hashing and the user name doesn't change.)
You don't need to generate anything and don't need to store further data.
A fairly simple technique:
$a = array('a', 'b', ...., 'A', 'B', ..., '9');
shuffle($a);
$salt = substr(implode($a), 0, 2); // or whatever sized salt is wanted
Unlike uniqid() it generates a random result.
I use this:
$salt = base64_encode(mcrypt_create_iv(PBKDF2_SALT_BYTES, MCRYPT_DEV_URANDOM));
If you want ultimate unique salt you should use a unique value entered and required by the user such as the email or the username, then hashing it using sha1 and then merge it - concatenate - with the salt value generated by your code.
Another, you have to extend $charUniverse by the mean of some special characters such as #,!#- etc.