Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A better password-based key-derivation function in WebCrypto #59

Open
bakkot opened this issue Jun 27, 2022 · 7 comments
Open

A better password-based key-derivation function in WebCrypto #59

bakkot opened this issue Jun 27, 2022 · 7 comments

Comments

@bakkot
Copy link

bakkot commented Jun 27, 2022

Introduction

[I have an existing issue here, but I'm hoping to get more eyes on it.]

The SubtleCrypto.deriveKey API exposes one password-based KDF, pbkdf2, which is quite old and is based on repeatedly performing SHA-1 or one of the SHA-2 variants. While it's still acceptable, society as a whole has put quite a lot of work into making SHA fast, including with custom hardware. For this reason pbkdf2 is no longer the default recommendation for password-based key derivation. Specifically, as I understand it, bcrypt and scrypt are the standard boring choices these days (with argon2 sometimes showing up).

Cite: the "password handling" section of this essay gives the right answers for password handling as

Percival, 2009: scrypt or PBKDF2.
Ptacek, 2015: In order of preference, use scrypt, bcrypt, and then if nothing else is available PBKDF2.
Latacora, 2018: In order of preference, use scrypt, argon2, bcrypt, and then if nothing else is available PBKDF2.

It would be nice if the web platform exposed something other than the "if nothing else is available" option.

Use Cases

All existing uses of pbkdf2 could be replaced by a more secure KDF.

Goals

Provide an implementation of a standard, more secure KDF.

Non-goals

Providing any other non-standard KDF, or any other crypto functionality.

Proposed Solution

SubtleCrypto.deriveKey should accept one or more new algorithms of the set { scrypt, bcrypt, argon2 }, along with appropriate configuration (e.g. cost factor).

Alternate Approaches

It is of course possible to implement these in userland, but a.) we shouldn't encourage implementing crypto algorithms and b.) that implementation will necessarily be much slower than a native one, which is bad for a KDF because you want to spend your resources as effectively as possible - a slower implementation means a lower cost factor for the KDF for a given amount of time.

The other alternative is to keep using the "if nothing else is available" option we currently have.

Privacy & Security Considerations

No considerable privacy or security concerns are expected, but we welcome community feedback.

Let’s Discuss

I don't know exactly which of the three reasonable choices are worth including. Personally I'd be inclined to add all of them, but maybe it would be better to just pick one.

@twiss
Copy link

twiss commented Jul 19, 2022

Hi 👋 As I've written in w3c/webcrypto#265 (comment), I definitely agree. It's unfortunate that, if developers are going by what's available in Web Crypto, that they're led to choose PBKDF2, so it would be great to add a more modern alternative to the spec.

IMO, it'd make the most sense to add Argon2, as it's the winner of the Password Hashing Competition, and a CFRG recommendation, standardized in RFC 9106. Adding scrypt and bcrypt would mostly be interesting for existing applications that happen to use it; for new applications, once Argon2 is there, there's not much need for scrypt or bcrypt, I think. So I would start with specifying only Argon2.

@tniessen, @panva and @lucacasonato, I believe you were also interested in implementing this, and possibly considering writing a spec for adding more modern algorithms in general? So one question is whether we want a small spec for Argon2 in Web Crypto, for example, or a larger one with other algorithms as well. Since the specifications of the various algorithms won't overlap that much, I don't think it matters that much either way, to be fair. But, let me know what your thoughts are, in general.

@TimoHocker
Copy link

I'd be most interested in Argon2 getting added to Web Crypto. Especially because my current project can't use Webassembly and I couldn't find any Argon2 implementation that doesn't rely on Webassembly. For now I can use Scrypt, but it's still extremely slow compared to a native implementation.

I think it would be best to consider the mentioned algorithms separately and add them in order of most recommended to least recommended, so that newly developed sites and applications can start using the most secure algorithms as soon as possible.

@gamedevsam
Copy link

My vote would be bcrypt since it's what Proton Pass uses.

@twiss
Copy link

twiss commented Jul 3, 2023

People might accuse me of conflicts of interest if I try to introduce bcrypt on that basis 😄

In all seriousness, I think it's more important to add the most secure algorithm, for the benefit of new applications (and new functionality in existing applications), rather than adding functions because of existing usage.

And, (speaking with Proton hat on for once), for what it's worth, also at Proton our long-term plan is to switch to using Argon2, on the basis that it's a better password hashing function than bcrypt, even though bcrypt is still better than PBKDF2, of course.

Adding Argon2 to Web Crypto might also help Proton and other applications using bcrypt or PBKDF2 switch to using Argon2, which would give a nice security and/or performance benefit. And that's after all the goal of having the Web Crypto API, in my opinion ☺️

@stripthis
Copy link

Adding Argon2 would also help us at Passbolt, for example to handle natively import from Keepass file format.

@quexten
Copy link

quexten commented Nov 3, 2023

Bitwarden is another application where this would help. Bitwarden already uses Argon2, via the WebAssembly library https://github.com/antelle/argon2-browser, but this has many issues (no automatic SIMD loading, no multi-threading for parallelism, does not work on iOS in lockdown mode) and in general is a maintenance burden.

A native API in browsers would greatly help here and might help make it the default key-derivation function.

@gamedevsam
Copy link

gamedevsam commented Nov 3, 2023

I've been using this package to build and embed argon2id into my browser based encryption tool: https://www.npmjs.com/package/hash-wasm

Tool: https://sambatista.com/secret

It works well as a UMD, and performance is generally acceptable even with some heavy computational requirements, here are the defaults I'm using to secure the passwords:

const ARGON2_ITERATIONS = 12; // key derivation (argon2id: https://soatok.blog/2022/12/29/what-we-do-in-the-etc-shadow-cryptography-with-passwords)
const ARGON2_MEMORY_SIZE = 131072; // 128 MiB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants