# [PROPOSED] password_hash RFC - Implementing simplified password hashing functions

- Thread: https://externals.io/message/61151
- Original archive: https://news-web.php.net/php.internals/61151
- Started by Anthony Ferrara on 2012-07-12T02:40:08+00:00
- Messages: 38
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/61151.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #61151 — Anthony Ferrara — 2012-07-12T02:40:08+00:00

URL: https://externals.io/message/61151#61151

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!

Thanks!

Anthony

---

## #61179 — Alex Aulbach — 2012-07-12T17:24:52+00:00

URL: https://externals.io/message/61151#61179 · In reply to: #61151

2012/7/12 Anthony Ferrara <ircmaxell@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

---

## #61180 — Nikita Popov — 2012-07-12T17:32:44+00:00

URL: https://externals.io/message/61151#61180 · In reply to: #61179

> 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"

See that 2y in the string? That's the version information. If a
different algorithm is used, a different string will be in there. This
also applies to changes to the algorithm itself. E.g. the 2y prefix is
already a modified version of the original bcrypt algorithm.

Nikita

---

## #61184 — Alex Aulbach — 2012-07-12T17:50:19+00:00

URL: https://externals.io/message/61151#61184 · In reply to: #61180

2012/7/12 Nikita Popov <nikita.ppv@gmail.com>:
> 
> > […]
>
> See that 2y in the string? That's the version information. If a
> different algorithm is used, a different string will be in there. This
> also applies to changes to the algorithm itself. E.g. the 2y prefix is
> already a modified version of the original bcrypt algorithm.
>
> Nikita

Cool. "y" is the algorithm? I just ask to be sure. :)

How do I know which version I'm using? Think about checking if I'm
able to handle this version-hashes. Or other things like "generate a
hash for version 1 instead of version 2, because I know what I'm
doing". I mean: We can just fail with verify, but it would be
sometimes great to know, why it fails. :)

-- 
Alex Aulbach

---

## #61186 — Stas Malyshev — 2012-07-12T18:32:17+00:00

URL: https://externals.io/message/61151#61186 · In reply to: #61151

Hi!

> https://wiki.php.net/rfc/password_hash

Looks good. The only question I have is for password_make_salt() - do we
need the user to specify length? I think length is defined by the
algorithm in the most cases.  Maybe convert it to password_make_salt(int
$salt_type = PASSWORD_SALT_BCRYPT, int $length)
with both arguments optional and one of salt types being
PASSWORD_SALT_OTHER which just generates given length?

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #61188 — Anthony Ferrara — 2012-07-12T18:34:45+00:00

URL: https://externals.io/message/61151#61188 · In reply to: #61186

Stas,

> https://wiki.php.net/rfc/password_hash
>
> Looks good. The only question I have is for password_make_salt() - do we
> need the user to specify length? I think length is defined by the
> algorithm in the most cases.  Maybe convert it to password_make_salt(int
> $salt_type = PASSWORD_SALT_BCRYPT, int $length)
> with both arguments optional and one of salt types being
> PASSWORD_SALT_OTHER which just generates given length?


My only heistation there is that SALT_* specifies the format. So all of the
 `crypt()` hashes would use that format (a-zA-Z0-9./). Perhaps the name is
bad, and it should be SALT_CRYPT instead (but this has the assumption that
salt formats will never change for `crypt()`)...

---

## #61189 — Anthony Ferrara — 2012-07-12T18:53:16+00:00

URL: https://externals.io/message/61151#61189 · In reply to: #61179

Alex,

First off, thanks for such a thorough reply!!!  Comments are inline.

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?"]
>

That's what $2y$ is for. It's a standard `crypt()` prefix algorithm
identifier. For example you can use $1$ for md5, $5$ for sha256 and $6$ for
sha512 algorithms. In the future, if new algorithms are added, it would be
added as a new prefix for `crypt()`...


> 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...
>

While I understand your point, I'm not sure that's as big of a deal. All it
takes is a simple if statement. It's not like a warning will be raised and
the hash will still be generated. If a warning is raised, it'll return
false. That's easy to check for, and IMHO more of a documentation problem
than a problem we should solve here...


> 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.
>

I want exceptions here too. But PHP doesn't use exceptions in its standard
library (aside from SPL), and I'm not sure this is a compelling enough case
to implement the first... I could be swayed, but I'm not sure the rest of
the team would.


> 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.
>

