El mejor enfoque para generar una clave API

89

Entonces, con muchos servicios diferentes actualmente, API de Google, API de Twitter, API de Facebook, etc.

Cada servicio tiene una clave API, como:

AIzaSyClzfrOzB818x55FASHvX4JuGQciR9lv7q

Todas las claves varían en longitud y los caracteres que contienen, me pregunto cuál es el mejor enfoque para generar una clave API.

No estoy pidiendo un lenguaje específico, solo el enfoque general para crear claves, en caso de que sean un cifrado de los detalles de la aplicación del usuario, o un hash, o un hash de una cadena aleatoria, etc. ¿Deberíamos preocuparnos por el algoritmo hash? (MSD, SHA1, bcrypt), etc.

Editar: he hablado con algunos amigos (correo electrónico / twitter) y me recomendaron usar un GUID con los guiones eliminados.

Sin embargo, esto me parece un poco complicado, con la esperanza de obtener algunas ideas más.

Phill
fuente
He respondido con más detalles aquí ... generando claves y usándolas como autenticación de hmac
Anshu Kumar

Respuestas:

58

Utilice un generador de números aleatorios diseñado para criptografía. Luego, codifica el número en base 64.

Este es un ejemplo de C #:

var key = new byte[32];
using (var generator = RandomNumberGenerator.Create())
    generator.GetBytes(key);
string apiKey = Convert.ToBase64String(key);
Edward Brey
fuente
2
Esto no es muy seguro, un atacante que obtenga acceso a su base de datos podría obtener la clave. Sería mejor generar la clave como un hash de algo único para el usuario (como una sal), combinado con un secreto del servidor.
James Wierzba
13
El almacenamiento de una clave de API generada aleatoriamente tiene las mismas características de seguridad que el almacenamiento de una contraseña hash. En la mayoría de los casos, está bien. Como sugiere, es posible considerar el número generado aleatoriamente como una sal y aplicar un hash con un secreto del servidor; sin embargo, al hacerlo, incurrirá en la sobrecarga de hash en cada validación. Tampoco hay forma de invalidar el secreto del servidor sin invalidar todas las claves de API.
Edward Brey
Buena solución, pero probablemente necesita la palabra clave var antes de apiKey :) var apiKey = Convert.ToBase64String (key);
Dawid Ohia
@ JohnM2 Correcto. Lo había dejado abierto, ya que apiKeypodría declararse en otro lugar. Agregué el tipo para mayor claridad.
Edward Brey
4
@JamesWierzba si el atacado ya está en su base de datos, entonces el hecho de que tengan acceso no seguro a su API es probablemente la menor de sus preocupaciones ...
Jon Story
29

Las claves de API deben tener las propiedades que:

  • Identificar de forma única a un usuario de API autorizado: la parte "clave" de la "clave API"
  • autenticar a ese usuario - no se puede adivinar / falsificar
  • se puede revocar si un usuario se comporta mal; por lo general, ingresan en una base de datos que puede eliminar un registro.

Por lo general, tendrá miles o millones de claves de API, no miles de millones, por lo que no es necesario que:

  • Almacene de manera confiable información sobre el usuario de la API porque se puede almacenar en su base de datos.

Como tal, una forma de generar una clave API es tomar dos piezas de información:

  1. un número de serie para garantizar la singularidad
  2. suficientes bits aleatorios para rellenar la clave

y firmarlos utilizando un secreto privado.

El contador garantiza que identifican de forma única al usuario y la firma evita la falsificación. La revocabilidad requiere verificar que la clave aún sea válida en la base de datos antes de hacer cualquier cosa que requiera autorización de clave API.

Un buen generador de GUID es una aproximación bastante buena de un contador incrementado si necesita generar claves desde varios centros de datos o no tiene una buena forma distribuida de asignar números de serie.


o un hash de una cadena aleatoria

El hash no evita la falsificación. Firmar es lo que garantiza que la clave vino de usted.

