Search code examples
password-hashargon2-ffi

Which hashing algorithm to use for API key?


My web application issues API keys to clients and I want to hash the API key in my database. However, it seems that if I follow best practices, whereby every hash has a different salt, then I cannot look up a user by their API key in my DB.

So my question is, which hashing algorithm is the "state of the art" in 2023 for this?

Example:

Suppose my user has been issued an api key, my-api-key. If I used argon2id for storing that password in the database, I have the following hash:

argon2id$19$8192$1$1$7eMA1uCGC2U$aIqS05xbn0DXdXNUKbDG1A

When the user makes an API call, it might look like this (in practice it would not be passed as a query param):

GET https://www.example.com?api_key=my-api-key

I want to be able to say (pseudocode):

hashed_api_key = hash("my-api-key")
SELECT * FROM users WHERE api_key = hashed_api_key

However, each time I call hash(), a random salt is used, and thus I have a different output:

argon2id$19$8192$1$1$vrDlrC4Qkmo$1lEogx/KgrJyPVS40Xgd+Q
argon2id$19$8192$1$1$D/8tzjThXNo$OsX5f4HjdJM5h5aENFk4DQ

What is the best practice for using hashed API keys for database lookups? Shall I use argon2 without a random salt? Or is there a different best practice?


Solution

  • If you prepend a unique and unhashed prefix to each issued api key, that provides a key to look up the salt. This also allows users to distinguish between keys in a key management ui (as suggested here).

    {prefix}.{api key}

    However, it may not be worth the added complexity, because, unlike passwords, you can ensure api keys have sufficient entropy, obviating the need for a salt.