Jump to content

PHP password generator (Which is considered secure)

Joveice

I have 2 scripts, and I'm wondering which is considered secure (if any). Feedback on how I can improve the best one is highly appreciated.

 

public function newpassword($id)
    {
        if ($id == null) {
            $id = 32;
        }
        $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890#-_+@#%&';
        $pass = array(); //remember to declare $pass as an array
        $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
        for ($i = 0; $i < $id; $i++) {
            $n = rand(0, $alphaLength);
            $pass[] = $alphabet[$n];
        }
        return implode($pass); //turn the array into a string
    }
public function newpassword2($id)
    {
        if ($id == null) {
            $id = 32;
        }
        $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890#-_+@#%&';
        $str = '';
        $max = mb_strlen($alphabet, '8bit') - 1;
        for ($i = 0; $i < $id; ++$i) {
            $str .= $alphabet[random_int(0, $max)];
        }
        return $str;
    }

So any security experts wanna take a look? or if you know more about cryptographically secure pseudorandom numbers than I do.

Back-end developer, electronics "hacker"

Link to comment
Share on other sites

Link to post
Share on other sites

Both are equally bad.

You should use mt_rand or mt_srand

Why limit the characters to only those in the array? There's other characters on all keyboards that can be easily typed:

 

 

charmap.png.f6322056f168852de3bc5a9329e2c42e.png

 

From "!" (0x21) to "~" (0x7E) all characters can be manually entered by keyboard or safely printed on screen or sent through email.

Sure, you may want to avoid similar characters like ' (apostrophe, 0x27) and ` (grave accent, 0x60) but it's no biggie.

 

so you could have:

 

function make_password($length=16) {

$code = '';

for ($i=0; $i<$length;$i++) {
	$character_code = mt_rand( 0x21 , 0x7E );
	$code .= chr( $character_code );
}
return $code;
}

But Honestly, a better password would be to pick 5-8 random words from a dictionary and capitalize some letters and add some punctuation or hyphens, exclamations, would make for better passwords. Then make a sha256 or md5 hash of that phrase and store that in the database (hashes are fixed length, good for DB storage)

 

obligatory xkcd

 

password_strength.png

 

 

 

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

^ This.

 

There is no such thing as a "secure generated password".

Write in C.

Link to comment
Share on other sites

Link to post
Share on other sites

Just now, Dat Guy said:

^ This.

 

There is no such thing as a "secure generated password".

"CSPRNG" as in "secure"

Back-end developer, electronics "hacker"

Link to comment
Share on other sites

Link to post
Share on other sites

There is a major difference between a random password and a secure password.

Write in C.

Link to comment
Share on other sites

Link to post
Share on other sites

54 minutes ago, mariushm said:

Both are equally bad.

You should use mt_rand or mt_srand

Why limit the characters to only those in the array? There's other characters on all keyboards that can be easily typed:

 

 

From "!" (0x21) to "~" (0x7E) all characters can be manually entered by keyboard or safely printed on screen or sent through email.

Sure, you may want to avoid similar characters like ' (apostrophe, 0x27) and ` (grave accent, 0x60) but it's no biggie.

 

so you could have:

 


function make_password($length=16) {

$code = '';

for ($i=0; $i<$length;$i++) {
	$character_code = mt_rand( 0x21 , 0x7E );
	$code .= chr( $character_code );
}
return $code;
}

But Honestly, a better password would be to pick 5-8 random words from a dictionary and capitalize some letters and add some punctuation or hyphens, exclamations, would make for better passwords. Then make a sha256 or md5 hash of that phrase and store that in the database (hashes are fixed length, good for DB storage)

 

obligatory xkcd

 

 

This doesent always create a length of the set length tho. I want it to be 32 in length if I say 32.

Back-end developer, electronics "hacker"

Link to comment
Share on other sites

Link to post
Share on other sites

30 minutes ago, Joveice said:

This doesent always create a length of the set length tho. I want it to be 32 in length if I say 32.

The length is specified by the parameter of the function, if the parameter is omitted then the default value of 16 is used.

 

In the for, there's one character generated in each loop . The loop starts at 0 ($i=0, and continues as long as i is smaller than length (16 by default). So after 16 loops, the condition is no longer valid ( $i is bigger or equal to $length and you're out of the for loop.

 

You can change the code of the function to fit your needs, I literally wrote it directly in the comment as something extremely basic.

Link to comment
Share on other sites

Link to post
Share on other sites

5 minutes ago, mariushm said:

The length is specified by the parameter of the function, if the parameter is omitted then the default value of 16 is used.

 