Mike Samuel
fuente
3
¿Es necesario el paso de firma de su algoritmo si la clave API presentada por un cliente se compara con una base de datos de claves API ya registradas en el servidor que proporciona la API? Parece que la firma sería redundante aquí si el servidor es el que proporciona las claves.
sappenin
3
@sappenin, sí. Si almacena una clave que no se puede adivinar en el servidor, no necesita evitar la falsificación. A menudo, las solicitudes de API son manejadas por cualquiera de una granja de máquinas: el servidor es uno de muchos servidores. La verificación de firmas se puede realizar en cualquier máquina sin un viaje de ida y vuelta a una base de datos que puede evitar condiciones de carrera en algunos casos.
Mike Samuel
1
@MikeSamuel si la clave API está firmada y no realiza un viaje de ida y vuelta a la base de datos, ¿qué sucede cuando la clave se revoca pero aún se usa para acceder a la API?
Abhyudit Jain
@AbhyuditJain, en cualquier sistema distribuido, necesita un orden de mensajes coherente (las revocaciones ocurren antes de los usos posteriores de las credenciales revocadas) u otras formas de limitar la ambigüedad. Algunos sistemas no realizan un recorrido de ida y vuelta en cada solicitud: si un nodo almacena en caché el hecho de que una clave estuvo en la base de datos durante 10 minutos, solo hay 10 minutos. ventana en la que un atacante puede abusar de una credencial revocada. Sin embargo, puede producirse una posible confusión: el usuario revoca una credencial, luego prueba que está revocada y se sorprende porque las sesiones no permanentes hacen que las dos solicitudes vayan a nodos diferentes.
Mike Samuel
5

Utilizo UUID, formateados en minúsculas sin guiones.

La generación es fácil ya que la mayoría de los idiomas lo tienen integrado.

Las claves de API pueden verse comprometidas, en cuyo caso un usuario puede querer cancelar su clave de API y generar una nueva, por lo que su método de generación de claves debe poder satisfacer este requisito.

Adam Ralph
fuente
15
No asuma que los UUID son difíciles de adivinar; no deben utilizarse como capacidades de seguridad (UUID especificación RFC4122 sección 6 ). Una clave de API necesita un número aleatorio seguro, pero los UUID no son imposibles de adivinar de forma segura .
Edward Brey
3
@EdwardBrey ¿qué pasa UUID uuid = UUID.randomUUID();en Java? ¿Estás diciendo que el azar no es lo suficientemente bueno?
Micro
8
@MicroR Un UUID aleatorio es seguro solo si el generador de números aleatorios utilizado para hacerlo es criptográficamente seguro y 128 bits son suficientes. Aunque el UUID RFC no requiere un generador de números aleatorios seguro, una implementación dada es libre de usar uno. En el caso de randomUUID , los documentos de la API establecen específicamente que utiliza un "generador de números pseudoaleatorios criptográficamente fuerte". Entonces, esa implementación particular es segura para una clave API de 128 bits.
Edward Brey
4

Si desea una clave de API con solo caracteres alfanuméricos, puede usar una variante del enfoque base64-random , solo usando una codificación base-62 en su lugar. El codificador base-62 se basa en esto .

public static string CreateApiKey()
{
    var bytes = new byte[256 / 8];
    using (var random = RandomNumberGenerator.Create())
        random.GetBytes(bytes);
    return ToBase62String(bytes);
}

static string ToBase62String(byte[] toConvert)
{
    const string alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    BigInteger dividend = new BigInteger(toConvert);
    var builder = new StringBuilder();
    while (dividend != 0) {
        dividend = BigInteger.DivRem(dividend, alphabet.Length, out BigInteger remainder);
        builder.Insert(0, alphabet[Math.Abs(((int)remainder))]);
    }
    return builder.ToString();
}
Edward Brey
fuente
1

Una clave de API debe ser un valor aleatorio. Lo suficientemente aleatorio como para que no se pueda predecir. No debe contener ningún dato del usuario o de la cuenta a la que pertenece. Usar UUID es una buena idea, si está seguro de que los ID creados son aleatorios.

Las versiones anteriores de Windows producían GUID predecibles, por ejemplo, pero esta es una vieja historia.

Dave Van den Eynde
fuente
4
Windows 2000 cambió a GUID mediante números aleatorios . Sin embargo, no hay garantía de que los números aleatorios no se puedan predecir. Por ejemplo, si un atacante crea varias claves de API para sí mismo, es posible que se pueda determinar un número aleatorio futuro que se utilizará para generar la clave de API de otro usuario. En general, no considere que los UUID sean imposibles de adivinar de forma segura .
Edward Brey