Meilleure approche pour générer une clé API

89

Donc, avec de nombreux services différents actuellement, des API Google, des API Twitter, des API Facebook, etc.

Chaque service a une clé API, comme:

AIzaSyClzfrOzB818x55FASHvX4JuGQciR9lv7q

Toutes les clés varient en longueur et les caractères qu'elles contiennent, je me demande quelle est la meilleure approche pour générer une clé API?

Je ne demande pas un langage spécifique, juste l'approche générale de la création de clés, devrait-il s'agir d'un cryptage des détails de l'application des utilisateurs, ou d'un hachage, ou d'un hachage d'une chaîne aléatoire, etc. Devrions-nous nous soucier de l'algorithme de hachage (MSD, SHA1, bcrypt) etc?

Edit: J'ai parlé à quelques amis (email / twitter) et ils ont recommandé d'utiliser simplement un GUID avec les tirets supprimés.

Cela me semble un peu hacky cependant, dans l'espoir d'avoir plus d'idées.

Phill
la source
J'ai répondu plus en détail ici .. générer des clés et les utiliser comme authentification hmac
Anshu Kumar

Réponses:

58

Utilisez un générateur de nombres aléatoires conçu pour la cryptographie. Puis base-64 encodez le nombre.

Ceci est un exemple C #:

var key = new byte[32];
using (var generator = RandomNumberGenerator.Create())
    generator.GetBytes(key);
string apiKey = Convert.ToBase64String(key);
Edward Brey
la source
2
Ce n'est pas très sécurisé, un attaquant qui accède à votre base de données pourrait obtenir la clé. Il serait préférable de générer la clé sous la forme d'un hachage de quelque chose d'unique à l'utilisateur (comme un sel), combiné avec un secret de serveur.
James Wierzba
13
Le stockage d'une clé API générée aléatoirement présente les mêmes caractéristiques de sécurité que le stockage d'un mot de passe haché. Dans la plupart des cas, ça va. Comme vous le suggérez, il est possible de considérer le nombre généré aléatoirement comme un sel et de le hacher avec un secret de serveur; cependant, ce faisant, vous encourez la surcharge de hachage à chaque validation. Il n'y a également aucun moyen d'invalider le secret du serveur sans invalider toutes les clés API.
Edward Brey
Bonne solution, mais vous avez besoin du mot-clé var avant apiKey probablement :) var apiKey = Convert.ToBase64String (key);
Dawid Ohia
@ JohnM2 C'est vrai. Je l'avais laissé ouvert, puisque apiKeyje pouvais être déclaré ailleurs. J'ai ajouté le type pour plus de clarté.
Edward Brey
4
@JamesWierzba si l'attaqué est déjà dans votre base de données, alors le fait d'avoir un accès non sécurisé à votre API est probablement la moindre de vos préoccupations ...
Jon Story
29

Les clés API doivent avoir les propriétés qu'elles:

  • identifier de manière unique un utilisateur API autorisé - la partie "clé" de la "clé API"
  • authentifier cet utilisateur - ne peut pas être deviné / falsifié
  • peut être révoqué si un utilisateur se comporte mal - en général, il saisit une base de données qui peut avoir un enregistrement supprimé.

En règle générale, vous aurez des milliers ou des millions de clés API et non des milliards, elles n'ont donc pas besoin de:

  • Stockez de manière fiable des informations sur l'utilisateur de l'API, car elles peuvent être stockées dans votre base de données.

En tant que tel, une façon de générer une clé API consiste à prendre deux informations:

  1. un numéro de série pour garantir l'unicité
  2. assez de bits aléatoires pour compléter la clé

et signez-les en utilisant un secret privé.

Le compteur garantit qu'ils identifient de manière unique l'utilisateur et la signature empêche la falsification. La révocabilité nécessite de vérifier que la clé est toujours valide dans la base de données avant de faire quoi que ce soit qui nécessite une autorisation de clé API.

Un bon générateur de GUID est une assez bonne approximation d'un compteur incrémenté si vous avez besoin de générer des clés à partir de plusieurs centres de données ou si vous ne disposez pas d'une bonne manière distribuée d'attribuer des numéros de série.


ou un hachage d'une chaîne aléatoire

Le hachage n'empêche pas la contrefaçon. La signature est ce qui garantit que la clé vient de vous.

