プリミティブとインターフェース
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
次に、(非公式に、より正式に)2 つの重要な
Tink、Primitive、Interface で使用されている言語
基本ロール
プリミティブは、すべてのアルゴリズムに対応する数学的オブジェクト
安全に実行できます。たとえば、AEAD プリミティブはすべての
Tink が要求するセキュリティ特性を満たす暗号化アルゴリズム
Aead の 1 つです。
プリミティブは、プログラミング言語や特定のソフトウェアに
あります。プリミティブとは単に
使用できます。たとえば、AEAD を考慮すると、基本的には
暗号化を実行する関数と、暗号化を実行する関数、
復号を実行します。
インターフェース
インターフェースとは、ユーザーがプリミティブにアクセスできるようにするための方法です。
たとえば、Tink は将来的に Mac
インターフェースを提供する予定です。
さらに StreamingMac
インターフェースも存在し、このインターフェースでは
メモリに直接読み込まれていないデータです
ここではインターフェースとプリミティブを明示的に区別しています。これにより、
この 2 つのインターフェースが与える数学的オブジェクトが
アクセス権は同じです。
ほとんどの読者は、上記の直感的な説明で十分でしょう。
それでも、ときには正式な
学びました。
暗号関数
暗号関数の概念は、暗号技術の概念ほど重要ではない
ただし、プリミティブを正式に定義するには導入する必要があります。
- 暗号関数
暗号関数は
\[ f: {\bf K} \times {\bf R} \times {\bf I} \to {\bf O}\]
集合 \({\bf K}\) (キースペース)、集合 \({\bf R} = \{0,1\}^{\infty}\)
(ランダム性、つまり無限のビット文字列の集合と想定)
set \({\bf I}\) (入力空間)を set \({\bf O}\) (出力空間)に設定します。
特定のランダム性パラメータを追加した理由は、後で明らかになります。
例として、これらのコンセプトをマッピングする方法の 1 つを示します。
AES-GCM有効なキーサイズ \(s_k\)、ノンスサイズ \(s_n\)、タグサイズごとに、
\(s_t\): AES-GCM は、2 つの暗号関数で構成されています。
1 つは暗号化用でもう 1 つは復号用ですどちらも同じキースペース \({\bf
K} = \{0,1\}^{s_k}\)を持ちます。
暗号化関数 \(\mathrm{Enc}\)の場合、最初の \(s_n\) ビットは
ノンスの選択にランダム性が使用されます。
\({\bf B} = \{0,1\}^8\) はバイトを表します。
暗号化関数の入力空間は、任意の長さのバイト文字列のペア \({\bf I} = {\bf B}^{*}
\times {\bf B}^{*}\) です。
ペアの最初の要素はメッセージであり、2 つ目の要素はメッセージです。
関連付けられていますAES-GCM 標準では、長さに上限があります。
任意の長さを許容し、代わりに特別な長さの
エラー記号 \(\bot\) を出力スペースに追加します。出力空間は \({\bf
O} = {\bf B}^* \cup \{\bot\}\)になります。ここで、
成功した計算の数(標準、出力で指定される連結)と \((\mathrm{IV} \|
\mathrm{ciphertext} \| \mathrm{tag})\)
\(\bot\): 一部の入力が長すぎる場合。したがって、固定キーの場合、
暗号化関数が \(\mathrm{Enc}_k : {\bf R} \times {\bf B}^*
\times {\bf B}^* \rightarrow {\bf B}^* \cup \{\bot\}\)型になります。
復号関数では \(\mathrm{Dec}\) キースペースは同じです。「
入力空間が偶発的に同じ: \({\bf I} ={\bf B}^* \times {\bf B}^*\)、
最初の要素は暗号化関数の出力になります
2 つ目は関連データです
出力空間も偶然に \({\bf O} = {\bf B}^* \cup
\{\bot\}\) なります。解釈は若干異なりますが、
as \(\bot\) は通常、認証エラーを示します(
(一部の入力が長すぎる場合に備えて出力など)です。
上記の形式化が唯一の選択肢ではないことを強調しておきます。
あります。たとえば、ノンスを入力の一部とみなすことができますが、
(まったく異なるプリミティブが生成されます)。
または、出力をノンスを含むトリプルとして定義することもできます。
(連結ではなく)暗号テキスト、タグで構成されます。または
キースペースを(任意に)制限して、
\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)。
- 暗号アルゴリズム:
(対称)暗号アルゴリズムはタプル
\[(f_1, ... f_k)\]
すべての関数が同じ鍵空間を持つ暗号関数の集合です。「
暗号アルゴリズムの型はタプル \((({\bf I}_1, {\bf
O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)です。
たとえば、キー、ノンス、タグの \((s_k, s_n, s_t)\) 有効なトリプルごとに、
AES-GCM\({}_{s_k, s_n, s_t}\) という暗号化アルゴリズムで
2 つの関数 \(\mathrm{Enc}\) と \(\mathrm{Dec}\) 前述のとおりです。
プリミティブとインターフェース
次に、暗号プリミティブを定義します。
- 基本ロール
- プリミティブとは、すべてのアルゴリズムが
\((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf
O}_k))\)型が同じで、アルゴリズムのキースペースがペア単位で互いに素である。
例として、Tink の \(\mathrm{AEAD}\) プリミティブについて考えてみましょう。複数の
その中には、鍵サイズが 128 ビットと 256 ビットの AES-GCM の
96 ビット AES-EAX(一部の鍵サイズ)、XChaCha20Poly1305 があります。持っている
互いに素であるものの、どれも同じ暗号機能を提供する
\(\mathrm{Enc}\) および \(\mathrm{Dec}\)。(どういうわけか目的が
この正式な議論では、AES-GCM の異なる鍵サイズをまとめていますが、
できます)。
プリミティブの定義
プリミティブの通常の考え方としては、最初に
そのプリミティブをすべての暗号関数とみなして、
保護します。
たとえば、AEAD の場合、 \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a),
a) = m\) は「always」とします。(ただし、たとえば平文が \(m\) 非常に
。さらに、Google にはセキュリティ特性があります。たとえば
暗号化は意味的に安全です。
AEAD プリミティブは、簡単に言えば、暗号アルゴリズムの集合体であり、
次の条件を満たす必要があります。言い換えると、実際には、特定のサービス アカウントを
プロパティに基づいて定義します。リストには、
定義できます。
インターフェース
Tink のインターフェースは、次の意味でプリミティブへのアクセスを提供します。
を使用して、入力空間から出力空間の要素を計算します。たとえば
Java の AEAD インターフェースについて考えてみましょう。
public interface Aead {
byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;
byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;
}
ランダム性にはアクセスできません。代わりに ユーザーは
入力空間の要素を提供します。ランダム性へのアクセスを禁止するには、
コースを意図的に提供しています1。
Tink は、1 つのプリミティブに複数のインターフェースを提供することがあります。
要件が異なることがあるため、これは非常に便利です。それでも、
代償が伴う: 一般に、提供するインターフェースが多ければ多いほど、
相互運用性を確保できますたとえば
ユーザーが Tink に基づいてライブラリを記述し、
Aead
オブジェクト(内部で暗号化するため)。Tink で提供される特典の数が多すぎる場合、
インターフェースが異なるため、 \(\mathrm{AEAD}\)
ユーザーが
ユーザーが選択したキーで機能するインスタンスの準備が整っていません。
同時に使用できます。そのため、インターフェースを増やすことはトレードオフとなります。
特に記載のない限り、このページのコンテンツはクリエイティブ・コモンズの表示 4.0 ライセンスにより使用許諾されます。コードサンプルは Apache 2.0 ライセンスにより使用許諾されます。詳しくは、Google Developers サイトのポリシーをご覧ください。Java は Oracle および関連会社の登録商標です。
最終更新日 2025-07-25 UTC。
[null,null,["最終更新日 2025-07-25 UTC。"],[[["\u003cp\u003eTink uses Primitives, which are mathematical representations of secure algorithms, and Interfaces, which provide user access to these Primitives.\u003c/p\u003e\n"],["\u003cp\u003ePrimitives are defined by the security properties they satisfy, for example, AEAD requires semantic security and correct decryption.\u003c/p\u003e\n"],["\u003cp\u003eInterfaces in Tink provide controlled access to Primitives, often abstracting away internal details like randomness generation for security reasons.\u003c/p\u003e\n"],["\u003cp\u003eOffering multiple Interfaces for the same Primitive can improve flexibility but may reduce interoperability between different Tink users or libraries.\u003c/p\u003e\n"],["\u003cp\u003eWhile Primitives are abstract and language-independent, Interfaces are specific to a programming language and provide a way for users to interact with the underlying algorithms.\u003c/p\u003e\n"]]],["Tink defines *Primitives* as mathematical objects representing secure algorithms, like AEAD, which consists of encryption/decryption functions. *Interfaces* are the means to access these primitives. A *Cryptographic Function* maps keys, randomness, and input to output. A *Cryptographic Algorithm* is a tuple of such functions with the same key space. A *Primitive* is a set of Cryptographic Algorithms that have the same type and disjoint key spaces. Interfaces grant users access to the primitive's output, without providing access to randomness.\n"],null,["# Primitives and Interfaces\n\nWe next define (informally, but then more formally), two important pieces of\nthe language used in Tink, the *Primitive* and the *Interface*.\n\nPrimitive\n---------\n\nA primitive is a *mathematical* object corresponding to all algorithms\nperforming some task securely. For example, the AEAD primitive consists of all\nencryption algorithms which satisfy [the security properties which Tink requires\nof an Aead](https://developers.google.com/tink/aead#minimal_security_guarantees).\n\nWe stress that primitives are not bound to a programming language, or a specific\nway of\naccessing them. Instead, one should think of the primitive as the purely\nmathematical object. For example, if we consider AEAD, fundamentally it will\nconsist of pairs of functions, one which performs encryption, and one which\nperforms decryption.\n\nInterfaces\n----------\n\nAn interface is a way in which we provide users access to a primitive.\nFor example, we expect that in the future Tink will provides a `Mac` interface,\nbut also a `StreamingMac` interface, which allows to compute the mac of\ndata which is not directly loaded into memory.\n\nNote that we explicitly distinguish interfaces and primitives here. This should\nmake clear that the mathematical object to which these two interfaces give\naccess are the same.\n\nFormal definitions\n------------------\n\nFor most readers, the above intuitive explanations are probably enough.\nNevertheless, we feel that it can be important sometimes to provide formal\ndefinitions of these concepts.\n\n### Cryptographic functions\n\nThe concept of a cryptographic function is not as important as the concept of a\nprimitive, but we need to introduce it to formally define primitive.\n\nCryptographic Function\n\n: A *cryptographic function* is a map\n\n \\\\\\[ f: {\\\\bf K} \\\\times {\\\\bf R} \\\\times {\\\\bf I} \\\\to {\\\\bf O}\\\\\\]\n\n from a set \\\\({\\\\bf K}\\\\) (the key space), a set \\\\({\\\\bf R} = \\\\{0,1\\\\}\\^{\\\\infty}\\\\)\n (randomness, which we assume to be the set of infinite bitstrings), and a\n set \\\\({\\\\bf I}\\\\) (the input space), to a set \\\\({\\\\bf O}\\\\) (the output space).\n\nIt will become clear later why we added a specific randomness parameter.\n\nAs an example, we show one possibility how these concepts can be mapped to\nAES-GCM. For each valid key size \\\\(s_k\\\\), nonce size \\\\(s_n\\\\), and tag size\n\\\\(s_t\\\\), AES-GCM consists of two cryptographic functions, one for\nencryption, and one for decryption. Both will have the same key space \\\\({\\\\bf\nK} = \\\\{0,1\\\\}\\^{s_k}\\\\).\n\nFor the encryption function \\\\(\\\\mathrm{Enc}\\\\), the first \\\\(s_n\\\\) bits of\nrandomness will be used to select the nonce.\n\nLet \\\\({\\\\bf B} = \\\\{0,1\\\\}\\^8\\\\) denote a byte.\nThe input space of the encryption function is the pairs \\\\({\\\\bf I} = {\\\\bf B}\\^{\\*}\n\\\\times {\\\\bf B}\\^{\\*}\\\\) of pairs of byte strings of arbitrary length.\nThe first element of the pair is meant to be the message, the second element is\nthe associated data. The AES-GCM standard has an upper limit on the lengths of\nthe inputs, but we prefer to allow arbitrary lengths, and instead add a special\nerror symbol \\\\(\\\\bot\\\\) to the output space. The output space then becomes \\\\({\\\\bf\nO} = {\\\\bf B}\\^\\* \\\\cup \\\\{\\\\bot\\\\}\\\\), where we arbitrarily define the result of\nsuccessful computations as the concatenation \\\\((\\\\mathrm{IV} \\\\\\|\n\\\\mathrm{ciphertext} \\\\\\| \\\\mathrm{tag})\\\\) as given in the standard, and output\n\\\\(\\\\bot\\\\), in case some input is too long. Hence, for a fixed key, the\nencryption function becomes of type \\\\(\\\\mathrm{Enc}_k : {\\\\bf R} \\\\times {\\\\bf B}\\^\\*\n\\\\times {\\\\bf B}\\^\\* \\\\rightarrow {\\\\bf B}\\^\\* \\\\cup \\\\{\\\\bot\\\\}\\\\).\n\nFor the decryption function \\\\(\\\\mathrm{Dec}\\\\) the key space is the same. The\ninput space coincidentally is the same: \\\\({\\\\bf I} ={\\\\bf B}\\^\\* \\\\times {\\\\bf B}\\^\\*\\\\),\nbut now the first element is meant to be the output of the encryption function,\nwhile the second one is still the associated data.\n\nThe output space also happens to be the same \\\\({\\\\bf O} = {\\\\bf B}\\^\\* \\\\cup\n\\\\{\\\\bot\\\\}\\\\) (again a coincidence). The interpretation is somewhat different,\nas \\\\(\\\\bot\\\\) usually denotes an authentication error (though it will also be the\noutput in case some input is too long).\n\nWe stress that the above formalization is *not* the only option to formalize the\nstandard. For example, one could consider the nonce a part of the input, instead\nof reading it from the randomness (which results in a very different primitive).\nAlternatively, one could define the output as a triple containing the nonce,\nthe ciphertext, and the tag (instead of the concatenation). Or one could\nrestrict the key space (somewhat arbitrarily) to\n\\\\({\\\\bf K} = \\\\{0,1\\\\}\\^{128} \\\\cup \\\\{0,1\\\\}\\^{256}\\\\).\n\nCryptographic Algorithm:\n\n: A (symmetric) *cryptographic algorithm* is a tuple\n\n \\\\\\[(f_1, ... f_k)\\\\\\]\n\n of cryptographic functions, where all functions have the same key space. The\n *type* of the cryptographic algorithm is the tuple \\\\((({\\\\bf I}_1, {\\\\bf\n O}_1), \\\\ldots, ({\\\\bf I}_k, {\\\\bf O}_k))\\\\).\n\nFor example, for each valid triple \\\\((s_k, s_n, s_t)\\\\) of key, nonce, and tag\nsize, AES-GCM\\\\({}_{s_k, s_n, s_t}\\\\) is a cryptographic algorithm with the\ntwo functions \\\\(\\\\mathrm{Enc}\\\\) and \\\\(\\\\mathrm{Dec}\\\\) described above.\n\n### Primitives and interfaces\n\nWe next define a cryptographic primitive.\n\nPrimitive\n: A *primitive* is a set of cryptographic algorithms, where all the algorithms\n have the same type \\\\((({\\\\bf I}_1, {\\\\bf O}_1), \\\\ldots, ({\\\\bf I}_k, {\\\\bf\n O}_k))\\\\), and the key spaces of the algorithms are pairwise disjoint.\n\nAs an example, consider the \\\\(\\\\mathrm{AEAD}\\\\) primitive in Tink. It has multiple\nalgorithms, among those are AES-GCM for key sizes 128 and 256 bits, with nonce\nsize 96 bits, AES-EAX with some key sizes, and XChaCha20Poly1305. They have\ndisjoint key spaces, but all provide the same cryptographic functions\n\\\\(\\\\mathrm{Enc}\\\\) and \\\\(\\\\mathrm{Dec}\\\\). (We do not see a purpose in somehow\ncollapsing different key sizes of AES-GCM in this formal discussion, but of\ncourse one could do so).\n\n#### Defining primitives\n\nThe usual way of thinking of primitives is to first define properties of the\ncryptographic functions, and then simply considering the primitive to be all\nsuch algorithms.\n\nFor example, for AEAD we would say that \\\\(\\\\mathrm{Dec}_k(\\\\mathrm{Enc}_k(m, a),\na) = m\\\\) is 'always' satisfied (except e.g. if the plaintext \\\\(m\\\\) is too\nlong). In addition, we have security properties; for example, for\na random key, the encryption is semantially secure.\n\nThe AEAD primitive is then simply the set of all cryptographic algorithms which\nsatisfy these properties. In other words, in practice, when we define a specific\nprimitive, we define it based on properties. We do not give a list of\nalgorithms, as the definition suggests.\n\n#### Interfaces\n\nAn *interface* in Tink gives access to a primitive, in the sense that it allows\nto compute an element of the output space from the input space. For example,\nconsider the AEAD interface in Java: \n\n public interface Aead {\n byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;\n byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;\n }\n\nNote that we do not give access to the randomness. Instead, we allow the user to\nprovide elements of the input space. Disallowing access to the randomness is of\ncourse on purpose.^[1](#fn1)^\n\nTink sometimes offers multiple interfaces for a single primitive.\nThis can be very useful, as requirements sometimes differ. Still, doing this\ncomes at a price: in general, the more interfaces one offers, the lower\ninteroperability is. For example, imagine\nthat someone writes a library based on Tink that requires the user to pass in an\n`Aead` object (to encrypt something internally). If Tink offers too many\ndifferent interfaces to the \\\\(\\\\mathrm{AEAD}\\\\) primitive, chances are high\nthat the user\ndoes not have an instance ready which works for the key the user picked and the\nlibrary at the same time. Hence, adding more interfaces is a trade-off. \n\n*** ** * ** ***\n\n1. AEAD ciphers have the property that they are secure\n against chosen ciphertext attacks, which is guaranteed only if there is no\n reuse of the nonce. The Aead interface in Tink is designed such that it\n prevents nonce reuse: the user cannot provide a nonce as input for encryption,\n instead, a new nonce is randomly generated for each encrypt operation. [↩](#fnref1)"]]