In the for, there's one character generated in each loop . The loop starts at 0 ($i=0, and continues as long as i is smaller than length (16 by default). So after 16 loops, the condition is no longer valid ( $i is bigger or equal to $length and you're out of the for loop.

 

You can change the code of the function to fit your needs, I literally wrote it directly in the comment as something extremely basic.

Yes and you have it set to 16, this is that script outputting 5 times.

Z*

;+5A6/6K%y~{hf1;

-&/0kb2oR,$T~Pxl

mE~de%&C>

~``,4

 

Back-end developer, electronics "hacker"

Link to comment
Share on other sites

Link to post
Share on other sites

Save this to a file with the .php extension in the folder where php.exe is located. I named it a.php :

 

<?php

for ($i=0; $i<26;$i++) {
echo "[". make_password() ."]\n"; 
}

function make_password($length=16) {

$code = '';

for ($i=0; $i<$length;$i++) {
	$character_code = mt_rand( 0x21 , 0x7E );
	$code .= chr( $character_code );
}
return $code;
}

?>

Now you can open a command window in that folder and type php.exe a.php  (where a.php is the name of the file)..

Here's what i get:

d:\Programs\php7>php a.php
[w[+@qSZI//Jm@O\L]
[m:3xS=_yU$&!}!(q]
[(y9HNm(-dm{lG\aH]
[SO{;~5uW>~tQ/q9_]
[.U(++QKvW&"=_F:6]
[a>7p%XBvl'j:>@_5]
[[fVR/Uk*[pNc{yQ(]
[rTQ3A2Q{1Y1;4u_A]
[9jH`$Lp}Fdht.3xI]
[UA-wq`@(zr\6nSsE]
[Q5mt2teR6"$OOUYD]
[6!~T~o`qK\><FGA7]
[lpo^hS)]Dh"m7J/Q]
[wPQRm0bV+thi:>uW]
[=VU?wy!#ix%nms;z]
[hKgbn8;{H&*%p-su]
[k(vH.eAk{:Yu,BNC]
[$]V}Fu0V)wzc\sJW]
[hFW*0"{8&{%QMRIx]
[Hty&->ymCG<\zuab]
[z;&UV):0E:85N-v`]
[s<uX>XCzj?z;E@t*]
[;@2C3=LXUqQ;<rLg]
["7;HJj$C6^%wtw"~]
[Fw9Ff:/T<~#0(h3z]
[DtM>\v&#;C2t3=h']

 

The brackets are there to tell you if perhaps some characters are simply not rendered by your browser (maybe bad font?) but are actually there.

The command window uses a font (Lucinda Console or Consolas or some raster font) which contains those letters.

 

OH ... your browser may treat the output as HTML in which case "<" and ">" characters have special meaning, if you want to show < or > on screen, you have to use &lt;  and &gt;  otherwise the browser will treat what's inside as tags

 

You also have to escape the & character as it has special meaning in HTML... so if you want the browser to show & on screen, you print &amp; (short for ampersand). Quote should also be escaped : &quot;

 

There's a built-in function to make texts html friendly , see htmlspecialchars : http://docs.php.net/manual/en/function.htmlspecialchars.php

 

So to show pass in a html document you'd say :

 

 

<?php

echo '<html><body><p>Here is the pass: ' . htmlspecialchars(make_password(16)). '</p></body></html>';

function make_password($length=16) {

$code = '';

for ($i=0; $i<$length;$i++) {
	$character_code = mt_rand( 0x21 , 0x7E );
	$code .= chr( $character_code );
}
return $code;
}

?>

 

 

Link to comment
Share on other sites

Link to post
Share on other sites

Unfortunately this new fad of picking random words to form a "statement" isn't very secure anymore for various reasons. Many times, password fields are truncated to a certain length, and I don't necessarily mean when they give you an upper limit on password length. Many times they truncate silently at some given length. Even so, it's extremely easy to use different rulesets with a dictionary attack to break passwords. It's not advisable to do this.

 

The most secure passwords are actually the random chains of characters like OP is thinking. However, you want to use all 95 printable ASCII characters to have as large of a character set as possible. Websites tend to disallow spaces but there's no actual reason to enforce such a rule.

 

Secondly, you can't use a standard random function. You need to use the language's cryptographically secure random function.

 

In other words, the main 3 things are:

Use the cryptgraphically secure random function, not the standard one.

Use all 95 printable ascii characters

Generate a length at minimum 16 characters and hope that no truncation is performed, and if so hope it is at least 12 or greater.

Link to comment
Share on other sites

Link to post
Share on other sites

3 hours ago, mariushm said:

But Honestly, a better password would be to pick 5-8 random words from a dictionary and capitalize some letters and add some punctuation or hyphens, exclamations, would make for better passwords. Then make a sha256 or md5 hash of that phrase and store that in the database (hashes are fixed length, good for DB storage)

 

You were right about character set in your post but everything else is basically wrong, ESPECIALLY this part. Do NOT use sha256 or even worse md5 to store passwords, EVER. It is a pathetically weak hashing algorithm. While salting and using many iterations definitely improves its effectiveness, it is too error-prone to still actually consider using.

 

Make sure to use a good, long, unique salt and to use an appropriate hashing algorithm such as bcrypt, scrypt, PBKDF2, or Argon2. 

Link to comment
Share on other sites

Link to post
Share on other sites

I'm aware md5 is outdated and collisions can be generated easily... and sha256 is also weak, but seriously... how extremely small are the chances that a hash of a random entered pass will match another password (esp. when you add some random user account specific salt or something).

IMHO they're hood enough to hash a password. Beats even huge websites that store passwords in plain text or limit passwords to 8 letters.

 

Link to comment
Share on other sites

Link to post
Share on other sites

It's not just about collisions, GPU-accelerated password hashing absolutely plows through them, with a Titan X Pascal able to do nearly 40 billion md5 hashes per second. There is absolutely no excuse for using an ineffective hashing algorithm, especially md5. They aren't "good enough" and that is the exact line of thinking the lazy engineers at huge companies use that end up having huge security breaches, like LinkedIn.

 

It takes minimal effort to implement an appropriate hashing algorithm over md5 or any other bad choice. There's literally no excuse to do so. Security is immeasurably important. Don't take shortcuts or be cheap. Too many people think they know better than security experts and try to do their own thing - it always ends in failure. Don't be one of those people. Learn how to do things properly and correctly and stay up-to-date in the subject.

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, hoboX10 said:

Too many people think they know better than security experts and try to do their own thing

100% agree with you

 

I don't even get the topic of this thread. What is a secure password in the first place? There are many opinions on what a secure / strong password is. Length, possible characters, randomness of the generator. They all come with the price, that humans are not so great in remembering a random string. But basically it's how many guesses you would need to guess the right password when you brute force it. But there are other aspects like dictionary attacks... 

But then password storing is a completely other field. There you have to care about salting and strong hashing function. It's about the time an attacker needs to generate a hash, compared to the time you have to generate a hash (because the user want's to login in an reasonable amount of time, and the crackers usually have dedicated hardware which is faster than your server in generating those hashes). Passwords should always be salted, if not you can easily hack hunderts at a time or compare like the password recovery answers for the same hashes (#adobe)

Business Management Student @ University St. Gallen (Switzerland)

HomeServer: i7 4930k - GTX 1070ti - ASUS Rampage IV Gene - 32Gb Ram

Laptop: MacBook Pro Retina 15" 2018

Operating Systems (Virtualised using VMware): Windows Pro 10, Cent OS 7

Occupation: Software Engineer

Link to comment
Share on other sites

Link to post
Share on other sites

Both functions are to be avoided.

 

You should take a look at http://php.net/manual/en/function.random-bytes.phphttp://php.net/manual/en/function.password-hash.php and http://php.net/manual/en/function.password-verify.php.

 

Create a random string using random_bytes. Then hash it with password_hash using bcrypt as algorithm. Store the hash in a DB

CPU: i7-12700KF Grill Plate Edition // MOBO: Asus Z690-PLUS WIFI D4 // RAM: 16GB G.Skill Trident Z 3200MHz CL14 

GPU: MSI GTX 1080 FE // PSU: Corsair RM750i // CASE: Thermaltake Core X71 // BOOT: Samsung Evo 960 500GB

STORAGE: WD PC SN530 512GB + Samsung Evo 860 500GB // COOLING: Full custom loop // DISPLAY: LG 34UC89G-B

Link to comment
Share on other sites

Link to post
Share on other sites

1 minute ago, Limecat86 said:

Both functions are to be avoided.

 

You should take a look at http://php.net/manual/en/function.random-bytes.phphttp://php.net/manual/en/function.password-hash.php and http://php.net/manual/en/function.password-verify.php.

 

Create a random string using random_bytes. Then hash it with password_hash using bcrypt as algorithm. Store the hash in a DB

This isent to be used as a login or something like that. I'm just trying to create a "click this for a new password" and it spits out a password and you can copy paste it.

if they are to be avoided how would a better random password generator look like?

Back-end developer, electronics "hacker"

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×