16

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!

Community
  • 1
  • 1
Indigo
  • 646
  • 5
  • 14

1 Answers1

5

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

Ben Edmunds
  • 878
  • 4
  • 6
  • Ah, of course I should have checked the source code! That is silly of me. – Indigo Mar 21 '18 at 14:24
  • 3
    However, the PHP documentation make it unnecessarily confusing. Why talk about a "Maximum amount of time" when you are just actually talking about iterations... – Indigo Mar 21 '18 at 14:24
  • 2
    FYI: anyone is welcome to suggest edits to these docs, via [the online documentation editor](https://edit.php.net/?project=PHP&perm=en/function.password-hash.php) or [pull request](https://github.com/salathe/phpdoc-en/blob/master/reference/password/functions/password-hash.xml). – salathe Mar 21 '18 at 16:38
  • I might do that indeed. However, I would have love to have more insight on why it was phrased that way... – Indigo Mar 21 '18 at 17:20
  • 1
    @Indigo - In an ideal scenario one would measure the time to calculate a single hash, and set the iterations so that the calculation time matches the maximum time you are willing to afford. The more iterations the safer but also more cpu intensive (it depends on the server). Surely this could be explained more clear. – martinstoeckli Mar 22 '18 at 07:51
  • Now I understand the rationale behind it. However, I think the PHP doc should have stay closer to how the spec present it, i.e. iterations use to tweak the running time independently of memory allocated. And maybe offers some pointers on how to find that number, as you explained yourself. – Indigo Mar 22 '18 at 12:40