fastkeys has asked for the wisdom of the Perl Monks concerning the following question:

Sorry, I couldn't find an answer to this anywhere and I need to get on ATM :)

I need to check a password is "sensible". One of the checks is that it does not contain daft characters or spaces.

Could somebody point me in the right direction of something that will return true if the password contains only A-Z a-z 0-9 and false if it contains anything else including a space.
<br Thanks

Alex

Replies are listed 'Best First'.
Re: Yet another REGEXP Question
by merlyn (Sage) on Feb 05, 2002 at 15:46 UTC
    That's an odd use of the word "sensible" applied to "password". Are you sure you don't mean "username" where you have "password"? A password restricted to \w+ is surely much easier to hack. Maybe if that is indeed a password, you need to rewrite the code that deals with passwords, rather than restricting the users to such a guessable set.

    -- Randal L. Schwartz, Perl hacker

      The character set mentioned is more than secure enough for the application.

      As to altering the code which deals with the passwords, that would be Mr Gate's department :)

      Thanks for your help

      Alex
Re: Yet another REGEXP Question
by AidanLee (Chaplain) on Feb 05, 2002 at 16:48 UTC

    Of course merlyn has a very important point -- the more different characters you allow in your password field, the harder to guess the password.

    To answer your question, though, you'll need something like this:

    if( $password =~ m/^[DesiredCharactersHere]+$/ ) { it's "reasonable" } else { it's not reasonable }

    It's a common saying that Perl gives you more than enough rope to hang yourself. Something similar can be said of the community too. We're not big on refusing to tell people some bit of knowledge. It's just that as we hand you that rope (and even telling you how to tie the knots), we're usually telling you why it isn't a good idea.

    Update: Thanks to merlyn for catching the security hole. I've left the code with the bug in place so his post continues to make sense.

    One thing I think is important to note about most of the replies that hasn't been explicitly mentioned is notice that almost all the code examples test for DesiredCharacters, not UndesiredCharacters. This is a best-practices approach to making sure you only get _exactly_ what you want in your password field, with no chances of forgetting to exclude anything undesired. That was my intention as well, but I seem to have let one (\n) slip in anyways.

      $password =~ m/^[DesiredCharactersHere]+$/
      Watch out! That permits "Desired\n"! I just zapped someone on the beginners list for that same mistake. Potential Big Security Hole.

      Better to use something like: $password !~ /[^DesiredCharactersHere]/ or even not $password =~ tr/DesiredCharactersHere//c.

      -- Randal L. Schwartz, Perl hacker

      A much more compact solution, given that s?he specified the characters s?he wanted, would be:

      if ($password =~ /\W/) { # It's "unreasonable" } else { # It's really easy to guess -- err, I mean "reasonable" }

      perl -pe '"I lo*`+$^X$\"$]!$/"=~m%(.*)%s;$_=$1;y^`+*^e v^#$&V"+@( NO CARRIER'

Re: Yet another REGEXP Question
by chromatic (Archbishop) on Feb 05, 2002 at 22:38 UTC
    Use a complemented transliteration in scalar or boolean context:
    if ( $password =~ tr/A-Za-z0-9//c ) { warn "Bad characters in <$password>\n"; }
    The question of "sensibility" is left to the implementor. :)

    Update: AidanLee found an extra right paren which has since been recycled. Oops.