¿Por qué utilizar una clave y un secreto de API?


93

Encontré muchas API que le dan al usuario tanto una clave de API como un secreto . Pero mi pregunta es: ¿cuál es la diferencia entre ambos?

En mi opinión, una llave puede ser suficiente. Digamos que tengo una clave y solo yo y el servidor la conocemos. Creo un hash HMAC con esta clave y hago una llamada a la API. En el servidor, creamos el hash HMAC nuevamente y lo comparamos con el hash enviado. Si es lo mismo, la llamada está autenticada.

Entonces, ¿por qué usar dos llaves?

Editar: ¿ o se usa esa clave API para buscar el secreto de la API?


Respuestas:


46

La criptografía de clave secreta se basa en usar la misma clave para codificar y luego decodificar un mensaje. Por lo tanto, solo aquellos que conocen el "secreto" pueden leer el mensaje.

La seguridad RSA se basa en 2 claves coincidentes. Hay una clave pública para cada usuario y todos pueden (deberían) conocerla. También hay una clave privada que solo el usuario debe conocer. Un mensaje cifrado por la clave pública solo puede ser descifrado por la clave privada y viceversa.

Así, si quiero enviarte un mensaje que solo tú puedes leer, obtengo (de la red) tu clave pública, cifro el mensaje con esa clave y tú eres la única persona que puede descifrarlo.

O, si quiero probarte que envié un mensaje, puedo encriptar el mensaje con mi clave privada, decirte (en texto abierto o en otro mensaje) cómo fue encriptado. Luego, podría descifrar el mensaje con mi clave pública y, si se vuelve legible, sabrá que provino de mí.

Esta forma de encriptación es bastante intensiva en computadoras, por lo que lo que a veces se hace es encriptar una "clave secreta" de un solo uso con tecnología RSA, luego encriptar el resto del mensaje con la clave secreta y luego encriptar mi firma de la segunda manera. Luego invierte este proceso para que, si el mensaje y la firma son legibles, usted y solo usted puede leerlo y está seguro de que yo envié el mensaje.

O

puede visitar este enlace para obtener una explicación más detallada.

¿Cómo funcionan las claves API y las claves secretas?


9
Buena respuesta, pero cuando utilizo secretos y claves de API con Facebook o Gmail, etc., en ningún momento tengo que cifrar o codificar nada. En esos casos, ¿cuál es el objetivo de los secretos y claves de la API?
Quintonn

2
Usando Facebook como ejemplo, hay dos escenarios en los que usaría app_secret. El primero no requiere hash. Se utiliza principalmente para evitar que su URL de redireccionamiento sea secuestrada. Después de que un usuario inicie sesión y le otorgue acceso a su aplicación si Facebook envió el token de acceso directamente a la URL de redireccionamiento, no tendría forma de verificar si el token de acceso era de Facebook. Podría publicar mi propio token de acceso a su URL de redireccionamiento y ejecutar acciones de Facebook que vendrían de su API. En cambio, Facebook envía un código a la URL de redireccionamiento. Luego, la api intercambia el código por el token de acceso real.
Ryan Thomas

2
Durante la última parte, al intercambiar el código por el token de acceso real, Facebook espera que su api verifique su identidad con una firma. En este escenario, no requieren criptografía de clave pública para firmar, simplemente confían en usted para mantener el secreto de su aplicación y usarlo como su firma. Siempre me pareció una tontería no seguir adelante y usar una función unidireccional para generar una firma, pero supongo que tienen razones como el rendimiento para conformarse con el uso directo del secreto de la aplicación.
Ryan Thomas

En el segundo caso de uso, usa hash criptográfico. Después de que tenga el access_token real para comenzar a interactuar con Facebook, es posible que desee seguridad adicional para evitar que su aplicación sea suplantada. En la consola de la aplicación de Facebook, puede activar una función que requiere que cada solicitud de la API de Facebook de su aplicación incluya su firma además del token de acceso. Solo estoy adivinando sus motivos, pero creo que en este punto no quieren que envíes repetidamente app_secret como firma con cada solicitud. Cuanto más lo envíe, mayor será la posibilidad de que app_secret se vea comprometida.
Ryan Thomas

