מסמך זה הוא הלכה מעשית: מה מותר ומה אסור כשמצפינים מידע ומעבירים קבצים מקצה לקצה. הוא נכתב מתוך הנחה אחת - שיש יריב. יריב שרואה את התעבורה שלך, יכול לגשת לתשתית שדרכה היא עוברת, ומחפש לא את תוכן ההודעה אלא את עצם קיומה. תחת ההנחה הזאת, החלק הקשה כמעט אף פעם אינו הצופן. אלגוריתמים מודרנים חזקים דיים שלא יישברו בכוח סביר בדורות הקרובים. מה שמפיל מערכות הוא כל מה שעוטף את הצופן: מטא-דאטה, דפוסים, תשתית והרגלים. הכלל המרכזי של אנן - "השרת לא רואה" - נגזר ישירות מכאן.
נקודת המוצאמודל האיום
לפני שכותבים שורת קוד אחת, מגדירים מפני מי מגינים. בלי מודל איום מפורש, כל החלטת אבטחה היא ניחוש. הנח שהיריב מסוגל ל:
- צפייה פסיבית - לראות כל בקשה שעוברת ברשת: כתובות, גדלים, עיתויים ונפחים.
- גישה לתשתית - לתפוס את השרת, את הלוגים ואת ספק הענן, ולקרוא כל מה ששמור שם.
- ניתוח תעבורה - להסיק מסקנות מהמעטפת בלבד, בלי לפענח בית אחד: מי מדבר עם מי, מתי, ובאיזו סדירות.
- התמדה - לשמור עותקים, לחזור לארכיונים, ולנתח אותך רטרואקטיבית שנים אחורה.
מה שהיריב הזה לא יוכל לעשות, אם בנית נכון, הוא לקרוא את התוכן. כל השאר - כן. תכנן בהתאם.
מקרה מבחןמה שנכשל
המקרה הלימודי ביותר בהיסטוריה של תקשורת סמויה מקוונת אינו כשל של צופן. בעשור הקודם קרסה מערכת תקשורת של גורם מודיעין גדול. לפי תחקירים פומביים היא הפעילה מאות אתרי כיסוי תמימים למראה - אתרי ספורט, תחביבים וחדשות מקומיות - שמאחורי תיבת החיפוש שלהם נפתח, בטריגר מוסכם, ערוץ סמוי. הצופן לא נשבר. את הרשת הפילה שרשרת טעויות שאין להן דבר עם הצפנה:
- תשתית משותפת. האתרים ישבו על בלוקי כתובות IP רצופים. חשיפת אתר אחד גררה מיד את שכניו - נקודת כשל אחת שגלגלה רשת שלמה.
- דפוס חוזר. כולם נבנו מאותה תבנית, עם אותו מנגנון אימות באותו מקום. מי שפיצח אחד, זיהה את כולם בסריקה אוטומטית.
- שחזור ממקור פומבי. חוקרים בנו מחדש את הרשת כולה מאתר יחיד, בעזרת ארכיוני אינטרנט וסריקות היסטוריות ישנות. שום דבר לא נמחק - הוא רק הפסיק להתעדכן.
- קומפרטמנטליזציה מדומה. כל אתר הוקצה לנכס יחיד כדי להגביל נזק. אבל כשקל למצוא את כל האתרים, הבידוד-לכאורה קרס: היריב מיפה את הסט כולו ופתר אותו כמכלול.
- התנהגות מסגירה. המשתמשים היו אמורים להגיע לערוץ דרך שרשרת ניתוב מטשטשת. לעיתים דילגו. הדפוס עצמו - כניסה ישירה, חוזרת, מאותו מקום - היה החתימה.
התוצאה, לפי הדיווחים: עשרות מקורות נחשפו. איש לא פענח מסר. המערכת פשוט הותירה חתימה שאמרה בקול "כאן יש ערוץ".
הבעיה הקשה איננה להצפין תוכן. הבעיה הקשה היא לא לייצר את הדפוס שמסגיר שקיים ערוץ בכלל.
תוכן מוצפן היטב, היושב במבנה צפוי, על תשתית אחידה, בעיתוי סדיר - הוא עדיין דגל אדום. אבטחה נמדדת בחוליה החלשה, והחוליה החלשה כמעט תמיד אינה המתמטיקה.
אַל תַּעֲשֶׂה
- אל תבלבל עמימות עם הצפנה. הומוגליפים, תווי אפס-רוחב, סטגנוגרפיה, פינים על מפה - כולם מסתירים, לא מצפינים. הם עוצרים עין מקרית, לא יריב שמחפש. סורק ייעודי מזהה התפלגות תווים חריגה בשבריר שנייה, ונרמול
Unicode מוחק מטען של תווים סמויים. הסתרה בלי הצפנה מתחתיה היא אשליה של ביטחון.
- אל תשים תוכן קריא על שרת שיכול לקרוא אותו. אם השירות רואה את הטקסט, את הצופה, את הזמן ואת ה-
IP - הפקדת את הסוד בידי צד שלישי. שירותי מפות, דפי "הדבקה", ענני קבצים ומקצרי כתובות - כולם רואים, כולם שומרים.
- אל תמחזר
nonce או מפתח. ב-AES-GCM שימוש חוזר ב-nonce עם אותו מפתח הוא אסון: הוא חושף את מפתח האימות, מאפשר זיוף הודעות, ומדליף את ה-XOR של הטקסטים. מפתח שחוזר על עצמו הופך צופן חזק לשקוף.
- אל תמציא צופן משלך. הצפנה נשברת בפרטים הקטנים - ריפוד, השוואות תלויות-זמן, טיפול בשגיאות. השתמש בספריות בדוקות (
WebCrypto), לא בקוד ביתי.
- אל תסמוך על
TLS לבדו. TLS מגן על הקו בין הדפדפן לשרת. הוא לא מגן עליך מפני השרת. ברגע שהבקשה מגיעה ליעד, ה-TLS הוסר והתוכן גלוי לכל מי ששולט בקצה.
- אל תיצור דפוס. אותה תבנית, אותו דומיין, אותה תשתית, אותו עיתוי - אחידות היא בדיוק מה שמאפשר שחזור של הכל מפריט אחד.
- אל תניח שמחיקה היא מחיקה. ארכיוני אינטרנט, לוגים, מטמון CDN וגיבויים - מה שעלה לרשת נשאר איפשהו, לרוב מחוץ לשליטתך.
עֲשֵׂה
- הצפן אצל הלקוח, לפני שדבר נוגע בחוט. ההצפנה קורית בדפדפן, בשני הקצוות. השרת מקבל ג'יבריש בלבד. זה ההבדל בין "אנחנו מגינים על המידע שלך" לבין "אין לנו מה לחשוף, גם אם נרצה".
- נצל את מה שהשרת לא רואה. ה-fragment של כתובת - כל מה שאחרי ה-
# - לעולם אינו נכלל בבקשת ה-HTTP. הדפדפן מחזיק אותו מקומית ואינו שולח אותו. מטען מוצפן שיושב שם עובר בין שני צדדים בלי שהשרת, הלוגים או ה-CDN יראו אותו אי פעם. זו "השרת לא רואה" בצורתה הטהורה.
- השתמש בצופן מאומת (
AEAD). AES-GCM או ChaCha20-Poly1305 מספקים סודיות ואימות שלמות כאחד - הנמען יודע לא רק שהתוכן חסוי, אלא שגם לא שונה בדרך. nonce אקראי וייחודי לכל הודעה.
- גזור מפתחות נכון. אם המפתח נובע מסיסמה, העבר אותה דרך פונקציית גזירה איטית ועמידה -
Argon2id, ובהיעדרה PBKDF2 במספר איטרציות גבוה. סיסמה גולמית אינה מפתח.
- החזק מפתחות מחוץ למערכת. המפתח מוסכם מראש בין הצדדים או מועבר בערוץ נפרד לחלוטין. מפתח שמוטמע בעמוד, או נשלח באותו ערוץ כמו המטען, ביטל את כל ההגנה.
- שאף לסודיות קדימה. חשיפת מפתח אחד לא צריכה לפתוח את כל העבר. מפתחות חד-פעמיים ומתחלפים מבטיחים שהודעה שנתפסה היום לא תיפתח ממפתח שידלוף מחר.
- מזער מטא-דאטה, לא רק תוכן. גם כשהתוכן חסום, המעטפת מדברת: גודל, עיתוי, תדירות. רפד הודעות לאורך אחיד, פזר עיתויים, והימנע מסדירות שאפשר לפרופל.
- בודד. אין נקודה אחת שחשיפתה מפילה את הכל. פזר תשתית, גוון דפוסים, ודאג שכל הודעה תעמוד בפני עצמה.
- העדף חד-פעמיות. מפתח חד-פעמי, קישור שפג בזמן, הודעה שאינה נשמרת לאחר קריאה. מה שאינו קיים - לא ניתן ליירט, לזמן לדין, או לגלות רטרואקטיבית.
- הנח שהערוץ עוין. הכיסוי אינו הדומיין ואינו שם המערכת. הכיסוי היחיד שמחזיק הוא שהתוכן חסר משמעות מוחלטת לכל מי שאין בידו המפתח.
כלל אצבע. אם אתה צריך לבחור לאן להשקיע - השקע בצמצום המטא-דאטה ובבידוד התשתית, לא בשדרוג הצופן. הצופן שלך כבר מספיק חזק. הדפוס שלך, כנראה, לא.
השורה התחתונה
צופן חזק הוא תנאי הכרחי, לא מספיק. המערכת שקרסה במקרה המבחן השתמשה בהצפנה סבירה, ובכל זאת נפלה - כי הדליפה מעולם לא הייתה בתוכן, אלא סביבו: בתשתית, בדפוס, בהתמדה.
בנה מתוך ההנחה שהכל ייתפס. ואם ייתפס - שלא יהיה מה לראות. לא בתוכן, כי הוא מוצפן אצלך, בקצה, במפתח שאינו כאן; ולא בדפוס, כי לא הותרת אחד.