קריפטוגרפיה
הצפנה, קידוד וגיבוב: מה כל אחד מהם עושה
הפרדה בין קידוד, הצפנה וגיבוב במעבדות עם Base64, SHA-256 ו-OpenSSL. למה Base64 אינו הגנה ולמה hash הוא חד־כיווני.
צופן קיסר מזיז כל אות מספר קבוע של מקומות. מצפינים את HELLO ל-KHOOR ביד, הופכים את הפעולה ובודקים למה השיטה נשברת.
צופן קיסר הוא צופן החלפה. כל אות מוחלפת באות אחרת שנמצאת מספר קבוע של מקומות ממנה באלפבית. מזיזים כל אות שלושה מקומות קדימה, והתוצאה של HELLO היא KHOOR. השם בא מיוליוס קיסר, שלפי המסורת נהג להצפין כך את ההודעות שלו. הצופן פשוט מספיק לעבודה ביד, ובגלל הפשטות הזאת הוא כמעט לא נותן אבטחה.
כותבים את האלפבית בשורה אחת. בשורה שנייה כותבים את אותו אלפבית מוזז בשלושה מקומות, וחוזרים להתחלה אחרי Z:
Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Shift: DEFGHIJKLMNOPQRSTUVWXYZABCכדי להצפין, מאתרים כל אות של הטקסט הגלוי בשורה העליונה ומעתיקים את האות שמתחתיה. H הופכת ל-K, E הופכת ל-H, L הופכת ל-O ו-O הופכת ל-R. כך התוצאה של HELLO היא KHOOR. המפתח הוא גודל ההזזה, כאן 3.
רווחים, ספרות וסימני פיסוק לא נמצאים באלפבית שבין A ל-Z. גרסה לימודית יכולה להשאיר אותם כמו שהם, וקוד ה-Python שבהמשך עושה בדיוק את זה.
הפענוח הוא אותה טבלה בכיוון ההפוך. מזיזים כל אות שלושה מקומות אחורה, וזה שקול להזזה של 23 מקומות קדימה:
KHOOR → HELLOעבור מפתח נתון, כל אות של הטקסט הגלוי ממופה לאות אחת בלבד של הטקסט המוצפן, וגם המיפוי ההפוך חד־משמעי. לכן אפשר לבטל את הצופן ברגע שיודעים את המפתח.
באלפבית האנגלי יש 26 אותיות, ולכן ההזזות חוזרות על עצמן כל 26 מקומות. הזזה של 29 עושה את אותו הדבר כמו הזזה של 3:
29 mod 26 = 3הזזה של −3 עושה את אותו הדבר כמו הזזה של 23. בקוד כדאי לחשב את ההזזה מודולו 26, כך שכל מספר שלם יעבוד.
הפונקציה הזאת מזיזה רק את האותיות A עד Z ו-a עד z, לא נוגעת בשאר התווים וחוזרת להתחלה בעזרת מודולו 26. כדי להמיר בין אותיות למספרים היא משתמשת בפונקציות ord וגם chr:
def caesar(text, shift):
out = []
for ch in text:
if ch.isascii() and ch.isalpha():
base = ord('A') if ch.isupper() else ord('a')
out.append(chr((ord(ch) - base + shift) % 26 + base))
else:
out.append(ch)
return ''.join(out)
print(caesar("HELLO", 3))
print(caesar("KHOOR", -3))
print(caesar("KHOOR", 23))
print(caesar("HELLO", 29))
print(caesar("ATTACK AT DAWN", 3))
print(caesar(caesar("Hello, World!", 13), 13))
print(caesar("Hello, World!", 13))
print(caesar("hello, world", 3))
print(caesar("KHOOR", 26 - 3) == caesar("KHOOR", -3))
print(sum(1 for s in range(1, 26) if caesar("KHOOR", s) == "HELLO"))
print(caesar("HELLO", 3) == caesar("HELLO", 29))הפלט של הרצת הסקריפט:
KHOOR
HELLO
HELLO
KHOOR
DWWDFN DW GDZQ
Hello, World!
Uryyb, Jbeyq!
khoor, zruog
True
1
Trueהפלט מאשר את מה שנאמר בסעיפים הקודמים. הזזות של −3 ושל 23 נותנות אותה תוצאה, וכך גם 3 ו-29. מבין ההזזות 1 עד 25, רק אחת מחזירה את KHOOR לטקסט HELLO. הפעלה כפולה של הזזה 13 מחזירה את הטקסט המקורי, וזה המקרה של ROT13 שמתואר בהמשך.
באלפבית של 26 אותיות יש רק 25 הזזות שמשנות את הטקסט. תוקף יכול לנסות את כולן ולבדוק איזו תוצאה קריאה. בטקסט באנגלית קל לזהות את התוצאה הקריאה, כך שההתקפה כמעט לא דורשת מאמץ.
גם שכיחות האותיות נשמרת אחרי ההזזה. באנגלית E נפוצה ו-Z נדירה, ולכן טקסט מוצפן שבו אות אחת מופיעה הרבה יותר מהאחרות הוא רמז חזק. גם בלי לנסות את כל ההזזות, ספירת האותיות מצביעה על המפתח.
הצופן שימושי ללימוד אוצר המילים של הקריפטוגרפיה: טקסט גלוי, טקסט מוצפן, מפתח, החלפה ו-brute force. אסור להשתמש בו כדי להגן על סיסמאות, נתוני לקוחות, מפתחות API או קבצים פרטיים. הצפנה אמיתית משתמשת באלגוריתמים מתוקננים, במפתחות שנוצרו כראוי ובניהול מפתחות זהיר. הערך על קריפטוגרפיה במילון של NIST נותן את ההגדרות הפורמליות של התחום.
ROT13 הוא צופן קיסר עם הזזה של 13. הוא ההופכי של עצמו: הפעלה כפולה מחזירה את הטקסט המקורי, כי 13 + 13 = 26, וסיבוב שלם סביב האלפבית לא משנה כלום. הפלט של ROT13 על Hello, World! הוא Uryyb, Jbeyq!, כפי שמופיע למעלה.
משתמשים ב-ROT13 כדי להסתיר ספוילרים או פאנץ׳ליינים ממבט חטוף. הוא לא נותן הגנה אמיתית, כי מי שמכיר את השיטה קורא אותו תוך שניות.
צריך להצפין ביד את ATTACK AT DAWN עם הזזה של 3, בלי לגעת ברווחים, ולהשוות לתשובה הזאת:
DWWDFN DW GDZQאחר כך כדאי לשנות את ההזזה בפונקציית ה-Python ולהריץ אותה על אותו טקסט. כדאי לנסות הזזה 0, הזזה 26 והזזה 13, ולנחש כל תוצאה לפני ההרצה. טקסט הבדיקה צריך להיות סינתטי או שלך, והתרגיל נשאר על המחשב שלך.
המאמר הבא, צופן קיסר ב-Python, מרחיב את הפונקציה הזאת עם טיפול בקלט ובדיקות.
להמשך קריאה: הערך על קריפטוגרפיה במילון של NIST והתיעוד של Python עבור ord וגם chr.
קריפטוגרפיה
הפרדה בין קידוד, הצפנה וגיבוב במעבדות עם Base64, SHA-256 ו-OpenSSL. למה Base64 אינו הגנה ולמה hash הוא חד־כיווני.
קריפטוגרפיה
למה hashes מהירים נכשלים בסיסמאות, מה salt ו-work factor עושים, ואיך מחשבים ומאמתים Argon2id ב-Python עם argon2-cffi.
קריפטוגרפיה
מפתחות ציבוריים ופרטיים מאפס: מה חתימה מוכיחה, למה המפתח הפרטי נשאר סודי, ומעבדת Ed25519 שבה קובץ ששונה נכשל באימות.