I think that halting execution if either function is called wrong is a bit
drastic. Again, I understand why, but I think it's a bit overkill in this
case...


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.
>

I don't either. But that's how the rest of the core works...


> 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.
>

That's a very good addition. It could be defined as such:

    array(
        NAME => constant_value
    )

So,

    array(
        'bcrypt' => `PASSWORD_BCRYPT` 
    )

I'll add that when I get a few minutes.

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. :)
>

It's the standard `crypt()` format, which is available in almost every single
programming language out there today. Which makes interoperability really
easy.

I would be very hesitant to invent our own format here, especially for the
interoperability standpoint. There are standards that exist, and unless
there's a *strong* reason not to use them, we should...


> 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!
>

I'm not sure why this needs to be a function. Wouldn't the documentation on
the internet be enough for this?


> 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. :)
>

And the common use-case should be that. But there are other use-cases that
are compelling enough to support. Use-cases such as requiring passwords to
be backwards compatible to older versions of PHP. Or requiring
compatibility with another environment (python, etc) which may not get the
new algorithm when PHP does. That's why the choice is there, and why it's
forced to be made by the developer...


> 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.
>

A documentation issue...


> 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.
>

A problem that password_get_algos would solve...


> ...snip...
>
> 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.
>

The password_best_algo() thought is intriguing, but I guess I don't see the
changing constant to be a big deal. It's an informed choice the developer
has to make, which is better than complicating the API by making it take 3
or 4 function calls to hash a password (IMHO)...


> 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.
>

There's no need. `password_get_info()` could be used for it, and I'm not sure
that there's even a valid use-case for such a function. Can you elaborate
over why you would use such a function?


> 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...
>

And password_hash($password) doesn't communicate that the function hashes a
password? If this is really an issue, please suggest a better prefix, as I
can't think of one that's better without being cryptic...


> 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?)
>

I've thought about passing in a string of allowed characters. The problem
with that is two fold:

1. It greatly increases the complexity of the algorithm for generating the
salt. Take a look at this:
https://github.com/ircmaxell/PHP-CryptLib/blob/master/lib/CryptLib/Core/BaseConverter.php

2. There's no usecase right now for salts that are of a different format
(but if one is found, it can be added). PBKDF2 would use a raw salt, and
all the other crypt algorithms would use the other format. Where's the
other need for salting?

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. :)
>

I hope I was not too firm either. I like some of the suggestions, and I
think some of them have real merit. But others concern me... Looking
forward to everyone else's thoughts...

Anthony

---

## #61190 — Alex Aulbach — 2012-07-12T22:10:56+00:00

URL: https://externals.io/message/61151#61190 · In reply to: #61189

2012/7/12 Anthony Ferrara <ircmaxell@gmail.com>:
> That's what $2y$ is for. It's a standard `crypt()` prefix algorithm
> identifier. For example you can use $1$ for md5, $5$ for sha256 and $6$ for
> sha512 algorithms. In the future, if new algorithms are added, it would be
> added as a new prefix for `crypt()`...

Ya, didn't know that - my lib was based on the hash-functions (5.3).
But I understand nearly.

Perhaps I oversee something, but how do I know, if I could process it
with this version of crypt?

> > […]
>
> I want exceptions here too. But PHP doesn't use exceptions in its standard
> library (aside from SPL), and I'm not sure this is a compelling enough case
> to implement the first... I could be swayed, but I'm not sure the rest of
> the team would.

Hum. I have arguments: developers tend to use the @-operator to
prevent disturbing error-messages. :)
Ok, serious: I don't like function where I cannot control what is
written to the logfiles.

For example: error messages in socket_open() can not be catched (its
quite difficult). But it's sometimes totally normal, that it will
fail. Think this is a design-failure in PHP, that it is so complicated
to catch the messages. But we go off-topic here.


> I think that halting execution if either function is called wrong is a bit
> drastic. Again, I understand why, but I think it's a bit overkill in this
> case...

Ok, it's a little bit too much and solves not the problem.


> > […]
>
>
>     array(
>         'bcrypt' => `PASSWORD_BCRYPT` 
>     )
>
> I'll add that when I get a few minutes.

Maybe more informations?

array(
  'bcrypt' => array(
        'id' => PASSWORD_BCRYPT,
        'default' => true,
        'name' => "BCrypt"
        'url' => "http://en.wikipedia.org/wiki/Bcrypt",
        'params' => array('cost','salt')
  )
)

Not elegant, but something like that's what I mean with the
algo_info()  .... self documention. see down...

