Performance of Argon2id Algorithm in Bitwarden as Compared to KeePass

Thanks for the data. It does seem (to me) that the time to decrypt your vault is <1 sec, so the balance of the time should be attributable to the KDF calculation. All these tests were done with the same production vault (and same device) that was giving you a 3-min unlock time for 56 iterations, right?

If so, then for Argon2id with 64 MiB memory, your device is apparently completing each KDF iteration in about 4 seconds. This would result in about 3 ¾ minutes unlock time for 56 iterations (similar to what you observed), although for a fair comparison to KeePass (which presumably can leverage parallel calculations) you should have used 28 iterations (projected to yield an unlock time of around 2 minutes).

Are you running any other memory-intensive apps on the same device while unlocking your vault?

Can you check how much free/available memory you have (before, during, and after the Argon2id unlock, and after relocking your vault), using resmon? Test this for the 56-iteration KDF, at a minimum.

I can collect perfmon data if you think its of value. But this is not a system resource constraint.

My current system has 16GB of RAM and at this present time only ~53% is consumed. I’d be really surprised if that much memory was consumed when unlocking my vault.

You’re probably right, but it wouldn’t hurt to peak at the changes in memory usage during the 3-minute unlock at least once, to see if you discover something unexpected that may explain why the Argon2id KDF seems slower than it should on your device.

That is certainly weird. Could you please go to this site:
https://antelle.net/argon2-browser/
And use:

Memory:65536
Parallelism: 4
Iterations: 3
(leave the rest default)

Then click “Run Webassembly”, and copy the resulting output. Next click Webassembly+SIMD and copy the resulting output.

The site is a more direct version of just the argon2 library. That should help triage problems further.

1 Like

There is already this community PR:

1 Like

Thank you, yes, I found that PR after I had made the comment above.

What about the addition of the check for else if (kdfConfig.iterations > 10) at Line 432 of crypto.service.ts? Is that on your radar already, or should I post a Github Issue?

And how come all these numerical values (e.g., upper & lower bounds) are hardcoded in different places in the repo, instead of using constants?

Should @RG.Tridius also change the “Type” to “Argon2di” for these tests, or does it not matter so much?

Here you go… I get an error for the +SIMD test on this system for some reason. Meaning, I tried it on another system and received no error.

Webassembly:
[00.000] Testing Argon2 using Binaryen native-wasm
[00.001] Memory: 1280 pages (81920 KB)
[00.001] Loading wasm…
[00.077] Wasm loaded, loading script…
[00.102] Running…
[00.102] Script loaded in 25ms
[00.102] Calculating hash…
[00.106] Params: pass=password, salt=somesalt, time=3, mem=65536, hashLen=32, parallelism=4, type=0
[09.795] Encoded: $argon2d$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$M6B5FKQiKToCIn7dC/4DlBrdSQsYA6lUKTAwLO4LBzg
[09.795] Hash: 33a07914a422293a02227edd0bfe03941add490b1803a9542930302cee0b0738
[09.795] Elapsed: 9689ms

Webassembly_SIMD:
[00.000] Starting worker…
[00.020] Worker started
[00.021] Testing Argon2 using Binaryen native-wasm
[00.021] Memory: 1280 pages (81920 KB)
[00.022] Loading wasm…
[00.032] Wasm loaded, loading script…
[00.039] Script loaded in 7ms
[00.039] Calculating hash…
[00.039] failed to asynchronously prepare wasm: CompileError: WebAssembly.instantiate(): invalid value type ‘s128’, SIMD disabled with --wasm-jitless @+167
[00.039] CompileError: WebAssembly.instantiate(): invalid value type ‘s128’, SIMD disabled with --wasm-jitless @+167

Ok interesting. What browser, what CPU and do you have something like energy saving mode enabled?

This would present an issue if users have already set the iterations above that value. I’d rather do form validation in the changekdf component.

And how come all these numerical values (e.g., upper & lower bounds) are hardcoded in different places in the repo, instead of using constants?

Yeah, should probably do that.

Browser: Microsoft Edge
image

CPU: Virtualized i7-12700K (4 Cores provisioned to VMWare VM)
image

No energy saving mode enabled.

Not sure how much the VM aspect of this matters. I work from VM’s daily for my job. I have no problems with daily tasks including Teams meetings with video streaming, camera feeds etc. FWIW.

