Why use an API key and secret?

61,923

Solution 1

Secret key cryptography relies on using the same key to encode and then later decode a message. Thus, only those who know the "secret" can read the message.

RSA security is based on 2 matching keys. There is a public key for each user, and everybody can (should) know it. There is also a private key that only the user should know. A message encrypted by the public key can only be decrypted by the private key, and visa versa.

Thus, if I want to send you a message that only you can read, I get (from the network) your public key, encrypt the message with that key and you are the only person who can decrypt it.

Or, if I want to prove to you that I sent a message, I can encrypt the message with my private key, tell you (in open text or in another message) how it was encrypted. Then you could decrypt the message with my public key, and if it becomes readable, you know it came from me.

This form of encryption is fairly computer intensive, so what sometimes done is, to encrypt a one-time "secret key" with RSA technology is used, then encrypt the rest of the message with the secret key, then encrypt my signature in the second fashion. You then reverse this process, so if the message and the signature are readable, you and only you can read it and you are ensured that I sent the message.

OR

you can visit this link for more detailed explanation.

How do API Keys and Secret Keys work?

Solution 2

You need two separate keys, one that tells them who you are, and the other one that proves you are who you say you are.

The "key" is your user ID, and the "secret" is your password. They just use the "key" and "secret" terms because that's how they've implemented it.

Solution 3

Simple answer, if I understood it correctly...

If you use your API key for encryption, how will the service know who is contacting them? How will they decrypt that message?

You use API key to state who you are, this is what you are sending in plain text. The SECRET key you do not send to anyone. You simply use it for encryption. Then you send the encrypted message. You do not send the key that was used for encryption, that would defeat the purpose.

Solution 4

One thing that I did not see mentioned here, although it is an extension of Marcus Adams's answer, is that you should not be using a single piece of information to both identify and authenticate a user if there is a possibility of timing attacks, which can use the differences in response times to guess how far a string comparison got.

If you are using a system which uses a "key" to look up the user or credential, that piece of information could be incrementally guessed over time by sending thousands of requests and examining the time that it takes for your database to find (or not find) a record. This is especially true if the "key" is stored in plaintext instead of a one-way hash of the key. You would want to store users's keys in a plaintext or symmetrically-encrypted for if you need to be able to display the key to the user again.

By having a second piece of information, or "secret", you can first look up the user or credential using the "key", which could be vulnerable to a timing attack, then use a timing-safe compare function to check the value of the "secret".

Here is Python's implementation of that function:

https://github.com/python/cpython/blob/cd8295ff758891f21084a6a5ad3403d35dda38f7/Modules/_operator.c#L727

And it is exposed in the hmac lib (and probably others):

https://docs.python.org/3/library/hmac.html#hmac.compare_digest


One thing to note here is that I don't think that this kind of attack will work on values that are hashed or encrypted before lookup, because the values that are being compared change randomly each time a character in the input string changes. I found a good explanation of this here.

Solutions for storing API keys would then be:

  1. Use a separate key and secret, use the key to look up the record, and use a timing-safe compare to check the secret. This allows you to show the user the key and secret to a user again.
  2. Use a separate key and secret, use symmetrical, deterministic encryption on the secret, and do a normal comparison of encrypted secrets. This allows you to show the user the key and secret again, and could save you from having to implement a timing-safe comparison.
  3. Use a separate key and secret, display the secret, hash and store it, then do a normal comparison of the hashed secret. This removes the necessity to use two-way encryption, and has the added benefit of keeping your secret secure if the system is compromised. It has the downside that you cannot show the secret to the user again.
  4. Use a single key, show it to the user once, hash it, then do a normal lookup of the hashed or encrypted key. This uses a single key, but it is not able to be shown to the user again. Has the benefit of keeping keys secure if the system is compromised.
  5. Use a single key, show it to the user once, encrypt it, and do a normal lookup of the encrypted secret. Can be shown to the user again, but at the cost of having keys vulnerable if they system is compromised.

Of these, I think that 3 is the best balance of security and convenience. I have seen this implemented on many websites when getting keys issued.

Also, I invite any actual security experts to critique this answer. I just wanted to get this out there as another discussion point.

Solution 5

There are answers explaining what the secret and (public) key is. It's a public-private key pair that they give confusing names to. But nobody says why the APIs require both, and many APIs only give you one secret! I've also never seen any API's docs explain why they have two keys, so the best I can do is speculate...

It's best to put only your public key in your request and sign the request locally with your private key; sending anything more shouldn't be needed. But some get away with just having the secret in the request. Ok, any good API will use some transport security like TLS (usually over HTTPS). But you're still exposing your private key to the server that way, increasing the risk of them somehow mishandling it (see: GitHub and Twitter's password logging bug recently discovered). And HTTPS is theoretically just as secure, but there are always implementation flaws out there.

But many – actually most it seems – APIs have you send both keys in requests since that's easier than making people do their own signatures; can't have pure cURL examples otherwise! In that case, it's pointless to have them separate. I guess the separate keys are just for in case they change the API later to take advantage of them. Or some have a client library that might do it the more secure way.

Share:
61,923

Related videos on Youtube

EsTeGe
Author by

EsTeGe

I have a Master of Science degree in IT and have a lot of interests in computers, especially networking (infrastructure) and webdesign.

Updated on July 08, 2022