> It's the standard `crypt()` format, which is available in almost every single
> programming language out there today. Which makes interoperability really
> easy.
>
> I would be very hesitant to invent our own format here, especially for the
> interoperability standpoint. There are standards that exist, and unless
> there's a *strong* reason not to use them, we should...

Sorry, just didn't know that. But was pure intention not to read too
much into the details.

Maybe something which should be documented carefully...

> > […]

> I'm not sure why this needs to be a function. Wouldn't the documentation on
> the internet be enough for this?

It's just an idea. Nothing really important, see above.


> > […]
>
> The password_best_algo() thought is intriguing, but I guess I don't see the
> changing constant to be a big deal. It's an informed choice the developer
> has to make, which is better than complicating the API by making it take 3
> or 4 function calls to hash a password (IMHO)...

I found no real need. Forget it. In an object-oriented context it
would make more sense.

> > […]
>
> There's no need. `password_get_info()` could be used for it, and I'm not sure
> that there's even a valid use-case for such a function. Can you elaborate
> over why you would use such a function?

I do not quite completly understand the version/algorithm here. I
think about fast checks for millions of hashes.
Hm. In my class, the string had a defined format. If it hadn't that
format, it needs to be converted. This function was to check that very
fast without parsing it. But yours is implemented in C, not PHP... if
you can check 50000 per minute with `password_get_info()` I think it is
fast enough. :)

> password? If this is really an issue, please suggest a better prefix, as I
> can't think of one that's better without being cryptic...

Indeed, I have no better suggestions.


-- 
Greets Alex

---

## #61193 — Ryan McCue — 2012-07-13T10:28:29+00:00

URL: https://externals.io/message/61151#61193 · In reply to: #61189

Anthony Ferrara wrote:
> I want exceptions here too. But PHP doesn't use exceptions in its standard
> library (aside from SPL), and I'm not sure this is a compelling enough case
> to implement the first... I could be swayed, but I'm not sure the rest of
> the team would.

Somewhat off-topic, but is there a reason why not? It seems to me that
introducing a new API without using PHP's best method of error handling
(IMHO) is a little silly.
-- 
Ryan McCue
<http://ryanmccue.info/

---

## #61211 — keisial@gmail.com — 2012-07-13T21:54:23+00:00

URL: https://externals.io/message/61151#61211 · In reply to: #61193

> Somewhat off-topic, but is there a reason why not? It seems to me that
> introducing a new API without using PHP's best method of error handling
> (IMHO) is a little silly.
I don't really trust exception throwing near password-managing functions.
Consider the following:

class UserLogin {
    var $loggedIn = false;
    function login() {
        $row = SELECT * FROM user WHERE username =
escape_string($_POST['user']) ;
        $this->checkPassword($row->password);
    }
    function checkPassword($pw_hash) {
        if (password_verify($_POST['password'], $pw_hash)
            $this->loggedIn = true;
    }
}

The codebase does no global exception handling (because it doesn't throw
exceptions itself),
and also nobody configured the server not to show errors/exceptions
(some say it was
purposely setup to show them).
 `password_verify()` "errors" if the parameters are not strings or the hash
doesn't match a
known hash format.
Which kind of error should you use? errors or exceptions? Provide a
reasoned answer.

---

## #61215 — Alex Aulbach — 2012-07-14T00:32:11+00:00

URL: https://externals.io/message/61151#61215 · In reply to: #61211

2012/7/13 Ángel González <keisial@gmail.com>:
> The codebase does no global exception handling (because it doesn't throw
> exceptions itself),
> and also nobody configured the server not to show errors/exceptions
> (some say it was
> purposely setup to show them).
> `password_verify()` "errors" if the parameters are not strings or the hash
> doesn't match a
> known hash format.
> Which kind of error should you use? errors or exceptions? Provide a
> reasoned answer.

Exceptions and a blank page/empty body for the user should be the default.

Because:
Think of it like a printer: If the printer has an error, it will not
continue to work, to avoid any break. The user needs to open all paper
trays, look into them and remove eventually the paper before the
printer can continue. For a login it's  the same kind of logic: If you
don't know what happened you need to look into any "tray". If you
implement more sensors (better exception handling), you may continue
without looking.

In detail:
- Normally the code has no error here. No real need for fetching exceptions.
- So, if there is an error, you don't know why (because you didn't fetch).
- Even if I know there was an error (password_hash() returns false): I
can not continue with any action, because I don't know why.
- If you don't know the reason of an error, it is in this case an
error to continue,
- which will be done automatically, if you don't fetch. Perfect.
- And  to make it not obvious for a hacker to get sufficient
informations about the type of exception, it is the most secure way to
display no information to a possible invader.

