แบบพื้นฐานและอินเทอร์เฟซ
จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน
บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ
ต่อไปเราจะอธิบาย (อย่างไม่เป็นทางการ แต่เป็นทางการมากขึ้น) สองส่วนสำคัญคือ
ภาษาที่ใช้ใน Tink, Primitive และ Interface
แบบพื้นฐาน
ค่าดั้งเดิมเป็นออบเจ็กต์ทางคณิตศาสตร์ที่เกี่ยวข้องกับอัลกอริทึมทั้งหมด
ดำเนินการบางอย่างได้อย่างปลอดภัย ตัวอย่างเช่น AEAD Primitive ประกอบด้วย
อัลกอริทึมการเข้ารหัสซึ่งเป็นไปตามคุณสมบัติด้านความปลอดภัยที่ Tink ต้องการ
ของ Aead
เราเน้นว่าเอกสารพื้นฐานไม่ได้เกี่ยวข้องกับภาษาโปรแกรมหรือ
ทางของ
เข้าถึงได้ ผู้คนควรมองว่าดั้งเดิมเป็น
ที่เป็นวัตถุทางคณิตศาสตร์ ตัวอย่างเช่น หากเราพิจารณา AEAD โดยพื้นฐานแล้ว
ประกอบด้วยฟังก์ชัน 1 คู่ ฟังก์ชันหนึ่งจะทำการเข้ารหัส
ทำการถอดรหัส
อินเทอร์เฟซ
อินเทอร์เฟซคือวิธีที่เราให้ผู้ใช้ได้เข้าถึงพื้นฐาน
เช่น เราคาดว่าในอนาคต 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\), ขนาด Nonce \(s_n\)และขนาดแท็ก
\(s_t\), AES-GCM ประกอบด้วยฟังก์ชันการเข้ารหัส 2 ฟังก์ชัน โดยฟังก์ชันหนึ่งสำหรับ
การเข้ารหัส และอีกรายการสำหรับถอดรหัส ทั้ง 2 อย่างจะมีพื้นที่คีย์เดียวกัน \({\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\}\) (แต่บังเอิญเสียที) การตีความจะแตกต่างกันบ้าง
โดยทั่วไป \(\bot\) จะหมายถึงข้อผิดพลาดในการตรวจสอบสิทธิ์ (แต่ก็เป็นข้อผิดพลาด
ในกรณีที่อินพุตบางรายการยาวเกินไป)
เราตอกย้ำว่าการจัดงานแบบเป็นทางการข้างต้นไม่ใช่ตัวเลือกเดียวที่จะทำให้
มาตรฐาน ตัวอย่างเช่น บางคนอาจถือว่า Nonce เป็นส่วนหนึ่งของข้อมูลที่ป้อน แทน
จากการอ่านค่าจากการสุ่ม (ซึ่งได้ผลลัพธ์ดั้งเดิมที่ต่างกันมาก)
หรืออาจกำหนดเอาต์พุตเป็น 3 ตัวที่มี Nonce
ข้อความเข้ารหัส และแท็ก (แทนการต่อคำ) หรืออาจมี
จำกัดพื้นที่คีย์ (ตามกฎเกณฑ์)
\({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)
- อัลกอริทึมการเข้ารหัส:
อัลกอริทึมวิทยาการเข้ารหัสลับ (แบบสมมาตร) คือ Tuple
\[(f_1, ... f_k)\]
ของฟังก์ชันการเข้ารหัส โดยที่ฟังก์ชันทั้งหมดมีพื้นที่คีย์เท่ากัน
ประเภทของอัลกอริทึมการเข้ารหัสคือทูเพิล \((({\bf I}_1, {\bf
O}_1), \ldots, ({\bf I}_k, {\bf O}_k))\)
ตัวอย่างเช่น สำหรับ 3 ค่า \((s_k, s_n, s_t)\) ของคีย์ ค่า Nonce และแท็กที่ถูกต้องแต่ละรายการ
AES-GCM\({}_{s_k, s_n, s_t}\) เป็นอัลกอริทึมการเข้ารหัสที่มี
2 ฟังก์ชัน \(\mathrm{Enc}\) และ \(\mathrm{Dec}\) อธิบายไว้ข้างต้น
แบบพื้นฐานและอินเทอร์เฟซ
ต่อไปเราจะนิยาม Primitive ของการเข้ารหัส
- แบบพื้นฐาน
- พื้นฐานคือชุดอัลกอริทึมวิทยาการเข้ารหัสลับที่โดยอัลกอริทึมทั้งหมด
มีประเภทเดียวกัน \((({\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 Primitive คือชุดของอัลกอริทึมการเข้ารหัสทั้งหมด
มีคุณสมบัติเหล่านี้ กล่าวคือ ในทางปฏิบัติ เมื่อเรากำหนด
พื้นฐาน เรานิยามตามสมบัติ เราไม่มีรายชื่อของ
ตามที่คำจำกัดความแนะนำ
อินเทอร์เฟซ
อินเทอร์เฟซใน 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 มีหลายอินเทอร์เฟซสําหรับ 1 แหล่งกำเนิด
ซึ่งอาจเป็นประโยชน์มาก เนื่องจากข้อกำหนดอาจแตกต่างกันไปในบางครั้ง แต่ก็ยังทำได้อยู่
มีราคาต่ำ: โดยทั่วไป ยิ่งอินเทอร์เฟซหนึ่งๆ นำเสนอมากเท่าไหร่ ยิ่งมีอินเทอร์เฟซที่หลากหลาย
ความสามารถในการทำงานร่วมกัน ตัวอย่างเช่น สมมติว่า
เขียนไลบรารีโดยใช้ Tink ซึ่งกำหนดให้ผู้ใช้ส่ง
ออบเจ็กต์ Aead
รายการ (เพื่อเข้ารหัสภายในบางอย่าง) หาก Tink เสนอบริการมากเกินไป
อินเทอร์เฟซที่แตกต่างกันกับ \(\mathrm{AEAD}\) พื้นฐาน มีโอกาสสูงที่จะ
ที่ผู้ใช้
ไม่มีอินสแตนซ์ที่พร้อมใช้งานสำหรับคีย์ที่ผู้ใช้เลือกและ
ไปพร้อมๆ กัน ดังนั้น การเพิ่มอินเทอร์เฟซจึงเป็นข้อดี
เนื้อหาของหน้าเว็บนี้ได้รับอนุญาตภายใต้ใบอนุญาตที่ต้องระบุที่มาของครีเอทีฟคอมมอนส์ 4.0 และตัวอย่างโค้ดได้รับอนุญาตภายใต้ใบอนุญาต Apache 2.0 เว้นแต่จะระบุไว้เป็นอย่างอื่น โปรดดูรายละเอียดที่นโยบายเว็บไซต์ Google Developers Java เป็นเครื่องหมายการค้าจดทะเบียนของ Oracle และ/หรือบริษัทในเครือ
อัปเดตล่าสุด 2025-07-25 UTC
[[["เข้าใจง่าย","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 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)"]]