Comments

  • EsTeGe
    EsTeGe almost 2 years

    I came across many APIs that give the user both an API key and a secret. But my question is: what is the difference between both?

    In my eyes, one key can be enough. Say I have a key and only I and the server know it. I create a HMAC hash with this key and do an API call. On the server, we create the HMAC hash again and compare it with the sent hash. If it's the same, the call is authenticated.

    So why use two keys?

    Edit: or is that API key used to lookup the API secret?

  • Quintonn
    Quintonn almost 8 years
    Good answer, but when I use API secrets and keys with Facebook or Gmail etc, at no point do I have to encrypt or hash anything. In those cases, what is the point of the API secrets and keys?
  • Ryan Thomas
    Ryan Thomas about 7 years
    Using Facebook as an example there are two scenarios you would use app_secret. The first one does not require hashing. It's primarily used to prevent your redirect url from being hijacked. After a user logs in and grants your app access if facebook sent the access token directly to the redirect url you would have no way of verifying if the access token was from Facebook. I could post my own access token to your redirect url and execute facebook actions that would come from your api. Instead facebook sends a code to the redirect url. The api then exchanges the code for the actual access token.
  • Ryan Thomas
    Ryan Thomas about 7 years
    During the latter part, exchanging the code for the actual access token, facebook expects your api to verify it's identity with a signature. In this scenario they don't require public key cryptography for signing they simply trust you to keep your app secret truly secret and to use it as your signature. This always seemed silly to me to not go ahead and use a one way function to generate a signature but I suppose they have there reasons such as performance for settling for the direct use of app secret.
  • Ryan Thomas
    Ryan Thomas about 7 years
    In the second use case you do use cryptographic hashing. After you have the actual access_token to start interacting with facebook you may want extra security to prevent your app from being impersonated. In the Facebook app console you can turn on a feature that requires every facebook api request from your app to include your signature in addition to the access token. I'm just guessing at their motives but I think at this point they don't want you repeatedly sending app_secret as the signature with every request. The more you send it the greater the chance of app_secret being compromised.
  • Ryan Thomas
    Ryan Thomas about 7 years
    I suppose since you've opted into this extra security feature you've also made a decision of sorts to allow the extra performance overhead of Facebook verifying your signature with a cryptographic hash call on their end. Anyway in this scenario you pass two values with your Facebook api requests. The access_token and a value named appsecret_proof that serves as your signature. App secret proof is generated by cryptographic hashing of the access_token using app_secret as the key.
  • kamuniaft
    kamuniaft over 6 years
    And what if u are communicating over https? What's the point of encrypting your message with some secret key then?
  • sudo
    sudo almost 6 years
    There are plenty of APIs that just give you one secret value.
  • AndroC
    AndroC almost 6 years
    You do. You send the api key to the server. So, this means that you are giving that value to anyone who may be intercepting your communication with the server.
  • sudo
    sudo almost 6 years
    Almost every API I've seen has you send both the key and the secret to the server. The connection to the server is encrypted with theoretically the same level of security. But I never give either to anyone else besides the server.
  • AndroC
    AndroC almost 6 years
    I never saw sending secret in plain text. Can you give me a link? What I saw is using secret to encrypt some data. And along with the encrypted data, sending apiKey so that the server knows how to decrypt the data.
  • sudo
    sudo almost 6 years
    twilio.com/docs/sms/tutorials/… and nexmo.github.io/Quickstarts/sms/send are the examples I saw that prompted me to search on StackOverflow.
  • AndroC
    AndroC almost 6 years
    Twilio is not exactly using these terms. But Nexmo sure is... But, after a quick glance, it seems like they are just calling the data secret and apiKey and what they actually doing is username and password. Which is completely different thing...
  • mavili
    mavili over 5 years
    I'm surprised this has been selected as the accepted answer. The question asks about API keys and secret keys, which I don't think they have anything to do with public key cryptography or encryption. The one from Marcus Adams is really the answer to this question.
  • Yall
    Yall over 5 years
    The point is always to reduce risk. If the https communication is compromised, then an attacker that can read your request won't be able to forge new ones. If your API is about to rank pictures of cats, no big deal, if it's a payment API you better have multiple layers of security :)
  • gseattle
    gseattle about 5 years
    Misnomer. The public key can be thought of as a lock which is open. A site locks up a message to you snapping that lock closed, and only you have the secret key to open it. When they are the ones generating the pair, they keep the lock (public "key") and send you just the secret key.
  • mfaani
    mfaani almost 5 years
    "in the second fashion." What is that exactly?
  • mfaani
    mfaani almost 5 years
    @RyanThomas it would be great if you put that into some answer. Or even extract a question from the comment and add your answer to it. You never know what will happen to comments...
  • mfaani
    mfaani almost 5 years
    I suppose the purpose it's two separate keys, is because different users of a single client app can have different secrets, otherwise if they were to all have the same secret then having a key isn't useful. Right?
  • Stefan Haberl
    Stefan Haberl almost 4 years
    Why don‘t these API use Bearer: authentication for that? You would have an ID and a pwd there.
  • mavili
    mavili almost 4 years
    How is this the accepted answer. Question and this answer dont talk about the same things! OP is asking about API keys, not cryptogrphic keys. I'm surprised this has been accepted as the correct answer. The one from @Marcus Adams below should be the correct answer.