Open Narrat opened 4 months ago
Definitely a place that needs improvement, thanks for the extensive analysis. Will be watching this PR, according to your intentions we should end up with less code and more readable ✌🏽
Not so sure on the less code part :D I tried at least... But yeah, tomb became a chunky shell script over the time :D
I will look into your PR and try to merge above conflicts as I did merge some duplicate code with mine, apologies for the mess.
to this analysis let me also add the possibility to run a timed benchmark before creating the key, so that a default above the minimum can be set according to the speed of machine. also the iteration setting then can refer to seconds rather than absolute value.
No worries. You could also say what should be dropped or changed and I adjust it :D No problem to adjust the test changes onto the test you added instead of the initial add of my own. If that was what you meant.
to this analysis let me also add the possibility to run a timed benchmark before creating the key, so that a default above the minimum can be set according to the speed of machine. also the iteration setting then can refer to seconds rather than absolute value.
Not sure if I follow completly, but imo it shouldn't be necessary to complicate it that much. Especially since the iteration in argon2
doesn't have the weight as for pbkdf2
. 3 vs 800000+ (as suggested by some parties).
Example of adjusting the iteration for argon2:
$ time argon2 holladollahey -m 12 -p 1 -t 3 <<< $(printf "test")
Type: Argon2i
Iterations: 3
Memory: 4096 KiB
Parallelism: 1
Hash: 6af9b7dc03d4530ec429b44df9cf7d9cdb46e0b309789199248508a8df064918
Encoded: $argon2i$v=19$m=4096,t=3,p=1$aG9sbGFkb2xsYWhleQ$avm33APUUw7EKbRN+c99nNtG4LMJeJGZJIUIqN8GSRg
0.010 seconds
Verification ok
argon2 holladollahey -m 12 -p 1 -t 3 <<< $(printf "test") 0,02s user 0,00s system 98% cpu 0,021 total
$ time argon2 holladollahey -m 12 -p 1 -t 30 <<< $(printf "test")
Type: Argon2i
Iterations: 30
Memory: 4096 KiB
Parallelism: 1
Hash: cf9ef6d124c4f31b944a647be7b41eab3ab0603385d88ff7feec826a6854e036
Encoded: $argon2i$v=19$m=4096,t=30,p=1$aG9sbGFkb2xsYWhleQ$z5720STE8xuUSmR757QeqzqwYDOF2I/3/uyCamhU4DY
0.073 seconds
Verification ok
argon2 holladollahey -m 12 -p 1 -t 30 <<< $(printf "test") 0,15s user 0,00s system 99% cpu 0,148 total
Increasing it tenfold doesn't add that much, whereas adjusting the memory requirement achieves more:
$ time argon2 holladollahey -m 12 -p 1 -t 3 <<< $(printf "test")
Type: Argon2i
Iterations: 3
Memory: 4096 KiB
Parallelism: 1
Hash: 6af9b7dc03d4530ec429b44df9cf7d9cdb46e0b309789199248508a8df064918
Encoded: $argon2i$v=19$m=4096,t=3,p=1$aG9sbGFkb2xsYWhleQ$avm33APUUw7EKbRN+c99nNtG4LMJeJGZJIUIqN8GSRg
0.016 seconds
Verification ok
argon2 holladollahey -m 12 -p 1 -t 3 <<< $(printf "test") 0,03s user 0,00s system 98% cpu 0,032 total
$ time argon2 holladollahey -m 17 -p 1 -t 3 <<< $(printf "test")
Type: Argon2i
Iterations: 3
Memory: 131072 KiB
Parallelism: 1
Hash: a3ded701563d8fa3b5fc68dc905eec06600426a995a3750a03ead1a99160aad0
Encoded: $argon2i$v=19$m=131072,t=3,p=1$aG9sbGFkb2xsYWhleQ$o97XAVY9j6O1/GjckF7sBmAEJqmVo3UKA+rRqZFgqtA
0.282 seconds
Verification ok
argon2 holladollahey -m 17 -p 1 -t 3 <<< $(printf "test") 0,54s user 0,03s system 99% cpu 0,570 total
The current implementation of my patches implements a default of 3 for --kdfiter
because default of argon2
. argon2
will use it as an absolute value, but the pbkdf2
implementation is different in that regard since it was introduced. It will take the input as seconds and run it through a command which calculates the number of iterations depending on $HOST
. Which was in the millions for the systems I tested on. And doing so is fine for this algo.
But adding the same for argon2
would be contrary to its design. With pbkdf2
the regular user also suffers from the timecost which isn't the case with argon2
. Instead it slows down the process for "dedicated" setups to crack a password like GPUs or ASICs where the number of cores is really high, but relatively sparse RAM available for every CPU. A case where pbkdf2
fails spectaculary since it's an algorithm which is really cheap to run and can therefore easily be parallelized. And then the timecost doesn't cost that much anymore. The hashes/second generated is vastly higher for pbkdf2
than for argon2
in that case. Only if $HOST
CPU itself is used pbkdf2
will be slower to crack, which is kinda a mood point as most of the home user systems have a GPU available. Taking my relatively old RX 480 into account those are 2000+ Cores compared to 4 CPU Cores.
Which opens up a can of worms for the future :D
argon2
implementation should be supported: The general advice is to use argon2id
The current handling of the KDF functionality is somewhat suboptimal in my opinion.
two variables:
KDF
forpbkdf
&ARGON2
für argon2 check and setting both variablesChecks on KDF: https://github.com/dyne/tomb/blob/master/tomb#L843 <-- enables --kdf in output of --help https://github.com/dyne/tomb/blob/master/tomb#L1149 <-- where it failed with
--kdftype=
https://github.com/dyne/tomb/blob/master/tomb#L1592 <-- only$KDF
is checked for enabling KDFChecks on argon2: argon2 implementation covered behind
$KDF
. Nothing is done with$ARGON2
itself.Changing ARGON2 to KDF is not practical as an not installed argon2 will unset
$KDF
.Additional thoughts: The input for
--kdf
should be optional. For argon2 a safe default will be assumed. That can also be done for pbkdf2. This can be done via removing checking--kdf
from the argon2 case (this option is already checked before entering switch/case). And setting the default value can be moved from theargon2
case. With 3 as default pbkdf2 results with 3000000, which AFAIR is deemed save. Although it can of course in every case a separate default value be set.Maybe a general case should be added to the switch/case. Makes it more recognizable if an unsupported kdf option was supplied instead of rather vaguely failing at line 1149.
And maybe rename the options?
--kdftype
->--kdf
NEW--kdfiter
to get declare an optional iteration value Would make possible to only supply--kdf <kdf-implementation>
to get a secured key. If one wants to adjust the default that can be additionally done via--kdfiter
and--kdfmem
.How to achieve: 1) Split switch/case and only check on
$ARGON2
or$KDF
. Disadvantage: Leads to duplicated code2) additional check on
$ARGON2
Nicer, but it usestomb-kdb-pbkdf2-gensalt
to generate a salt. Available via the pbkdf2 implementation from tomb. Can "tomb-kdb-pbkdf2-gensalt" be replaced? Maybe: https://stackoverflow.com/questions/23837061/a-random-string-generator-in-a-bash-script-isnt-respecting-the-number-of-given/23837515#23837515 as fallback, if the C-program isn't availableCurrent changes that are untested. Just a prototype of the thoughts I had on the topic: