2019 twenty-four merry days of Perl Feed

J1ngle? No...zxcvbn

Data::Password::zxcvbn - 2019-12-01

Zero Cool Situation

Butters Jollycane stared up in amazement at the towering piles of gifts before him. Never before has he seen such large piles of presents for so few people. There was one pile for "Dade Murphey", another for "Kate Libby" and another for someone with the dubious name of "Cereal Killer".

What's worse, up until a week ago these people had been scheduled for a coal delivery, after a prank they'd been involved in with taking over some automated office lights in a tower block to display dubious messages had got them assigned to the naughty list. So why had Pepper Frostyflakes over in accounting used his login to assign them such lavish gifts at 3am this morning?

Hack The Planet!

"I was asleep in my bed at three am this morning!", Pepper exclaimed, "Do I look like an Elf on the Shelf, up all night long? I need my beauty sleep".

"And your password is secure?", Jollycane asked.

"It's locked away right here, where it always is", Pepper replied as he unlocked his desk draw and pulled out a dog-eared post-it note. "I wrote it down and locked it away because of the silly password rules you tech Elfs put in place - you know, with the numbers and uppercase and lowercase and weird punctuation you guys always want."

Pepper flipped over the post it note which had just one word written on it: J1ngle?

Jollycane's jaw dropped. It was obvious that not only had they been hacked by some young miscreants, but they'd done it just by guessing Pepper's super simple password.

Never fear, zxcvbn is here

Jollycane thought for a minute if he should give Pepper the same lecture he'd given the last six elves that had had their password guessed by mischievous agents. It's not enough to switch an 1 for an i or uppercase the first letter. It's just a simple matter of programming to try those basic transformations too. But Pepper had followed the policy...maybe it was time for a change.

What Jollycane needed was some way to rate the passwords users were using. Luckily, Dropbox has been working on this problem and published their zxcvbn algorithm that can do just that. And there's a Perl implementation on the CPAN, Data::Password::zxcvbn.

#!/usr/bin/perl

use 5.024;
use warnings;

use Data::Password::zxcvbn qw( password_strength);
my $result = password_strength($ARGV[0]);

The result is a hashref that contains a lot of useful information about the strength of the password. At the most basic we have the score:

my @passwords = (
    'password',
    'p@ssword',
    'J1ngle?',
    'horse staple battery generator',
    'B2aFkgEhZvFstE9',
);
foreach my $password (@passwords) {
    my $result = password_strength( $password );
    say "$result->{score} $password";
}

This goes from 0 (never use) to 4 (as secure as the algorithm can figure).

    0 password
    0 p@ssword
    1 J1ngle?
    4 horse staple battery generator
    4 B2aFkgEhZvFstE9

What does that mean in a practical sense? Well, since Santa's workshop hasn't implemented any rate limiting on their website logins (ooops, they should really do that) the hackers can probably make, say, oh, ten requests a second to try and log in. How long would it take for each of the passwords to be broken?

use Time::Duration qw( duration );
foreach my $password (@passwords) {
    my $result = password_strength( $password );
    my $duration = duration(
        $result->{crack_times_seconds}
               ->{online_no_throttling_10_per_second}
    );
    say "$password would be cracked $duration";
}

Which means:

    password would be cracked just now
    p@ssword would be cracked just now
    J1ngle? would be cracked 9 hours and 33 minutes
    horse staple battery generator would be cracked 2475117468353 years and 229 days
    B2aFkgEhZvFstE9 would be cracked 3170979 years and 72 days

Okay, that really brings it home the difference in password security! Jollycane should implement a rule that no password with a score less than four can be used.

But how can he do that? We've obviously established that simple rules that users (and hackers!) can easily follow don't help matters. What users need is some interactive feedback about why the passwords they're trying to use aren't secure, and what they should do to improve them. password_strength provides help with that too:

foreach my $password (@passwords) {
    my $result = password_strength( $password );
    next if $result->{score} > 3;

    say "# $password";

    my $feedback = $result->{feedback};
    say "WARNING: $feedback->{warning}"
        if $feedback->{warning};
    say "* $_" foreach $feedback->{suggestions}->@*;

    say "";
}

This gives us output we can show the end user:

    # password
    WARNING: This is a top-10 common password
    * Add another word or two. Uncommon words are better.

    # p@ssword
    WARNING: This is similar to a commonly used password
    * Predictable substitutions like '@' instead of 'a' don't help very much
    * Add another word or two. Uncommon words are better.

    # J1ngle?
    * Capitalization doesn't help very much
    * Predictable substitutions like '@' instead of 'a' don't help very much
    * Add another word or two. Uncommon words are better.

Rollout

Jollycane rolled out the new policy and got all his users to change their passwords. Hopefully that would be enough to keep out those undeserving hooligans....at least until tomorrow....

Gravatar Image This article contributed by: Mark Fowler <mark@twoshortplanks.com>