דילוג לתוכן
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

הצפנה, קידוד וגיבוב: מה כל אחד מהם עושה

הפרדה בין קידוד, הצפנה וגיבוב במעבדות עם Base64, SHA-256 ו-OpenSSL. למה Base64 אינו הגנה ולמה hash הוא חד־כיווני.

מתחילים8 דקות קריאהמאת NotHoly

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

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

מתחילים כאן

צריך טרמינל עם base64, sha256sum וגם openssl. ב-Windows 11 הפקודות שלהלן רצות ב-Git Bash, שמגיע עם Git for Windows. יש גם גרסת PowerShell לשלב הגיבוב. לא נדרש ידע קודם בקריפטוגרפיה, אבל קריאה של המאמר על צופן קיסר קודם עוזרת להבין את הרעיון של מפתח.

כל פקודה במעבדה בטוחה להרצה על המחשב שלך. צריך להשתמש בקובץ בדיקה, לא בסוד אמיתי.

שלושה תפקידים שונים

שלוש הפעולות עונות על שלוש שאלות שונות.

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

כדאי לזכור את הטבלה הזו במהלך המעבדה. שאר המאמר מסביר כל שורה.

קידוד משנה את הייצוג

קידוד כותב נתונים מחדש בצורה אחרת כדי שמערכת תוכל להעביר אותם. הדוגמה הקלאסית היא Base64. הוא לוקח בתים וכותב אותם ב-64 תווים הניתנים להדפסה: A עד Z, a עד z, 0 עד 9, + וגם /, והתו = משמש למילוי. הפורמט מוגדר ב-RFC 4648. קבצים מצורפים לאימייל, data URLs והרבה payloads של API משתמשים בו כי התעבורה מצפה לטקסט.

ב-Base64 אין סוד. המיפוי ציבורי וקבוע. כל כלי שמכיר את הכלל יכול להחזיר את הפלט לקלט. זו המטרה של קידוד: תאימות בין מערכות, לא סודיות.

הצפנה מסתירה נתונים מאחורי מפתח

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

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

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

גיבוב יוצר טביעת אצבע

פונקציית hash קריפטוגרפית מקבלת קלט בכל אורך ומחזירה פלט באורך קבוע. SHA-256 מוגדר ב-FIPS 180-4, והפלט שלו הוא תמיד 256 ביטים, שנכתבים כ-64 תווים הקסדצימליים. למתחילים חשובות שתי תכונות:

  • אותו קלט תמיד נותן אותו פלט.
  • שינוי קטן בקלט אמור לשנות את הפלט עד כדי כך שהוא ייראה לא קשור. פונקציות hash טובות מתוכננות כך שלא יהיה מעשי למצוא שני קלטים עם אותו פלט.

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

ה-hash הוא טביעת אצבע, לא מנעול. כל אחד יכול לחשב SHA-256 של קובץ ציבורי. hash מוכיח ששני עותקים תואמים. הוא לא מסתיר את הקובץ.

למה זה משנה

רוב טעויות האבטחה האמיתיות בתחום הזה נובעות משימוש בכלי הלא נכון.

  • מתכנת שומר מפתח API ב-Base64 וקורא לזה "מוצפן". כל מי שרואה את הערך יכול לבטל את הקידוד בפקודה אחת.
  • צוות בודק הורדה בעזרת hash, אבל ה-hash מפורסם באותו דף כמו הקובץ, ומוגש מאותו שרת שנפרץ. הבדיקה מוכיחה רק שהקובץ תואם לדף.
  • אפליקציית ווב שומרת סיסמאות ב-SHA-256 רגיל. אפשר לתקוף מסד נתונים גנוב במהירות באמצעות ניחושים, כי SHA-256 תוכנן להיות מהיר. ההנחיות של OWASP לאחסון קריפטוגרפי קובעות שיש להגן על סיסמאות באלגוריתמי גיבוב סיסמאות מאובטחים במקום בהצפנה הפיכה, ומפנות ל-Password Storage Cheat Sheet לפרטים. הבחירות הרגילות הן גיבובי סיסמאות איטיים עם salt, כמו Argon2id, scrypt, bcrypt או PBKDF2. המאמר הבא בסדרה עוסק ב-Argon2id.

