עקביות

חשוב ש-Tink יפעל "באותו אופן" בכל שפות התכנות. הקונספט הזה לא פשוט, אבל הכי חשוב:

כדי לשמור על עקביות, Tink משתמש בבדיקות חוצות-שפות שאפשר למצוא במאגר GitHub חוצה-השפות. הבדיקות האלה מאמתות את העקביות ואת יכולת הפעולה ההדדית של שפות שונות.

עם זאת, הגדרת העקביות היא לא פשוטה כמו שאפשר לצפות. לכן, בדף הזה מופיעה ההגדרה שלנו. באופן בסיסי, Tink מספק שני סוגים של עקביות:

הקשר

ברמה הכללית, Tink מספק את ממשקי ה-API הבאים:

  • מניפולציה של קבוצת מפתחות: Tink מספק ממשקי API להוספת מפתחות חדשים לקבוצת מפתחות, להסרת מפתחות מקבוצת מפתחות ולשינוי המפתח הראשי בקבוצת מפתחות.

  • סריאליזציה של קבוצת מפתחות: Tink מספק ממשקי API לסריאליזציה של קבוצת מפתחות לרצף של בייטים, ולהפך – לנתח קבוצת מפתחות מרצף של בייטים.

  • יצירת פרימיטיב: Tink מספק API ליצירת ממשק לפרימיטיב מקבוצת מפתחות. לדוגמה, כדי ליצור אובייקט Aead מקבוצת מפתחות ב-Java, המשתמש קורא ל-keysetHandle.getPrimitive(config, Aead.class).

  • שימוש בפרימיטיב: הממשק שנוצר בשלב יצירת הפרימיטיב מספק API לביצוע פעולות קריפטוגרפיות.

יש שתי שאלות חשובות שצריך לשאול לגבי ממשקי ה-API האלה:

  • יצירה: בהינתן קבוצת מפתחות שעברה סריאליזציה, שפה ופרימיטיב, האם אפשר ליצור את הפרימיטיב מקבוצת המפתחות הזו בשפה?

  • הערכה: אם אפשר ליצור פרימיטיב בשפה מסוימת מקבוצת מפתחות נתונה, איך האובייקט הפרימיטיבי מתנהג?

חשוב לציין ש-Tink לא מספק עקביות בניתוח של קבוצת מפתחות. לדוגמה, יכול להיות ש-Tink C++‎

  • מנתח בהצלחה קבוצות מפתחות שמכילות מפתחות CHACHA20-POLY1305, למרות שפעולות CHACHA20-POLY1305 AEAD לא מוטמעות ב-Tink.
  • מנתח בהצלחה קבוצות מפתחות עם מפתחות באורך של בייט אחד, שנכשלים בכל הפעולות הקריפטוגרפיות.

ההתנהגויות האלה עשויות להשתנות בגרסאות משניות.

עקביות בהערכה

עקביות בהערכה חשובה יותר מעקביות בתהליך היצירה: אם AEAD ב-Java לא יכול לפענח את ההצפנה של AEAD ב-C++‎, למשתמשים יש בעיה חמורה.

באופן כללי, המטרה של Tink היא להיות עקבי באופן הברור מאליו לגבי פרימיטיבים. לדוגמה, אם קובץ בינארי של C++‎ מחשב חתימה באמצעות public_key_sign->Sign(data), קריאת האימות התואמת של Java,‏ publicKeyVerify.verify(signature, data), אמורה להצליח.

אבל גם כאן יש כמה דברים שצריך לשים לב אליהם. לדוגמה, סוג ההחזרה של aead.Encrypt ב-Java הוא byte[]. לפי מפרט שפת Java‏ (JLS) §10.7, האורך של מערך הוא מסוג int, שיכול להיות לכל היותר 2147483647 לפי §JLS 4.2.1. לכן, הצפנה של מערך באורך 2147483647 נכשלת ב-Java: להצפנה יש תקורה מסוימת, כלומר הפלט יהיה ארוך מדי. עם זאת, בשפות אחרות ההצפנה יכולה להצליח עם קלט כזה.

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

היוצא מן הכלל הוא שפעולות מסוימות עלולות להיכשל בנסיבות חריגות.

עקביות ביצירה

לא תמיד אפשר ליצור פרימיטיבים לכל קבוצות המפתחות. לדוגמה, Tink לא מאפשר למשתמשים ליצור AesSivKey אם אורך חומר המפתח הוא 128 ביטים.

עם זאת, Tink מספק עקביות באופן הבא: אם שתי שפות תומכות בסוג מפתח, קבוצת המפתחות שבהן אפשר ליצור את הפרימיטיב חופפת. כמובן שאם שפה מסוימת לא תומכת בסוג מפתח, אי אפשר ליצור אובייקט פרימיטיבי.

עקביות ביצירה פחות חשובה מעקביות בהערכה, ויש יותר חריגים לכלל הזה מאשר לעקביות בהערכה. המגבלות האלה מתועדות ברשימת סוגי המפתחות הנתמכים. לדוגמה, בסוג המפתח ECIES,‏ Tink מאפשר לבחור באיזה עקום אליפטי להשתמש להסכם מפתח, אבל Java לא תומכת ב-X25519. לכן, יצירת מפתח באמצעות X25519 ב-Java נכשלת.


  1. במסמך הזה אנחנו משתמשים במונח Keyset כדי לציין את האובייקט שנקרא KeysetHandle ברוב השפות. ↩