I know this will break current behaviour completly. But it's the most
secure way to do. And security is the reason of this discussion.
To implement this we need for example a special type of exception (e.
g. "interface non_displayable"), which will remove the error-messages.

-- 
Alex

---

## #61256 — Alex Aulbach — 2012-07-15T20:07:37+00:00

URL: https://externals.io/message/61151#61256

2012/7/14 Andrew Faulds <ajfweb@googlemail.com>:
> Well... if people have poorly configured servers spitting out debug
> info in production mode, I don't think it is our problem. It is
> theirs.

Do you want to make it secure or do you want to discuss?

-- 
Greetings Alex Aulbach

---

## #61257 — Daniel Convissor — 2012-07-15T21:09:24+00:00

URL: https://externals.io/message/61151#61257 · In reply to: #61189

Hi Anthony:

> I want exceptions here too. But PHP doesn't use exceptions in its standard
> library (aside from SPL)

DateTime uses exceptions.

--Dan

-- 
 T H E   A N A L Y S I S   A N D   S O L U T I O N S   C O M P A N Y
            data intensive web and database programming
                http://www.AnalysisAndSolutions.com/
        4015 7th Ave #4, Brooklyn NY 11232  v: 718-854-0335

---

## #61258 — keisial@gmail.com — 2012-07-15T21:21:24+00:00

URL: https://externals.io/message/61151#61258 · In reply to: #61256

> 2012/7/14 Andrew Faulds <ajfweb@googlemail.com>:
> > […]
> Do you want to make it secure or do you want to discuss?
Seems Andrew mail didn't get to the list.
Yes, production servers shouldn't be showing debug info. But we know
that a large fraction of them do.
As coder of a php application, I often can't set the configuration of
the system
where it will be installed. Sometimes not even the person installing it
can set
it correctly (eg. shared hostings), it can be changed under your foot
(eg. an update,
someone did so to debug a different application...) or even be set
explicitely (I
want my users to warn me when they see errors !).
If spitting out errors prevented XHTML validation, I wouldn't care that
much (obviously,
the code shouldn't generate the warning to begin with, but it's not a
big deal if users
were briefly shown it). But we are talking about passwords and password
hashes. Not
something you want to risk exposing. Specially when we are trying to
make a good
interface to encourage secure handling of passwords.


PS: Alex, your non-displayable exception would indeed work (although I
would make it
a class property).

---

## #61260 — Alex Aulbach — 2012-07-15T23:19:02+00:00

URL: https://externals.io/message/61151#61260 · In reply to: #61258

Ok. I think, I go too much off topic. Sorry.

But I want to repeat
- we never know in which context the program will run. And good
security means, thait it shouldn't care, in which context it runs.
- everything, which can go wrong will go wrong (Murphy); if there is
any chance to make it wrong, there will be someone, which make it
wrong. (and in this case they will point to PHP: "see, I have said it
is unsecure..." :) ).
- in security context this means: The hashes will be stolen/we can
login without password etc.
- No documentation or any other thing can prevent that
- So we need to do everything, which is possible to avoid it. The best
thing would be, that we can guarantee, that it is not possible.
- As positive side-effect we can have more possibilities in PHP :)


More off topic:
Let me explain that last sentence: I dont know exactly how this can be
implemented, but I think every warning, error and so on could be an
exception instead. Just an idea, but I think this can remove
complexity, because - even if I think the current error-handling is
quite well designed - it is a source of sercurity-problems (and some
other more or less ugly things). I think about a default
exception-handling which can be overridden (like the error-handlers).
Could be an interesting concept. :) And of course its something which
needs time.


-- 
Sevus
Alex Aulbach

---

## #61263 — Anthony Ferrara — 2012-07-16T00:13:11+00:00

URL: https://externals.io/message/61151#61263 · In reply to: #61260

Alex,

On Sun, Jul 15, 2012 at 7:19 PM, Alex Aulbach <alex.aulbach@gmail.com>wrote:

> Ok. I think, I go too much off topic. Sorry.
>
> But I want to repeat
> - we never know in which context the program will run. And good
> security means, thait it shouldn't care, in which context it runs.
>

Could you explain what you mean by context here? I'm not following...


