pods icon indicating copy to clipboard operation
pods copied to clipboard

Update password.php

Open orchid-hybrid opened this issue 10 years ago • 15 comments

Initial commit adding password hashing support to password fields.

This adds two new options to the password field: Hash (a boolean) and Salt (a string). Hashing is enabled by default but is optional (for backwards compatability) and can be turned off.

We've chosen one iteration and 32 bytes for the size of the derived key. I think these values would be suitable in general.

Note that this means users should not inspect the value of a password field anymore: The way to interface with hashed passwords is to hash the value you want to test it against with the same salt and compare.

Reference for the choice of pbkdf2 with sha1: http://security.stackexchange.com/a/31846/45116

orchid-hybrid avatar Jun 10 '14 01:06 orchid-hybrid

This looks great, but what steps can we take to ensure values aren't saved and re-hashed over and over?

sc0ttkclark avatar Jun 10 '14 14:06 sc0ttkclark

I've improved 'schema' by using $length, that's much nicer.

Thanks for pointing this out! I verified that re-hashing like that is an issue in my testing setup and I see two types of solution to this:

(A) Add a tag to hashes so that strings can be tested for whether or not they need to be hashed. (B) When saving a value into the database, check whether the previous value is equal to the value about to be inserted - only compute the hash if it's not.

I feel that B does not naturally fit and might require performing an extra database lookup so I went ahead and implemented A by adding a "{SHA1}" tag to the hashes and verified that this resolves that issue.

orchid-hybrid avatar Jun 10 '14 23:06 orchid-hybrid

This will not work on php 5.2? We need to keep things compatible with the least Wordpress needs, WP is 5.2, hash_pbkdf2 is 5.5.0 or greater.

We could add one of the PHP implementations, maybe, if Sc0tt is allright with it.

unknownnf avatar Jun 11 '14 09:06 unknownnf

What does WordPress use? Why not just use that?

sc0ttkclark avatar Jun 11 '14 19:06 sc0ttkclark

http://codex.wordpress.org/Function_Reference/wp_hash_password

sc0ttkclark avatar Jun 11 '14 19:06 sc0ttkclark

I think the best suggestion to avoid re-hashing is also to follow WordPress's lead:

wordpress-password

There is no use in populating the password box after the password has been hashed and saved. The original password is discarded and the hash is of no use. Better to present an empty input and change the label to "change password" or similar.

Also, it would be a nice touch to add another option for "verify", which would display a 2nd input that must match the first before allowing save.

pglewis avatar Jun 11 '14 19:06 pglewis

Verify would be cool, but would probably require some more thinking on our side to make it possible to add another field row from input() or another method.

sc0ttkclark avatar Jun 11 '14 19:06 sc0ttkclark

One more thing from the brainstorming session in #pods-dev: we should also expose a (public static?) method to check the input against the hash. Implementors need this functionality and the details should be in the field, not external.

To sum up where we are, roughly in order of importance:

  1. Use the WordPress wp_hash_password() function to keep compatibility with older PHP. The default implementation adds salt on its own so the salt option can probably be dropped, one less thing to manage.
  2. Expose a method to check an input against a hash
  3. Do not populate the password field, check for any input to change the password and/or look into using the HTML5 placeholder attribute to distinguish "no password" entered.
  4. A way to clear the password field (use case: post password)
  5. A verify option that would show a 2nd "re-enter password" field that must match the first
  6. An option to display strength meter from WordPress on the password input(s) with the default as being 'on'

If any of these (verify, for example) presents a major technical roadblock then we should create a new enhancement issue for it and push it until later. Having the core features and supporting hashing is more important than having every wish-list item.

@sc0ttkclark says we'll up the bounty on this for the hard work. This is definitely needed functionality so I'm very glad it's getting this attention.

pglewis avatar Jun 11 '14 21:06 pglewis

4 and 5 are nice to haves, I'd focus on 1, 2, and 3.

5 may be unrealistic with the current Forms API, there's no way to add another row to certain form UI, and they're not all the same, so it's possible it could get tricky.

I'd like to propose a final number 6: An option to display strength meter from WordPress on the password input(s) with the default as being 'on'.

sc0ttkclark avatar Jun 11 '14 21:06 sc0ttkclark

I think that using wp_hash_password is a great idea since it handles the salts transparently (this is a big improvement on ease-of-use). I've gone and implemented this change to see how it takes and two slight problems came up regarding (2).

First regarding wp_check_password in pluggable.php: This procedure is used by wordpress to test a password against a hash but it also takes a user_id (it automatically fixes up old md5 hashes into bcrypted hashes for the user with that id), if we set user_id to null then it wont perform any database updates like that but it does still call apply_filters( 'check_password', $check, $password, $hash, $user_id ). I'm not sure whether or not that's desirable - to stop these filters being triggered you could duplicate the password testing mechanism like so:

$wp_hasher = new PasswordHash(8, true);
$check = $wp_hasher->CheckPassword($password, $hash);

but the issue with this is that functions in pluggable.php are designed to be replacable, so password testing would actually break on wordpress instances that have a custom password hashing plugin. if calling apply_filters is ok, I'll go ahead and commit that.


Secondly since hashing is optional, the password test mechanism should of course work in both cases - but if a programmer tried to test passwords in the following way:

$pod = pods($name, $id);
$hash = $pod->field("password");
$hash->check_password($pass, $hash);

then check_password has no way to tell if the password is hashed or not, the options set for that field needs to be passed to check_password too or at least a boolean saying whether or not you're comparing against a hash or plaintext (but that doesn't seem good for usability). What kind of interface would work best for this?

orchid-hybrid avatar Jun 12 '14 10:06 orchid-hybrid

I'll go over your latest info either late tonight or tomorrow my time. Thanks for continuing on!

pglewis avatar Jun 12 '14 23:06 pglewis

Ah the first section of my last post was a bit long, let me summarize:

There's a slight issue with using wp_check_password directly in that it triggers a filter - if that's ok we can use it. If not we could use PasswordHash/CheckPassword from phpass directly but it wouldn't be plugin-replaceable.

I'll investigate (3) now.

orchid-hybrid avatar Jun 13 '14 03:06 orchid-hybrid

Hey, I just wanted to bump this conversation and see whether the core implementation of password hashing is something that could be sponsored so it can be released ASAP?

lougreenwood avatar Dec 03 '16 18:12 lougreenwood

bump... :)

lougreenwood avatar Dec 09 '16 23:12 lougreenwood

@lougreenwood contact me on our Slack to discuss further

sc0ttkclark avatar Dec 10 '16 02:12 sc0ttkclark