1
Supongo que desde que optó por esta función de seguridad adicional, también tomó una especie de decisión para permitir la sobrecarga de rendimiento adicional de Facebook verificando su firma con una llamada de hash criptográfica en su extremo. De todos modos, en este escenario, pasa dos valores con sus solicitudes de api de Facebook. El access_token y un valor llamado appsecret_proof que sirve como su firma. La prueba secreta de la aplicación se genera mediante hash criptográfico del access_token utilizando app_secret como clave.
Ryan Thomas

55

Necesita dos claves separadas, una que les diga quién es usted y la otra que demuestre que es quien dice ser .

La "clave" es su ID de usuario y el "secreto" es su contraseña. Simplemente usan los términos "clave" y "secreto" porque así es como lo han implementado.


1
¿Y si te comunicas a través de https? Entonces, ¿cuál es el punto de encriptar su mensaje con una clave secreta?
kamuniaft

6
El punto es siempre reducir el riesgo. Si la comunicación https se ve comprometida, un atacante que pueda leer su solicitud no podrá falsificar otras nuevas. Si su API está a punto de clasificar imágenes de gatos, no es gran cosa, si es una API de pago, es mejor que tenga varias capas de seguridad :)
Yall

Supongo que el propósito son dos claves separadas, es porque diferentes usuarios de una sola aplicación cliente pueden tener diferentes secretos; de lo contrario, si todos tuvieran el mismo secreto, tener una clave no es útil. ¿Derecho?
Cariño

¿Por qué estas API no usan Bearer:autenticación para eso? Allí tendrías una identificación y una pwd.
Stefan Haberl

7

Respuesta simple, si la entendí correctamente ...

Si usa su clave API para el cifrado, ¿cómo sabrá el servicio quién se está comunicando con ellos? ¿Cómo descifrarán ese mensaje?

Utiliza la clave API para indicar quién es, esto es lo que está enviando en texto sin formato. La clave SECRETA no le envía a nadie. Simplemente utilícelo para el cifrado. Luego envías el mensaje encriptado. No envía la clave que se utilizó para el cifrado, eso anularía el propósito.


Tú lo haces. Envías la clave api al servidor. Entonces, esto significa que le está dando ese valor a cualquiera que pueda estar interceptando su comunicación con el servidor.
ancajic

Casi todas las API que he visto te hacen enviar tanto la clave como el secreto al servidor. La conexión al servidor está encriptada teóricamente con el mismo nivel de seguridad. Pero nunca se lo doy a nadie más que al servidor.
sudo

Nunca vi el envío secretde texto sin formato. ¿Puedes darme un enlace? Lo que vi es usar secretpara cifrar algunos datos. Y junto con los datos encriptados, enviando apiKeypara que el servidor sepa cómo desencriptar los datos.
ancajic

twilio.com/docs/sms/tutorials/… y nexmo.github.io/Quickstarts/sms/send son los ejemplos que vi que me llevaron a buscar en StackOverflow.
sudo

Twilio no utiliza exactamente estos términos. Pero Nexmo seguro que es ... Pero, después de un rápido vistazo, parece que sólo están pidiendo los datos secrety apiKeyy lo que realmente está haciendo es usernamey password. Que es una cosa completamente diferente ...
ancajic

3

Hay respuestas que explican qué es la clave secreta y (pública). Es un par de claves pública-privada al que le dan nombres confusos. Pero nadie dice por qué las API requieren ambos, ¡y muchas API solo le brindan un secreto! Tampoco he visto ningún documento de API que explique por qué tienen dos claves, así que lo mejor que puedo hacer es especular ...

