Primitives et interfaces

Nous définissons ensuite (informellement, mais ensuite de manière plus formelle), deux éléments importants de la langue utilisée dans Tink, le primitif et l'interface.

Primitif

Une primitive est un objet mathématique correspondant à tous les algorithmes l’exécution d’une tâche en toute sécurité. Par exemple, la primitive AEAD comprend de chiffrement répondant aux propriétés de sécurité requises par Tink d'un Aead.

Nous soulignons que les primitives ne sont pas liées à un langage de programmation chemin de y accéder. Au lieu de cela, il faut considérer le primitif comme le objet mathématique. Par exemple, si nous prenons l'exemple d'AEAD, se composent de paires de fonctions, l'une qui effectue le chiffrement et l'autre effectue le déchiffrement.

Interfaces

Une interface est un moyen par lequel nous fournissons aux utilisateurs un accès à une primitive. Par exemple, à l'avenir, Tink fournira une interface Mac, mais aussi d'une interface StreamingMac, qui permet de calculer des données qui ne sont pas directement chargées en mémoire.

Notez que nous distinguons ici explicitement les interfaces et les primitives. Cela devrait indiquer clairement que l'objet mathématique auquel ces deux interfaces donnent l'accès sont identiques.

Définitions formelles

Pour la plupart des lecteurs, les explications intuitives ci-dessus suffisent probablement. Néanmoins, nous pensons qu'il peut parfois être important de fournir une de ces concepts.

Fonctions cryptographiques

Le concept de fonction cryptographique n'est pas aussi important que le concept de primitive, mais nous devons l'introduire pour définir formellement la primitive.

Fonction cryptographique

Une fonction cryptographique est une fonction

\[ f: {\bf K} \times {\bf R} \times {\bf I} \to {\bf O}\]

à partir d'un ensemble \({\bf K}\) (l'espace clé), d'un ensemble \({\bf R} = \{0,1\}^{\infty}\) (caractère aléatoire, que nous supposons comme étant l'ensemble de chaînes de bits infinies) et set \({\bf I}\) (l'espace d'entrée) sur un ensemble \({\bf O}\) (l'espace de sortie).

Vous découvrirez plus tard pourquoi nous avons ajouté un paramètre de caractère aléatoire spécifique.

À titre d'exemple, nous montrons une possibilité de mise en correspondance de ces concepts AES-GCM Pour chaque taille de clé valide \(s_k\), taille de nonce \(s_n\)et taille de tag \(s_t\), AES-GCM se compose de deux fonctions cryptographiques, une pour le chiffrement et l’autre pour le déchiffrement. Les deux auront le même espace clé \({\bf K} = \{0,1\}^{s_k}\).

Pour la fonction de chiffrement \(\mathrm{Enc}\), les \(s_n\) premiers bits de le caractère aléatoire sera utilisé pour sélectionner le nonce.

Désignons \({\bf B} = \{0,1\}^8\) un octet. L'espace d'entrée de la fonction de chiffrement correspond aux paires \({\bf I} = {\bf B}^{*} \times {\bf B}^{*}\) de paires de chaînes d'octets de longueur arbitraire. Le premier élément de la paire est censé être le message, le second est les données associées. La norme AES-GCM impose une limite supérieure à la longueur aux entrées, mais nous préférons autoriser des longueurs arbitraires et ajouter à la place d'erreur \(\bot\) à l'espace de sortie. L'espace de sortie devient alors \({\bf O} = {\bf B}^* \cup \{\bot\}\), où nous définissons arbitrairement le résultat de les calculs réussis comme la concaténation \((\mathrm{IV} \| \mathrm{ciphertext} \| \mathrm{tag})\) comme indiqué dans la norme, et la sortie \(\bot\), au cas où une entrée serait trop longue. Par conséquent, pour une clé fixe, la fonction de chiffrement devient de type \(\mathrm{Enc}_k : {\bf R} \times {\bf B}^* \times {\bf B}^* \rightarrow {\bf B}^* \cup \{\bot\}\).

Pour la fonction de déchiffrement \(\mathrm{Dec}\) , l'espace clé est le même. La espace d'entrée est par coïncidence le même: \({\bf I} ={\bf B}^* \times {\bf B}^*\), mais maintenant le premier élément est censé être la sortie de la fonction de chiffrement, tandis que le second reste les données associées.

L'espace de sortie est également le même \({\bf O} = {\bf B}^* \cup \{\bot\}\) (c'est encore une coïncidence). L'interprétation est un peu différente, car \(\bot\) indique généralement une erreur d'authentification (bien qu'il s'agisse également de sortie au cas où une entrée serait trop longue).

