Collections de clés

Tink utilise des collections de clés pour activer la rotation des clés. Officiellement, une collection de clés est une liste non vide1 de clés dans laquelle une clé est désignée comme clé primaire (la clé utilisée par exemple pour signer et chiffrer de nouveaux textes bruts). En outre, les clés d'une collection de clés obtiennent un identifiant unique2 et un état de clé qui permet de désactiver des clés sans les supprimer d'une collection.

Les collections de clés sont le principal moyen pour les utilisateurs d'accéder aux clés (via la classe KeysetHandle). Ainsi, chaque utilisateur dispose du code pour gérer plusieurs clés à la fois. Pour la plupart des utilisateurs de cryptographie, gérer plusieurs clés est nécessaire: il doit être possible de changer de clé (les anciennes clés peuvent être divulguées, par exemple), et il n'y a presque jamais de "passer à la clé suivante" atomique qui peut être appliqué aux machines que le code exécute et à l'ensemble du texte chiffré, à l'échelle mondiale et instantanément. Par conséquent, l'utilisateur doit écrire du code qui fonctionne lorsqu'une touche passe d'une touche à l'autre.

Exemple: AEAD

Prenons l'exemple d'une collection de clés AEAD, qui contient plusieurs clés pour la primitive AEAD. Comme expliqué précédemment, chaque clé spécifie deux fonctions de manière unique : \(\mathrm{Enc}\) et \(\mathrm{Dec}\). Désormais, la collection de clés spécifie également deux nouvelles fonctions: \(\mathrm{Enc}\) . \(\mathrm{Dec}\) - \(\mathrm{Enc}\) équivaut simplement à la fonction \(\mathrm{Enc}\) de la clé primaire de la collection de clés, tandis que la fonction \(\mathrm{Dec}\) tente de déchiffrer toutes les clés, en les parcourant dans un certain ordre (voir ci-dessous pour découvrir comment Tink améliore les performances).

Il est intéressant de noter que les collections de clés sont des clés complètes : elles offrent une description complète des fonctions \(\mathrm{Enc}\) et\(\mathrm{Dec}\) utilisées. Cela signifie que les utilisateurs peuvent écrire une classe qui reçoit en entrée une KeysetHandle, exprimant l'idée que la classe a besoin d'une description complète des objets \(\mathrm{Enc}\) et \(\mathrm{Dec}\) pour fonctionner correctement. Cela permet à l'utilisateur d'écrire des API qui communiquent que: pour utiliser cette classe, vous devez me fournir la description d'une primitive cryptographique.

Rotation des clés

Prenons l'exemple d'un utilisateur Tink écrivant un programme qui obtient d'abord une collection de clés d'un service de gestion des clés, puis crée un objet AEAD à partir de cette collection, puis utilise cet objet pour chiffrer et déchiffrer les textes chiffrés.

Un tel utilisateur est automatiquement préparé à la rotation des clés et change d'algorithme au cas où son choix actuel ne répondait plus à la norme.

Il faut toutefois être prudent lors de la mise en œuvre d'une telle rotation des clés : tout d'abord, le service de gestion des clés doit ajouter une nouvelle clé à la collection de clés (mais pas encore la définir comme clé principale). Ensuite, la nouvelle collection de clés doit être déployée auprès de tous les binaires, de sorte que chaque binaire utilisant cette collection dispose de la clé la plus récente. Ce n'est qu'alors que la nouvelle clé doit être définie comme principale pour que la collection de clés obtenue soit à nouveau distribuée à tous les binaires à l'aide de celle-ci.

Identifiants clés dans le texte chiffré

Prenons à nouveau l'exemple d'une collection de clés AEAD. Si cela est fait naïvement, le déchiffrement d'un texte chiffré nécessite que Tink tente d'effectuer le déchiffrement avec toutes les clés de la collection de clés, car il n'y a aucun moyen de savoir quelle clé a été utilisée pour chiffrer la collection. Cela peut avoir un impact important sur les performances.

De ce fait, Tink permet de préfixer les textes chiffrés avec une chaîne de cinq octets dérivée de l'ID. Conformément à la philosophie des "clés complètes" ci-dessus, ce préfixe fait partie de la clé, et tous les textes chiffrés dérivés avec cette clé doivent avoir ce préfixe. Lorsque les utilisateurs créent des clés, ils peuvent choisir d'utiliser un tel préfixe pour la clé ou d'utiliser un format de texte chiffré sans.

Lorsqu'une clé se trouve dans une collection de clés, Tink calcule ce tag à partir de l'ID de la clé dans la collection de clés. Le fait que les ID soient uniques2 dans une collection de clés implique que les tags sont uniques. Par conséquent, si seules des clés avec tag sont utilisées, il n'y a pas de perte de performances par rapport au déchiffrement avec une seule clé: Tink n'a besoin d'essayer que l'une des clés lors du déchiffrement.

Toutefois, comme le tag fait partie de la clé, cela implique également que celle-ci ne peut figurer dans une collection de clés que si elle possède un ID spécifique. Cela a des implications pour la description de l'implémentation d'objets clés dans différents langages.


  1. Certaines parties de Tink traitent toujours les collections de clés comme un ensemble. Toutefois, cela doit être modifié. En effet, l'ordre est généralement important: par exemple, considérons le cycle de vie typique d'une rotation des clés avec Aead. Tout d'abord, une nouvelle clé est ajoutée à une collection de clés. Cette clé n'est pas encore définie comme principale, mais elle est active. Cette nouvelle collection de clés est déployée pour tous les binaires. Une fois que tous les binaires connaissent la nouvelle clé, la clé devient principale (ce n'est qu'à ce stade que l'utilisation de cette clé est sûre). Dans cette deuxième étape, la rotation des clés doit connaître la dernière clé ajoutée. 

  2. Pour assurer la compatibilité avec une bibliothèque interne de Google, Tink permet de disposer de collections de clés dans lesquelles les ID sont répétés. À l'avenir, cette prise en charge ne sera plus disponible.