Rasshu
Rasshu

Reputation: 1799

Match At least 1 uppercase, 1 special, 4 non-sequential numbers, length is 6 to 14

I'm trying to match at least 1 uppercase anywhere, 1 special anywhere, 4 non-sequential numbers anywhere and length is 6 to 14.

I tried the following regex:

((?=(.*[^A-Za-z0-9])+)(?=(.*[A-Z])+)(?=(.*\d){4,})(?=.*[a-z])+)(?!=.*([\d])\\1\\1\\1\\1).{6,14}

But all the following strings are matching:

abDc#E0%F9$845, 
abDc#E0%F9$8y6, 
abDc#E0981, 
#ab1DcE09w1234  **(4 sequential numbers)**, 
#ab1111DcE09, 
E$ab1Dc098, 
1$Eab1Dc0989, 
T3$s7p4s$123, 
T1234$stPass    **(4 sequential numbers)**

And doesn't match:

testpass, 
abDc#E0%F9$8y67 (15 characters), 
t3stpass, 
te$stpass, 
TestPass, 
T3$stpass

How can I fix it?

Upvotes: 2

Views: 1225

Answers (3)

Toto
Toto

Reputation: 91385

How about:

if (preg_match('/^(?=.*[A-Z])(?=(?:.*\d){4,})(?=.*[!@$%^&*()_+=-]).{6,14}$/', $string)) {
    // remove all non digit
    $tmp = preg_replace('/\D+/', '', $string);
    if (preg_match('/0123|1234|2345|3456|4567|5678|6789|3210|4321|5432|6543|7654|8765|9876|0000|1111|2222|3333|4444|5555|6666|7777|8888|9999/', $string)) {
        echo "Failed\n";
    }
    echo "Pass\n";
} else {
    echo "Failed\n";
}

Where:

(?=.*[A-Z])             : at least one uppercase
(?=(?:.*\d){4,})        : at least 4 digits
(?=.*[!@$%^&*()_+=-])   : at least one special character
.{6,14}                 : from 6 to 14 character long

Upvotes: 1

Rasshu
Rasshu

Reputation: 1799

Used the following PHP page to test the regex.

1) strlen checks string length
2) first preg_match checks one or more uppercase letter
3) second preg_match checks at least 4 numbers
4) third preg_match checks 4 sequential numbers (ascending and descending)
5) fourth preg_match checks at least one special character

<?php
if (isset($_GET['string'])) {
    if ($_GET['string'] != '') {
        $string = $_GET['string'];
    } else {
        echo "Empty string.";
    }
}
?>
<pre>
<html>
  <head>
    <title>Regular Expression Tester</title>
  </head>
  <body>
    <form action="" method="get">
      <input type="text" name="string" />
      <input type="submit" value="Send" />
</form>
</pre>
<?php
if (isset($_GET['string'])) {

    if(strlen($string) >= 6 && strlen($string) <= 14) { // length between 6 and 14
        echo "Size between 6 and 14: <b><span style=\"color:green;\">OK</span></b>", "<br>";

        if (preg_match('#[A-Z]+#', $string)) { // one or more uppercase chars
            echo utf8_decode("At least one uppercase: <b><span style=\"color:green;\">OK</span></b>"), "<br>";

            if (preg_match('#(?=.*[0-9]{1}.*[0-9]{1}.*[0-9]{1}.*[0-9]{1})#', $string)) { // it has at least 4 numbers anywhere
                if (!preg_match('#(0123|1234|2345|3456|4567|5678|6789|3210|4321|5432|6543|7654|8765|9876|0000|1111|2222|3333|4444|5555|6666|7777|8888|9999)#', $string)) { // sequential numbers
                    echo utf8_decode("4 non-sequential numbers: <b><span style=\"color:green;\">OK</span></b>"), "<br>";

                    if (preg_match('#[!@$%^&*()_+=-]+#', $string)) { // special chars
                        echo utf8_decode("At least one special character: <b><span style=\"color:green;\">OK</span></b>"), "<br>";
                        echo utf8_decode("<br>$string <b><span style=\"color:green;\">PASSED</span></b>");
                        exit;

                    } else {
                        echo utf8_decode("At least one special character: <b><span style=\"color:red;\">FAILED</span></b>"), "<br>";
                    }

                } else {
                    echo utf8_decode("4 non-sequential numbers: <b><span style=\"color:red;\">FAILED</span></b>"), "<br>";
                }
            } else {
                echo utf8_decode("4 non-sequential numbers: <b><span style=\"color:red;\">FAILED</span></b>"), "<br>";
            }

        } else {
            echo utf8_decode("At least one uppercase: <b><span style=\"color:red;\">FAILED</span></b>"), "<br>";
        }

    } else {
        echo "Size between 6 and 14: <b><span style=\"color:red;\">FAILED</span></b>", "<br>";
    }

    echo utf8_decode("<br>$string <b><span style=\"color:red;\">DIDN'T PASS</span></b>");
}
?>
  <pre>
  </body>
</html>
</pre>

Screenshots:

regex tester 1

regex tester 2

regex tester 3

EDIT: But T1e2$3t4 didn't pass, so the problem is in the 2nd preg_match. It's searching 4 numbers IN A ROW, not 4 numbers in ANY position.

EDIT 2: Changed that regex to #(?=.*[0-9]{1}.*[0-9]{1}.*[0-9]{1}.*[0-9]{1})# and it's working completely now.

Thanks, everyone! :-)

Upvotes: 0

dlyaza
dlyaza

Reputation: 238

Try this, please test it before using it:

function validate_password($password){

 if(empty($password))
  return false;

 if(strlen($password) < 4 || strlen($password) > 14)
  return false;

 $uppercase_test = preg_match('#[A-Z]+#', $password);

 //include special charactors that you want
 $special_test = preg_match('#[!@$%^&*()_+=-]+#', $password);

 $nonsequencial_number_test = !preg_match('#(\d)\\1{4,}#', $password);

 if($uppercase_test && $special_test && $nonsequencial_number_test){
  return true;
 }

 return false;

}
var_dump(validate_password('abDc#E0%F9$8y6'));

Upvotes: 1

Related Questions