It could very well be that the VM is interfering with argon2. Argon2 specifically uses the cache structure of x86 cpus, and if running in a VM, then the cache might be cleared by context switches to other vms. Additionally, it might also be the cause for SIMD not working, I’m not too familiar with VMware, and whether it allows SIMD instructions within VMs. The CPU, browser and OS should support it.

FWIW, there is only a single VM running on the host.

Its not 100% clear but SIMD may actually be hidden by the hypervisor in this case.

https://kb.vmware.com/s/article/1005764

This link references a CPU feature masking configuration used with VMWare ESXi clusters for compatibility purposes. This doesn’t really apply to me since I’m running the Workstation SKU on a single host.

But interesting nonetheless…

Done.

2 Likes

Do you have access to the host system? If you do, can you do the same test on the host system?

Even if there is not that many context switches the VM somehow interfering is my best guess as to what’s going on here.

Great news! Any idea which release this will be included in? The release notes don’t always provide sufficient detail to determine what has changed.

Yes, the host system(s) are my personal machines. I only use VM’s due to requirements for accessing work related resources. This sets the stage for my use case scenario.

Earlier in this thread I mentioned how the specs for a given machine vary as I use different systems at times. Today I’m on a different, slower, VM which happens to be the one that I estimated a ~10 minute duration for unlocking the vaut. Interestingly this VM does not produce the error when using SIMD. The key differences between these two VM’s is the underlyig hardware and Hypervisor version.

Here are the Webassembly tests from this VM…

Webassembly:
[00.000] Testing Argon2 using Binaryen native-wasm
[00.000] Calculating hash…
[00.012] Params: pass=password, salt=somesalt, time=3, mem=65536, hashLen=32, parallelism=4, type=0
[18.281] Encoded: $argon2d$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$M6B5FKQiKToCIn7dC/4DlBrdSQsYA6lUKTAwLO4LBzg
[18.281] Hash: 33a07914a422293a02227edd0bfe03941add490b1803a9542930302cee0b0738
[18.281] Elapsed: 18269ms

Webassembly_SIMD:
[00.000] Starting worker…
[00.061] Worker started
[00.064] Testing Argon2 using Binaryen native-wasm
[00.064] Memory: 1280 pages (81920 KB)
[00.064] Loading wasm…
[00.254] Wasm loaded, loading script…
[00.268] Script loaded in 14ms
[00.268] Calculating hash…
[00.272] Running…
[00.274] Params: pass=password, salt=somesalt, time=3, mem=65536, hashLen=32, parallelism=4, type=0
[21.262] Encoded: $argon2d$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$M6B5FKQiKToCIn7dC/4DlBrdSQsYA6lUKTAwLO4LBzg
[21.262] Hash: 33a07914a422293a02227edd0bfe03941add490b1803a9542930302cee0b0738
[21.262] Elapsed: 20986ms

These results do reflect that I’m on a less performant system today. But no SIMD related error and KeePass still outperforms with Argon2id on this system.

That’s not surprising, since KeePass presumably doesn’t rely on SIMD.

Can you do the tests using the antelle.net site directly from the host, instead of from the VM, as a comparison?

Sure thing…

This information is the same tests but collected from the host for today’s VM:

Webassembly:
[00.000] Testing Argon2 using Binaryen native-wasm
[00.000] Calculating hash…
[00.010] Params: pass=password, salt=somesalt, time=3, mem=65536, hashLen=32, parallelism=4, type=0
[07.494] Encoded: $argon2d$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$M6B5FKQiKToCIn7dC/4DlBrdSQsYA6lUKTAwLO4LBzg
[07.494] Hash: 33a07914a422293a02227edd0bfe03941add490b1803a9542930302cee0b0738
[07.494] Elapsed: 7484ms

Webassembly_SIMD:
[00.000] Starting worker…
[00.020] Worker started
[00.022] Testing Argon2 using Binaryen native-wasm
[00.022] Memory: 1280 pages (81920 KB)
[00.022] Loading wasm…
[00.092] Wasm loaded, loading script…
[00.099] Script loaded in 7ms
[00.099] Calculating hash…
[00.100] Running…
[00.103] Params: pass=password, salt=somesalt, time=3, mem=65536, hashLen=32, parallelism=4, type=0
[11.522] Encoded: $argon2d$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$M6B5FKQiKToCIn7dC/4DlBrdSQsYA6lUKTAwLO4LBzg
[11.522] Hash: 33a07914a422293a02227edd0bfe03941add490b1803a9542930302cee0b0738
[11.522] Elapsed: 11418ms

Then there is something else going on beyond the VM interfering with SIMD. Can you provide hardware specs for this particular host?