با مجموعهها، منظم بمانید
ذخیره و طبقهبندی محتوا براساس اولویتهای شما.
Tink از Keysets برای فعال کردن چرخش کلید استفاده می کند. به طور رسمی، مجموعه کلید یک لیست غیرخالی 1 از کلیدها است که در آن یک کلید اصلی تعیین می شود (کلیدی که به عنوان مثال برای امضا و رمزگذاری متن های ساده جدید استفاده می شود). علاوه بر این، کلیدهای یک مجموعه کلید دارای شناسه منحصربهفرد 2 و وضعیت کلید هستند که به شما امکان میدهد کلیدها را بدون حذف آنها از مجموعه کلید غیرفعال کنید.
مجموعه کلیدها راه اصلی دسترسی کاربران به کلیدها هستند (از طریق کلاس KeysetHandle ). این تضمین می کند که هر کاربر کدی برای مدیریت چندین کلید در یک زمان دارد. برای اکثر کاربران رمزنگاری، استفاده از کلیدهای متعدد یک ضرورت است: باید امکان تغییر کلیدها وجود داشته باشد (برای مثال، کلیدهای قدیمی ممکن است درز کنند)، و تقریباً هرگز یک "تغییر به کلید بعدی" اتمی وجود ندارد که بتوان آن را اعمال کرد. برای ماشینها، کد اجرا میشود و همه متنهای رمزی، در سطح جهانی و در یک لحظه. از این رو، کاربر باید کدی بنویسد که وقتی یکی از یک کلید به کلید دیگر تغییر می کند، کار می کند.
مثال: AEAD
یک مجموعه کلید AEAD را در نظر بگیرید که حاوی چندین کلید برای AEAD اولیه است. همانطور که قبلا توضیح داده شد، هر کلید به طور منحصر به فرد دو تابع را مشخص می کند: \(\mathrm{Enc}\) و \(\mathrm{Dec}\). اکنون مجموعه کلید دو عملکرد جدید را نیز مشخص می کند: \(\mathrm{Enc}\) و \(\mathrm{Dec}\) - \(\mathrm{Enc}\) به سادگی با تابع برابر است \(\mathrm{Enc}\) از کلید اصلی مجموعه کلید، در حالی که تابع \(\mathrm{Dec}\) سعی می کند با همه کلیدها رمزگشایی کند، و به ترتیب آنها را مرور می کند ( در زیر ببینید چگونه Tink عملکرد این را بهبود می بخشد).
جالب است بدانید که Keyset ها کلیدهای کامل هستند: آنها توضیح کاملی از عملکردها هستند \(\mathrm{Enc}\) و\(\mathrm{Dec}\) استفاده می شود. این بدان معنی است که کاربران می توانند کلاسی بنویسند که ورودی KeysetHandle را می گیرد و این ایده را بیان می کند که کلاس به توضیح کاملی از اشیا نیاز دارد. \(\mathrm{Enc}\) و \(\mathrm{Dec}\) به درستی عمل کند . این به کاربر امکان میدهد APIهایی بنویسد که این را به شما منتقل میکند: برای استفاده از این کلاس، باید شرح یک رمزنگاری اولیه را به من ارائه دهید.
چرخش کلید
یک کاربر Tink را در نظر بگیرید که برنامه ای می نویسد که ابتدا یک مجموعه کلید را از یک KMS دریافت می کند، سپس یک شی AEAD از این مجموعه کلید ایجاد می کند و در نهایت از این شی برای رمزگذاری و رمزگشایی متون رمز استفاده می کند.
چنین کاربری به طور خودکار برای چرخش کلید آماده می شود. و تغییر الگوریتم ها در صورتی که انتخاب فعلی آنها دیگر با استاندارد مطابقت نداشته باشد.
هر چند هنگام اجرای چنین چرخشی کلید باید تا حدودی مراقب بود: اول، KMS باید یک کلید جدید به مجموعه کلید اضافه کند (اما هنوز آن را به عنوان اصلی تنظیم نکرده است). سپس، مجموعه کلید جدید باید در همه باینری ها پخش شود، به طوری که هر باینری که از این مجموعه کلید استفاده می کند، جدیدترین کلید را در مجموعه کلید داشته باشد. تنها در این صورت باید کلید جدید اصلی شود و مجموعه کلیدهای حاصل دوباره با استفاده از مجموعه کلید در بین همه باینری ها توزیع می شود.
شناسه های کلیدی در متون رمزی
دوباره مثالی از مجموعه کلید AEAD را در نظر بگیرید. اگر ساده لوحانه انجام شود، رمزگشایی یک متن رمزی مستلزم آن است که Tink سعی کند با تمام کلیدهای Keyset رمزگشایی کند، زیرا هیچ راهی برای دانستن اینکه کدام کلید برای رمزگذاری مجموعه کلید استفاده شده است وجود ندارد. این می تواند باعث سربار عملکرد بزرگ شود.
به همین دلیل، Tink اجازه می دهد تا متن های رمزی را با یک رشته 5 بایتی مشتق شده از ID پیشوند قرار دهید. با پیروی از فلسفه "کلیدهای کامل" در بالا، این پیشوند بخشی از کلید است و تمام متنهای رمزی که تاکنون با این کلید مشتق شدهاند باید این پیشوند را داشته باشند. هنگامی که کاربران کلیدها را ایجاد می کنند، می توانند انتخاب کنند که آیا کلید باید از چنین پیشوندی استفاده کند یا از قالب متن رمزی بدون آن استفاده شود.
هنگامی که یک کلید در یک مجموعه کلید قرار دارد، Tink این تگ را از روی شناسه ای که کلید در مجموعه کلید دارد محاسبه می کند. این واقعیت که شناسه ها در یک مجموعه کلید منحصر به فرد هستند نشان می دهد که برچسب ها منحصر به فرد هستند. از این رو، اگر فقط از کلیدهای برچسبگذاری شده استفاده شود، در مقایسه با رمزگشایی با یک کلید، کاهش عملکردی وجود ندارد: تینک فقط باید یکی از کلیدها را هنگام رمزگشایی امتحان کند.
با این حال، از آنجایی که تگ بخشی از کلید است، این نیز نشان میدهد که کلید تنها در صورتی میتواند در یک مجموعه کلید باشد که یک شناسه خاص داشته باشد. این در هنگام توصیف اجرای اشیاء کلیدی در زبانهای مختلف، پیامدهایی دارد.
برخی از بخشهای تینک هنوز Keysets را به عنوان یک مجموعه در نظر میگیرند. با این حال، این باید تغییر کند. دلیل آن این است که ترتیب به طور کلی مهم است: برای مثال، چرخه عمر معمول چرخش کلید با Aead را در نظر بگیرید. ابتدا یک کلید جدید به یک مجموعه کلید اضافه می شود. این کلید هنوز اولیه نیست، اما فعال است. این مجموعه کلید جدید برای همه باینری ها عرضه می شود. هنگامی که همه باینری ها کلید جدید را می دانند، کلید اصلی می شود (فقط در این مرحله استفاده از این کلید امن است). در این مرحله دوم، چرخش کلید باید آخرین کلید اضافه شده را بداند. ↩
برای سازگاری با کتابخانه داخلی Google، Tink اجازه می دهد تا مجموعه کلیدهایی داشته باشید که شناسه ها در آنها تکرار می شوند. این پشتیبانی در آینده حذف خواهد شد. ↩
تاریخ آخرین بهروزرسانی 2025-07-25 بهوقت ساعت هماهنگ جهانی.
[null,null,["تاریخ آخرین بهروزرسانی 2025-07-25 بهوقت ساعت هماهنگ جهانی."],[[["\u003cp\u003eIn Tink, a Keyset is a list of keys, with one primary key and unique IDs for key rotation and management.\u003c/p\u003e\n"],["\u003cp\u003eKeysets are crucial for enabling key rotation without requiring users to implement it themselves.\u003c/p\u003e\n"],["\u003cp\u003eTink optimizes decryption by using key identifiers in ciphertexts to avoid trying all keys in a keyset.\u003c/p\u003e\n"],["\u003cp\u003eWhile Keysets offer significant advantages, users should consider careful key rotation procedures.\u003c/p\u003e\n"],["\u003cp\u003eTink primarily uses Keysets for key access, ensuring user code can handle multiple keys, which is often necessary for robust cryptography.\u003c/p\u003e\n"]]],["Tink uses **Keysets**, a list of keys with one designated as primary, to enable key rotation. Keyset keys have unique IDs and a status, allowing for disabling without removal. Encryption uses the primary key, while decryption iterates through all keys. Ciphertexts can be prefixed with a unique 5-byte tag derived from the key's ID to optimize decryption. Key rotation involves adding a new key, distributing the updated keyset, then setting the new key as primary, ensuring all binaries are updated.\n"],null,["# Keysets\n\n| In Tink, a **Keyset** is a list of keys, with one designated primary key.\n\nTink uses Keysets to enable key rotation. Formally, a keyset is a non-empty\nlist^[1](#fn1)^ of keys in which one key is designated primary (the key\nwhich is used for example to sign and encrypt new plaintexts). In addition, keys\nin a keyset get a unique ID^[2](#fn2)^ and a key status which allows\nto disable keys without removing them from a keyset.\n\nKeysets are the main way in which users can access keys (via the class\n`KeysetHandle`). This ensures that every user has code to handle multiple keys\nat once. For most users of cryptography, handling multiple keys is\n*a necessity*: it needs to be possible to change keys (old keys can be leaked,\nfor example), and there is almost never an atomic \"switch to the next key\"\nwhich can be applied to the machines the code runs and all ciphertexts,\nglobally, and in an instant. Hence, the user needs to write code which\nworks when one changes from one key to the next one.\n| **Note:** The full support of Keysets is one big advantage Tink has over other libraries: they facilitate key rotation, which otherwise every user would have to implement by themselves.\n\nExample: AEAD\n-------------\n\nConsider an AEAD keyset, which contains multiple keys for the AEAD\nprimitive. As explained before, each key uniquely specifies two functions:\n\\\\(\\\\mathrm{Enc}\\\\) and \\\\(\\\\mathrm{Dec}\\\\). The keyset now also specifies two new\nfunctions: \\\\(\\\\mathrm{Enc}\\\\) and \\\\(\\\\mathrm{Dec}\\\\) - \\\\(\\\\mathrm{Enc}\\\\) simply\nequals the function \\\\(\\\\mathrm{Enc}\\\\) of the primary key of the keyset, while\nthe function \\\\(\\\\mathrm{Dec}\\\\) tries to decrypt with all keys, going through\nthem in some order (see [below](#keyids) for how Tink improves the performance\nof this).\n\nIt is interesting to note that Keysets are *full keys* :\nthey are a complete description of the functions \\\\(\\\\mathrm{Enc}\\\\) and\n\\\\(\\\\mathrm{Dec}\\\\) used. This means that users can write a class which takes as\ninput a `KeysetHandle`, expressing the idea that the class needs a *complete\ndescription of objects \\\\(\\\\mathrm{Enc}\\\\) and \\\\(\\\\mathrm{Dec}\\\\) to function\nproperly*. This enables user to write APIs which communicate that: to use\nthis class you need to provide me the description of a cryptographic primitive.\n\nKey rotation\n------------\n\nConsider a Tink user, writing a program which first obtains a keyset from\na KMS, then creates an AEAD object from this keyset, and finally uses this\nobject to encrypt and decrypt ciphertexts.\n\nSuch a user is automatically prepared for key rotation; and switching\nalgorithms in case their current choice does not meet the standard anymore.\n\nOne has to be somewhat careful though when implementing such key rotation:\nFirst, the KMS should add a new key to the keyset (but not yet set it as a\nprimary). Then, the new keyset needs to be rolled out to\nall binaries, so that every binary using this keyset has the newest key in\nthe keyset. Only then should the new key be made primary, and the resulting\nkeyset is again distributed to all binaries using the keyset.\n\nKey identifiers in ciphertexts\n------------------------------\n\nConsider again the example of an AEAD keyset. If done naively,\ndecrypting a ciphertext requires Tink to try to decrypt with all the keys in\nthe Keyset, as there is no way of knowing which key was used to encrypt the\nkeyset. This can cause a large performance overhead.\n\nBecause of this, Tink allows to prefix ciphertexts with a 5-byte string derived\nfrom the ID. Following the philosophy of 'Full Keys' above, this prefix\nis *part of the key*,\nand all ciphertexts ever derived with this key should have this prefix. When\nusers create keys, they can choose whether the key should use such a prefix, or\nif a ciphertext format without it should be used.\n| **Note:** Some primitives don't allow such tagging; for example in a [PRF](https://en.wikipedia.org/wiki/Pseudorandom_function_family) there is no obvious way how to embed such a prefix. For these keys, Tink does not offer such a facility.\n\nWhen a key is in a keyset, Tink computes this tag from the ID the key has in the\nkeyset. The fact that IDs are unique[^2^](#fn2) within a keyset implies\nthat the tags are unique. Hence, if only tagged keys are used, there is no\nperformance\nloss compared to decrypting with a single key: Tink only needs to try one of\nthe keys when decrypting.\n\nHowever, since the tag is part of the key, this also implies that the key can\nonly be in a keyset if it has one specific ID. This has some implications when\ndescribing the implementation of [key objects](/tink/design/key_objects) in\ndifferent languages. \n\n*** ** * ** ***\n\n1. Some parts of Tink still treat Keysets as a set. However, this\n should be changed.\n\n The reason is that the order is in general\n important: for example, consider the typical lifecycle of a key rotation with\n Aead. First, a new key is added to a keyset. This key is not made primary yet,\n but active. This new keyset is rolled out to all binaries. Once all binaries\n know the new key, the key is made primary (only at this point using this key\n is safe). In this second step, key rotation needs to know the last key added. [↩](#fnref1)\n\n2. For compatibility with a Google internal library, Tink\n allows to have keysets in which IDs are repeated. This support will be\n removed in the future. [↩](#fnref2)"]]