הבנת ההבדל בשלב מוקדם חוסכת את המלכודות האלה.

מעבדה 1: קידוד עם Base64

לפתוח Git Bash בתיקייה ריקה. לקודד ביטוי קצר ואז לבטל את הקידוד של התוצאה.

bash
echo -n 'hello lab' | base64

הפלט שקיבלתי על המחשב הזה עם OpenSSL 3.2.4 ו-Git Bash:

text
aGVsbG8gbGFi

עכשיו מבטלים את הקידוד של הפלט:

bash
echo -n 'aGVsbG8gbGFi' | base64 -d

פלט:

text
hello lab

שני דברים לשים אליהם לב. קודם כול, לא היה מעורב שום מפתח. שנית, echo -n חשוב כאן. בלי -n, הפקודה echo מוסיפה ירידת שורה ופלט ה-Base64 משתנה. כדי להשוות, אפשר להריץ echo 'hello lab' | base64: אני קיבלתי aGVsbG8gbGFiCg==. Base64 הופך כאן 9 בתים ל-12 תווים, ולכן הפלט ארוך מהקלט.

השאלה לבדיקה: האם מישהו בלי שום סוד יכול להפוך את זה? כן. זה המבחן שמפריד בין קידוד להצפנה.

מעבדה 2: גיבוב עם SHA-256

להעביר את אותו ביטוי דרך SHA-256:

bash
echo -n 'hello lab' | sha256sum

פלט:

text
8fc6baba79a0d60b37dee612ccc1ec096ef52dba8cb0a24a6451e8bfb0e4d761 *-

עכשיו להוסיף סימן קריאה אחד ולהריץ שוב:

bash
echo -n 'hello lab!' | sha256sum

פלט:

text
36902fb7fdea33458ad09dfeb52118dc47f99a8ca2b9001080366d55511de915 *-

לשני ה-hashes אין דפוס משותף שאפשר לראות. תו אחד שינה את כל הפלט. שניהם באורך 64 תווים הקסדצימליים, כלומר 256 ביטים.

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

גיבוב של קובץ וזיהוי שינוי

ליצור קובץ קטן ולגבב אותו:

bash
echo 'secret note' > note.txt
sha256sum note.txt

על המחשב שלי, עם סיומות שורה של Unix בקובץ, הפלט היה:

text
b5f891a5e064fec661025d0b0ec2de157487a6c2e5cc46dc0971fee56f86c645 *note.txt

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

חלופה ב-Windows PowerShell

אם PowerShell נוח יותר, יש ב-Windows פקודה מובנית:

powershell
Get-FileHash note.txt -Algorithm SHA256

בפלט צריך לחפש את השורה Hash, שמציגה 64 תווים הקסדצימליים. ה-hash תלוי בבתים המדויקים בקובץ. הפקודה Set-Content של PowerShell כותבת סיומות שורה של Windows (CRLF), ששונות מסיומת LF בדוגמת ה-Bash שלמעלה. על המחשב שלי, קובץ שנכתב כך נתן את ה-hash הזה:

text
406A5646AE75CA75D032F306ABD33085DC9F656E3109BB962AEAB335EEC9ED85

אותם בתים שגובבו עם sha256sum ב-Git Bash נתנו את אותו ערך באותיות קטנות. אם ה-hash שלך שונה מדוגמת ה-Bash אבל תואם לתוצאת PowerShell עבור הקובץ שלך, הסיבה היא סיומות השורה.

מעבדה 3: הצפנת קובץ עם OpenSSL

ליצור פתק ולהצפין אותו עם AES-256-CBC. OpenSSL יבקש סיסמה. כדאי לבחור סיסמה שקל לזכור ושמשמשת רק למעבדה הזו.

bash
echo 'secret note' > note.txt
openssl enc -aes-256-cbc -pbkdf2 -salt -in note.txt -out note.enc

