14.4.6. תפעול: מפתחות, פקיעת תוקף ופתרון תקלות

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

14.4.6.1. הגנה על המפתח הפרטי

בכל פעם שהמצלמה מציגה תעודה – בתור שרת TLS, או בתור הלקוח ב-mTLS – המפתח הפרטי שלה חייב להימצא על ההתקן, בפורמט DER גולמי, על מערכת הקבצים או ב-ROMFS. כשהוא מאוחסן כך, הוא קריא לכל קוד שרץ על המצלמה ולכל מי שיש לו גישה פיזית אליה: כונן ה-USB mass-storage, פקודת REPL, או זיכרון הפלאש (flash) הגולמי. ROMFS ודגלי קריאה-בלבד מונעים שינוי, לא חילוץ. התייחס לכל מפתח פרטי שנשלח על התקן כניתן לשחזור בידי תוקף נחוש בעל גישה פיזית או גישת קוד.

אין בכך כדי להפוך את TLS לחסר תועלת – הדבר מעצב את אופן הפריסה שלו:

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

  • שמור על תעודות בעלות חיים קצרים. מפתח גנוב שימושי רק כל עוד התעודה שלו בתוקף; אורך חיים קצר בשילוב סבב שגרתי תוחם את הנזק (ראה Certificate expiry and rotation למטה).

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

  • לעולם אל תשלח מפתח בתוך קובץ קושחה ציבורי. מפתח שנצרב לתוך ROMFS בבנייית קושחה שאתה מפיץ אינו סודי; לכל מי שמוריד את הקושחה יש אותו. הקצאה פר-התקן פירושה תכנות המפתח אחרי הקושחה הגנרית, לא בתוכה.

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

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

14.4.6.2. פקיעת תוקף תעודות וסבב

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

  • חתום-עצמית. בחרת את אורך החיים עם -days. כשתוקפו פג עליך לחולל מחדש את המפתח/התעודה ולפרוס אותם שוב: העתק מחדש את קבצי ה-DER, או בנה מחדש וצרוב מחדש את קובץ ה-ROMFS אם התעודה צרובה בו. בחר ערך -days שתזכור באמת לפעול עליו.

  • CA ציבורי. אלה בעלי חיים קצרים בכוונה. Let’s Encrypt מנפיק תעודות ל-90 יום ומצפה לחידוש אוטומטי בערך כל 60 יום; אין אפשרות של ”התקן פעם אחת ושכח“.

המגמה הרחבה היא חד-כיוונית: התוקף המרבי של תעודות TLS שזוכות לאמון ציבורי ממשיך להתכווץ. הוא היה 825 יום, כיום מוגבל ל-398 יום, ופורום ה-CA/Browser אימץ לוח זמנים שמוריד אותו בהדרגה לכ-47 יום עד 2029. המסקנה לתכנון התקן היא להניח שתעודות הן בעלות חיים קצרים ושהסבב חייב להיות אוטומטי או לפחות שגרתי – אל תשלח מוצר שתלוי בהחלפה ידנית של תעודה בת עשר שנים.

מבחינה מעשית, על המצלמה: העדף תכנונים שבהם ניתן להחליף את התעודה בלי צריבה מחדש (מערכת קבצים ניתנת לכתיבה בתוספת נתיב עדכון מרחוק, או הפעלת המצלמה כלקוח שנותן אמון ב-CA שאתה מסבב מרכזית). אם תעודה חייבת להימצא ב-ROMFS, תזמן עדכוני קושחה סביב אורך חייה.

14.4.6.3. פתרון תקלות

  • השעון חייב להיות מכוון. מצלמה שלא כיוונה את שעונה מאז ההפעלה נכשלת בבדיקת תוקף התעודה – קרא ל-ntptime.settime() תחילה.

  • שם המארח חייב להתאים. כאשר הלקוח מעביר server_hostname הוא חייב להתאים ל-subjectAltName של התעודה (או ל-CN במחסניות ישנות יותר), אחרת האימות נכשל.

  • פורמט שגוי. קובץ PEM שמועתק למצלמה לא ייטען – המר ל-DER תחילה.

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

  • מפתחות Ed25519 נכשלים. השתמש ב-ECDSA P-256/P-384 או RSA, לא ב-Ed25519.

  • שגיאות הן OSError. MicroPython אינו ממש ssl.SSLError; כשלי TLS (תעודה פגומה, תוקף פג, CA לא ידוע, שגיאת פורמט, כשל לחיצת יד) נזרקים כ-OSError.