אנשים מתארים VPN כ„כזה שמשתמש בהצפנת מפתח ציבורי” ואז מדמיינים שכל חבילה ננעלת בתעודה של השרת. התמונה הזו שגויה באופן שחשוב כשקוראים קובץ קונפיגורציה או קלט של חבילות. החצי הציבורי של VPN עוסק בהוכחה מי הוא העמית ובהסכמה על חומר סודי; החצי הסימטרי הוא מה שבאמת מגן על התעבורה, חבילה אחר חבילה, לאורך כל חיי ההפעלה.

לשני החצאים תוחלת חיים שונות, אופני כשל שונים ודברים שונים שאפשר לפרסם בבטחה. ברגע שמפרידים ביניהם, שאלות כמו „האם RSA 2048 חלש מ-AES-128” מפסיקות לבלבל, כי הן מעולם לא היו בנות השוואה.

שלוש פעולות שמערבבים יחד

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

לחיצות ידיים של VPN משתמשות בעיקר בשתיים הראשונות. תעודה אינה מפתח הצפנה; היא הצהרה חתומה שקושרת שם למפתח ציבורי ומאפשרת לצד השני להחליט אם לסמוך על המפתח שקיבל זה עתה. הקמת מפתחות ב-TLS 1.3, למשל, נשענת על הסכם מפתחות (EC)DHE ועל חתימות תעודה, לא על הצפנת ההפעלה במפתח הציבורי של השרת.

מה שתהליך לחיצת הידיים באמת מייצר

בלחיצת ידיים מודרנית, כל צד מייצר זוג מפתחות אפמרלי, מחליף את החצאים הציבוריים ומחשב סוד משותף שלעולם לא חוצה את החוט. הסוד הזה עובר לאחר מכן בפונקציית גזירת מפתחות כדי לייצר מפתחות נפרדים לכל כיוון, בתוספת ה-nonces וחומר ה-IV ששכבת הרשומה זקוקה לו. WireGuard עושה זאת במבנה המבוסס על Noise; TLS 1.3 עושה זאת עם HKDF מעל תמליל לחיצת הידיים.

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

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

למה נתונים בנפח גדול משתמשים במפתחות סימטריים

צפנים סימטריים מתמודדים היטב עם נפח: AES-GCM או ChaCha20-Poly1305 מעבדים כל חבילה במפתח שכבר בזיכרון, מאמתים את הכותרת ומגדילים מונה. הצד המקבל בודק את ה-nonce ואת תג האימות, וזורק כל מה שנכשל או חוזר. זה זול מספיק כדי לרוץ בקצב קו על חומרה רגילה, ואותה מבנה נותן סודיות ושלמות במעבר אחד.

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

תוחלת חיים, חידוש מפתחות וסודיות קדימה

מפתחות הפעלה נועדו לפוג. TLS 1.3 מאפשר הודעת KeyUpdate לגלגל את מפתחות התעבורה; WireGuard מחדש הפעלה לאחר זמן או מספר הודעות מוגדר ושומר את הישן לזמן קצר עבור חבילות בדרך. OpenVPN מנהל משא ומתן מחדש על מפתחות ערוץ הנתונים שלו לפי לוח זמנים, כאשר reneg-sec שולט במרווח.

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

לקרוא קונפיגורציות ואבחון בלי לערבב אובייקטים

בפועל בוחרים פרוטוקול שלם ואת הפרימיטיבים שלו שנתמכים בו, לא מרכיבים אחד משלכם. מפתח --tls-crypt של OpenVPN מגן על ערוץ הבקרה; ערוץ הנתונים משתמש בצפנים סימטריים שנוהלו. רשומות PrivateKey ו-PublicKey של WireGuard הן חומר זהות, בעוד שמפתחות התעבורה שלו נגזרים פנימית. קריאת השדות האלה כאותו סוג של סוד מובילה לטעויות כמו הדבקת מפתח ציבורי במקום שבו שייך מפתח פרטי.

שמרו חומר ציבורי בנפרד מהפרטי. תעודה, מפתח ציבורי של WireGuard וטביעת אצבע בטוחים לשיתוף בכרטיס. מפתח פרטי, מפתח משותף מראש ומפתח הפעלה מיוצא אינם. כשמשווים חוזק, השווו בתוך אותו סוג: מזהה עקומה אליפטית, גודל מודולוס RSA וגודל מפתח AES מודדים דברים שונים תחת הנחות שונות. מפרט TLS 1.3 הוא עיון שימושי לאיך שתי השכבות משתלבות, גם כשהמנהרה שלכם אינה TLS.

מאמרים קשורים