OpenSSL מבקש את הסיסמה, והקובץ המוצפן נכתב אל note.enc. האפשרות -salt מוסיפה salt אקראי, כך שהצפנה של אותו קובץ פעמיים נותנת פלט שונה. קובץ מוצפן שנוצר עם -salt מתחיל בטקסט ASCII הזה: Salted__. בדקתי את זה על המחשב שלי. שאר הקובץ בינארי ולא קריא.

עכשיו מפענחים אותו:

bash
openssl enc -d -aes-256-cbc -pbkdf2 -in note.enc

להזין את אותה סיסמה. פלט:

text
secret note

הפענוח עובד רק עם הסיסמה הנכונה. בדקתי עם סיסמה שגויה. OpenSSL הדפיס bad decrypt ויצא עם שגיאה.

הצפנה לבדה לא מזהה שינויים

בשלב הבא משנים בית אחד בקובץ המוצפן ומנסים לפענח אותו. הפכתי ביט אחד בתוך בלוק ה-ciphertext של עותק בשם tampered.enc. הפענוח נכשל עם bad decrypt, והפקודה יצאה עם סטטוס 1.

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

שלושתם זה לצד זה

להעביר את אותו טקסט דרך כל פעולה ולהשוות:

פעולה פקודה פלט על hello lab (נצפה)
קידוד echo -n 'hello lab' | base64 aGVsbG8gbGFi
גיבוב echo -n 'hello lab' | sha256sum 8fc6baba...e4d761
הצפנה openssl enc ... -in note.txt נתונים בינאריים, צריך את הסיסמה כדי לקרוא

מה כל פלט מאפשר:

  • Base64 מאפשר לכל אחד לשחזר את hello lab.
  • ה-hash מאפשר לאמת שקלט מועמד הוא hello lab, אבל לא לשחזר את הקלט מה-hash לבדו.
  • הקובץ המוצפן מאפשר לשחזר את secret note רק עם הסיסמה.

טעויות נפוצות

לקרוא ל-Base64 "הצפנה" או "obfuscation" כשמדובר בסודות. Base64 לא מסתיר כלום. כל מי שרואה מחרוזת Base64 יכול לבטל את הקידוד שלה. סודות שומרים במנהל סודות או באחסון מוצפן, לא בצורה מקודדת.

להשתמש ב-hash כמנעול. hash הוא חד־כיווני, אבל קלטים קצרים או נפוצים אפשר לנחש. אם מגבבים את hello lab, תוקף עם רשימת ביטויים נפוצים משחזר אותו בלי לשבור את SHA-256. לכן גיבוב סיסמאות צריך salts ואלגוריתמים איטיים.

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

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

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

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

איך להמשיך

לחזור על שלוש המעבדות עם ביטוי אחר, ואז עם קובץ של כמה קילובייטים. פלט ה-Base64 גדל בערך בשליש, ה-hash נשאר באורך 64 תווים, והקובץ המוצפן גדל רק בכותרת וב-padding.

בהמשך כדאי לקרוא על גיבוב סיסמאות. הבעיה שם היא עלות הניחוש, לא הגיבוב כשלעצמו. המאמר הבא בסדרה, איך גיבוב סיסמאות עובד עם Argon2id, מסביר salts, work factors ולמה חשוב ש-hashes יהיו איטיים. לרענון של צד הצפנים, אפשר לקרוא קודם את צופן קיסר ב-Python. הוא מציג מפתח ואלגוריתם בצורה שאפשר לבדוק.

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

מקורות

מקורות

  1. RFC 4648: The Base16, Base32, and Base64 Data Encodings
  2. FIPS 180-4: Secure Hash Standard (SHS), with update 1
  3. OWASP Cryptographic Storage Cheat Sheet

עוד בנושא קריפטוגרפיה

קריפטוגרפיה

סיסמאות ו-hashing עם Argon2id

למה hashes מהירים נכשלים בסיסמאות, מה salt ו-work factor עושים, ואיך מחשבים ומאמתים Argon2id ב-Python עם argon2-cffi.

ביניים8 דקות קריאה