Es mejor poner solo su clave pública en su solicitud y firmar la solicitud localmente con su clave privada; enviar nada más no debería ser necesario. Pero algunos se salen con la suya con solo tener el secreto en la solicitud. Ok, cualquier buena API usará alguna seguridad de transporte como TLS (generalmente sobre HTTPS). Pero todavía está exponiendo su clave privada al servidor de esa manera, lo que aumenta el riesgo de que de alguna manera la manejen mal (consulte: El error de registro de contraseñas de GitHub y Twitter descubierto recientemente). Y HTTPS es teóricamente igual de seguro, pero siempre existen fallas de implementación.

Pero muchas API, en realidad la mayoría, hacen que envíe ambas claves en las solicitudes, ya que es más fácil que hacer que las personas hagan sus propias firmas; de lo contrario, no se pueden tener ejemplos puros de cURL En ese caso, no tiene sentido separarlos. Supongo que las claves separadas son solo para en caso de que cambien la API más adelante para aprovecharlas. O algunos tienen una biblioteca cliente que podría hacerlo de manera más segura.


1

Una cosa que no vi que se menciona aquí, aunque es una extensión de la respuesta de Marcus Adams, es que no debería usar una sola pieza de información para identificar y autenticar a un usuario si existe la posibilidad de ataques de tiempo , que pueden utilice las diferencias en los tiempos de respuesta para adivinar hasta dónde llegó una comparación de cadenas.

Si está utilizando un sistema que usa una "clave" para buscar el usuario o la credencial, esa información podría adivinarse gradualmente con el tiempo enviando miles de solicitudes y examinando el tiempo que le toma a su base de datos encontrar (o no buscar) un registro. Esto es especialmente cierto si la "clave" se almacena en texto plano en lugar de un hash unidireccional de la clave. Querrá almacenar las claves de los usuarios en un texto plano o cifradas simétricamente si necesita poder mostrar la clave al usuario nuevamente.

Al tener una segunda información, o "secreto", primero puede buscar el usuario o la credencial usando la "clave", que podría ser vulnerable a un ataque de sincronización, luego use una función de comparación segura de sincronización para verificar el valor de el secreto".

Aquí está la implementación de Python de esa función:

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

Y está expuesto en la hmacbiblioteca (y probablemente en otros):

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


Una cosa a tener en cuenta aquí es que no creo que este tipo de ataque funcione con valores hash o cifrados antes de la búsqueda, porque los valores que se comparan cambian aleatoriamente cada vez que cambia un carácter en la cadena de entrada. Encontré una buena explicación de esto aquí .

Las soluciones para almacenar claves API serían:

  1. Use una clave y un secreto separados, use la clave para buscar el registro y use una comparación segura de tiempo para verificar el secreto. Esto le permite volver a mostrarle al usuario la clave y el secreto.
  2. Use una clave y un secreto separados, use un cifrado simétrico y determinista en el secreto y haga una comparación normal de los secretos cifrados. Esto le permite mostrarle al usuario la clave y el secreto nuevamente, y podría evitar que tenga que implementar una comparación segura en el tiempo.
  3. Use una clave y un secreto separados, muestre el secreto, hash y almacénelo, luego haga una comparación normal del secreto hash. Esto elimina la necesidad de utilizar encriptación bidireccional y tiene el beneficio adicional de mantener su secreto seguro si el sistema se ve comprometido. Tiene la desventaja de que no puede volver a mostrar el secreto al usuario.
  4. Use una sola clave , muéstresela al usuario una vez, hash y luego haga una búsqueda normal de la clave cifrada o hash. Utiliza una única clave, pero no se puede volver a mostrar al usuario. Tiene la ventaja de mantener las claves seguras si el sistema se ve comprometido.
  5. Utilice una única clave , muéstresela al usuario una vez, cifrela y realice una búsqueda normal del secreto cifrado. Se puede volver a mostrar al usuario, pero a costa de que las claves sean vulnerables si el sistema se ve comprometido.

De estos, creo que 3 es el mejor equilibrio entre seguridad y conveniencia. He visto esto implementado en muchos sitios web cuando se emiten claves.

Además, invito a cualquier experto en seguridad real a criticar esta respuesta. Solo quería sacar esto como otro punto de discusión.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.