Paswords… *sigh*
by TheWatcher on Feb.04, 2013, under Perl, Web devel
So, one thing I’m currently dealing with is the handling of user account passwords. Not the storing of said passwords (or rather, salted hashes of them) – that part is actually really easy: push it through Crypt::Eksblowfish::BCrypt‘s bcrypt()
function with a randomly generated salt and decent cost (I use 14 at the moment, many sources I’ve seen recommend 10), store the result for later use in password validation.
No, the problem I’m dealing with is password policies. Originally I was considering just omitting any password policy enforcement – everyone has seen jokes along the lines of
13:11 <@froztbyte> <@gamajun> "Your password needs to contain a capital letter, a number, an emoji, and a plot containing a protagonist and a twisted ending."
and some of the ones out there are, frankly, nearly that level of utterly ridiculous. Not only do these policies make it much harder for users to deal with passwords, they can actually make attacks easier – in part they can reduce the search space needed, and when combined with some knowledge of human behaviour, you can get a pretty good handle on the general format of passwords people will use. ((I had a much longer rant ready for here, but really it’s not worth carrying on about it – just assume that I’m in the camp of people who think that password policies are potentially dangerous simply because of the false sense of security they can engender.))
There are things that can be done to mitigate some problems – lock out users after a number of login failures to prevent brute-force guessing attacks, and ensure stored passwords are salted and hashed using a high cost algorithm in case the database itself is compromised – but policies are far from the panacea some security ‘experts’ seem to think they are.
12 years of dealing with real-world functionally-computer-illiterate users (irony being, many of them work in a university Computer Science department) and their approach to password security has pretty much convinced me that relying solely on passwords to provide anything beyond a modicum of security is hilarious naive and ultimately doomed. But that said, passwords are an established convention, and more or less the only remotely convenient (if not viable) option in most situations – so in the end I decided that some support for policy enforcement would be useful. If nothing else, it gives some people a fuzzy feeling, and I’ll almost certainly end up being asked for it anyway. The thing that needs deciding after that is just what can be dictated…
There are the obvious things, like the number of characters required and the composition of the password as in the example above. Those can be specified as a series of minimums for each auth method ((Although, for the moment, only Webperl::AuthMethod::Database will actually make use of it – the other auth methods do no support password changes, so they don’t need to enforce policies)), where if no value is set there is no minimum, no policy regarding it:
policy_min_length
, passwords must be at least this number of characters long.policy_min_lowercase
, at least this number of lowercase characters must be present.policy_min_uppercase
, at least this many uppercase characters must be included.policy_min_digits
, the minimum number of digits that must be used.policy_min_other
, the number of non-alphanumeric characters that must be present.
There are other options, though: one is to invoke cracklib via Crypt::Cracklib and let it judge the password’s quality, rejecting passwords that do not pass muster (something that’s probably a good idea, regardless of policy, really). Another option is to calculate the password’s entropy, and reject passwords with entropy below a set threshold. There is at least one perl module to do this – Data::Password::Entropy – and it seems mostly decent, although it appears to produce somewhat more generous values for some test passwords than Tyler Akins’ Strength Test calculator. I’ve decided I may as well allow them as options, so:
policy_use_cracklib
, if true, the password is checked using cracklib to determine whether it is acceotable.policy_min_entropy
, passwords must have at least this entropy to be considered strong enough
Now I just need to set about documenting these well enough, including some decent scales for the entropy. The Strength Test page linked above has some recommendations for entropy ranges for different strengths of password, but as I say Data::Password::Entropy generates slightly higher results, so I will need to do some testing to provide decent recommendations.
Oh, yeah, and I need to actually code this stuff. I might actually get to do that if things would stop breaking…