Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argon2 Algorithm in PHP7: understanding the time_cost parameter

I'm trying to implement the Argon2 algorithm in an authentification library. I want to be able to provide some useful tips for the users to set the parameters.

While I understand how memory_cost and threads parameters affect the algorithm, I can't seem to wrap my head around the time_cost parameter.

What the PHP doc says:

time_cost (integer) - Maximum amount of time it may take to compute the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_TIME_COST.

Interrogation 1 - The default value is 2. It seems to represent a time, sadly, the unit seems missing. Is it in seconds? Milliseconds?

This SO answer says the default is 2 seconds.

What the Argon2 specs says:

In Chapter 3.1 Inputs, there is no mention of time here, only about a number of iterations.

Number of iterations t (used to tune the running time independently of the memory size) can be any integer number from 1 to 2^32−1;

A time-related value is defined in Chapter 9 Recommended Parameters, it says:

Figure out the maximum amount x of time (in seconds) that each call can afford

[...]

Run the scheme of type y, memory m and h lanes and threads, using different number of pass t. Figure out the maximum t such that the running time does not exceed x. If it exceeds x even for t = 1, reduce m accordingly.

Hash all the passwords with the just determined values m, h, and t.

Interrogation 2 - So does this mean PHP exposes the amount of time x and determine the correct amount of iterations t?

What the PHP RFC says:

A time cost that defines the execution time of the algorithm and the number of iterations

[...]

The time cost represents the number of times the hash algorithm will be run.

Interrogation 3 - They talk about both a time and a number of iterations. Now I'm even more confused. Is it a time or a number of iterations? If I run a hash with time_cost = 2, does this mean it will take 2 seconds?


The benchmark

To help me understand a bit, I've made this little benchmark script. I got the following result (1 thread):

m_cost (MB) |  1  |  2  |  4  |  8  | 16  | 32  | 64  | 128 | 256
            =====================================================
t_cost=1    |  1  |  2  |  5  | 10  | 24  | 46  | 90  | 188 | 348
t_cost=2    |  2  |  4  |  8  | 18  | 39  | 75  | 145 | 295 | 636
t_cost=3    |  3  |  6  | 12  | 26  | 53  | 102 | 209 | 473 | 926
t_cost=4    |  5  |  9  | 30  | 56  | 78  | 147 | 309 | 567 |1233
t_cost=5    |  4  |  9  | 19  | 40  | 79  | 165 | 359 | 690 |1372
t_cost=6    |  5  | 12  | 23  | 49  | 93  | 198 | 399 | 781 |1777
t_cost=7    |  6  | 14  | 29  | 53  | 118 | 259 | 508 |1036 |2206
t_cost=8    |  8  | 16  | 33  | 82  | 179 | 294 | 528 |1185 |2344

I still don't get how the time_cost could be a time in seconds.

If it is an upper bound (meaning the max time it could run), then it's not even helpful. For example, t_cost=8 and m_cost=16MB could seem reasonable, as it takes around 200ms to run. But this means the algorithm could one day take up to 8 seconds to run? The usability would be disastrous!


I really tried to do my research, and I'm not really comfortable that I need to ask to understand this.

But this is really confusing. Since it is related to security, I really want to get to the bottom of this.

Thanks for your insights!

like image 477
Indigo Avatar asked Mar 21 '18 10:03

Indigo


1 Answers

From what I can tell, it's the number of iterations in the ARGON2 algo.

If you track it back through the PHP source, you get

https://github.com/php/php-src/blob/master/ext/standard/password.c#L528

which calls

https://github.com/P-H-C/phc-winner-argon2/blob/master/src/argon2.c#L67

So here, t_cost maps to the number of passes ^

Also note:

See https://password-hashing.net/submissions/specs/Argon-v3.pdf - 2.1.1 - Inputs: Number of iterations t can be any integer number from 1 to 232 − 1

like image 76
Ben Edmunds Avatar answered Nov 07 '22 07:11

Ben Edmunds