Hi Everyone. I have the following preg_match to check user passwords contain

elseif (!preg_match( "((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,15})",$bpwd ) ) {

1 Upper Case Letter
1 lower case letter
1 number

It works as described, but what I am looking to do is to create a stronger password requirement.
I would like to add the following special characters !,@,?,# to be required when users are creating passwords.

Any help would be greatly appreciated.
Thanks

MD5 has no place in password security any more. Hasn't for a long time now. It's an old and easily defeated algorithm. These days you should at the very least be using something akin to SHA512 or Whirlpool, if not something more advanced like Bcrypt or PBKDF2.

Besides, this is not what the OP was asking for.

Any help would be greatly appreciated.

With the way your current regex is set up, you should be able to just add a nother forward-looking group, like (?=.*[!@?#]), making the whole thing look like: ((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@?#]).{8,15}).

commented: nods +14
commented: correct +7

@Atli - Cheers I will include your suggestion - Thanks.
Re MD5 - I'm pretty new to php and even I understand that SHA1 is more powerful than MD5 for hashing data.

Maybe I know more than I think...

That really is one of the weirdest regex setups I've ever seen :p. The following does what you asked for, but in a simpler way:

<?php
$is_valid = true;

// To check for allowed characters:
$regex = '/^[a-z0-9!@?#]+$/i';

if(!preg_match($regex, $password))
    $is_valid = false;

// To check the length:
$string_length = strlen($password);

if($string_length < 8 || $string_length > 15)
    $is_valid = false;

Sha1 is also considered insecure nowadays, you should check out the hash() function of PHP, which allows you to use, for example, SHA512 encryption. Example:

<?php
$password = 'hello';
$hashed = hash('sha512', $password);

@minitauros, the problem with your approach is that it doesn't require that all the characters are present, just that the password consists only of the character ranges listed. Your code would verify AAAAAAAA as a valid password, even though it only has a single uppercase letter.

If you wanted to do this without the relatively advanced regex, you'd have to search for each part in the password separately, more like:

function validate_password_format($password, $min=8, $max=15) {
    $length = strlen($password);
    if ($length < $min || $length > $max) {
        return false;
    }

    $patterns = array(
        "/[a-z]/",
        "/[A-Z]/",
        "/\d/",
        "/[!@?#]/"
    );
    foreach ($patterns as $pattern) {
        if (!preg_match($pattern, $password)) {
            return false;
        }
    }
    return true;
}

... you should check out the hash() function of PHP

PHP 5.5 introduced the password_hash function, which makes it extremely easy to create highly secure Bcrypt passwords in PHP. This is really how people should be hashing passwords these days. - Even if you don't have the ability to use 5.5 yet, adding these functions to lower versions can easily be done through 3rd party libraries.

... SHA512 encryption

This is a fairly minor thing, but he word "encryption" is not really a good choice there. There is a significant difference betweeen "encryption" and "hashing", and the SHA algorithms are the latter. (Encryptions can be decrypted, hashes can not be.)

commented: taught, with thought, expressed kindly, there should be a place to add +2 +12

@Atli
Woops, I misunderstood, you are totally right. You'd be better off using a loop probably, as you show in your example.

You'd be better off using a loop

He'd be better off using a single regex like Atli originally posted, much faster execution, less steps, and more elegant code to read.

Yes, except that the regex that the topic starter provided and that Atli modified in his first post will not securely check if the length of the string is really between 8 and 15 characters. Therefore you would still have to add a length check. I myself (but that's just my opinion, of course) find the code in Atli's last post the most elegant, because it is clear there which regex has what function.

Good point about the length. That's easily fixed, though. Just add the start and end anchors.

(^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@?#]).{8,15}$)

Personally I don't see the point in having an upper limit for password lengths though. I'd just leave it like this, so that it only makes sure the lower limit is reached. (I also hate using parenthesis as end delimiters, so...)

/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@?#]).{8}/

Whether or not this is more elegant or not, that's debatable. Comes down to your own view on things I suppose. I don't really see much difference in clarity between the function I wrote and this regex, but then again I'm pretty familiar with reading and writing complex regular expressions. I know that isn't the case for a lot of people, including some of the best developers I know.

Hi Everyone, I am new to PHP as my opening question may point out.

Just wanted to say a massive thank you to all who have replied, DannyWeb is amazing for problems like this, Love the way everyone gets involved with showing different approaches.

Thanks again,

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.