Mike Samuel
la source
3
L'étape de signature de votre algorithme est-elle nécessaire si la clé API présentée par un client est comparée à une base de données de clés API déjà enregistrées sur le serveur fournissant l'API? On dirait que la signature serait redondante ici si le serveur est celui qui fournit les clés.
sappenin le
3
@sappenin, oui. Si vous stockez une clé impossible à deviner sur le serveur, vous n'avez pas besoin d'empêcher la falsification. Souvent, les demandes d'API sont gérées par l'un quelconque d'une batterie de machines - le serveur est l'un des nombreux serveurs. La vérification de signature peut être effectuée sur n'importe quelle machine sans aller-retour vers une base de données, ce qui peut éviter les conditions de course dans certains cas.
Mike Samuel
1
@MikeSamuel si la clé API est signée et que vous ne faites pas d'aller-retour vers la base de données, que se passe-t-il lorsque la clé est révoquée mais toujours utilisée pour accéder à l'API?
Abhyudit Jain
@AbhyuditJain, Dans tout système distribué, vous avez besoin d'un ordre des messages cohérent (les révocations se produisent avant les utilisations ultérieures des informations d'identification révoquées) ou d'autres moyens de limiter l'ambiguïté. Certains systèmes n'effectuent pas un aller-retour à chaque demande - si un nœud met en cache le fait qu'une clé était dans la base de données pendant 10 minutes, il n'y a que 10 minutes. fenêtre dans laquelle un attaquant peut abuser d'un identifiant révoqué. Une confusion possible peut cependant en résulter: l'utilisateur révoque une information d'identification, puis teste qu'elle est révoquée, et est surpris car les sessions non persistantes amènent les deux requêtes à aller vers des nœuds différents.
Mike Samuel
5

J'utilise des UUID, formatés en minuscules sans tirets.

La génération est facile car la plupart des langues l'ont intégrée.

Les clés API peuvent être compromises, auquel cas un utilisateur peut souhaiter annuler sa clé API et en générer une nouvelle, votre méthode de génération de clé doit donc être en mesure de répondre à cette exigence.

Adam Ralph
la source
15
Ne supposez pas que les UUID sont difficiles à deviner; ils ne doivent pas être utilisés comme capacités de sécurité (spécification UUID RFC4122 section 6 ). Une clé API a besoin d'un nombre aléatoire sécurisé, mais les UUID ne sont pas impossibles à deviner en toute sécurité .
Edward Brey
3
@EdwardBrey qu'en est-il UUID uuid = UUID.randomUUID();en Java? Êtes-vous en train de dire que le hasard n'est pas assez bon?
Micro
8
@MicroR Un UUID aléatoire n'est sécurisé que si le générateur de nombres aléatoires utilisé pour le créer est cryptographiquement sécurisé et que 128 bits sont suffisants. Bien que la RFC UUID ne nécessite pas de générateur de nombres aléatoires sécurisé, une implémentation donnée est libre d'en utiliser un. Dans le cas de randomUUID , la documentation de l'API indique spécifiquement qu'elle utilise un "générateur de nombres pseudo-aléatoires cryptographiquement puissant". Cette implémentation particulière est donc sécurisée pour une clé API de 128 bits.
Edward Brey
4

Si vous voulez une clé API avec uniquement des caractères alphanumériques, vous pouvez utiliser une variante de l' approche base64-random , en utilisant uniquement un encodage base-62 à la place. L'encodeur base 62 est basé sur cela .

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
la source
1

Une clé API doit être une valeur aléatoire. Assez aléatoire pour que cela ne puisse être prédit. Il ne doit contenir aucun détail sur l'utilisateur ou le compte auquel il est destiné. L'utilisation des UUID est une bonne idée, si vous êtes certain que les ID créés sont aléatoires.

Les versions antérieures de Windows produisaient des GUID prévisibles, par exemple, mais c'est une vieille histoire.

Dave Van den Eynde
la source
4
Windows 2000 est passé aux GUID en utilisant des nombres aléatoires . Cependant, rien ne garantit que les nombres aléatoires ne peuvent pas être prédits. Par exemple, si un attaquant crée plusieurs clés API pour lui-même, il peut être possible de déterminer un futur nombre aléatoire utilisé pour générer la clé API d'un autre utilisateur. En général, ne considérez pas les UUID comme impossible à deviner en toute sécurité .
Edward Brey