בפעם הראשונה ששלחתי מערכת כניסה, עשיתי את הדבר שכל הדרכה מאותה תקופה אמרה לי לעשות: מאוחסן md5($password) בטבלת המשתמשים והמשיך הלאה זה עבד, וזה היה בשקט אסון שנים של בניית auth לתוך תוספי וורדפרס ואפליקציות Laravel מאוחר יותר, יש לי הרבה יותר בריא כבוד הפער בין " בדיקת הסיסמה עובר" ו " הסיסמאות בטוחות אם מסד נתונים זה דולף." Bcrypt הוא הכלי שסוגר את רוב הפער הזה, וזה ברירת המחדל כמעט בכל מסגרת שאני מגיע אליה אז בניתי א מחולל bcrypt על Toolz.dev שמקריב סיסמה עם גורם עלות שאתה שולט בו, מאמת סיסמה מול גיבוב קיים, ועושה את כל זה בדפדפן שלך כך ששום דבר שאתה מקליד לא נשלח לשום מקום. זה המדריך אליו וכדי להקרין את עצמו.
TL;DR: Bcrypt הופך סיסמה ל-hash מלוח, איטי בכוונה של 60 תווים, כך שמסד נתונים שדלף אינו רשימת סיסמאות שדלפה. הכליז מחולל bcrypt hashes כל סיסמה עם גורם עלות מתכוונן (4 עד 31), מאמת סיסמה מול hash שאתה מדביק, ומראה את הגרסה, העלות והמלח שהיא ניתחה. זה מייצר את התקן
$2b$פורמט את OpenBSD, PHPpassword_hashספריות bcrypt של Laravel ו-Node כולן מקבלות, והיא פועלת לחלוטין בצד הלקוח.
מה זה bcrypt?
Bcrypt היא פונקציית גיבוב סיסמאות שתוכננה על ידי נילס פרובוס ודיוויד מזיירס והוצגה במאמר USENIX משנת 1999 " תוכנית סיסמה ניתנת להתאמה לעתיד". הוא בנוי על צופן הבלוק Blowfish, אבל עם טוויסט: במקום להצפין נתונים, הוא מריץ את Blowfish's שלב הגדרת המפתח שוב ושוב, תוך שימוש בסיסמה ומלח אקראי כחומר המפתח. התוצאה היא גיבוב חד כיווני שזול לחישוב פעם אחת ויקר לחישוב מיליארד פעמים, שזה בדיוק הנכס שאחסון סיסמאות צריך.
זה " יקר בכוונה" הרעיון הוא הלב של זה. hash למטרות כלליות כמו SHA-256 מתוכנן להיות מהיר, כי סכומי בדיקה ובדיקות תקינות רוצים מהירות. hashing סיסמה רוצה את ההיפך. אם תוקף גונב את מסד הנתונים שלך, הדבר היחיד שעומד בינם לבין כל סיסמת טקסט רגיל הוא כמה זמן לוקח לנחש. hash מהיר מאפשר ל-GPU מודרני לבדוק מיליארדי מועמדים בשנייה; hash bcrypt במכסי עלות הגיוניים של כמה אלפים לשנייה לליבה. אותו קובץ שדלף, תוצאה שונה בתכלית.
Bcrypt שרד יותר משני עשורים כי הוא קיבל את היסודות הנכונים וכי הוא ניתן להתאמה גורם העלות אומר שאותו אלגוריתם שהיה מכוון לחומרה של 1999 ניתן לחייג לחומרה של 2026 מבלי לשנות שום דבר אחר. זה נשאר אופציה מומלצת ב- גיליון בגידות אחסון סיסמאות OWASP, וזה ברירת המחדל מחוץ לקופסה ב-Laravel, Spring Security, ועוד הרבה ערימות שאני עובד בהן. אם אתה רוצה את הרקע העמוק יותר מדוע גיבוב מהיר שגוי עבור העבודה הזו, ה כלים מקוונים לפרטיות נתונים המדריך מכסה את ההיגיון שדחף את כל התעשייה לעבר גיבוב איטי ומלוח.
מה מכיל גיבוב bcrypt?
אחד הדברים היפים ביותר ב-bcrypt הוא שהפלט שלו מתאר את עצמו. קח חשיש אמיתי:
$2b$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
קרא משמאל לימין, פיצול על סימני הדולר, והוא אומר לך את כל הדרוש כדי לאמת סיסמה נגדו:
| שדה | דוגמה | משמעות |
|---|---|---|
| גרסה | 2b |
גרסת ה-bcrypt. 2b הוא פורמט OpenBSD המתוקן הנוכחי |
| עלות | 12 |
גורם העבודה. הגדרת המפתח מריצה 2^12 = 4096 איטרציות |
| מלח | R9h/cIPz0gi.URNNX3kh2O |
22 תווים של Base64 מותאם אישית, פענוח ל-16 בתים אקראיים |
| לעכל | PST9/PgBkqquzi.Ss7KIUgO2t0jWMUW |
31 תווים המקודדים את פלט ה-bcrypt של 23 בתים |
מכיוון שהמלח והעלות חיים בתוך המחרוזת, האימות לא צריך שום דבר אחר. כאשר אתה מדביק חשיש לתוך מחולל bcrypt מצב אימות, זה קורא את העלות ומלח ישר מתוך המחרוזת, recomputes את העיכול עם כי בדיוק מלח, ו משווה אין עמודת מלח נפרד לנהל, וזו אחת הסיבות bcrypt הוא כל כך נעים לאחסן: זה שדה אטום יחיד בטבלת המשתמשים שלך.
האלפבית המותאם אישית Base64 שווה הערה, כי הוא מכשיל אנשים. Bcrypt משתמש ./A-Za-z0-9, שזה סדר שונה מ-Base64 הסטנדרטי מלח bcrypt הוא לא מחרוזת Base64 סטנדרטית, אז אל תנסה לפענח אותו עם כלי Base64 גנרי ולצפות לבייטים משמעותיים אם אתה סקרן לגבי הגרסה הסטנדרטית המשמשת בכל מקום אחר, ה קידוד base64 המדריך עובר באלפבית הרגיל והיכן הוא מופיע.
כיצד אוכל ליצור hash bcrypt?
בכלי זה שלושה שלבים: הקלד סיסמה, בחר עלות, לחץ על צור.מתחת למכסה המנוע, יצירת hash עושה יותר ממה שהוא נראה. ראשית נוצר מלח אקראי חזק מבחינה קריפטוגרפית של 16 בתים באמצעות ה-Web Crypto API. לאחר מכן bcrypt מריץ את לוח הזמנים היקר של המפתחות שלו, זורע את Blowfish עם הסיסמה והמלח וחוזר על זמני עלות של 2^. לבסוף הוא מצפין מחרוזת קסם קבועה ("OrpheanBeholderScryDoubt") 64 פעמים עם מצב הצופן המתקבל ו-Base64-מקודד את הפלט. כל הריקוד הזה מייצר את ה-hash בן 60 התווים.
ההפתעה הנפוצה ביותר היא שגיבוב של אותה סיסמה פעמיים נותן שני גיבובים שונים. זה נכון ומכוון. כל גיבוב מקבל מלח אקראי משלו, אז שני משתמשים ששניהם בוחרים hunter2 בסופו של דבר עם ערכים מאוחסנים שונים לחלוטין תוקף שגונב את הטבלה לא יכול לדעת ששני חשבונות חולקים סיסמה, ולא יכול לעשות שימוש חוזר בטבלה מחושבת מראש בין חשבונות אם אתה רוצה לשחזר גיבוב ספציפי לבדיקה, אתה מספק את מחרוזת המלח המלאה ולא עלות חשופה, וזה בדיוק מה שמצב אימות עושה באופן פנימי.
בקוד היישום שלך אתה אף פעם לא מרכיב שום דבר מזה ביד אתה קורא לספרייה:
// PHP
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
// Node with bcrypt / bcryptjs
const hash = await bcrypt.hash(password, 12)
// Laravel
use Illuminate\Support\Facades\Hash;
$hash = Hash::make($password); // bcrypt by default
הכלי Toolz מיועד לרגעים סביב הקוד הזה: בדיקת שפיות איך נראה גיבוב בעלות נתונה, יצירת גיבוב ידוע עבור זרע או מתקן בדיקה, או אישור שגיבוב שמצאת בתצורה תואם את הסיסמה אתה חושב שזה עושה.
כיצד אוכל לבחור גורם עלות?
גורם העלות הוא הכפתור האחד שאתה צריך לחשוב עליו, והתשובה הכנה היא " מידה, אל תעתיק." כלל האצבע מ-OWASP הוא ש-hash בודד צריך לקחת איפשהו בסביבות רבע שנייה בחומרת הייצור שלך. היעד הזה מאזן שני כוחות מנוגדים: נמוך מדי ואתה הופך את הפיצוח לזול, גבוה מדי וכל כניסה לגיטימית משלמת את המחיר, מה שחשוב כאשר נקודת קצה עמוסה עוברת גיבוב בכל בקשה.
כי העלות היא כוח של שתיים, כל שלב מכפיל את העבודה עלות 11 הוא איטי פי שניים מאשר עלות 10, עלות 12 הוא איטי פי ארבעה בחומרת שרת טיפוסית של שנות ה-2020, עלות 10 עד 12 אדמות בשכונה הנכונה, וזו הסיבה שמסגרות ברירת מחדל שם הכלי מציג הערכת זמן גסה כשאתה גורר את המחוון כדי שתוכל להרגיש כמה מהר העלות מורכבת, אבל התייחס לזה כמדריך יחסי, לא כמדד של השרת שלך המספר האמיתי תלוי במעבד שלך, והדרך היחידה לדעת את זה היא הזמן password_hash על הקופסה שתפעיל אותו.
דפוס מעשי אחד שכדאי לדעת: מכיוון שהעלות מאוחסנת בתוך כל hash, אתה יכול להעלות אותה לאורך זמן ללא הגירה בכניסה מוצלחת יש לך את הטקסט הפשוט ביד לרגע, אז אתה בודק אם ה-hash המאוחסן #39; העלות נמוכה מהיעד הנוכחי שלך, ואם כן, מחדש ועדכן. PHP חושף זאת ישירות דרך password_needs_rehash. זה אומר שהאבטחה שלך עומדת בקצב החומרה מבלי לכפות איפוס סיסמה.
Bcrypt לעומת SHA-256, Argon2 ו-scrypt
ההשוואה שהכי חשובה היא bcrypt מול hash מהיר רגיל, ונגד הפונקציות החדשות יותר קשות בזיכרון. הנה איך הם מסתדרים לאחסון סיסמאות:
| פונקציה | מלוח | לאט בכוונה | זיכרון קשה | טוב לסיסמאות? |
|---|---|---|---|---|
| MD5 / SHA-256 | לא (כשלעצמו) | לא | לא | לא, הרבה יותר מדי מהר |
| bcrypt | כן, מובנה | כן, עלות מתכווננת | לא | כן, מומלץ |
| scrypt | כן | כן | כן | כן |
| ארגון2id | כן | כן | כן | כן, מועדף למערכות חדשות |
SHA-256 חשוף של סיסמה, אפילו מלוח, הוא הכלי הלא נכון: הוא מיועד למהירות, כך שמסד נתונים דלף של גיבוב SHA-256 מלוח נופל במהירות ל-GPU. אם אתה צריך רק תקציר מהיר עבור סכום בדיקה או מפתח מטמון ולא סיסמה, זה מה ש מחולל hash הוא עבור, וההבחנה היא כל העניין.Argon2id, הזוכה בתחרות גיבוב הסיסמאות לשנת 2015, מוסיף קשיות זיכרון, שמתנגדת לחומרה המותאמת אישית שיכולה להאיץ את bcrypt, וזו הבחירה הראשונה עבור מערכת חדשה לגמרי שבה אתה שולט בזמן הריצה. אבל bcrypt אינו מיושן. הוא נבדק קרב, זוהי ברירת המחדל בכלים שבהם אני משתמש מדי יום, והבחירה בה היא החלטה נכונה, במיוחד כאשר המסגרת שלך שולחת אותה. הטעות שיש להימנע ממנה היא לא "bcrypt במקום Argon2," זה " גיבוב מהיר במקום כל אחד מהם." לסיור רחב יותר בכלי האבטחה המשתלבים עם גיבוב, ה כלי פרודוקטיביות למפתחים למדריך יש את המפה.
מה לגבי מגבלת 72 בתים וגוצ'ות אחרות?
Bcrypt קורא רק את 72 הבתים הראשונים של הסיסמה כל דבר שעבר שמתעלמים ממנו בשקט, מה שעבור סיסמאות רגילות אף פעם לא משנה אבל יכול לנשוך ביטוי סיסמה ארוך מאוד, במיוחד אחד עם תווי UTF-8 מרובי בתים שבו ספירת הבתים מטפסת מהר יותר מספירת התווים הכלי מזהיר אותך בכל פעם שהקלט שלך חוצה 72 UTF-8 בתים כך שהקטיעה לעולם אינה הפתעה שקטה מערכות מסוימות פועלות סביב הגבול על ידי גיבוב מראש של הסיסמה עם SHA-256 ו-Base64 - קידוד זה לפני מסירתה ל-bcrypt, מה שמקפל סיסמה ארוכה באופן שרירותי לקלט קצר קבוע; אם תעשה זאת, עשה זאת באופן עקבי הן בהרשמה והן בכניסה.
הגוצ'ה השני הוא קידומת הגרסה. אתה תראה $2a$, $2y$, ו $2b$ בטבע. $2a$ היה המקורי, $2y$ האם הוצג תג ספציפי ל-PHP לאחר שנמצא באג להרחבת סימנים בכמה יישומים, וכן $2b$ האם הגרסה המתוקנת הנוכחית של OpenBSD. עבור גיבובים חדשים שאתה רוצה $2b$, וזה מה שהכלי הזה מייצר שלושתם מאמתים באופן זהה עבור סיסמאות ASCII רגילות; ההבדלים צצים רק עם בתים מסוימים שאינם ASCII ליד הגבול של 72 בתים. כאשר אתה מדביק אסימון בכלי שגם בודק אישורים מובנים, כמו ה מפענח JWT, זכור ש-hash bcrypt אינו אסימון שאתה מפענח כדי לקרוא מטען; זה תקציר חד כיווני בלי מה לחשוף.
איפה מחולל bcrypt מתאים בזרימת עבודה אמיתית
בפני עצמו hash הוא רק חצי מהסיפור, אז המיקסר יושב לצד כלי האישורים האחרים שאני שומר על פתוח. כשאני זורע מסד נתונים של בדיקות או מגדיר חשבון הדגמה, אני מייצר את הסיסמה בעצמה עם מחולל סיסמאות, בדוק שהוא מנקה פס חוזק הגיוני עם בודק חוזק סיסמא, ורק אז תריץ את זה דרך ה מחולל bcrypt כדי לקבל את ה-hash המאוחסן. הסדר הזה חשוב: סיסמה אקראית חזקה מאחורי hash cost-12 bcrypt היא באמת קשה לפיצוח, בעוד שסיסמה חלשה מאחורי אותו hash עדיין נופלת להתקפת מילון, מכיוון שהתוקף צריך רק לנחש את קומץ המועמדים הסבירים ולא את כל מרחב המפתחות. גורם העלות קונה לך זמן; אנטרופיית הסיסמה היא מול מה הזמן הזה מושקע.
מצב האימות מרוויח את מקומו במהלך ניפוי באגים כאשר כניסה נכשלת באופן מסתורי בבימוי, הדרך המהירה ביותר לבודד את הבעיה היא להדביק את ה-hash המאוחסן ואת הסיסמה שאתה מאמין שהיא נכונה ולראות אם הם תואמים התאמה פירושה שהבאג נמצא במעלה הזרם, באופן שבו הסיסמה מגיעה לבדיקה; אי התאמה פירושה שה-hash המאוחסן נכתב עם סיסמה אחרת או קידוד מעוות. כל תשובה חוסכת ממך לנחש, ומכיוון שכל העניין פועל באופן מקומי, אתה יכול לעשות זאת עם hash אמיתי שנשלף ממסד נתונים מבלי שה-hash הזה יעזוב את המחשב שלך. זה אותו עיקרון בצד הלקוח מאחורי כל כלי באתר, ולכל דבר הנוגע באישורים זה לא נחמד, זו הדרישה.
שאלות נפוצות
האם זה בטוח ל-hash סיסמה אמיתית במחולל bcrypt זה?
כן, מכיוון שה-hashing קורה כולו בדפדפן שלך ושום דבר לא נשלח לשום מקום. אתה יכול לאשר זאת בכרטיסייה רשת של כלי המפתחים שלך: יצירת hash אינה מבקשת. עם זאת, לשונית דפדפן אינה מנהל סיסמאות, אז הימנע מהדבקת האישורים החיים של חשבון ייצור בכל דף אינטרנט שלא בנית, וסגור את הכרטיסייה כשתסיים.
מדוע אותה סיסמה מייצרת גיבוב bcrypt שונה בכל פעם?
מכיוון ש-bcrypt מייצר מלח אקראי חדש עבור כל גיבוב ומערבב אותו לתוצאה. זוהי תכונה: שני משתמשים שבוחרים באותה סיסמה עדיין מקבלים גיבוב מאוחסן שונה, כך שתוקף לא יכול לזהות סיסמאות משותפות או לעשות שימוש חוזר בטבלה מחושבת מראש. האימות עדיין עובד מכיוון שהמלח מאוחסן בתוך מחרוזת ה-hash עצמה.
באיזה גורם עלות עלי להשתמש עבור bcrypt?
השתמש בעלות הגבוהה ביותר שזרימת הכניסה שלך יכולה לסבול ללא עיכוב מעצבן, אשר עבור רוב שרתי שנות ה-2020 עולה 10 עד 12. OWASP מציע שגיבוב בודד אמור לקחת בערך רבע שנייה על חומרת הייצור שלך. מכיוון שכל שלב מכפיל את העבודה, מדוד בשרת שלך במקום להעתיק מספר, והעלה את העלות כל כמה שנים ככל שהחומרה מואצת.
האם ניתן להחזיר גיבוב bcrypt בחזרה לסיסמה?
מס 'Bcrypt היא פונקציה חד כיוונית, ולכן אין דרך מתמטית להפוך hash בחזרה לתוך הסיסמה המקורית ההתקפה היחידה היא ניחוש: תוקף hashes סיסמאות מועמד עם אותו מלח ועלות ובודק עבור התאמה זו הסיבה גורם העלות משנה, כי זה קובע כמה יקר כל ניחוש, ומדוע סיסמאות ייחודיות חזקות בתוספת עלות גבוהה להפוך את הניחוש לא מעשי.
האם bcrypt עדיין מאובטח ב-2026, או שעלי לעבור ל-Argon2?
Bcrypt עדיין נחשב מאובטח לאחסון סיסמאות ונשאר אפשרות מומלצת בגיליון הצ'יט של אחסון סיסמאות של OWASP. Argon2id, הזוכה בתחרות גיבוב הסיסמאות לשנת 2015, מועדף עבור מערכות חדשות שבהן אתה שולט בזמן הריצה מכיוון שהוא מתנגד גם להתקפות GPU וחומרה מיוחדת. Bcrypt היא בחירה נכונה, במיוחד כאשר המסגרת שלך שולחת אותה כברירת מחדל; הטעות האמיתית היא שימוש ב-hash מהיר לשימוש כללי במקום כל פונקציית גיבוב סיסמאות.
מהי מגבלת 72 בתים ב-bcrypt?
Bcrypt קורא רק את 72 הבתים הראשונים של הסיסמה המקודדת UTF-8, כך שמתעלמים מכל התווים שמעבר לכך. עבור סיסמאות רגילות זה אף פעם לא משנה, אבל ניתן לקצץ ביטוי סיסמה ארוך מאוד, וזו הסיבה שמערכות מסוימות מגבשות מראש את הסיסמה עם SHA-256 לפני bcrypt. כלי זה מזהיר אותך בכל פעם שהקלט שלך עולה על 72 בתים כך שהקיצוץ לעולם אינו מפתיע.
מה המשמעות של הקידומות $2a$, $2b$ ו-$2y$?
הם תגיות גרסה עבור פורמט הפלט bcrypt. $2a$ היה המקורי, $2y$ היה תיקון ספציפי ל-PHP עבור באג הרחבת סימן, ו-$2b$ היא גרסת OpenBSD המתוקנת הנוכחית. עבור גיבובים חדשים $2b$ נכון, וזה מה שהכלי הזה מייצר שלושתם מאמתים באופן זהה עבור סיסמאות ASCII; ההבדלים מופיעים רק עם בתים מסוימים שאינם ASCII בגבול של 72 בתים.
האם bcrypt זהה להצפנה?
מס 'הצפנה היא הפיכה עם מפתח, כך נתונים מוצפנים ניתן לפענח בחזרה למקור. hashing Bcrypt הוא חד כיווני איטי בכוונה, והוא נועד לאימות בלבד: אתה אף פעם לא צריך לשחזר את הסיסמה, רק כדי לאשר מישהו הקליד את הנכון אחסון סיסמאות עם הצפנה במקום hashing הוא דפוס אנטי, כי מי שמחזיק את המפתח יכול לשחזר כל סיסמה.