> - everything, which can go wrong will go wrong (Murphy); if there is
> any chance to make it wrong, there will be someone, which make it
> wrong. (and in this case they will point to PHP: "see, I have said it
> is unsecure..." :) ).
> - in security context this means: The hashes will be stolen/we can
> login without password etc.
> - No documentation or any other thing can prevent that
>

You can not make something idiot proof. If you try, the universe will just
invent better idiots.

Instead, as long as the function works in a sane manner, and the
documentation reflects the edge-cases and concepts, I think it's fine.


> - So we need to do everything, which is possible to avoid it. The best
> thing would be, that we can guarantee, that it is not possible.
>

If that was the case, there would be no PHP or any other language for that
matter. You can't stop people from being stupid. What you can do however is
make the documentation and implementation so bloody easy to use that *I
didn't know* becomes the only sane excuse...


> - As positive side-effect we can have more possibilities in PHP :)
>
>
> More off topic:
> Let me explain that last sentence: I dont know exactly how this can be
> implemented, but I think every warning, error and so on could be an
> exception instead. Just an idea, but I think this can remove
> complexity, because - even if I think the current error-handling is
> quite well designed - it is a source of sercurity-problems (and some
> other more or less ugly things). I think about a default
> exception-handling which can be overridden (like the error-handlers).
> Could be an interesting concept. :) And of course its something which
> needs time.
>

The default exception handling can be overriden today:
http://us2.php.net/set_exception_handler

But I agree with your larger point. The only problem with it is that it
would take an engine wide shift to do. Which I think is out of scope for a
point release, and there's no reason (that I can see) to tie this
implementation to that shift. Let's implement this with the normal error
handling methods, and then handle it uniformly later...

Anthony

---

## #61296 — Alex Aulbach — 2012-07-16T13:40:02+00:00

URL: https://externals.io/message/61151#61296 · In reply to: #61263

Hi Anthony,

Sorry, I'm really off topic here. What I suggest here is just to think
about new ways to make PHP more secure - and I think how to work with
errors is an important thing in this case.
It's here, because the password-rfc is just a good example for
security. :) It's not critic to the RFC, which I like.


2012/7/16 Anthony Ferrara <ircmaxell@gmail.com>:
> > […]
>
> Could you explain what you mean by context here? I'm not following...

Hm. I mean configuration, or 32 vs. 64 bit. Someone could turn
display_errors off and complains seeingf only a blank page. The other
can complain about seeing stupid password-function-warnings in his
browser, because he turned it on. Someone could have installed an own
error-handler which will run crazy with those errors. Someone
complains, that the methods are not compiled in his version of PHP.
And so on. We don't know the context. Sometimes it could be more
secure to send errors to the users, sometimes not. Sometimes it's a
real failure, sometimes we can ignore it.

But here and now our focus is security. The question is: Which is the
most secure method to do something without knowing the context. I
think this can be decided in most times very well.

> > […]
>
>
> You can not make something idiot proof. If you try, the universe will just
> invent better idiots.

:) Yeah. But we won't make it fool proof, we want to make it secure.
Big difference, because this can be defined in some cases very well,
even if you don't know the context.

And again: We are off topic here; those are things, which cannot be
fixed by some methods in PHP. But for me it's obvious to speak about
it, when I speak about security.


> > […]
>
> If that was the case, there would be no PHP or any other language for that
> matter. You can't stop people from being stupid.

We cannot prevent stupidity, but we can prevent the impacts. Like with
my printer example: If the printer don't know what happend, he will
force to look into every printer-tray, before it will print again,
just because it is the most secure way.

I think, this should be default for PHP, too (but it's just my
opinion). Only if we know what we're doing, we can handle the error.
It should be something, which must be programmed, not configured. This
will avoid context.


> What you can do however is
> make the documentation and implementation so bloody easy to use that *I
> didn't know* becomes the only sane excuse...

Good docs is a part of good security. In this case it's also concepts
of handling errors. And much other stuff.

Again: This is off-topic. The RFC is very fine, it's a good work, I
like it! Really, I do! :)

But for me - as PHP-developer - it's like renewing all doors of a
house with newest technique, but forgetting the windows. :) Security
is a concept. My suggestions aren't perfect. Just want to talk about
it; I think those concepts need time.

-- 
Alex Aulbach

---

## #61299 — Andrew Faulds — 2012-07-16T13:45:37+00:00

URL: https://externals.io/message/61151#61299 · In reply to: #61296

