تینک از مجموعه کلیدها (Keysets) برای فعال کردن چرخش کلید استفاده میکند. به طور رسمی، یک مجموعه کلید، فهرستی غیرتهی از کلیدها است که در آن یک کلید به عنوان کلید اصلی تعیین میشود (کلیدی که برای مثال برای امضا و رمزگذاری متنهای ساده جدید استفاده میشود). علاوه بر این، کلیدهای موجود در یک مجموعه کلید، یک شناسه منحصر به فرد 2 و یک وضعیت کلید دریافت میکنند که امکان غیرفعال کردن کلیدها را بدون حذف آنها از یک مجموعه کلید فراهم میکند.
مجموعه کلیدها (Keysets) روش اصلی دسترسی کاربران به کلیدها هستند (از طریق کلاس 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 باید سعی کند با تمام کلیدهای موجود در مجموعه کلید رمزگشایی کند، زیرا هیچ راهی برای دانستن اینکه از کدام کلید برای رمزگذاری مجموعه کلید استفاده شده است وجود ندارد. این میتواند باعث سربار عملکردی زیادی شود.
به همین دلیل، Tink اجازه میدهد تا متنهای رمزی را با یک رشته ۵ بایتی مشتق شده از شناسه، پیشوند گذاری کنند. با پیروی از فلسفه «کلیدهای کامل» که در بالا ذکر شد، این پیشوند بخشی از کلید است و همه متنهای رمزی که تاکنون با این کلید مشتق شدهاند باید این پیشوند را داشته باشند. هنگامی که کاربران کلیدها را ایجاد میکنند، میتوانند انتخاب کنند که آیا کلید باید از چنین پیشوندی استفاده کند یا اینکه از قالب متن رمزی بدون آن استفاده شود.
وقتی کلیدی در یک مجموعه کلید است، تینک این برچسب را از شناسهای که کلید در مجموعه کلید دارد محاسبه میکند. این واقعیت که شناسهها در یک مجموعه کلید منحصر به فرد هستند، نشان میدهد که برچسبها منحصر به فرد هستند. از این رو، اگر فقط از کلیدهای برچسبگذاری شده استفاده شود، در مقایسه با رمزگشایی با یک کلید واحد، هیچ افت عملکردی وجود ندارد: تینک فقط باید هنگام رمزگشایی یکی از کلیدها را امتحان کند.
با این حال، از آنجایی که تگ بخشی از کلید است، این همچنین نشان میدهد که کلید فقط در صورتی میتواند در یک مجموعه کلید باشد که یک شناسه خاص داشته باشد. این موضوع هنگام توصیف پیادهسازی اشیاء کلید در زبانهای مختلف، پیامدهایی دارد.
کلیدهایی با نیاز به شناسه اما بدون پیشوند خروجی
برخی از کلیدها باید یک شناسه خاص داشته باشند اما هیچ پیشوندی به خروجی خود اضافه نکنند. برای مثال، کلیدهای امضا با نوع NO_PREFIX_WITH_PREHASH_ID (که با نوع پیشوند خروجی WITH_ID_REQUIREMENT ذخیره میشوند) امضاهایی بدون پیشوند تولید میکنند. وقتی از چنین کلیدی با Prehash اولیه استفاده میکنید، Tink شناسه کلید را در مقدار prehash مینویسد، به طوری که یک امضاکننده از راه دور میداند با کدام یک از کلیدهای خود امضا کند.
همانند کلیدهایی که از پیشوند استفاده میکنند، چنین کلیدی فقط میتواند در یک مجموعه کلید تحت آن یک شناسه باشد. شناسه کلید در مقدار پیش هش، درست مانند پیشوند خروجی، فراداده ساده است: امضا آن را متصل نمیکند و تأییدکنندگان هرگز آن را نمیبینند. برای طرحبندی سطح بایت، به قالب سیم Tink مراجعه کنید.
برخی از بخشهای Tink هنوز با Keysetها به عنوان یک مجموعه رفتار میکنند. با این حال، این باید تغییر کند. دلیل آن این است که ترتیب به طور کلی مهم است: برای مثال، چرخه عمر معمول چرخش کلید با Aead را در نظر بگیرید. ابتدا، یک کلید جدید به یک keyset اضافه میشود. این کلید هنوز اصلی نشده، اما فعال است. این keyset جدید به همه فایلهای باینری اضافه میشود. هنگامی که همه فایلهای باینری کلید جدید را بدانند، کلید اصلی میشود (فقط در این مرحله استفاده از این کلید ایمن است). در این مرحله دوم، چرخش کلید باید آخرین کلید اضافه شده را بداند. ↩
برای سازگاری با کتابخانه داخلی گوگل، تینک اجازه میدهد تا مجموعه کلیدهایی داشته باشیم که در آنها شناسهها تکرار میشوند. این پشتیبانی در آینده حذف خواهد شد. ↩