العناصر الأولية والواجهات
تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
نحدد بعد ذلك (بشكل غير رسمي، ولكن بعد ذلك بشكل رسمي)، جزأين مهمين من
اللغة المستخدمة في Tink وPrimitive والواجهة.
أساسي
العنصر الأساسي هو كائن رياضي يتوافق مع جميع الخوارزميات.
أداء بعض المهام بأمان. على سبيل المثال، يتكون مجموعة AEAD الأساسية من جميع
خوارزميات التشفير التي تلبي خصائص الأمان التي يتطلبها تطبيق Tink
لعيد الحب.
نؤكد على أن المبادئ الأولية غير ملزمة بلغة برمجة أو لغة محددة
طريقة
الوصول إليها. وبدلاً من ذلك، ينبغي للمرء أن تفكر في العنصر الأساسي على أنه
كائن رياضي. فعلى سبيل المثال، إذا وضعنا في الاعتبار AEAD، فإنه سيأخذ في الأساس
تتكون من أزواج من الدوال، واحدة تنفذ التشفير، وأخرى
تنفيذ فك التشفير.
واجهات
الواجهة هي طريقة نوفّر من خلالها للمستخدمين إمكانية الوصول إلى واجهة أساسية.
فعلى سبيل المثال، نتوقع أن يوفر Tink في المستقبل واجهة Mac
،
ولكنها تحتوي أيضًا على واجهة StreamingMac
، التي تسمح بحساب منصات mac
البيانات التي لا يتم تحميلها مباشرةً في الذاكرة
تجدر الإشارة إلى أننا نميّز بين الواجهات والعناصر الأساسية هنا بشكل واضح. من المفترض أن يؤدي هذا
وضح أن الكائن الرياضي الذي تعطيه هاتان الواجهتان
الوصول إليها هي نفسها.
بالنسبة إلى معظم القرّاء، قد تكون التفسيرات البسيطة أعلاه كافية.
ومع ذلك، نشعر أنه قد يكون من المهم في بعض الأحيان تقديم معلومات
تعريفات هذه المفاهيم.
دوال التشفير
لا يعتبر مفهوم دالة التشفير مهمًا مثل مفهوم
أساسي، لكننا بحاجة إلى تقديمه لتعريفه رسميًا.
- وظيفة التشفير
دالة التشفير هي خريطة
\[ f: {\bf K} \times {\bf R} \times {\bf I} \to {\bf O}\]
من مجموعة \({\bf K}\) (مساحة المفتاح)، مجموعة \({\bf R} = \{0,1\}^{\infty}\)
(العشوائية، التي نفترض أنها مجموعة من سلاسل البت اللانهائية)
set \({\bf I}\) (مساحة الإدخال)، على مجموعة \({\bf O}\) (مساحة الإخراج).
وسيتضح لاحقًا سبب إضافة معلمة عشوائية محددة.
كمثال، نعرض احتمالاً واحدًا لكيفية تعيين هذه المفاهيم على
AES-GCM لكل حجم صالح للمفتاح \(s_k\)، وحجم غير محدَّد \(s_n\)، وحجم علامة صالح
\(s_t\)، تتكون تقنية AES-GCM من وظيفتي تشفير، إحداهما
والأخرى لفك التشفير. سيكون لكل منهما مساحة المفتاح \({\bf
K} = \{0,1\}^{s_k}\)نفسها.
بالنسبة لدالة التشفير \(\mathrm{Enc}\)، أول \(s_n\) بت من
العشوائية لتحديد الجزء غير العادي.
دع \({\bf B} = \{0,1\}^8\) يشير إلى بايت.
مساحة الإدخال لدالة التشفير هي أزواج \({\bf I} = {\bf B}^{*}
\times {\bf B}^{*}\) أزواج سلاسل البايت ذات الطول العشوائي.
من المفترض أن يكون العنصر الأول من الزوج هو الرسالة، أما العنصر الثاني فهو
البيانات المرتبطة بها. هناك حد أقصى لمعيار 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}^*\)،
ولكن من المفترض أن يكون العنصر الأول الآن هو ناتج دالة التشفير،
بينما لا تزال النتيجة الثانية هي البيانات المرتبطة.
يتصادف أن تكون مساحة الإخراج هي نفسها \({\bf O} = {\bf B}^* \cup
\{\bot\}\) (مصادفة مرة أخرى). يكون التفسير مختلفًا إلى حد ما،
كما أن \(\bot\) عادةً ما تشير إلى خطأ في المصادقة (رغم أنها ستكون أيضًا
الإخراج في حالة أن يكون بعض المدخلات طويلاً جدًا).
نشدّد على أنّ إضفاء الطابع الرسمي أعلاه ليس الخيار الوحيد لإضفاء الطابع الرسمي على
القياسية. على سبيل المثال، يمكن للمرء أن يعتبر ذلك جزءًا من المدخل، بدلاً من
قراءتها من خلال العشوائية (والتي ينتج عنها منهج أساسي مختلف تمامًا).
وبدلاً من ذلك، يمكن للمرء أن يحدد المخرج على أنه ثلاثي يحتوي على الأرقام غير المعروفة،
والنص المشفر والعلامة (بدلاً من التسلسل). أو يمكن للمرء
تقييد المساحة الرئيسية (بشكل عشوائي إلى حد ما)
\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)
- خوارزمية التشفير:
خوارزمية التشفير (المتماثلة) هي صف
\[(f_1, ... f_k)\]
من وظائف التشفير، حيث يكون لكل الدوال المساحة الرئيسية نفسها. تشير رسالة الأشكال البيانية
type لخوارزمية التشفير هو الصف \((({\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}\) هي خوارزمية تشفير
الدالتين \(\mathrm{Enc}\) و \(\mathrm{Dec}\) الموضحة أعلاه.
الأساسيات والواجهات
نحدد فيما يلي طريقة التشفير الأساسية.
- أساسي
- الطريقة الأساسية هي مجموعة من خوارزميات التشفير، حيث يتم حذف جميع الخوارزميات
لها نفس النوع \((({\bf I}_1, {\bf O}_1), \ldots, ({\bf I}_k, {\bf
O}_k))\)، وتكون المساحات الرئيسية للخوارزميات منفصلة زوجية.
على سبيل المثال، يمكنك الاطّلاع على السمة \(\mathrm{AEAD}\) الأساسية في Tink. يتضمن العديد من
خوارزميات مثل AES-GCM للمفاتيح 128 و256 بت، مع استخدام nonce
بحجم 96 بت، ومعيار AES-EAX مع بعض أحجام المفاتيح، وXChaCha20Poly1305. لديهم
مسافات المفاتيح المنفصلة، لكن جميعها يوفر نفس دوال التشفير
\(\mathrm{Enc}\) و \(\mathrm{Dec}\)(لا نرى غرضًا بطريقة ما.
بدمج أحجام رئيسية مختلفة من AES-GCM في هذه المناقشة الرسمية، ولكن
بالدورة التدريبية التي يمكن للمرء أن يفعلها).
تحديد الأساسيات
الطريقة المعتادة للتفكير في الأساسيات هي تحديد خصائص
لدوال التشفير، ثم نعتبر أن العنصر الأساسي هو جميع
مثل هذه الخوارزميات.
على سبيل المثال، بالنسبة لـ AEAD، يمكننا القول إن \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a),
a) = m\) هي 'always' راضٍ (باستثناء إذا كان النص العادي \(m\) مثالاً أيضًا
طويلة). بالإضافة إلى ذلك، لدينا خصائص أمان، على سبيل المثال، بالنسبة إلى
مفتاحًا عشوائيًا، فسيكون التشفير آمنًا من حيث المعنى.
ويكون معيار AEAD هو ببساطة مجموعة من خوارزميات التشفير التي
تلبي هذه الخصائص. بمعنى آخر، من الناحية العملية، عندما نحدِّد فئة معيّنة
أساسي، فإننا نحدده بناءً على الخصائص. لا نقدم قائمة
الخوارزميات، كما يشير التعريف.
واجهات
تتيح الواجهة في Tink الوصول إلى واجهة أولية، بمعنى أنه يسمح
لحساب عنصر في مساحة الإخراج من مساحة الإدخال. على سبيل المثال:
ضع في اعتبارك واجهة AEAD في Java:
public interface Aead {
byte[] encrypt(byte[] plaintext, byte[] associated_data) throws GeneralSecurityException;
byte[] decrypt(byte[] ciphertext, byte[] associated_data) throws GeneralSecurityException;
}
يُرجى العِلم أنّنا لا نمنح إذن الوصول العشوائي. بدلاً من ذلك، نسمح للمستخدم
تقدم عناصر مساحة الإدخال. يعود عدم السماح بالوصول إلى العشوائية
عن قصد.1
يوفر Tink أحيانًا واجهات متعددة لعنصر أساسي واحد.
وقد يكون ذلك مفيدًا جدًا، فقد تختلف المتطلبات في بعض الأحيان. ومع ذلك، فإن القيام بذلك
بسعر: بشكل عام، كلما زاد عدد الواجهات التي تقدمها، انخفض
التوافقية. على سبيل المثال، تخيل
أن شخصًا ما يكتب مكتبة بناءً على Tink تتطلب من المستخدم أن يمر
كائن Aead
(لتشفير عنصر داخليًا). إذا كان Tink تقدم الكثير جدًا
الواجهات المختلفة إلى \(\mathrm{AEAD}\) الأساسية، فهناك احتمال كبير
من أن المستخدم
لا يحتوي على مثيل جاهز يصلح للمفتاح الذي اختاره المستخدم
المكتبة في نفس الوقت. وبالتالي، فإن إضافة المزيد من الواجهات هي الحل البديل.
إنّ محتوى هذه الصفحة مرخّص بموجب ترخيص Creative Commons Attribution 4.0 ما لم يُنصّ على خلاف ذلك، ونماذج الرموز مرخّصة بموجب ترخيص Apache 2.0. للاطّلاع على التفاصيل، يُرجى مراجعة سياسات موقع Google Developers. إنّ Java هي علامة تجارية مسجَّلة لشركة Oracle و/أو شركائها التابعين.
تاريخ التعديل الأخير: 2025-07-25 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-07-25 (حسب التوقيت العالمي المتفَّق عليه)"],[[["\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)"]]