Nous soulignons que la formalisation ci-dessus n'est pas la seule option pour formaliser standard. Par exemple, on peut considérer que le nonce fait partie de l'entrée, à la place de la lecture à partir du caractère aléatoire (ce qui se traduit par une primitive très différente). On peut également définir la sortie comme un triple contenant le nonce, le texte chiffré et le tag (au lieu de la concaténation). Ou peut-être limiter l'espace clé (de manière quelque peu arbitraire) à \({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)

Algorithme cryptographique:

Un algorithme cryptographique (symétrique) est un tuple

\[(f_1, ... f_k)\]

des fonctions cryptographiques, où toutes les fonctions ont le même espace de clé. La Le type de l'algorithme cryptographique est le tuple \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\).

Par exemple, pour chaque triple \((s_k, s_n, s_t)\) valide de clé, de nonce et de tag AES-GCM\({}_{s_k, s_n, s_t}\) est un algorithme cryptographique deux fonctions \(\mathrm{Enc}\) et \(\mathrm{Dec}\) décrites ci-dessus.

Primitives et interfaces

Nous allons ensuite définir une primitive cryptographique.

Primitif
Une primitive est un ensemble d'algorithmes cryptographiques dans lesquels tous les algorithmes sont du même type \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\), et les espaces clés des algorithmes sont disjoints par paire.

Prenons l'exemple de la primitive \(\mathrm{AEAD}\) dans Tink. Il comporte plusieurs tels que l'algorithme AES-GCM pour des clés de 128 et 256 bits, et le code nonce taille 96 bits, AES-EAX avec certaines tailles de clé et XChaCha20Poly1305. Ils ont espaces de clés disjoints, mais fournissent tous les mêmes fonctions cryptographiques \(\mathrm{Enc}\) et \(\mathrm{Dec}\). (Nous ne voyons pas un but en quelque sorte différentes tailles de clés d'AES-GCM dans cette discussion formelle, mais de bien sûr !).

Définir des primitives

Les primitives sont généralement considérées comme des primitives, lorsqu'elles définissent d'abord les propriétés des fonctions cryptographiques, puis d'envisager simplement la primitive ces algorithmes.

Par exemple, pour AEAD, nous dirons que \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a), a) = m\) est "always" Satisfait (e), sauf si le texte en clair \(m\) est trop (longue durée). De plus, nous avons des propriétés de sécurité : par exemple, pour une clé aléatoire, le chiffrement est sémantiquement sécurisé.

La primitive AEAD est simplement l'ensemble de tous les algorithmes cryptographiques qui sont conformes à ces propriétés. En d'autres termes, en pratique, lorsque nous définissons primitive, nous le définissons en fonction des propriétés. Nous ne donnons pas une liste de comme le suggère la définition.

Interfaces

Une interface dans Tink donne accès à une primitive, dans le sens où elle permet pour calculer un élément dans l'espace de sortie à partir de l'espace d'entrée. Par exemple : Prenons l'exemple de l'interface AEAD en Java:

public interface Aead {
  byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;
  byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;
}

Notez que nous n'accordons pas l'accès au caractère aléatoire. Au lieu de cela, nous permettons à l'utilisateur de fournissent les éléments de l'espace d'entrée. Interdire l'accès au caractère aléatoire est volontairement1.

Tink propose parfois plusieurs interfaces pour une même primitive. Cela peut s'avérer très utile, car les exigences diffèrent parfois. Malgré tout, faire cela a un prix: en général, plus une interface propose d'interfaces, l'interopérabilité. Par exemple, imaginez que quelqu'un écrit une bibliothèque basée sur Tink qui nécessite de transmettre Aead (pour chiffrer un élément en interne). Si Tink en propose trop interfaces différentes au \(\mathrm{AEAD}\) primitive, il y a de fortes chances que l'utilisateur n'a pas d'instance prête à l'emploi qui fonctionne pour la clé choisie par l'utilisateur et bibliothèque en même temps. Par conséquent, l'ajout d'autres interfaces est un compromis.


  1. Les chiffrements AEAD ont la propriété d'être sécurisés contre les attaques par texte chiffré choisi, ce qui n’est garanti que s’il n’y a pas la réutilisation du nonce. L'interface Aead de Tink est conçue pour empêche la réutilisation des nonces: l'utilisateur ne peut pas fournir de nonce comme entrée pour le chiffrement. à la place, un nouveau nonce est généré de manière aléatoire pour chaque opération de chiffrement.