gmpassos / argon2

Pure Dart Argon2 algorithm (the winner of the Password Hash Competition 2015) for all Dart platforms (JS/Web, Flutter, VM/Native).
Apache License 2.0
9 stars 1 forks source link

What does memory mean? #2

Open chickahoona opened 1 year ago

chickahoona commented 1 year ago

Could you please specify what Memory means? so are we talking about 2^X Bytes / Bits / Kilobits / ...

I am asking as OWASP recommends at least 19 MiB of RAM and I'd like to know which setting would reflect that?

https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html

gmpassos commented 1 year ago

See:

https://github.com/gmpassos/argon2/blob/master/lib/src/argon2_base.dart#L132

It's the memory used to store the "hashing blocks".

The Argon2 algorithm allows a custom amount of memory to compute the hash, what increases the computation cost (a feature needed in some use cases).

See: https://medium.com/analytics-vidhya/password-hashing-pbkdf2-scrypt-bcrypt-and-argon2-e25aaf41598e

And some description of the behavior:

The Argon2 password hashing algorithm is designed to be memory-hard, meaning that it requires a significant amount of memory to perform the hashing operation. This is intended to make the algorithm resistant to attacks that use specialized hardware, such as ASICs or FPGAs, to accelerate the hashing process.

The memory parameter in Argon2 specifies the amount of memory to be used for the hashing operation, measured in kibibytes (KiB). The higher the memory parameter, the more memory will be used by the algorithm, and the more difficult it will be for an attacker to perform brute-force attacks.

When the memory parameter is increased, the amount of time required to perform the hashing operation also increases, which can make the algorithm less suitable for use in some scenarios, such as low-power devices or high-traffic web applications. However, the memory parameter can be adjusted to strike a balance between security and performance, depending on the specific requirements of the application.

Overall, the memory parameter plays a crucial role in determining the security and performance characteristics of the Argon2 hashing algorithm. It is important to choose an appropriate value for this parameter to ensure that the algorithm provides adequate security against attacks while also meeting the performance requirements of the application.

chickahoona commented 1 year ago

So if I take measured in kibibytes (KiB)., may I assume that the default example with memoryPowerOf2: 16 corresponds to 2^16KiB or 65536 KiB or 64 MiB?

GleammerRay commented 10 months ago

@chickahoona I have recently tried this package instead of dargon2 (uses argon2-cpp libraries) and its memory parameter corresponds one-to-one to the argon2-cpp (and argon2-cli) memory parameter in terms of key generation but with a significant decrease in generation speed.

I have also compared speeds and memory use in a CLI application that is shipped together with my app using /usr/bin/time -v, here are the results with parallelism/lanes = 4, memory = 65536, iterations = 2:

Implementation User time (seconds) Maximum resident set size (kbytes)
argon2 2.63 210168
dargon2 0.51 77340
pointycastle 2.69 210816

I wouldn't expect memory use to co-align one-to-one, especially if using a high-level implementation such as the one provided by this package.

gmpassos commented 10 months ago

Did tou tried to run it compiled?

dart compile exe path/to/file.dart

If you are running it from the Dart VM (dart run file.dart), it will take some time to analyze and compile the code, before really run it.

gmpassos commented 10 months ago

Note that the best way to perform a benchmark is not to compute the process time, but run the operation internally for some seconds (10s), and get the operations per/sec that you get in each implementation.

GleammerRay commented 10 months ago

@gmpassos indeed, my CLI executable is compiled via dart compile exe for release builds. dart run runs way slower. Regarding the tests, yes, they were not super serious but I did run them several times and time was within 0.05s range.

GleammerRay commented 10 months ago

I also tried the library in my Flutter app and there was a noticeable delay in login times compared with argon2-cpp. Kinda what I expected considering how this is a pure Dart implementation. I wanted to get rid of having to ship a .dll with my CLI executable but I guess I'm out of luck for now.

gmpassos commented 10 months ago

Get rid of DLLs is a good thing.

Well, you could preload the Argon2BytesGenerator before the user click the login button, reducing the login time for the user:

 var argon2 = Argon2BytesGenerator();
 argon2.init(parameters);
GleammerRay commented 10 months ago

I will consider trying that sometime, thank you. To be honest, I am much more worried about memory use than time, as memory is often scarce on mobile devices. In either way, this is a pretty good implementation in case anyone needs it for low-memory web argon2 scenarios, keep up the good work. 👍

gmpassos commented 10 months ago

Have you tried the pointycastle version? It was based on this version, but they improved the internal int representation.

https://pub.dev/packages/pointycastle

gmpassos commented 10 months ago

It loads a different implementation depending on the platform:

https://github.com/bcgit/pc-dart/blob/master/lib/key_derivators/argon2_native_int_impl.dart https://github.com/bcgit/pc-dart/blob/master/lib/key_derivators/argon2_register64_impl.dart

GleammerRay commented 10 months ago

I have updated my original comment with test results. pointycastle actually runs somewhat worse (although insignificantly) than argon2. Great job!

Regarding pre-loading, mine is a special case where user can have more than one account and has the freedom to customize their argon2 parameters during runtime so I don't see how or when I can use the initialize function. I believe I'm better off keeping whatever I was using before.

Thank you!

wbusey0 commented 2 months ago

So if I take measured in kibibytes (KiB)., may I assume that the default example with memoryPowerOf2: 16 corresponds to 2^16KiB or 65536 KiB or 64 MiB?

I am also interested in this question. It would help if the memory and memoryPowerOf2 were documented in the code. Making wrong assumptions of this parameter will cause security issues.

Thank you for your work 🙇