We shouldn't neuter the language because some stupid people might do
stupid people. Use appropriate error handling, not inappropriate error
handling because it might catch someone out who has a poorly
configured server.


> Hi Anthony,
>
> Sorry, I'm really off topic here. What I suggest here is just to think
> about new ways to make PHP more secure - and I think how to work with
> errors is an important thing in this case.
> It's here, because the password-rfc is just a good example for
> security. :) It's not critic to the RFC, which I like.
>
>
> 2012/7/16 Anthony Ferrara <ircmaxell@gmail.com>:
> > […]
>
> Hm. I mean configuration, or 32 vs. 64 bit. Someone could turn
> display_errors off and complains seeingf only a blank page. The other
> can complain about seeing stupid password-function-warnings in his
> browser, because he turned it on. Someone could have installed an own
> error-handler which will run crazy with those errors. Someone
> complains, that the methods are not compiled in his version of PHP.
> And so on. We don't know the context. Sometimes it could be more
> secure to send errors to the users, sometimes not. Sometimes it's a
> real failure, sometimes we can ignore it.
>
> But here and now our focus is security. The question is: Which is the
> most secure method to do something without knowing the context. I
> think this can be decided in most times very well.
>
> > […]
>
> :) Yeah. But we won't make it fool proof, we want to make it secure.
> Big difference, because this can be defined in some cases very well,
> even if you don't know the context.
>
> And again: We are off topic here; those are things, which cannot be
> fixed by some methods in PHP. But for me it's obvious to speak about
> it, when I speak about security.
>
>
> > […]
>
> We cannot prevent stupidity, but we can prevent the impacts. Like with
> my printer example: If the printer don't know what happend, he will
> force to look into every printer-tray, before it will print again,
> just because it is the most secure way.
>
> I think, this should be default for PHP, too (but it's just my
> opinion). Only if we know what we're doing, we can handle the error.
> It should be something, which must be programmed, not configured. This
> will avoid context.
>
>
> > […]
>
> Good docs is a part of good security. In this case it's also concepts
> of handling errors. And much other stuff.
>
> Again: This is off-topic. The RFC is very fine, it's a good work, I
> like it! Really, I do! :)
>
> But for me - as PHP-developer - it's like renewing all doors of a
> house with newest technique, but forgetting the windows. :) Security
> is a concept. My suggestions aren't perfect. Just want to talk about
> it; I think those concepts need time.
>
> --
> Alex Aulbach
>
> --
> 
> 
>



-- 
Andrew Faulds (AJF)
http://ajf.me/

---

## #61308 — Alex Aulbach — 2012-07-16T14:28:19+00:00

URL: https://externals.io/message/61151#61308 · In reply to: #61299

2012/7/16 Andrew Faulds <ajfweb@googlemail.com>:
> We shouldn't neuter the language because some stupid people might do
> stupid people. Use appropriate error handling, not inappropriate error
> handling because it might catch someone out who has a poorly
> configured server.

I think it's not neutering, it's extending to a new level. Which is in
the beginning always uncomfortable. :)

And I think it depends on what architecture-features PHP should
follow. E. g. simpleness or security (security means often simpleness)
or ... or ...?

-- 
Alex Aulbach

---

## #61889 — Jonathan Bond-Caron — 2012-07-31T12:32:56+00:00

URL: https://externals.io/message/61151#61889 · In reply to: #61188

> 
> > […]


-- `password_hash()`

password_hash_rfc(string $password, int $algo, array $options = array())

My personal opinion is the api should be:

password_hash(string $password, string $secret = '', array $options =
array());

where $options['method'] = PASSWORD_METHOD_BCRYPT;

Some people mentioned that the method/algorithm in should be the api? What
was the problem if `crypt()` stores the actual method/algorithm in the hash?

Using this api, we let `crypt()` should a random salt value and we pick our
secret.

Say you have:
define('MY_HASHING_SECRET', 'hhtrg54~%$%4....long');
$password = '1234';

password_hash_rfc($password . MY_HASHING_SECRET, PASSWORD_METHOD_BCRYPT);
password_hash($password, MY_HASHING_SECRET);

Note here that in both cases we let `crypt()` generate a random salt that is
different for every password and store in the password.

But our 'secret' that is appended to every password is not stored in a
database for example, it's in some ways similar to a private key.

-- password_make_salt()

I would remove the need for this function.

I think it's important the api emphasizes the importance of keeping a
'secret' + has the added value that every password hash is different with a
 `crypt()` salt.

