Hi Nikita, Andrey and all,
My apologies, I misread mails by super sloppy reading.
I'll explain basis by my idea clearly and properly this time.
This mail is long.
Basis of my idea is
- Salt is made to optional only for applications that such value is not
available. (From RFC 5869) - Omitting salt could lead to security disaster. i.e. password leak.
- Combined key, output key and salt, as final key(combined key) is common
in many use cases. - Many HKDF applications with PHP must/should have salt for better
implementation. - API should encourage "salt" use by its signature. (From RFC 5869)
Ref: https://tools.ietf.org/html/rfc5869
Before restart discussion, there should be rationale for others.
In theory, cryptographic hashes are cryptographically secure. Therefore,
following operations should be considered as secure by definition.
$new_key = sha1('some original key' . 'strong salt' . 'some info');
$signature = sha1('some data' . 'strong key');
However, in real world, people come up with better idea for cryptographic
hashes. Sometimes people invent efficient way to attack cryptographic
hashes.
HMAC is known and proven method to generate more secure signature.
Therefore,
$signature = hash_hmac('sha1', 'some data', 'some key');
is secure even when cryptographic hash had minor defect(s).
HKDF is made to generate secure new keys from existing key suitable
for required operations by using HMAC.
HKDF inputs
- IKM, input key which may be weak or strong
- salt, some entropy which makes HKDF stronger overall, may be secret or
non secret/weak or strong. - info, which specifies HKDF contexts that are non secret usually. e.g. a
protocol number, algorithm identifiers, user identities, etc. - length(L), output key length
HKDF calculates output key(OKM) as follows
Extract step
PRK = HMAC-Hash(salt, IKM)
This step is designed to make strong output key(OKM) and PRK always.
OKM to be secure, either IKM or salt must be strong.
Expand step
N = ceil(L/HashLen)
T = T(1) | T(2) | T(3) | ... | T(N)
OKM = first L octets of T
where:
T(0) = empty string (zero length)
T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
Note: OKM is output key material that is return value from HKDF.
This step is designed to make derived key have the length(L) from
strong key(PRK) generated by Extract step. Key context(info) is
distinguished by this step also.
Both salt and info is optional, but RFC 5869 states differently.
"HKDF is defined to operate with and without random salt. This is
done to accommodate applications where a salt value is not available.
We stress, however, that the use of salt adds significantly to the
strength of HKDF, ensuring independence between different uses of the
hash function, supporting "source-independent" extraction, and
strengthening the analytical results that back the HKDF design."
This statement implies salt is almost mandatory parameter for HKDF
when salt can be used. In contrast, info is described as pure optional
parameter for key context.
"While the 'info' value is optional in the definition of HKDF, it is
often of great importance in applications. Its main objective is to
bind the derived key material to application- and context-specific
information. For example, 'info' may contain a protocol number,
algorithm identifiers, user identities, etc."
With regard to mandatoriness parameters, strong salt is mandatory to derive
cryptographically strong key when input key is weak, while info/length is
optional always.
In addition, it is common that salt being used as a part of combined keys.
Salt is mandatory for such applications. There are many authentication
implementations that use
- key which does not disclose original key by hashing
- nonce(salt)
Access permission with timeout is another typical usage that requires
timestamp as salt and combined key.
HKDF can produce secure key, which protects input key(IKM) and
generates strong output key (OKM), but this is true only when
IKM or salt is strong. Use of weak IKM and salt could lead password leak.
For above reasons, I'm proposing change
string hash_hkdf(string $hash, string $ikm [, int $length=0 [, string
$info='' [, string $salt='']]])
to
string hash_hkdf(string $hash, string $ikm, string $salt [, string
$info='' [, int $length=0 ]])
- To omit salt, $salt=NULL. $salt='' raise exception.
Making the salt required makes no sense to me.
HKDF has a number of different applications:
a) Derive multiple strong keys from strong keying material. Typical case
for this is deriving independent encryption and authentication keys from a
master key. This requires only specification of $length. A salt is neither
necessary nor useful in this case, because you start with strong
cryptographic keying material.
Very true.
Shorter password would hide IKM/salt/info state, so shorter output
key could be said more secure. e.g. SHA512 and 32 bytes output key
This is only applicable when IKM and/or salt is strong, though.
If we could assume IKM to be always cryptographic
Extract step
PRK = HMAC-Hash(salt, IKM)
is not needed, but only
T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
In short, if key is strong,
hash_hmac('sha256', $key, 1)
substr(hash_hmac('sha256', $key, 1), 0, $length)
is good enough. Thus, HKDF is not needed.
But in real world, IKM does not have to be cryptographically secure.
Therefore, HKDF users must ensure secure PRK by
PRK = HMAC-Hash(salt, IKM)
This requirement makes "salt" more important than "length" because
strong PRK is mandatory for HKDF security. i.e. IKM or salt must be
strong always.
For the same reason as "Apply HTML escape for all vars", random salt
regardless of key strength whenever possible, is safer. It prevents
weak IKM leak by misuse effectively.
b) Generating per-session (or similar) keys from a (strong cryptographic)
master key. For this purpose you can specify the $info parameter. again, a
salt is neither necessary nor useful in this case. (You could probably also
use $salt instead of $info in this case, but the design of the function
implies that $info should be used for this purpose.)
Assuming
$_SESSION['master_key'] = random_bytes(80); // Keep this for this
session.
and current hash_hkdf()
function signature
string hash_hkdf(string $hash_function, string $ikm, [int $length [,
string $info [, string $salt]]]);
Your idea might be
$new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0,
session_id()
);
Although it works. Session ID is not identity, but key that identifies
user's
connection. Key(entropy) value for info parameter violates the RFC
recommended
info usage.
OR
You might be assuming logged in session, then username can be used as info
parameter.
$new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0,
$_SESSION['username']);
username is non secret user identifier. This usage matches RFC recommended
usage.
However, username is only available for logged in session, when username is
changed
during session it stops working. It stops working at logout also. And most
important of all,
this is not a per-session, but per-user...
The RFC compliant implementation with PHP is to use session_id()
as secret
salt.
$new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0, '',
session_id()
);
This method is better because it works regardless of authentication/changed
username. However, this version still has problem with regenerated session
ID.
This could be fixed with better salt.
$_SESSION['salt'] = session_create_id()
;
then
$new_key = hash_hkdf('sha256', $_SESSION['master_key'], 0, '',
$_SESSION['salt']);
This works for any session always. Both $new_key and $_SESSION['salt']
could be
safely passed as page content unlike session_id()
as salt.
I have other examples like these that illustrates, users should consider
salt usage.
c) Extracting strong cryptographic keying material from weak cryptographic
keying material. Standard example here is extracting strong keys from DH
g^xy values (which are non-uniform) and similar. This is the usage that
benefits from a $salt.
Even when strong IKM is used, low entropy salt like timestamp can be used
as combined key. This use case would be one of the most used with PHP.
Remember that HKDF is an extract-and-expand algorithm, and the extract step
(which uses the salt) is only necessary if the input keying material is
weak. We always include the extract step for compatibility with the overall
HKDF construction (per the RFCs recommendation), but it's essentially just
an unnecessary operation if you work on strong keying material.
I presume reply to a) should be sufficient for this.
Strong(cryptographic) key, e.g. random_bytes(80), can be used in many
cases.
Even when key supposed to be strong key, it would be better
to use salt to derive even stronger key. This practice will prevent
users to omit salt for weak input keys accidentally.
Slat could be used as combined key also.
The only thing that we may want to discuss is whether we should swap the
$info and the $salt parameters. This depends on which usage (b or c) we
consider more likely.
"length" has little relevance with respect to IKM protection and output key
(OKM)
security. While it is user's responsibility to ensure secure PRK and
protect
IKM by
Extract step
PRK = HMAC-Hash(salt, IKM)
HKDF info parameter is unrelated to IKM protection and output key as per
the RFC,
but salt has the responsibility. Therefore, "salt" must have priority over
"info" and
"length", IMHO.
Importance with regard to security: salt >>>> info > length
We also must consider how output key and salt is used in real world PHP
applications.
There are applications that use output key and salt as combined key.
e.g. authentication, access key with expiration
// URL access key with expiration
$expire = `time()` + 90; // 90 sec timeout. Low entropy salt is allowed
with strong IKM.
$key = hash_hkdf('sha256', $_SESSION['strong_master_key'], 0, $URL,
$expire);
// Send $key and $expire as combined key for $URL
hash_hkdf()
is key generation function and output key and salt are used as
"combined key" in many use cases. Parameter being as key is important.
Therefore,
commonly used combined key(salt) is better to locate after IKM.
Importance with regard to common use case: salt >> info > length
Although there are HKDF usage without salt, many HKDF applications with PHP
require or are better with salt. e.g. Previous per-session encryption.
Developers
will develop better application if they consider how salt could be used.
Therefore,
salt is better to be required parameter and omit it only when salt cannot
be used.
Importance with regard to education: salt >>> info > length
(User must learn safe salt usage)
"length" is the least for me. "salt" and "info" has important effect for
derived
key/input key security. These 2 should have priority over "length".
Making the most responsible/sensitive parameter(salt) which is currently
optional
to required parameter should not be a issue for users.
If it is C, I don't care and accept whatever signature. C is full of pit
holes already. I just don't want to see news, "Passwords are stolen from
PHP
app!". hash_hkdf()
is could be misused easily like
hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily,
Nice!
hash_hkdf('sha256', $weak_ikm, 9, 'Super User Only'); // Safe key for super
user
hash_hkdf('sha256', $strong_ikm, 4); // Secure and nice password for super
secret
These are security disaster. If salt is required, users would always think
about it
at least. Length should not be shortened unless user is absolutely sure.
If there are unclear sentences, please let me know.
Thank you for reading long mail!
Regards,
P.S. I'll be more careful, but I become very sloppy mail reader sometimes.
I appreciate if you could let know via private email. Thank you!
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Nikita, Andrey and all,
<snip>
Regards,
P.S. I'll be more careful, but I become very sloppy mail reader sometimes.
I appreciate if you could let know via private email. Thank you!--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi,
Although there are HKDF usage without salt, many HKDF applications with PHP
require or are better with salt. e.g. Previous per-session encryption.
Developers
will develop better application if they consider how salt could be used.
Therefore,
salt is better to be required parameter and omit it only when salt cannot
be used.
---
One such real-world use case: Defuse v1 used HKDF without a salt.
https://github.com/defuse/php-encryption/blob/b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L157-L170
https://github.com/defuse/php-encryption/blob/b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L358
In version 2, we included a 32-byte random salt for each encryption, which
was stored next to the AES-256-CTR nonce in the ciphertext. (Both the nonce
and HKDF-salt, as well as the version information header, are covered by
the HMAC of the ciphertext.)
The end result: Instead of having to worry about birthday collisions after
you've seen 2^64 AES outputs (because 128-bit randomly generated nonce),
now you need 2^192 before you have a useful collision.
Although the RFC itself says that salts are optional, the argument to make
them required in PHP's implementation has merit. The only downside is: If
you're integrating with an implementation that doesn't require salts, and
the application doesn't use salts, you're out of luck. Is that enough of a
downside to dismiss an argument for better security? Maybe.
Scott Arciszewski
Chief Development Officer
Paragon Initiative Enterprises https://paragonie.com/
Hi Scott,
On Wed, Feb 8, 2017 at 5:22 AM, Scott Arciszewski scott@paragonie.com
wrote:
One such real-world use case: Defuse v1 used HKDF without a salt.
https://github.com/defuse/php-encryption/blob/
b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L157-L170
https://github.com/defuse/php-encryption/blob/
b87737b2eec06b13f025cabea847338fa203d1b4/Crypto.php#L358In version 2, we included a 32-byte random salt for each encryption, which
was stored next to the AES-256-CTR nonce in the ciphertext. (Both the nonce
and HKDF-salt, as well as the version information header, are covered by
the HMAC of the ciphertext.)The end result: Instead of having to worry about birthday collisions after
you've seen 2^64 AES outputs (because 128-bit randomly generated nonce),
now you need 2^192 before you have a useful collision.Although the RFC itself says that salts are optional, the argument to make
them required in PHP's implementation has merit. The only downside is: If
you're integrating with an implementation that doesn't require salts, and
the application doesn't use salts, you're out of luck. Is that enough of a
downside to dismiss an argument for better security? Maybe.
There are applications that do not require salt. In this case, all users
has to do is
$salt = NULL
to omit $salt.
Current signature has $length as the first optional parameter which would
be set
to "0" in many cases if not most. i.e. Just deriving new key from strong
$ikm would
not be typical.
Requiring "$salt = NULL" to omit salt would not hurt API use much compare
to
current signature that requires "$length = 0" for most cases, I suppose.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Forgot to mention the most important.
Is that enough of a downside to dismiss an argument for better security?
Maybe
I suppose so.
It is very clear that "salt" is the most important for derived key security,
"info" is next, then "length".
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi,
On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski scott@paragonie.com
wrote:
Although the RFC itself says that salts are optional, the argument to make
them required in PHP's implementation has merit. The only downside is: If
you're integrating with an implementation that doesn't require salts, and
the application doesn't use salts, you're out of luck. Is that enough of a
downside to dismiss an argument for better security? Maybe.
I said this in another thread already, but I'll re-iterate here ... Using a
salt should be recommended, but the suggestion here takes that out of
context and misses a key point - that the Length and Info params are not of
any less importance overall.
- Length is effectively the key size and is in fact not optional in
RFC5869*. You have to really know what you're doing if you don't use it,
and choose the hash function very carefully. I'd argue that if you know
this well enough, you'd also know what to do with Salt. - Info is technically optional, but pretty much the feature why you'd
choose HKDF over other KDFs. It's what makes HKDF's more useful in that it
enables derivation of multiple OKMs from a single IKM. If you don't need
Info, chances are you don't need HKDF.
One could use Salt for the purposes of Info, but that would be misusing the
algorithm.
Over-focusing on Section 3.1 of the specification, while at the same time
ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because
the note about it mentions the word "security". Noble, but misguided.
I'd have no problem if ALL of the params were made non-optional - I'm all
for that, but either do that or leave it untouched.
- RFC 5869: https://tools.ietf.org/html/rfc5869
Cheers,
Andrey.
Hi Scott,
There are applications that do not require salt. In this case, all users
has to do is
$salt =NULL
to omit $salt.
Great.
Hi,
On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski scott@paragonie.com
wrote:Although the RFC itself says that salts are optional, the argument to
make them required in PHP's implementation has merit. The only downside is:
If you're integrating with an implementation that doesn't require salts,
and the application doesn't use salts, you're out of luck. Is that enough
of a downside to dismiss an argument for better security? Maybe.I said this in another thread already, but I'll re-iterate here ... Using
a salt should be recommended, but the suggestion here takes that out of
context and misses a key point - that the Length and Info params are not of
any less importance overall.
- Length is effectively the key size and is in fact not optional in
RFC5869*. You have to really know what you're doing if you don't use it,
and choose the hash function very carefully. I'd argue that if you know
this well enough, you'd also know what to do with Salt.- Info is technically optional, but pretty much the feature why you'd
choose HKDF over other KDFs. It's what makes HKDF's more useful in that it
enables derivation of multiple OKMs from a single IKM. If you don't need
Info, chances are you don't need HKDF.One could use Salt for the purposes of Info, but that would be misusing
the algorithm.
Over-focusing on Section 3.1 of the specification, while at the same time
ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because
the note about it mentions the word "security". Noble, but misguided.I'd have no problem if ALL of the params were made non-optional - I'm all
for that, but either do that or leave it untouched.
- RFC 5869: https://tools.ietf.org/html/rfc5869
Cheers,
Andrey.
Given everything discussed in this sub-thread so far, I would be in favor
of making everything non-optional.
Scott Arciszewski
Chief Development Officer
Paragon Initiative Enterprises https://paragonie.com/
Hi all and Scott,
On Wed, Feb 8, 2017 at 11:22 PM, Scott Arciszewski scott@paragonie.com
wrote:
Hi,
On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski scott@paragonie.com
wrote:Although the RFC itself says that salts are optional, the argument to
make them required in PHP's implementation has merit. The only downside is:
If you're integrating with an implementation that doesn't require salts,
and the application doesn't use salts, you're out of luck. Is that enough
of a downside to dismiss an argument for better security? Maybe.I said this in another thread already, but I'll re-iterate here ... Using
a salt should be recommended, but the suggestion here takes that out of
context and misses a key point - that the Length and Info params are not of
any less importance overall.
- Length is effectively the key size and is in fact not optional in
RFC5869*. You have to really know what you're doing if you don't use it,
and choose the hash function very carefully. I'd argue that if you know
this well enough, you'd also know what to do with Salt.- Info is technically optional, but pretty much the feature why you'd
choose HKDF over other KDFs. It's what makes HKDF's more useful in that it
enables derivation of multiple OKMs from a single IKM. If you don't need
Info, chances are you don't need HKDF.One could use Salt for the purposes of Info, but that would be misusing
the algorithm.
Over-focusing on Section 3.1 of the specification, while at the same time
ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because
the note about it mentions the word "security". Noble, but misguided.I'd have no problem if ALL of the params were made non-optional - I'm all
for that, but either do that or leave it untouched.
- RFC 5869: https://tools.ietf.org/html/rfc5869
Cheers,
Andrey.Given everything discussed in this sub-thread so far, I would be in favor
of making everything non-optional.
I'm OK with making 'salt' and 'info' required. Users should
consider 'info'(key context) could be used almost always before
omitting it.
I suppose most developers will use 'length' for shorter length.
i.e. Weaker output keys. If it's not too short, shorter key length works.
I'm not sure if shorter output key length, that would weaken the key,
does any good in general .
Note: longer output key does not make output key stronger. It may
hide used hash function, though.
Most use cases would be AWS S3 pre-signed URL like
usage that users do not have to care long keys. With such
use cases, users are better to use key as is. i.e. Use default
hash output length.
There may be vote option for length, but I'm in favor of leave
it as optional. I do care about parameter order, but what to be
required is not too much concern to me.
Regards,
BTW, I don't think of typical PHP application that requires
human typable short password with HKDF. What kind of
application would be? Thank you.
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Yasuo,
The fact that you continue to talk about passwords and other low-entropy
data as IKM shows, yet again, that you don't understand HKDF.
It is simply not a password-based KDF; if you want that - use PBKDF2.
Please read Section 4* of the spec:
https://tools.ietf.org/html/rfc5869.html#section-4
In fact, at one point I suggested the function be named just 'hkdf()' as a
way of discouraging such misuse, because a lot of people associate the word
"hash" with password handling.
And this ...
I suppose most developers will use 'length' for shorter length.
i.e. Weaker output keys. If it's not too short, shorter key length works.
Shows that you shouldn't be trusted with anything related to cryptography
either.
I may be no cryptographer myself, but one thing I know for sure is that
shorter than required key lengths are never ok, and most encryption
algorithms have a fixed key length.
Also, this is the last time I reply to you on this topic. You're just
impossible to reason with.
Cheers,
Andrey.
Hi Andrey,
How the manual page would be. Would it be
"Even though 'slat' is the last optional parameter that users may omit
easily
by mistake, users must set strong salt for weak $ikm. This is
mandatory
requirement for HKDF to work. In addition, it is advices to set salt
whenever
possible as RFC 5689 recommends"
It can't make sense for new function.
The fact that you continue to talk about passwords and other low-entropy
data as IKM shows, yet again, that you don't understand HKDF.
It is simply not a password-based KDF; if you want that - use PBKDF2.
Please read Section 4* of the spec: https://tools.ietf.org/html/
rfc5869.html#section-4
PHP would not be a language that builds low level crypto library/feature.
I'm not sure what you mean by this. What sentences you refer as I don't
understand?
I assumed you would like to derive human typable password because
you prefer to have the most priority for "length". Do you have any typical
"length" use with PHP?
HKDF relies on PRK being cryptographically strong.
Extract step
PRK = HMAC-Hash(salt, IKM)
You should understand users must make sure either "salt" or "IKM" is
strong for HKDF to work. Since hash_hkdf()
is generic function, you never
can make sure IKM to be strong always.
With this fact alone, salt must have the most priority.
In fact, at one point I suggested the function be named just 'hkdf()' as a
way of discouraging such misuse, because a lot of people associate the word
"hash" with password handling.
And this ...
I suppose most developers will use 'length' for shorter length.
i.e. Weaker output keys. If it's not too short, shorter key length works.Shows that you shouldn't be trusted with anything related to cryptography
either.
I may be no cryptographer myself, but one thing I know for sure is that
shorter than required key lengths are never ok, and most encryption
algorithms have a fixed key length.
Are you assuming converting crypto keys to be other length would be
the typical HKDF usage with PHP?
Then, I have to say your assumption is wrong.
It would be most used for CSRF key generation, object access
control, e.g. AWS S3 presigned URL, or anything related to web
app, not low level crypto.
Discussion so far would not justify use of vulnerable, i.e. PRK could
be weak very easily, signature.
And you don't answer questions to you:
Why you recommends following usage?
hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily,
Nice! <= Must not do this.
What's the reason why you trying to disregard RFC 5869 strongly recommends?
Parameter order must reflect
- importance of the parameter
- likelihood to be used
Salt is the most important for both input and output key security.
Salt is mandatory and/or can be used for almost always with PHP.
Salt usage results in better design/security.
Salt is often used as final key as combined key.
Does 'length' and/or 'info' achieve or designed for aboves? I don't think
so.
BTW, I don't think of typical PHP application that requires
human typable short password with HKDF. What kind of
application would be?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Andrey,
How the manual page would be. Would it be
"Even though 'slat' is the last optional parameter that users may omit
easily
by mistake, users must set strong salt for weak $ikm. This is
mandatory
requirement for HKDF to work. In addition, it is advices to set salt
whenever
possible as RFC 5689 recommends"It can't make sense for new function.
The fact that you continue to talk about passwords and other low-entropy
data as IKM shows, yet again, that you don't understand HKDF.
It is simply not a password-based KDF; if you want that - use PBKDF2.
Please read Section 4* of the spec: https://tools.ietf.org/html/rf
c5869.html#section-4PHP would not be a language that builds low level crypto library/feature.
I'm not sure what you mean by this. What sentences you refer as I don't
understand?I assumed you would like to derive human typable password because
you prefer to have the most priority for "length". Do you have any typical
"length" use with PHP?HKDF relies on PRK being cryptographically strong.
Extract step
PRK = HMAC-Hash(salt, IKM)You should understand users must make sure either "salt" or "IKM" is
strong for HKDF to work. Sincehash_hkdf()
is generic function, you never
can make sure IKM to be strong always.With this fact alone, salt must have the most priority.
In fact, at one point I suggested the function be named just 'hkdf()' as
a way of discouraging such misuse, because a lot of people associate the
word "hash" with password handling.And this ...
I suppose most developers will use 'length' for shorter length.
i.e. Weaker output keys. If it's not too short, shorter key length
works.Shows that you shouldn't be trusted with anything related to cryptography
either.
I may be no cryptographer myself, but one thing I know for sure is that
shorter than required key lengths are never ok, and most encryption
algorithms have a fixed key length.Are you assuming converting crypto keys to be other length would be
the typical HKDF usage with PHP?
Then, I have to say your assumption is wrong.It would be most used for CSRF key generation, object access
control, e.g. AWS S3 presigned URL, or anything related to web
app, not low level crypto.Discussion so far would not justify use of vulnerable, i.e. PRK could
be weak very easily, signature.And you don't answer questions to you:
Why you recommends following usage?
hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily,
Nice! <= Must not do this.
What's the reason why you trying to disregard RFC 5869 strongly recommends?
Parameter order must reflect
- importance of the parameter
- likelihood to be used
Salt is the most important for both input and output key security.
Salt is mandatory and/or can be used for almost always with PHP.
Salt usage results in better design/security.
Salt is often used as final key as combined key.Does 'length' and/or 'info' achieve or designed for aboves? I don't think
so.
BTW, I don't think of typical PHP application that requires
human typable short password with HKDF. What kind of
application would be?Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi,
HKDF relies on PRK being cryptographically strong.
Yes, but not for the reasons you might suspect.
The main use case of HKDF is to completely prevent related-key attacks,
while splitting a single key into several for domain-specific purposes.
Figuring out a subkey (by sheer luck) should also not give an attacker
enough information to recreate the IKM.
HKDF isn't meant for key stretching (e.g. use an 80-bit secret in an
application that requires a 256-bit secret). That's what a password hashing
function is for. (Bcrypt, Argon2, etc.)
You should understand users must make sure either "salt" or "IKM" is
strong for HKDF to work. Since hash_hkdf()
is generic function, you never
can make sure IKM to be strong always.
Not quite. IKM has to be strong. The salt? Not so much.
In cryptography protocols, salts are considered public information (even if
you don't go out of your way to publish it).
If you have a weak IKM but a strong salt (32 bytes from random_bytes()
),
you should still consider the OKM weak.
Salt is the most important for both input and output key security.
Salt is mandatory and/or can be used for almost always with PHP.
Salt usage results in better design/security.
Salt is often used as final key as combined key.
Don't get me wrong: Having secure random salts is useful (serves as a
useful way to enlarge the effective nonce in a symmetric encryption
protocol).
But the cryptographic secret in this protocol is IKM. Not the salt.
Scott Arciszewski
Chief Development Officer
Paragon Initiative Enterprises https://paragonie.com/
Hi Scott and all,
On Thu, Feb 9, 2017 at 10:52 PM, Scott Arciszewski scott@paragonie.com
wrote:
HKDF relies on PRK being cryptographically strong.
Yes, but not for the reasons you might suspect.
The main use case of HKDF is to completely prevent related-key attacks,
while splitting a single key into several for domain-specific purposes.
Figuring out a subkey (by sheer luck) should also not give an attacker
enough information to recreate the IKM.HKDF isn't meant for key stretching (e.g. use an 80-bit secret in an
application that requires a 256-bit secret). That's what a password hashing
function is for. (Bcrypt, Argon2, etc.)
You should understand users must make sure either "salt" or "IKM" is
strong for HKDF to work. Since
hash_hkdf()
is generic function, you nevercan make sure IKM to be strong always.
Not quite. IKM has to be strong. The salt? Not so much.
In cryptography protocols, salts are considered public information (even
if you don't go out of your way to publish it).If you have a weak IKM but a strong salt (32 bytes from
random_bytes()
),
you should still consider the OKM weak.
Salt is the most important for both input and output key security.
Salt is mandatory and/or can be used for almost always with PHP.
Salt usage results in better design/security.
Salt is often used as final key as combined key.Don't get me wrong: Having secure random salts is useful (serves as a
useful way to enlarge the effective nonce in a symmetric encryption
protocol).But the cryptographic secret in this protocol is IKM. Not the salt.
I agree that your description matches many typical crypto
encryptions/authentication/etc.
As you would know, there are some exceptions that encryption key is not
really a random
(Not cryptographically strong) If user could use strong IKM, they should
use it, then
salt could be for additional security. (HKDF IKM could be weak, salt could
be secret, but
you mentioned typical use case and best practice in crypto)
The most typical HKDF application with PHP is access token key derivations
with timestamp
such as CSRF and Object Access token. For these applications, salt usage is
strongly
recommended, info(context) is recommended, length is OK with hash default.
e.g.
Generating CSRF token keys
$expire = time()
+900; // Even, non secret, low entropy salt makes HKDF OKM
significantly stronger.
$csrf_token = bin2hex(hash_hkdf('sha256', $_SESSION['CSRF_TOKEN_SEED'], 0,
'', $expire));
then, send $expire and $csrf_token as access key.
This could be done with hash_hmac()
already.
$csrf_token = hash_hmac('sha256', $_SESSION['CSRF_TOKEN_SEED'], $expire));
What's really good about HKDF is it can add additional non secret optional
context(domain) safely, as you mentioned.
// Make CSRF token only valid to 'Admin' features.
$csrf_token = bin2hex(hash_hkdf('sha256', $_SESSION['CSRF_TOKEN_SEED'], 0,
'Admin', $expire));
// Should be OK, but this is risky compare to above.
$csrf_token = hash_hmac('sha256', $_SESSION['CSRF_TOKEN_SEED'], $expire.
'-Admin'));
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Andrey,
I suppose most developers will use 'length' for shorter length.
i.e. Weaker output keys. If it's not too short, shorter key length works.Shows that you shouldn't be trusted with anything related to cryptography
either.
I may be no cryptographer myself, but one thing I know for sure is that
shorter than required key lengths are never ok, and most encryption
algorithms have a fixed key length.Also, this is the last time I reply to you on this topic. You're just
impossible to reason with.
I think I finally understand what you don't understand.
Please read "Current Status" section of the draft PHP RFC.
https://wiki.php.net/rfc/improve_hash_hkdf_parameter#current_status
hash_hkdf()
is simple hash_hmac()
extension, why should not hash_hkdf()
have
compatible signature with hash_hmac()
? Aside from it, $salt is "key" in
many cases.
There is no reason "key" to be the last optional parameter.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi Andrey,
On Tue, Feb 7, 2017 at 10:22 PM, Scott Arciszewski scott@paragonie.com
wrote:Although the RFC itself says that salts are optional, the argument to
make them required in PHP's implementation has merit. The only downside is:
If you're integrating with an implementation that doesn't require salts,
and the application doesn't use salts, you're out of luck. Is that enough
of a downside to dismiss an argument for better security? Maybe.I said this in another thread already, but I'll re-iterate here ... Using
a salt should be recommended, but the suggestion here takes that out of
context and misses a key point - that the Length and Info params are not of
any less importance overall.
From the HKDF algorithm, importance is clear. Salt >>> info > length.
Salt is the most important to secure input key. You seem to think following
is the most important.
- Salt could be optional only when input key is cryptographically strong.
What this means is
-
Salt is absolute mandatory parameter unless input key is
absolutely strong key. -
Length is effectively the key size and is in fact not optional in
RFC5869*. You have to really know what you're doing if you don't use it,
and choose the hash function very carefully. I'd argue that if you know
this well enough,
- Info is technically optional, but pretty much the feature why you'd
choose HKDF over other KDFs. It's what makes HKDF's more useful in that it
enables derivation of multiple OKMs from a single IKM. If you don't need
Info, chances are you don't need HKDF.
There is huge difference between "Required to be implemented" and
"Required/important as parameter".
Implementation requirement is nothing to do with parameter
requirement/importance.
'salt' could be omitted the application that input key is always strong.
This cannot be applied to
generic API like hash_hkdf()
that would be used by countless applications.
Why you recommends following usage?
hash_hkdf('sha256', $weak_ikm, 9); // We can generate strong key easily,
Nice! <= Must not do this.
One could use Salt for the purposes of Info, but that would be misusing the
algorithm.
I totally agree.
HKDF is specific about 'salt' and 'info' task. Salt is entropy to make
input/output
key strong/stronger. Info is for output key context.
Over-focusing on Section 3.1 of the specification, while at the same time
ignoring Section 3.2 - arbitrarily making OptionalParamX mandatory because
the note about it mentions the word "security". Noble, but misguided.
What's the reason why you trying to disregard RFC 5869 strongly recommends?
"designers of applications are therefore encouraged to provide salt
values to
HKDF if such values can be obtained by the application."
It seems you're mixed up with "Implementation requirement" and "Parameter
requirement/importance".
After all, we are implementing RFC 5869, why we should not follow
recommendation?
I'd have no problem if ALL of the params were made non-optional - I'm all
for that, but either do that or leave it untouched.
- RFC 5869: https://tools.ietf.org/html/rfc5869
While I don't mind requiring both 'salt' and 'info', I strongly disagree
with the current parameter order and 'length' is pure optional parameter.
'info' is important but optional. 'salt' can only be optional when input
key
is absolutely cryptographically strong.
Parameter order must reflect
- importance of the parameter
- likelihood to be used
Salt is the most important for both input and output key security.
Salt is mandatory and/or can be used for almost always with PHP.
Salt usage results in better design/security.
Salt is often used as final key as combined key.
Does 'length' and/or 'info' achieve or designed for aboves? I don't think
so.
hash_hkdf()
is generic API. $ikm cannot be strong key always.
Assuming $ikm to be strong is simply wrong assumption.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net