Reputation: 39
In my system each user can have multiple api keys. I want to hash api keys and store in a database their hashes. I'm using comeonin for this.
1) is it sensible to store hashes of api keys rather than their plain, original values?
2) when an api request comes in, there's only a plain api key value in it and no user email along with it -- this is my system is designed.
How should I check if an api key is valid? Will I have to do this -- recalculate a hash?
given_api_plain_key = get_key_from_request()
# re-hash it again
# but how about the original salt???
given_api_hash_key = Comeonin.Bcrypt.hashpwsalt(given_api_plain_key)
case Repo.get_by(ApiKey, key_hash: given_api_hash_key) do
nil -> IO.puts("not found")
a -> IO.puts("gooood")
end
Or is there a better way?
Upvotes: 4
Views: 932
Reputation: 6629
(1) is it sensible to store hashes of api keys rather than their plain, original values?
Your goal seems to be to protect against grand compromises that might happen if somebody gets access to your database (for example, via SQL injection, command injection, or reverse shell on your system). In this case, yes it is sensible, especially if each user has a different API key. However this link is worth reading for other considerations that might affect your decision.
(2) How should I check if an api key is valid?
It is clear that you need to hash the input and see if matches to something in your database.
(3) Implementation.
You do not want to apply the same protection that you use for passwords. Passwords tend to have low entropy by nature, and therefore we need tools like bcrypt to process them. Bcrypt is slow by design (to prevent brute force attacks), and uses salts to help the security of poorly chosen passwords.
API keys should not have low entropy, and therefore you do not need slow functions to process them. In fact, slow functions bring DoS risks, so you definitely do not want to do a bcrypt every request that comes in. Salting also complicates your use case (salts work when you know who is providing the input, but in your case you do not know who it is coming from beforehand).
Short answer: Just use SHA256, no salt needed.
Upvotes: 4