title: Argon2 Algorithm in PHP7: understanding the time_cost parameter
body: <p>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.</p>
  <p>While I understand how <code>memory_cost</code> and <code>threads</code> parameters affect the algorithm, I can't seem to wrap my head around the <code>time_cost</code> parameter.</p>
  <h2>What the <a href="http://php.net/manual/en/function.password-hash.php" rel="noreferrer">PHP doc says</a>:</h2>
  <blockquote>
  <p>time_cost (integer) - Maximum amount of time it may take to compute the Argon2 hash. Defaults to PASSWORD_ARGON2_DEFAULT_TIME_COST.</p>
  </blockquote>
  <p><em><strong>Interrogation 1 -</strong></em> The default value is 2. It seems to represent a <em>time</em>, sadly, the unit seems missing. Is it in seconds? Milliseconds?</p>
  <p>This <a href="https://stackoverflow.com/questions/47602044/how-do-i-use-the-argon2-algorithm-with-password-hash/47602045#47602045">SO answer</a> says the default is 2 <em>seconds</em>.</p>
  <h2>What the <a href="https://password-hashing.net/argon2-specs.pdf" rel="noreferrer">Argon2 specs says</a>:</h2>
  <p>In Chapter 3.1 <em>Inputs</em>, there is no mention of time here, only about a number of iterations.</p>
  <blockquote>
  <p>Number  of  iterations <code>t</code> (used  to  tune  the  running  time  independently of  the  memory  size)  can  be  any integer number from 1 to 2^32−1;</p>
  </blockquote>
  <p>A time-related value is defined in Chapter 9 <em>Recommended Parameters</em>, it says:</p>
  <blockquote>
  <p>Figure out the maximum amount <code>x</code> of time (in seconds) that each call can afford</p>
  <p>[...]</p>
  <p>Run the scheme of type <code>y</code>, memory <code>m</code> and <code>h</code> lanes and threads, using different number of pass <code>t</code>. Figure out the maximum <code>t</code> such that the running time does not exceed <code>x</code>. If it exceeds <code>x</code> even for <code>t = 1</code>, reduce <code>m</code> accordingly.</p>
  <p>Hash all the passwords with the just determined values <code>m</code>, <code>h</code>, and <code>t</code>.</p>
  </blockquote>
  <p><em><strong>Interrogation 2 -</strong></em> So does this mean PHP exposes the amount of time <code>x</code> and determine the correct amount of iterations <code>t</code>?</p>
  <h2>What the <a href="https://wiki.php.net/rfc/argon2_password_hash" rel="noreferrer">PHP RFC</a> says:</h2>
  <blockquote>
  <p>A time cost that defines the execution time of the algorithm and the number of iterations</p>
  <p>[...]</p>
  <p>The time cost represents the number of times the hash algorithm will be run.</p>
  </blockquote>
  <p><em><strong>Interrogation 3 -</strong></em> 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 <code>time_cost = 2</code>, does this mean it will take 2 seconds?</p>
  <hr />
  <h2>The benchmark</h2>
  <p>To help me understand a bit, I've made this <a href="https://gist.github.com/Indigo744/e92356282eb808b94d08d9cc6e37884c" rel="noreferrer">little benchmark script</a>.
  I got the following result (1 thread):</p>
  <pre><code>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
  </code></pre>
  <p>I still don't get how the <code>time_cost</code> could be a time in seconds.</p>
  <p>If it is an upper bound (meaning the max time it could run), then it's not even helpful. For example, <code>t_cost=8</code> and <code>m_cost=16MB</code> 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!</p>
  <hr />
  <p>I really tried to do my research, and I'm not really comfortable that I need to ask to understand this.</p>
  <p>But this is really confusing. Since it is related to security, I really want to get to the bottom of this.</p>
  <p>Thanks for your insights!</p>