Thoughts?

---

## #61890 — Jonathan Bond-Caron — 2012-07-31T13:07:58+00:00

URL: https://externals.io/message/61151#61890 · In reply to: #61889

> Say you have:
> define('MY_HASHING_SECRET', 'hhtrg54~%$%4....long'); $password =
> '1234';
> 
> password_hash_rfc($password . MY_HASHING_SECRET,
> PASSWORD_METHOD_BCRYPT); password_hash($password, MY_HASHING_SECRET);
> 
> Note here that in both cases we let `crypt()` generate a random salt that
> is different for every password and store in the password.
> 
> But our 'secret' that is appended to every password is not stored in a
> database for example, it's in some ways similar to a private key.
> 
> -- password_make_salt()
> 

Another comment about this, the 'secret' in this case in somewhat similar
the 'purpose' of the salt:
http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf

S = purpose || rv
P = password

What I'm proposing is:
S = rv (random value from crypt)
P = password || purpose

In the end, it's the same thing we're feeding into the hash (more data/bits)

Whatever api is used, I think it's important to allow appending this purpose
or secret that's not stored directly in the final `crypt()` hash.

---

## #61891 — Anthony Ferrara — 2012-07-31T13:25:19+00:00

URL: https://externals.io/message/61151#61891 · In reply to: #61889

Jonathan,

On Tue, Jul 31, 2012 at 8:32 AM, Jonathan Bond-Caron <jbondc@openmv.com>wrote:

> 
> > […]
>
>
> -- `password_hash()`
>
> password_hash_rfc(string $password, int $algo, array $options = array())
>
> My personal opinion is the api should be:
>
> password_hash(string $password, string $secret = '', array $options =
> array());
>
> where $options['method'] = PASSWORD_METHOD_BCRYPT;
>
> Some people mentioned that the method/algorithm in should be the api? What
> was the problem if `crypt()` stores the actual method/algorithm in the hash?
>
> Using this api, we let `crypt()` should a random salt value and we pick our
> secret.
>
> Say you have:
> define('MY_HASHING_SECRET', 'hhtrg54~%$%4....long');
> $password = '1234';
>
> password_hash_rfc($password . MY_HASHING_SECRET, PASSWORD_METHOD_BCRYPT);
> password_hash($password, MY_HASHING_SECRET);
>
> Note here that in both cases we let `crypt()` generate a random salt that is
> different for every password and store in the password.
>
> But our 'secret' that is appended to every password is not stored in a
> database for example, it's in some ways similar to a private key.
>

Please see this section of the RFC:
https://wiki.php.net/rfc/password_hash#the_api_does_not_support_pepper


> -- password_make_salt()
>
> I would remove the need for this function.
>
> I think it's important the api emphasizes the importance of keeping a
> 'secret' + has the added value that every password hash is different with a
> `crypt()` salt.
>
> Thoughts?

---

## #61892 — Jonathan Bond-Caron — 2012-07-31T14:28:11+00:00

URL: https://externals.io/message/61151#61892 · In reply to: #61891

>
> RFC: 
> https://wiki.php.net/rfc/password_hash#the_api_does_not_support_pepper
> 

Thanks, I missed it... 

I strongly disagree with this, the 'pepper' IMHO is a best practice for web
applications. 

I prefer to live with the idea that an attacker may comprise some
database(s) in the 'cloud' but not the physical machine where you can store
the pepper either in a file, share memory etc... 

As far as missing research papers, it's hard to do research on the benefit
of keeping something private. If/when databases do get hacked, it's rarely
released to the public how it happened.

When it comes to web applications, my opinion is odds are greater in SQL
injection / data theft success then gaining physical access to the machine.
#1 SQL Injection: https://www.owasp.org/index.php/Top_10_2010

Sure it's an added layer of security but it's hard to deny the 'pepper'
can't help protect passwords against the #1 risk for php/web applications.


A pepper in UNIX `crypt()` itself would be obviously useless, the user already
has access to the physical machine (cat /etc/passwd).

---

## #61893 — Nikita Popov — 2012-07-31T14:44:24+00:00

URL: https://externals.io/message/61151#61893 · In reply to: #61892

