Information Security Stack Exchange is a question and answer site for information security professionals. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Aren't API keys considered usernames and API secrets considered passwords? Why is it that API servers like Amazon Web Services allow you to view your API secret in plain text? It makes me think they store it in plain text or at least in a decrypt-able format.

Isn't it better if API secrets were treated as passwords that you should type-in to create then hashed in the database instead of being handed to you in plain text? If for some reason their API secret database were compromised it will easily open the flood gates for many applications that are using their API. However if it was hashed in a non decrypt-able manner then all is not easily lost.

share|improve this question
I have noticed this too (for AWS and every other API) and been curious. – Ellie Kesselman Aug 13 '12 at 0:07
The short answer to your question is this: API secrets are symmetric keys, not passwords. What makes you think they don't store it in a decryptable format? – David Schwartz Aug 13 '12 at 10:47
@DavidSchwartz I didn't say that. I said it's either plain text or decrypt-able. – IMB Aug 13 '12 at 11:28

No. The API keys need to be stored in cleartext.

They are not passwords: they are cryptographic keys. These keys are used for things like authenticating requests (using SHA1-HMAC). The server needs to know the crypto key to apply the cryptographic algorithms.

Therefore, the API key needs to be stored in cleartext on the server. If the server stored only a hash of the API key, it could not verify the authenticity of messages from the client or authenticate messages sent to the client.

share|improve this answer
What is preventing an API server from hashing a key for storage since it can hash the user input (i.e., the client) for comparison the same way password storage works? – IMB Aug 13 '12 at 11:31
@IMB, If you hash the API key, and both sides use the hash of the API key as the actual cryptographic key (say, for use with a message authentication code), then you've gained nothing: the hash now becomes the effective key, and both sides are storing that in plaintext. The point is that a cryptographic key is not the same as a password. A password can be stored hashed; a cryptographic key generally cannot. – D.W. Aug 13 '12 at 18:02
@IMB, Amazon Web Services doesn't use HTTP Digest auth. And, HTTP Digest auth is insecure against a network attacker. Instead, Amazon Web Services uses a symmetric-key message authentication code to "sign" messages. That is more secure, but it requires a cleartext crypto key. – D.W. Aug 13 '12 at 19:26
@IMB, If you want to know about HTTP Digest auth over SSL, I'd encourage you to create a new question and ask about that one separately -- that's a different topic, and the answer for HTTP Digest auth over SSL is different from the answer for AWS. (Do note: HTTP Digest auth does not use an "API key".) – D.W. Aug 13 '12 at 19:57
@IMB, again, please move any questions about storage of the secrets for HTTP Digest Authentication to a separate question. Please avoid extended discussion of it in this comment thread. – D.W. Aug 13 '12 at 20:09

Hashing is not storage; it irreversibly destroys data. We can get away with calling password hashing as "password storage" because when we actually need the password, we have a handy human operator to type it in. Indeed, when we hash the password we do not store the password, but only a token sufficient to verify the typed-in password.

An API key must be stored in such a way that it can be used again in an unattended fashion. The server must really store it, instead of just remembering a ghost of it, because it needs the genuine key to access the API.

share|improve this answer
Is there any reason why an API server can't hash user input (i.e., hash the key)? And compare it to the hashed key stored in the server. Seems to me there's no special reason why keys can't be hashed. – IMB Aug 13 '12 at 11:34
@IMB, see my response at the other place where you posted this same question. – D.W. Aug 13 '12 at 18:04
@D.W., link, please? – user359996 Feb 8 '13 at 20:34
@user359996, – D.W. Feb 8 '13 at 21:47

Whilst it would be more secure to hash the API tokens, it presents a usability problem: the tokens are long and random, and would have to be told to the user only once before hashing. This makes it a little difficult to secure them with a hash.

My suggestion for a secure scenario would be the following:

  1. Generate a random salt value and store it in the database. This salt must not be equal to the user's password salt.
  2. Take the user's plaintext password and compute KDF(password, salt), where KDF is a key-derivation function such as bcrypt. Call the resulting value k.
  3. Generate an API key.
  4. Encrypt the API key value with AES, using k as the key, and store the ciphertext in the database.
  5. Discard the plaintext API key and k.

When the user logs in, the webapp knows their password and uses it to compute k, which is then used to decrypt the API key and display it to them.

When the user wishes to use the API, they must send k as well as the plaintext API key, over SSL. The webapp can then decrypt the stored API key value using k and compare it to the given API key. If they match, it's valid. This allows API key use without the app needing to store the user's password.

If an attacker breaches the database, they must crack the user's password in order to compute k.

share|improve this answer
And what in case of password change? – Andrew Smith Aug 12 '12 at 23:51
Just a suggestion the unique salt can be anything from the user's password or something that remains constant like the userID. Point being, encryption better than plain text anyday. – Rohan Durve - Decode141 Aug 13 '12 at 1:45
@AndrewSmith During password change the user should always be required to enter their existing password, to prevent walk-by attacks. This allows the computation of k. – Polynomial Aug 13 '12 at 5:44
@RohanDurve-Decode141 In this case, yes, it could be the user ID. However, I normally give the advice to avoid using externally known values as salts in all cases, because the differences are subtle and things get complicated when dealing with password hashes. In this case, though, user ID is fine. – Polynomial Aug 13 '12 at 5:46
Yeah, yeah! ...a missing part of the sentence caused that. I meant, "The answer is just a rough suggestion..." and was aimed at Mr. Smith. :) Ps. I didn't downvote. – Rohan Durve - Decode141 Aug 13 '12 at 12:25

No it's not okay for some kind of services.


1. Upon user connection with login password, generate a key derived from his/her password to encrypt data for this user and keep it in a session on the server.

That way, each user will have a unique key. This derived key must not be reversible, this is the main point. Using hash_mac or other hashing method with salt and/or master key will allows this.

2. Use this key to encrypt the generated API Secret using AES 256 with a random iv for each user.


2.bis Use this key to generate the real encryption key at the very last moment and encrypt the API method using the same way as in 2. to avoid in memory floating passwords.

3. Store the iv in the data base along with the user id and app id in a dedicated table

4. Store the encrypted API Secret in the database in the appropriate table.


Now when the user connect to his control panel you can recreate the key, fetch the iv, decipher the API Secret for this user and display it in clear text. You also display the key and ask for both when making API Call so that you can verify the App Secret.

If you want to avoid to display the key and not have to request it on API call you can also for authentication use the same method as for login. Meaning you can create another table to store a random key/salt for each client app and store a hash_mac version of the API Secret. Thus only the API ID and API Secret are required to authenticate API Request. but it's more work.


This is practically the same as @Polynomial answer.

This way it's very very difficult for someone hacking your server and database to steal your users credentials and make api call on their behalf. You can now assess that if a request has been accepted from a API client it's the right client or it's their leakage.

If the user loses his password then you regenerate a new API Secret and Key from his new password.

share|improve this answer

Well in this backend you can also provision server and read all the data anyway. You need to make sure that nobody can access your backend, otherwise he will read all of your data at once including backups.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.