פרימיטיבים וממשקים

לאחר מכן נגדיר (באופן רשמי, אבל באופן רשמי יותר), שני חלקים חשובים השפה שבה משתמשים ב-Tink, ב-Primitive וב-Interface.

פרימיטיבי

פרימיטיבי הוא אובייקט מתמטי שתואם לכל האלגוריתמים לבצע משימה כלשהי באופן מאובטח. לדוגמה, רכיב ה- D D מורכב מכל אלגוריתמים להצפנה שעונים על מאפייני האבטחה שנדרשים ל-Tink. של Aead.

אנחנו מדגישים שפרימיטיביים לא מחויבים לשפת תכנות, או דרך לגשת אליהם. במקום זאת, צריך לחשוב על הפרמיטיביות מתמטיות. לדוגמה, אם נתייחס ל-D, באופן בסיסי הדבר יהיה שמורכב מזוגות של פונקציות, אחת שמבצעת הצפנה מבצעים פענוח.

ממשקים

ממשק הוא הדרך שבה אנחנו מספקים למשתמשים גישה למודל ראשוני. לדוגמה, אנחנו מצפים שבעתיד 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\) בדרך כלל מציין שגיאת אימות (למרות שזה יהיה גם במקרה שהקלט ארוך מדי).

אנחנו מדגישים שהרשמיות שלמעלה היא לא האפשרות היחידה לבסס את המדיניות רגילה. לדוגמה, אפשר להתייחס לצופן חד-פעמי (nonce) של הקלט, של קריאתו מהרנדומיזציה (וכתוצאה מכך מתקבלת פרימיטיבית שונה מאוד). לחלופין, אפשר להגדיר את הפלט כמשולש שמכיל את הצופן החד-פעמי (nonce), המידע המוצפן (ciphertext) והתג (במקום עם השרשור). או שאפשר להגביל את מרחב המפתח (באופן שרירותי במידה מסוימת) \({\bf K} = \{0,1\}^{128} \cup \{0,1\}^{256}\)

אלגוריתם קריפטוגרפי:

אלגוריתם קריפטוגרפי (סימטרי) הוא פרח

\[(f_1, ... f_k)\]

פונקציות קריפטוגרפיות שבהן לכל הפונקציות יש אותו שטח מפתח. הסוג של האלגוריתם הקריפטוגרפי הוא החצובה (tuple) \((({\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 ביטים, בגודל 96 ביט, AES-EAX עם מפתחות בגודל מסוים ו-XChaCha20Poly1305. יש להם מרחבי מפתח נפרדים, אבל כולם מספקים את אותן פונקציות קריפטוגרפיות \(\mathrm{Enc}\) וגם \(\mathrm{Dec}\). (אנחנו לא רואים מטרה בצורה כלשהי כיווץ גודלי מפתחות שונים של AES-GCM בדיון הרשמי, כמובן שאפשר לעשות זאת).

הגדרת עקרונות ראשוניים

דרך החשיבה הרגילה של פרימיטיבים היא להגדיר תחילה תכונות של פונקציות קריפטוגרפיות, ואז פשוט לחשוב על הפרמיטיביות אלגוריתמים כאלה.

לדוגמה, עבור D – נקבע שהפרמטר \(\mathrm{Dec}_k(\mathrm{Enc}_k(m, a), a) = m\) הוא 'תמיד' (למעט, למשל, אם גם הטקסט ללא הצפנה \(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}\) לפרימיטיבי, יש סיכוי גבוה שהמשתמש אין מכונה מוכנה שמתאימה למפתח שהמשתמש בחר בו-זמנית. לכן, הוספת עוד ממשקים תבוא לידי ביטוי.


  1. להצפנה מסוג AEAD יש את המאפיין שבו הם מאובטחים נגד התקפות מידע מוצפן (ciphertext) שנבחרו, שמובטחת רק אם לא שימוש חוזר בצופן חד-פעמי. ממשק Aead ב-Tink תוכנן כך מונע שימוש חוזר חד-פעמי (nonce): המשתמש לא יכול לספק צופן חד-פעמי כקלט להצפנה, במקום זאת, נוצר צופן חד-פעמי (nonce) חדש באופן אקראי לכל פעולת הצפנה.