> Thanks, I missed it...
>
> I strongly disagree with this, the 'pepper' IMHO is a best practice for web
> applications.
>
> I prefer to live with the idea that an attacker may comprise some
> database(s) in the 'cloud' but not the physical machine where you can store
> the pepper either in a file, share memory etc...
>
> As far as missing research papers, it's hard to do research on the benefit
> of keeping something private. If/when databases do get hacked, it's rarely
> released to the public how it happened.
>
> When it comes to web applications, my opinion is odds are greater in SQL
> injection / data theft success then gaining physical access to the machine.
> #1 SQL Injection: https://www.owasp.org/index.php/Top_10_2010
>
> Sure it's an added layer of security but it's hard to deny the 'pepper'
> can't help protect passwords against the #1 risk for php/web applications.
>
>
> A pepper in UNIX `crypt()` itself would be obviously useless, the user already
> has access to the physical machine (cat /etc/passwd).

If you really want to use a secret you should encrypt the resulting
password hash with a proper encryption algorithm. Hashing algorithms
are not designed for this purpose.

Nikita

---

## #61894 — Anthony Ferrara — 2012-07-31T14:54:48+00:00

URL: https://externals.io/message/61151#61894 · In reply to: #61892

On Tue, Jul 31, 2012 at 10:28 AM, Jonathan Bond-Caron <jbondc@openmv.com>wrote:

> > […]
>
> Thanks, I missed it...
>
> I strongly disagree with this, the 'pepper' IMHO is a best practice for web
> applications.
>

Again, I have not seen this being said by any security or cryptography
expert.


> I prefer to live with the idea that an attacker may comprise some
> database(s) in the 'cloud' but not the physical machine where you can store
> the pepper either in a file, share memory etc...
>

Ok. So I register an account before I get the database. Now the only thing
that I need to crack is the pepper (since I know the salt, hash and
original password for my sentinel account).


> As far as missing research papers, it's hard to do research on the benefit
> of keeping something private. If/when databases do get hacked, it's rarely
> released to the public how it happened.
>

It's very easy to do research on that. There are mathematical proofs that
encryption is secure if the secret is secure. I've yet to see that done
with a "pepper" used in the manner that you're requesting...


> When it comes to web applications, my opinion is odds are greater in SQL
> injection / data theft success then gaining physical access to the machine.
> #1 SQL Injection: https://www.owasp.org/index.php/Top_10_2010


Wrong. OWASP #1 is not SQL Injection. It's Injection. Including SQL
Injection, but also including other forms of injection (header injection,
script injection, etc).

And that doesn't count that many use SQL Injection as a gateway
towards privilege escalation which on many systems will hand them access to
the file-system...


>
> Sure it's an added layer of security but it's hard to deny the 'pepper'
> can't help protect passwords against the #1 risk for php/web applications.
>

I'm not denying the concept. I'm denying the implementation.The existing
algorithms expect to see a password. Not a password concatenated with a
secret. Sure, it sounds logical that it would make it more secure. But
cryptography is not based on what sounds logical. It's based on what's
proven. And if it's not proven, it's deemed to be insecure until proven
otherwise.

If you want to do it in your code, that's one thing. But unproven
cryptography has no business in a language level implementation.

Furthermore,

That link that you posted actually explains things quite a bit. The salt
value that's indicated there is actually defined as:

A non-secret binary value that is used as an input to the key
derivation function PBKDF specified in this Recommendation to
allow the generation of a large set of keys for a given password.

Now, what does that mean? To understand that, we need to understand what a
secret is. A secret is basically a piece of information that the algorithm
relies upon for security. Meaning that the algorithm is not secure if the
secret is known. A non-secret piece of information is one that the security
of the algorithm is not dependent upon. So encryption requires a secret, as
the security of the encryption depends on the key being secret (if it's
exposed, all security is broken). Since hashing is designed to use a
non-secret salt, the security of the hashing algorithm does not depend on
it being secret.



With all of that said, if you really want a secret in there, don't hijack
the hashing algorithm to do it. There are two somewhat decent alternatives:

HMAC the password with the secret prior to passing it to
 `password_hash()`/crypt().  HMAC is secure and is designed for this exact
purpose.

Or,

Encrypt the resulting hash with a secure encryption function (RIJNDAEL_128
+ CBC) prior to inserting it in the database. That way, each component uses
standard algorithms as they were designed to be used.

But I want to stress something else. Properly managing secrets is VERY
difficult. It's not even really possible in PHP, due to the way
copy-on-write works, and how variables are removed. To implement this sort
of a system correctly is not something even highly competent developers can
typically do. It really is that difficult to get right.

Anthony

---

Next page: https://externals.io/message/61151.md?page=2
