2012/7/12 Anthony Ferrara <ircmax...@gmail.com>: > Hello all, > > Since the discussion has died down around the concept, I have updated the > RFC and moved it into Proposed (under discussion) status. > > I have updated the RFC to include a section on discussion points containing > points that I know were raised but I felt were not closed (there was some > debate or disagreement). I tried to include a simple description of both > arguments, and the position the RFC currently takes and a brief reason why. > > https://wiki.php.net/rfc/password_hash > > Please have a look and provide any feedback!
Hello Anthony, I like your RFC. I can say this, because I wrote a similar project about a year ago as a PHP-class and came to the same results. No, that's not correct: Nearly the same results! There are small gaps between my results and the suggested. I explain in detail in order of "feeled priority". [I don't had a look into the current C implementation, because I want to keep my mind clean from the needs of the C-developers side: I want to focus on the PHP-developer side.] 1. The resulting string should have a version information. For example the first char. the example hash will look like "1$2y$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi", instead of "$2y$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi" Maybe it is legal to interpret a missing version as "this is version 1"? But it is important, that it has now a version for future-compatibility. This is, becaus encryption is developed since I program and will develop further within the next thousand years. With a version-information we can guarantee that the algorithms can work, even if the hash-format changes markable (because needed, because new unforseeable aspects of encryption come in focus). In my project, this version-information helped me to distinct between old password-hashes and new ones. [I think this is also a good argument against "password_hash() should have no defaults", because this is a more than obvious sign to everyone "hey, there could be a version 2, how will that look like?"] 2a) I'm not happy with the behavour to raise warnings. Maybe I'm splitting hairs, but if there is one error, the chance is by experience very big, that there is another. So, if a developer for example will not check the results of password_hash(), false is stored in the database. And if he makes a second error (and the chance is as said very big in this case), you may be able to log in with this or do other ugly stuff. Don't say "impossible". I've seen things... In my project I had really very good results, when I just throw exceptions in the case that something goes wrong. This is the highly visible sign for a bad developer, that he has made something wrong or for a customer, installing a new version, that he now has a big problem and should go back to the older version. I really want exceptions here, because they prevent such missuse very effective and cannot be overgone. By minimim it should stop execution, if the password_hash() or password_verify() is called wrong, because I think, this is more secure than just to continue, which is in my eyes definitily a mistake. Maybe I'm wrong and this behaviour will make it possible to hack the database? But I don't belive that... With other words: I think how to deal with warnings in this "potentially hazardous" methods needs a little bit more discussion and I'm currently not satisfied with it, because it doesn't prevent stupid errors. 2b) I don't like that the functions sometimes will return FALSE, sometimes NULL. Not logical for PHP-developer and will lead by guarantee to code which is checked wrong. Again: I would prefer to fetch exceptions. If this is not possible I want either NULL or FALSE as result for all functions, but not NULL or FALSE. 3a) I would await a function "password_algos()" (like hash_algos()), which returns me all available algorithms. The available algorithms should also be displayed in PHPINFO(). This is because I need to check, if the current version has built it in. 3b) I don't like the encryption of the algorithm ("2y", WTF, what's that? :) ). Look at the function hash_algos(). There are full qualified names of algorithms. Why don't use just the names? Is it, because of some more bytes needed? :) Ok, I mean: why not using a good name, so that someone can guess what it is, without knowing the docs? That's just my thinking as PHP-developer, because this is not logical for me to encrypt the encryption-algorithm. :) 3c) I think about changes. Password algorithms are a thing of changing over time. So I would like to have a function like "password_algo_info($algo)", which returns me as a developer a detailed information about what this algorithm needs to work propper and what the full description of this is (including e.g. an url, where I can look for more information), because I think that this is eventually a thing, which is extended rapidly and the documentation is to slow to go with it. Or you are working with an older version in which the algo works different. Not very important and maybe needs more discussion. But I think something is here better than nothing. Again: very low prio! 4a) I don't like the hole CONSTANT-stuff. I don't want to have a doozen of fixed CONSTANTS, because I don't need them. The only constant is, that the list of constants will rise. :) Ok, more serious: I really don't need a constant for a thing, which is currently known to be changed in future. If the password is always stored with the currently most secure algorithm I don't need that. And as a developer this is, what I want! I don't want to care about the details, I want to be sure, that this is the currently most secure way to do it. That's what I want. I don't want to know, which algorithms exists. I don't need to choose between them. I just use them, because some smarter guys than me have thought thouroughly about what is most secure. :) I can not think about an situation where I need to set it in my code under normal circumstances. And if I really need to choose an algorithm, it is better a configurable option in my program, thats just good style. (For example a configuration-file, or a call-option.) A constant means: It is fixed in my code. That's good, if it doesn't change. Another example: if I need to choose the algorithm as an administrator, I choose it in my admin-interface from a select-field. The value is then stored as as string and not as a constant-name. I need to create that list of available algorithms. I don't need constants. The only situations, where constants may be needed are, if you write a converter or something like that and even in this case constants won't make the code better or more secure, they only help to prevent silly programming mistakes. The real mistakes are: Development and Production have slightly different versions. Or you may have a big problem, if your IDE is not matching to the used PHP-version. If you have constants, you will never program arround that. If you don't you need to think about how it would be self-configuring... In short: No real need for constant (except that you get warnings, if you take a constant, which is not available, but see above: If needed, it will be in a config-file as text). It would be another situation, if this would be a feature, which will not change much over the time. But it will. I need to generate displayable lists and more intuitive algorithm names than just "2y". 4b) I don't like the idea to change a constant (PASSWORD_DEFAULT) with a new version of PHP. This may break in some ugly situation your hole PHP-update, because you didn't thought about this change. :) Again: I think, that chhoosing the best algorithm should normally not be the job of the developer. I don't see the need. But to make it possible I suggest to have a function "password_best_algo()" instead, which returns a name of password_algos(). Why a function instead of a constant? You can add a parameter "$version" to this function and in this case the function returns the best algorithm for that version of a password-hash. I think this is eventually important, but maybe I'm looking too far into the future or forgot to think this completly through. 5. I added something like "is_password_hash()", to check, if a hash has the right syntax (not semantic) to work with it. This prevents internally also, that hashes with version 2 can work together with the class for version 1. 6. This is hair-splitting again, but least important: I don't like the name "password*" for the functions. This is because the functions don't return a password. Impractical names will give (some less experienced developers) wrong ideas of what the functions may do. It should be clear: This is a hash-function, you fill in a password and get a hash. But "hash*" is already used. I have no good solution for that and it is not quite important, but how would it be with "pwhash*", "phash*" or "hashpass"? Something good to remember... Maybe needs further discussion, but as said: Not so important, maybe someone has a good idea... Some comments to the discussion points: password_make_salt() Is Not Needed: I like that function, because it can be used to generate a random password(). Just google for "generate password" to see what I mean. It should have a third mode, where the "/"-char is not included for that case, because it may make problems. Maybe it is also a good idea that you can pass a string, which includes the allowed chars for this function. And because it can be used for completly other things than just hashes or passwords I think renaming or an alias would be useful e.g. "str_random()". (UTF8?) password_needs_rehash() is not needed: I think it's needed. Think about 5 years from now: bcrypt() is found to be insecure. Now we have to rebuild the hash. Not possible over night. Could be done while logging in and checking if it needs rehashing with this function. Again: This are only suggestions from the sight of an experienced PHP-developer. It's totally clear, that you have another sight. But I hope they are helpful. Hope you are not too firm with me, I'm new to this list. :) -- Alexander Aulbach -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php