למה passkey בטוח — אימות בלי לשלוח את הסוד

· עודכן בתאריך: · · passkey, WebAuthn, FIDO2, אבטחה, authentication, phishing, מערכות מידע

היסטוריית עדכונים (גרסה ראשונה, פורסמה בתאריך 29 Jul 2026)
פרסום ראשון
לצטט את המאמר הזה(DOI: 10.5281/zenodo.22175432)

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

Go Komura (2026). למה passkey בטוח — אימות בלי לשלוח את הסוד. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22175432 https://comcomponent.com/he/blog/passkey-why-secure/

DOI (הגרסה האחרונה)
10.5281/zenodo.22175432
DOI (הגרסה הזו)
10.5281/zenodo.22175433

חדשות ששוב דלפו סיסמאות משירות גדול כבר לא מפתיעות אף אחד. מריצים תרגילי phishing כל שנה, ומספר האנשים שנלכדים אף פעם לא מגיע לאפס. “אל תעשו reuse לסיסמאות, תאריכו אותן, ושינוי תקופתי… כבר לא צריך” — גם העצות התהפכו.

passkey, שהתפשט במהירות בשנים האחרונות, הוא שיטת authentication ש-Apple, Google ו-Microsoft מקדמים יחד כמענה למצב הזה.1 לעיתים קרובות מציגים אותו כ”נוח — נכנסים עם טביעת אצבע או פנים”. זה לא העיקר. הערך האמיתי של passkey הוא שהוא מעביר את בסיס האבטחה מערנות אנושית למבנה של הפרוטוקול.

  • סיסמאות דולפות כי משתמשים לא זהירים, אז נחנך אותם → בני אדם תמיד טועים
  • נחנך אנשים לזהות אתרים מזויפים → אפשר לבנות אתר מזויף שאי אפשר לזהות
  • עם passkey → אין סוד לשלוח מלכתחילה, ובאתר מזויף חתימה לא יכולה לעבור

המאמר הזה מסביר בתרשימים למה passkey בטוח, מתוך מה ששבור בסיסמאות. אחר כך הוא עונה לשאלות המובנות — האם synced passkey באמת בטוח, והאם יש חולשות — ומסיים בנקודות הפריסה המעשית ליישומי Web ולסביבות Windows.

1. קודם המסקנות

הסיבות ש-passkey בטוח מתכנסות לשלוש נקודות.

  1. אין סוד בשרת. מה שהשרת שומר הוא רק ה-public key, מידע שאי אפשר לנצל גם אם דלף. גם אם כל מסד הנתונים נשאב, אין לתוקף חומר להתחזות שאפשר לקחת הביתה.2
  2. הסוד לא עובר ברשת. מה שנשלח ב-login הוא חתימה על ערך אקראי חד-פעמי (challenge). כיון שה-private key לא יוצא מה-authenticator של המכשיר, האזנה או ממסור בכל נקודה בנתיב לא מניבים סוד.2
  3. באתר מזויף החתימה לא עוברת. passkey כבול לדומיין של האתר, והדפדפן כופה את התאמת הדומיין. גם אם משתמש מרומה באתר מזויף, ה-passkey של האתר האמיתי פשוט לא מופיע כמועמד, ואפילו אם ממסרים חתימה, האימות בשרת דוחה אותה.3

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

הקשר בין המונחים — passkey, WebAuthn, FIDO2, CTAP

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

מונח שם רשמי למה הוא מתייחס
WebAuthn Web Authentication API (המלצת W3C) התקן בין הדפדפן לאתר. API שדורש יצירת key pair וחתימה ב-navigator.credentials
CTAP Client to Authenticator Protocol (FIDO Alliance) התקן בין הדפדפן ל-authenticator חיצוני. החלק שמדבר עם security key או טלפון דרך USB, NFC או Bluetooth
FIDO2 — השם הכולל למסגרת שמחברת את שני אלה. FIDO2 = WebAuthn + CTAP
passkey — השם ל-FIDO2 credentials שיכולים להיכנס לבדם במקום סיסמה (discoverable credentials)

טבלה 1: passkey הוא שם על בסיס FIDO2, לא שם תקן

כלומר “לתמוך ב-passkey” פירושו, בשפת המימוש, “לממש WebAuthn”. CTAP הוא השכבה שהדפדפן ומערכת ההפעלה מטפלים בה כשמשתמשים ב-authenticator חיצוני, ולכן מי שבונה יישום Web לא נוגע בו ישירות.

ב-diagram, solid line מציינת relation שתמיד מתקיים ו-dashed line מציינת relation מותנה (התנאים מופיעים בהסבר של כל relation ב-detail page). הרשימה המלאה של ה-relations (סה”כ 38, כולל evidence ו-certainty) וההגדרות של ה-concepts המרכזיים נמצאות ב-detail page של ה-knowledge map (ביפנית). Data: JSON-LD / Turtle

2. מה שבור באימות בסיסמה

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

שרתדפדפןמשתמששרתדפדפןמשתמשמחזיק את הסוד (סיסמה) בראש[חולשה 1] אפשר לנחש / עושים reuse[חולשה 2] אפשר להזין באותו אופןגם באתר מזויף (אי אפשר להבחין במראה)[חולשה 3] הסוד זורם בנתיבמוגן ב-TLS אבל בקצה חוזר ל-plaintext[חולשה 4] סודות (hashes) של כל המשתמשים מצטבריםדליפה הופכת ליעד ל-offline brute forceמזין סיסמהשולח את הסיסמה עצמהמשווה ל-hash השמור

איור 1: באימות בסיסמה, הסוד עצמו קיים בכל השלבים

מנקודת מבט של תוקף, זה מבנה עם הרבה מטרות שקל לפגוע בהן.

  • חולשה 1 (המשתמש): חוזק שאפשר לזכור, ו-reuse בכמה אתרים. דליפה במקום אחד מתפשטת לכל החשבונות (password-list attack).
  • חולשה 2 (רגע ההזנה): אם מכינים אתר מזויף שאי אפשר להבדיל מהאמיתי, המשתמש מוסר את הסוד בעצמו (phishing).
  • חולשה 3 (הנתיב): יש TLS ולכן האזנה לנתיב עצמו קשה, אבל אם משחילים נקודת ממסור במראה לגיטימי זה לא עוזר (AiTM בהמשך).
  • חולשה 4 (השרת): גם אם שומרים ב-hash, אם מסד הנתונים דולף אפשר להריץ offline brute force. סיסמאות חלשות נשברות לפי הסדר.

“אז נוסיף one-time code (SMS או TOTP)” זו ה-MFA המסורתית, אבל גם כאן מבנה שליחת סוד משותף לא משתנה. ב-TOTP השרת ואפליקציית ה-authenticator חולקים אותו seed (סוד), ואת הקוד בן 6 הספרות שנוצר המשתמש יכול בסוף להזין גם באתר מזויף. בפועל, phishing מסוג AiTM (Adversary-in-the-Middle) שממסר בזמן אמת לאתר האמיתי פורץ את צמד הסיסמה+קוד כפי שהוא. CISA (סוכנות הסייבר של ארה”ב) מונה כ-phishing-resistant MFA רק שניים: שיטת FIDO/WebAuthn, ואימות מבוסס PKI כמו smart card (PIV/CAC), וממקמת את FIDO כ-gold standard — מסיבה זו.4

כלומר הבעיה אינה חוזק הסיסמה אלא עצם המבנה של “חולקים סוד ושולחים אותו בכל authentication”.

3. מה זה passkey — לא שולחים סוד, מוכיחים שמחזיקים בו

passkey הוא credential מבוסס public-key cryptography שעומד על שני תקנים: WebAuthn של W3C ו-CTAP של FIDO Alliance (יחד FIDO2).21 זה נשמע קשה, אבל המבנה פשוט.

שרתהמכשיר של המשתמשהתאמה מקומיתזוג מתמטי(הצד שיוצר חתימה)public keyאי אפשר לנצל גם אם דלףמידע לאימות בלבדauthenticator (vault)Windows Hello / Face ID /screen lock ב-Android / security keyprivate keyלא יוצא מכאן בכללטביעת אצבע / פנים / PIN= רק לפתוח את ה-vaultגם זה לא יוצא החוצה

איור 2: הישות של passkey היא key pair לכל אתר. צד הסוד לא יוצא מהמכשיר, והשרת מחזיק רק public key לאימות

  • private key הוא המפתח שיכול ליצור חתימה. הוא נשמר ב-authenticator במכשיר (Windows Hello, Face ID/Touch ID ב-iPhone, screen lock ב-Android, או security key כמו YubiKey) ולא יוצא החוצה.
  • public key הוא המפתח שיכול רק לאמת חתימה, ואותו מפקידים בשרת. לחשב private key מתוך public key הוא בלתי אפשרי חישובית, אז זה מידע שאפשר לדלוף בלי נזק.
  • ביומטריה כמו טביעת אצבע או פנים משמשת רק כדי לפתוח את ה-vault מקומית, וגם היא לא יוצאת מהמכשיר. ביומטריה לא נשלחת לשרת.1

רישום: מוסרים רק את ה-public key

כך נראה הרישום של passkey באתר.

authenticatorדפדפןשרת (example.com)authenticatorדפדפןשרת (example.com)מה שהשרת קיבל הוא רקמידע שאי אפשר לנצל גם אם דלףבקשת רישום (challenge אקראי + מידע על האתר)צור מפתח לאתר הזה (example.com)אימות זהות בטביעת אצבע / פנים / PIN (מקומי)יוצר key pair חדששומר את ה-private key בפניםpublic key + credential ID (תווית המפתח)שולח public key + credential IDשומר כ-public key של החשבון

איור 3: ברישום, מה שזורם ברשת ונשמר בשרת הוא רק ה-public key

הנקודה החשובה: ה-key pair נוצר כבול לדומיין של האתר (RP ID). passkey שנוצר ל-example.com עובד רק באתר example.com (RP ID הוא ברמת דומיין, אז דפים תחת אותו דומיין כמו login.example.com יכולים להשתמש בו, אבל דומיין לא קשור לא יכול). הקישור הזה הוא הבסיס לעמידות ל-phishing בהמשך.3

בנוסף, key pair נוצר מחדש לכל אתר. ה-passkey של אתר A ושל אתר B לא קשורים מתמטית, אז מושג ה-reuse עצמו לא קיים, וגם אין חומר להצליב משתמשים בין אתרים.

Authentication: מחזירים חתימה חד-פעמית

כך נראה login. השוו לאימות בסיסמה (איור 1).

authenticatorדפדפןשרת (example.com)authenticatorדפדפןשרת (example.com)בנתיב זורמת רק חתימה חד-פעמיתגניבה לא עוזרת ל-challenge הבאבקשת login (challenge אקראי חד-פעמי)בקשת חתימה ל-example.comאימות זהות בטביעת אצבע / פנים / PIN (מקומי)יוצר חתימה ב-private keyצורב challenge + origin + hash של RP IDחתימה (לא ה-private key עצמו)שולח את החתימהמאמת את החתימה ב-public key השמורבודק גם challenge, origin ו-RP ID

איור 4: גם ב-authentication הסוד לא זז. מה שזורם הוא רק הוכחה חד-פעמית

השרת מנפיק בכל פעם challenge אקראי חדש, וה-authenticator חותם על “ה-challenge הזה + ה-origin שהדפדפן רואה עכשיו + ה-hash של ה-RP ID”. השרת מאמת את החתימה ב-public key השמור, ומוודא שה-challenge הוא מה שהוא הנפיק, ושה-origin וה-RP ID שייכים לאתר שלו.5

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

  • אין סוד בשרת: מה שנשמר הוא רק public key. גם אם דלף, התוקף לא יכול ליצור חתימה, אז אי אפשר “לקחת הביתה ולשבור” כמו hash של סיסמה.
  • הסוד לא זורם: גם אם גונבים את החתימה מהנתיב, ה-challenge חד-פעמי ולכן replay לא עובד.

נשארת הסיבה השלישית, “באתר מזויף החתימה לא עוברת” — זה היתרון הגדול ביותר של passkey. נפריד לפרק.

4. למה phishing נכשל ברמת המבנה

phishing על סיסמה מצליח כי אפשר להזין את הסוד האמיתי באתר מזויף. לבני אדם קשה (במיוחד כשהם עייפים) להבחין בין example.com ל-examp1e.com, ושדה הסיסמה עובד אותו דבר בשני האתרים.

ב-passkey, את ההתאמה הזו עושה הדפדפן באופן מכני, לא האדם. לפי מפרט WebAuthn, הדפדפן יכול לקרוא ל-authenticator רק כשהדומיין של ה-origin שמוצג עכשיו תואם ל-RP ID של ה-passkey.3 כך זה נראה כשנכנסים לאתר מזויף.

השרת האמיתי (example.com)אתר מזויף (examp1e.com)proxy מסוג AiTM שממסר לאמיתידפדפןמשתמשהשרת האמיתי (example.com)אתר מזויף (examp1e.com)proxy מסוג AiTM שממסר לאמיתידפדפןמשתמשגם אם איכשהו נוצרת חתימה,היא צורבת examp1e.com,ולכן האימות בשרת האמיתי תמיד נופלנכנס למסך login שנראה זהה(מאחורי הקלעים) מתחיל את תהליך ה-login האמיתיchallengeממסר את ה-challenge ודורש חתימהה-origin עכשיו הוא examp1e.comאי אפשר להציע את ה-passkey של example.comחתימה לא נוצרת (אין דרך לרמות את המשתמש)

איור 5: phishing מסוג AiTM פורץ סיסמה+one-time code, אבל ב-passkey זה נכשל כבר בשלב החתימה

שימו לב שההגנה כפולה.

  1. לא מופיע כמועמד: הדפדפן מציג רק passkey עם RP ID שתואם ל-origin. בדומיין מזויף, ה-passkey של האתר האמיתי לא מופיע ברשימה, אז המשתמש אפילו לא יכול “להשתמש בטעות”.
  2. החתימה לא עוברת: נושא החתימה כולל את ה-origin שהדפדפן אימת ואת ה-hash של ה-RP ID. השרת האמיתי מצליב את זה באימות, ולכן חתימה שנוצרה ב-origin אחר תמיד נדחית.5

הגנה מ-phishing על סיסמה הסתמכה על זה שהמשתמש יסתכל טוב על ה-URL. ב-passkey המשתמש לא צריך לזהות אתר מזויף מלכתחילה. זה המשמעות המדויקת של phishing-resistant, וזו הסיבה ש-CISA ו-NIST (המכון הלאומי לתקנים בארה”ב) מתייחסים ל-FIDO/WebAuthn כמקרה מיוחד.46

מסכמים לפי סוג התקפה.

התקפה סיסמה סיסמה+TOTP passkey
ניחוש / brute force ✗ חלש △ הקוד חוסם אבל הסיסמה עצמה נשארת חלשה ○ אין מה לנחש
reuse (list attack) ✗ דליפה במקום אחד מתפשטת לכולם △ אתרים בלי קוד נשברים ראשונים ○ מפתח עצמאי לכל אתר
דליפת DB בשרת ✗ brute force offline על ה-hash ✗ גם ה-seed של TOTP (סוד משותף) דולף ○ יש רק public key
phishing קלאסי (הזנה באתר מזויף) ✗ אפשר להזין ✗ אפשר להזין גם את הקוד ○ לא מופיע כמועמד, והחתימה לא עוברת
AiTM (ממסור בזמן אמת) ✗ ממסרים כמו שזה ✗ ממסרים יחד עם הקוד ○ התאמת origin מונעת חתימה
replay (שימוש חוזר בתקשורת) ✗ אותה סיסמה תקפה שוב ושוב △ קוד שנגנב לפני שהמשתמש השתמש בו תקף (מימוש נכון דוחה קוד שכבר התקבל) ○ challenge חד-פעמי בכל פעם

טבלה 2: השוואת עמידות לפי סוג התקפה. ה-“○” של passkey מגיע מהמבנה, לא מתפעול או ערנות

5. האם synced passkey בטוח

אחרי מה שקראנו עד כאן, השאלה המובנת היא: “אמרתם שה-private key לא יוצא מהמכשיר, אז איך passkey שנוצר ב-iPhone עובד גם ב-iPad?” שאלה טובה, והתשובה: יש שני סוגים של passkey.

קודם טבלת סיכום. הפרק הזה והבא מסבירים למה כל שורה בטבלה נראית כך.

היבט synced passkey device-bound passkey
דוגמאות iCloud Keychain, Google Password Manager, password managers כמו 1Password security key (YubiKey וכו’), Windows Hello, passkey בתוך Microsoft Authenticator
איפה נשמר ה-private key credential vault של הפלטפורמה. מועתק בין מכשירי אותו חשבון מוצפן end-to-end בחומרה של ה-authenticator. לא יוצא מחוץ ל-TPM או Secure Element
אובדן / החלפת מכשיר שחזור למכשיר חדש אחרי כניסה לאותו Apple ID / חשבון Google ה-passkey של אותו authenticator אבוד. מניחים רישום של כמה authenticators
single point of failure חשבון הענן של הפלטפורמה המכשיר הפיזי עצמו
התאמה לניהול ארגוני המפתח נכנס לחשבון ענן אישי, ולכן קשה לארגון לדעת איפה הוא ולבטל באופן מרוכז. מתאים ל-BYOD ולסביבות קטנות מנהל יכול להפיץ ולבטל, ומקום המפתח ברור. מתאים לסביבות עם נהלים מחמירים
התאמה ל-AAL של NIST AAL2 אם עומדים בדרישות. לא ל-AAL3 כי אפשר לייצא את ה-private key6 authenticator שמוגן בחומרה ושאי אפשר לשלוף ממנו מפתח יכול לעמוד גם בדרישות AAL36

טבלה 3: synced מול device-bound. הבחירה היא בין חוזק מול אובדן לבין יכולת לנהל איפה המפתח נמצא

device-bound passkeysecurity key (YubiKey וכו') /Windows Hello /Microsoft Authenticator (Entra ID)ה-private key לא יוצא פיזיתמהחומרה (מוגן ב-TPM וכו')יתרון: מקום המפתח ברור, במקום אחדשים לב: חובה לרשום כמה למקרה אובדןsynced passkey (ברירת המחדל לצרכן)iCloud Keychain /Google Password Manager /password managers כמו 1Passwordסנכרון end-to-end בין מכשיריאותו חשבוןגם הספק לא יכול לקרואיתרון: חזק בהחלפת מכשיר ובאובדןשים לב: צריך להגן על חשבון הענן עצמו

איור 6: synced מול device-bound. בשניהם ה-private key לא נשלח לשרת; מה שמשתנה הוא מרכז הכובד של ההגנה

synced passkey הוא כזה שבו iCloud Keychain או Google Password Manager מסנכרנים את ה-private key בין מכשירי אותו חשבון. הנקודה החשובה: הסנכרון הוא end-to-end encryption. גם Apple וגם Google מצהירים במפורש ש-passkey מוצפן במכשיר לפני הסנכרון, ושהספק עצמו לא יכול לקרוא את התוכן.78 כלומר העיקרון “ה-private key לא יוצא מהמכשיר” מתרכך בפועל ל-“ה-private key לא יוצא מהמכשיר ב-plaintext”, ובתמורה מקבלים עמידות להחלפת מכשיר ולאובדן.

צריך לנסח במפורש איך ההקלה הזו משנה את מודל האיום. המקום שצריך להגן עליו מתכנס מ”השרת של כל אתר” ל”חשבון ענן אחד”. מול דליפת DB של האתרים ומול phishing נשארים חזקים כמו קודם, אבל עכשיו השתלטות על Apple ID / חשבון Google עצמו הופכת ל-single point of failure. לכן חשבון הפלטפורמה שבו מפקידים passkey צריך את ההגנה החזקה ביותר (screen lock חזק, סידור אמצעי שחזור, ואם אפשר security key פיזי). גם NIST פרסם באפריל 2024 את NIST SP 800-63B Supplement 1: Incorporating Syncable Authenticators Into NIST SP 800-63B, ומיקם רשמית ש-syncable authenticator (synced passkey) יכול לעמוד ב-AAL2 (Authenticator Assurance Level 2) אם עומדים בדרישות. אבל כיון שאפשר לייצא את ה-private key, לא משתמשים ב-synced ל-AAL3 שדורש סביבה מבודדת בחומרה.6

device-bound passkey הוא הסוג שבו ה-private key לא יוצא מהחומרה. security key כמו YubiKey הוא הדוגמה הקלאסית, ובארגונים גם passkey של Microsoft Entra ID (זה שנוצר בתוך Microsoft Authenticator) הוא device-bound.9 גם Windows Hello ב-Windows מגן על ה-private key תחת TPM אם יש TPM. מנגנון “vault חומרה שלא מוציא מפתחות” הוא אותו בסיס שפורט במאמר על TPM.

עוד נקודה: אולי תהויתם למה ב-login לדפדפן במחשב עם passkey מהטלפון מבקשים לסרוק QR. זה לא רק מעבר מסך. זו שיטה היברידית (cross-device authentication של FIDO) שמאשרת קרבה פיזית בין הטלפון למחשב ב-Bluetooth. כך חוסמים התקפה שבה תוקף מרוחק מבקש מאדם אחר לאשר login למחשב שלו דרך QR.1

6. לא silver bullet — החולשה לא נעלמת, היא זזה

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

תוקףהאימות עצמוחתימה על challenge[קשה]תהליך שחזור חשבוןמדווחים שאיבדו passkey,מאפסים ב-SMS או במייל,ורושמים passkey של התוקףfallback במקבילאם סיסמה ו-SMS login נשארו,זו החוליה החלשהחשבון ענןב-synced, Apple ID /חשבון Google הוא single point of failuresessionאם גונבים cookie אחרי login,שיטת האימות כבר לא רלוונטית

איור 7: כשהכניסה (authentication) מתחזקת, ההתקפה עוברת לתהליך שחזור, ל-fallback, לחשבון ענן ול-session

בפועל יש ארבעה סיכונים שנשארים.

  1. fallback במקביל הופך לחוליה החלשה. אם רק “הוספתם passkey” אבל סיסמה ו-SMS login נשארו, התוקף פשוט משתמש בהם. עמידות ל-phishing ברמת החשבון כולו נעצרת ברמת אמצעי ה-login החלש ביותר. לב הפריסה אינו הוספת passkey אלא צמצום וביטול מתוכננים של fallback.
  2. תהליך השחזור הופך למשטח התקפה חדש. מתחזים למי שאיבד מכשיר, מגיעים לתמיכה או לאיפוס במייל, ורושמים passkey של התוקף. בפועל, social engineering על helpdesk כדי לעקוף authentication חזק הוא אמצעי שגרתי בפריצות גדולות. ככל שהאימות מתחזק, כך חשוב יותר איך מתכננים אימות זהות בתהליך השחזור.
  3. ב-synced, חשבון הענן הוא single point of failure. כפי שבפרק הקודם. צריך להגן על החשבון שבו מפקידים passkey, ובארגון גם לקבוע מדיניות לאיזו פלטפורמה מותר לסנכרן.
  4. גניבת session לא נעצרת. passkey מגן רק על רגע ה-login. אם גונבים session cookie אחרי login ב-malware או XSS, שיטת האימות כבר לא רלוונטית. נשארת עבודה בשכבה אחרת: תוקף token, binding, וניהול תקינות מכשיר.

זה לא טיעון “עדיף בלי passkey”. גם אחרי שמחליפים מנעול בדלת, נעילת החלונות היא עבודה נפרדת. להפך: כשמקום החולשה ברור, אפשר לרכז משאבי הגנה בתהליך שחזור ובניהול session.

7. פריסה בפועל — WebAuthn API וסביבת Windows

לבסוף, נקודות למי שמיישם.

להוסיף passkey login לשירות Web שלכם

בצד הדפדפן יש שתי פונקציות של WebAuthn API. רישום קורא ל-navigator.credentials.create(), authentication ל-navigator.credentials.get().

// רישום (צד הדפדפן)
const credential = await navigator.credentials.create({
  publicKey: {
    challenge: challengeFromServer,   // ערך אקראי חד-פעמי שהשרת יצר
    rp: { id: "example.com", name: "Example" },
    user: { id: userIdBytes, name: "taro@example.com", displayName: "太郎" },
    pubKeyCredParams: [{ type: "public-key", alg: -7 }],  // ES256
    authenticatorSelection: {
      residentKey: "required",        // הופך ל-discoverable credential (= passkey)
      userVerification: "required",   // מחייב user verification בביומטריה או PIN
    },
  },
});
// את ה-public key שולפים מ-credential.response, ואת ה-credential ID
// מ-credential.id / credential.rawId ברמה העליונה. גם את תשובת הרישום
// מאמתים בצד השרת (challenge, origin, RP ID) לפני השמירה,
// כמו בזמן authentication

משמעות הפרמטרים העיקריים:

פרמטר תפקיד זהירות במימוש
challenge ערך אקראי חד-פעמי שהשרת יוצר בכל פעם משתמשים בערך אקראי קריפטוגרפי שאי אפשר לנחש. בצד השרת מאמתים שזה “שלנו, ועדיין לא שומש” וצורכים אותו
rp.id הדומיין שאליו כובלים את ה-credential (RP ID) אם משמיטים, זה הדומיין האפקטיבי של ה-origin הקורא. אפשר לציין רק בטווח הדומיינים הניתנים לרישום, למשל example.com מ-login.example.com
user.id מזהה המשתמש הפנימי של השרת (user handle) ערך opaque עד 64 bytes. לא שמים כמו שהוא מידע מזהה כמו כתובת דוא”ל או שם משתמש2
user.name / user.displayName מחרוזות שמוצגות ב-UI של ה-authenticator או הדפדפן כדי שהמשתמש יבחר חשבון לתצוגה בלבד. השרת לא אמור לסמוך על הערך הזה כדי לזהות חשבון
pubKeyCredParams מונה אלגוריתמי public key מקובלים לפי עדיפות בנוסף ל--7 (ES256) כדאי לציין גם -257 (RS256) כדי להרחיב את טווח ה-authenticators שמתקבלים
authenticatorSelection תכונות שנדרשות מה-authenticator residentKey: "required" הופך ל-passkey (discoverable credential), ו-userVerification: "required" מחייב user verification בביומטריה או PIN

טבלה 4: הפרמטרים העיקריים של navigator.credentials.create()

סביבת בדיקה: WebAuthn API נחשף רק ב-secure context, ולכן בדף שמוגש ב-http:// גולמי קריאה ל-navigator.credentials נכשלת. החריג הוא http://localhost (וגם 127.0.0.1), שמטופלים כ-origin מהימן, כך שבמכונת פיתוח אפשר לנסות בלי HTTPS. אבל RP ID חייב להיות הדומיין האפקטיבי של ה-origin (או דומיין האב שלו), כך ש-passkey שנוצר ב-localhost לא עובד בדומיין הייצור. גם בלי authenticator ביד, הפעלת virtual authenticator בלשונית WebAuthn בכלי המפתחים של Chrome מאפשרת להריץ רישום ו-authentication מקצה לקצה.

// authentication (צד הדפדפן)
const assertion = await navigator.credentials.get({
  publicKey: {
    challenge: challengeFromServer,
    rpId: "example.com",
    userVerification: "required",
  },
  // מציע את ה-passkey כמועמד ל-autofill בשדה הכניסה. בודקים
  // קודם תמיכה ב-PublicKeyCredential.isConditionalMediationAvailable(),
  // ובדפדפנים שאינם תומכים חוזרים לקריאה רגילה בלי mediation
  mediation: "conditional",
  // (ב-<input> היעד נדרש autocomplete="username webauthn")
});
// מאמתים בצד השרת את החתימה של assertion.response

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

  • הצלבת challenge: האם זה challenge שלא שומש שאתם הנפקתם. האם הוא חד-פעמי (הגנה מ-replay). בנוסף, שמירה קשורה ל-session של הדפדפן (ניסיון ה-login) בזמן ההנפקה, והתרת צריכה רק מתשובה מאותו session. אם זה רפוי, נפתח מקום לתוקף לשלוח דרך דפדפן הקורבן חתימה על challenge שמיועד לו, ולהכניס את הקורבן לחשבון התוקף (login CSRF).
  • הצלבת origin: האם origin ב-clientDataJSON הוא ה-origin החוקי של האתר (לב ההגנה מ-phishing).
  • הצלבת hash של RP ID: האם rpIdHash ב-authenticatorData תואם ל-SHA-256 של ה-RP ID של האתר.
  • אישור סוג הטקס והדגלים: האם type ב-clientDataJSON הוא webauthn.get ב-authentication ו-webauthn.create ברישום. האם דגל UP (user present) ב-authenticatorData דולק. אם דרשתם user verification (UV), האם גם דגל UV דולק.
  • אימות חתימה: האם החתימה מאומתת נכון ב-public key שנשמר ברישום.
  • קישור לחשבון: האם שולפים את credential ID (ו-userHandle) שהוצג במסד הנתונים שלכם, ומנפיקים session לבעלים של ה-credential הזה. אמון ללא תנאי בשם משתמש שהוזן בנפרד פותח חור של כניסה כאדם אחר עם חתימה נכונה.
  • שמירה והשוואה של signCount: שומרים את signCount ב-authenticatorData לפי credential, ומאשרים שהערך הבא גדול מהקודם. ערך קטן או שווה לקודם (כולל שוויון) מטופל כסימן לשכפול (clone) של authenticator. עם זאת, synced passkey לרוב מחזיר תמיד 0, ולכן 0 מול 0 מתירים כחריג.

לכתוב את האימות הזה ביד הוא מתכון לתאונה, ולכן משתמשים בספרייה עם ניסיון (fido2-net-lib ב-.NET, SimpleWebAuthn ב-Node.js וכו’). פרטי המפרט (פענוח CBOR, הסכמת אלגוריתם, ניהול challenge) משאירים לספרייה, ואנחנו מתרכזים בשמירה ובביטול של challenges, ב-UI לניהול כמה passkeys, ובתכנון תהליך השחזור — זו חלוקת העבודה הנכונה.

בסביבת Windows ומערכות פנימיות

מקהל הקוראים של האתר הזה — מי שאחראי למערכות עסקיות ב-Windows — די בשלוש הנקודות הבאות.

  • לקוח Windows כבר תומך. Windows 11 תומך ביצירה, שימוש וניהול של passkey עם Windows Hello כ-authenticator (הגדרות > חשבון > passkeys), וה-private key מוגן בחומרה אם יש TPM.10 WebAuthn דרך דפדפן (Edge/Chrome) עובד גם ב-Windows 10.
  • בסביבת Entra ID מפעילים “passkey = שיטת authentication מסוג FIDO2”. Microsoft Entra ID תומך ב-security keys וב-passkey בתוך אפליקציית Microsoft Authenticator (device-bound), ואם דורשים phishing-resistant MFA ב-authentication strength של Conditional Access, אפשר להגביל גישה למשאבים היעד ל-passkey וכדומה.9 המעבר מעולם NTLM ומדיניות תוקף סיסמה אינו מתקדם בקפיצה אחת, ולכן לצד מלאי תשתית ה-authentication שטופל במאמר על NTLM ו-Kerberos, הנוהל הקבוע הוא לחייב קודם phishing-resistant MFA בחשבונות מנהל.
  • גם ביישום Web פנימי התועלת זהה. אבל HTTPS היא הנחה. WebAuthn API לא עובד אלא ב-secure context, ולכן גם ביישום intranet (מלבד localhost בפיתוח) HTTPS וסידור שם דומיין פנימי שניתן להשתמש בו כ-RP ID הם קודם. אחרי שזה סגור, RP ID פועל גם מול דומיין פנימי. במובן של פרידה מפתקיות סיסמה, לא נדיר שהאפקט יוצא מהר יותר בפנים מאשר בשירות חיצוני.

8. סיכום

  • חולשת הסיסמה אינה החוזק אלא המבנה של “חולקים סוד ושולחים אותו בכל authentication”. הסוד קיים אצל המשתמש, בשדה הקלט, בנתיב ובשרת, ולכן יש הרבה יעדי התקפה. גם הוספת one-time code מפסידה ל-phishing מסוג AiTM כי ממסרים אותו.
  • passkey הוא key pair של public-key cryptography לכל אתר, מוסרים לשרת רק public key שאי אפשר לנצל גם אם דלף, וב-login שולחים רק חתימה על challenge חד-פעמי. אין סוד בשרת, ואין סוד שזורם בנתיב.
  • בחתימה צורבים את ה-origin ואת ה-RP ID שהדפדפן אימת, ולכן באתר מזויף ה-passkey של האמיתי לא מופיע כמועמד, וגם ממסור נופל באימות. שהמשתמש לא צריך לזהות אתר מזויף הוא מהות phishing-resistant, ובסיס ההגנה עבר מתשומת לב אנושית למבנה הפרוטוקול.
  • synced passkey מסונכרן ב-end-to-end encryption, וחזק בהחלפת מכשיר ובאובדן. בתמורה המקום שצריך להגן עליו מתכנס לחשבון ענן, ולכן הגנה על Apple ID / חשבון Google עצמו הופכת להנחה. ארגון יכול גם לבחור device-bound (security key, passkey של Authenticator ב-Entra ID).
  • passkey לא מחסל התקפות אלא דוחק אותן למקום חלש. סיסמה במקביל, תהליך שחזור חשבון וגניבת session נשארים משטח התקפה, ולב הפריסה הוא צמצום מתוכנן של fallback וחיזוק תהליך השחזור.
  • המימוש הוא שתי הפונקציות create / get של WebAuthn API + אימות שרת. את האימות לא כותבים לבד אלא משאירים לספרייה עם ניסיון, ומקצים כוח לניהול challenges, UI של כמה passkeys, ותכנון שחזור.

מאמרים קשורים

תחומי ייעוץ קשורים

KomuraSoft LLC מטפלת בסיוע למימוש WebAuthn של passkey login למערכות Web פנימיות, בתכנון פריסת phishing-resistant MFA בסביבת Entra ID, וב-Custom Software Development שכולל שילוב authentication ביישומים עסקיים ל-Windows כמו WinForms/WPF.

  1. FIDO Alliance, Passkeys ו-How FIDO Works. על כך ש-passkey הוא FIDO credential שמחליף סיסמה; על כך שנתונים ביומטריים אינם נשלחים מהמכשיר ומשמשים רק להתאמה מקומית; על כך שבמאי 2022 Apple, Google ו-Microsoft הצהירו יחד על הרחבת התמיכה במעבר ללא סיסמה לפי תקן FIDO; ועל כך שבשימוש חוצה-מכשירים (cross-device) משתמשים בשיטה היברידית של QR ו-proximity check ב-Bluetooth. ↩ ↩2 ↩3 ↩4 ↩5

  2. W3C, Web Authentication: An API for accessing Public Key Credentials Level 2 (המלצת W3C). על כך ש-WebAuthn הוא API ליצירה ולשימוש ב-credentials מבוססי public-key cryptography; על כך שה-private key של ה-credential נשמר ב-authenticator ורק ה-public key ו-credential ID נרשמים בשרת (Relying Party); על כך שה-authentication נעשה בחתימה (assertion) על challenge שהשרת שולח; ועל יעדי התכנון של היקף ה-credential וההגנה. בנוסף, המאמר מפנה לכך שה-API נחשף רק ב-secure context; לכך ש-RP ID כשמשמיטים הופך לדומיין האפקטיבי של ה-origin הקורא; ולכך ש-user handle (user.id) הוא ערך opaque עד 64 bytes ושלא לכלול בו מידע מזהה כמו שם משתמש או כתובת דוא”ל (§14.6.1 User Handle Contents). ↩ ↩2 ↩3 ↩4 ↩5

  3. W3C, Web Authentication Level 2 — §5.1.3 Create / RP ID validation, §13.4.9 Regarding phishing. על כך ש-public-key credential מוגבל בהיקף ל-RP ID (מזהה Relying Party = דומיין); על כך שהדפדפן (הלקוח) מאמת את ההתאמה בין הדומיין הניתן לרישום של ה-origin הקורא ל-RP ID, ומסרב ליצור או להשתמש ב-credential כשאין התאמה; ועל כך שבכך אי אפשר לגשת מ-origin מזויף ל-credentials של אתר אחר, ול-WebAuthn יש עמידות להתקפות phishing כולל סוג man-in-the-middle. ↩ ↩2 ↩3

  4. CISA, Implementing Phishing-Resistant MFA (גיליון עובדות מאוקטובר 2022). על כך שמ-MFA שמשתמש ב-SMS, קול, push notification או OTP פגיע ל-phishing, להתקפות AiTM (ממסור) ולהתקפות MFA fatigue; על כך שכשיטות phishing-resistant מנויים FIDO/WebAuthn authentication ואימות מבוסס PKI (smart card וכו’), ו-FIDO/WebAuthn ממוקם כ-gold standard; ועל כך שארגון צריך לעבור קודם ל-phishing-resistant MFA מחשבונות בסיכון גבוה. ↩ ↩2

  5. W3C, Web Authentication Level 2 — §7.2 Verifying an Authentication Assertion. על כך שנוהל האימות בצד השרת קובע אימות type, challenge (התאמה למה שהנפיק בעצמו) ו-origin ב-clientDataJSON; אימות ש-rpIdHash ב-authenticatorData תואם ל-hash SHA-256 של ה-RP ID הצפוי; אישור דגלי User Present / User Verified; ואימות חתימה ב-public key השמור. ↩ ↩2 ↩3

  6. NIST, Incorporating Syncable Authenticators Into NIST SP 800-63B (נספח מאפריל 2024, משולב במהדורה 4 של SP 800-63B). על כך ש-syncable authenticator (synced passkey) יכול לעמוד ב-AAL2 כשה-private key נשמר ומשוכפל ב-sync fabric באופן שעומד בדרישות; על כך שמאידך cryptographic authenticators של AAL3 דורשים סביבה מוגנת ומבודדת בחומרה, ולכן syncable authenticator שה-private key שלו ניתן לייצוא אינו בשימוש ב-AAL3; ועל כך ששיטות שמבצעות origin verification כמו WebAuthn מאורגנות כבעלות verifier impersonation resistance (phishing resistance). PDF המקור ב-NIST SP 800-63B Supplement 1. ↩ ↩2 ↩3 ↩4

  7. תמיכת Apple, About the security of passkeys. על כך ש-passkeys מסונכרנים ב-iCloud Keychain; על כך ש-iCloud Keychain מוצפן end-to-end וגם Apple אינה יכולה לקרוא; ועל כך שהסנכרון מוגן במפתחות במכשירי המשתמש, ומוכן שחזור דרך escrow עם rate limit. ↩

  8. Google, Security of Passkeys in the Google Password Manager. על כך שה-private key של ה-passkey מוצפן במכשיר ואז מסונכרן; על כך ש-end-to-end encryption מונעת מ-Google עצמה לגשת לתוכן ה-private key; ועל כך שהשחזור דורש הגנה המבוססת על screen lock של המכשיר וכו’. ↩

  9. Microsoft Learn, Enable passkeys (FIDO2) for Microsoft Entra ID. על כך ש-Entra ID תומך ב-passwordless authentication עמיד ל-phishing במפתחות אבטחה FIDO2 וב-passkeys של Microsoft Authenticator (device-bound); ועל כך שאפשר להפעיל במדיניות שיטות authentication ולדרוש ב-authentication strength של Conditional Access (phishing-resistant MFA). ↩ ↩2

  10. Microsoft Learn, Support for passkeys in Windows. על כך ש-Windows 11 תומך ביצירה ובשימוש ב-passkeys עם Windows Hello; על כך שאפשר לנהל passkeys שמורים מ-הגדרות > חשבון > passkeys; על כך ש-credentials של Windows Hello מוגנים בחומרה בסביבה שבה TPM זמין; ועל כך שאפשר להשתמש ב-passkeys במכשיר נייד דרך QR. ↩

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

העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.

שאלות נפוצות

שאלות נפוצות בפניות בנושא המאמר.

מה ההבדל האמיתי בין passkey לסיסמה?
סיסמה עובדת כך: המשתמש והשרת חולקים אותו סוד, ובכל login שולחים אותו. הסוד נמצא בראש של המשתמש, בשדה הקלט, על הקו, ובמסד הנתונים של השרת — ולכן כל אחד מהמקומות האלה הוא יעד להתקפה. passkey משתמש ב-key pair של public-key cryptography, וה-private key לא נשלח לשרת. ב-device-bound passkey ה-private key לא יוצא מה-authenticator בכלל; גם ב-synced passkey הוא יוצא מהמכשיר רק מוצפן end-to-end. מה שהשרת שומר הוא ה-public key — מידע שאי אפשר לנצל גם אם דלף — ומה שנשלח ב-login הוא חתימה על challenge חד-פעמי. כלומר הסוד המשותף שהיה החולשה של הסיסמה פשוט לא קיים. בנוסף, key pair נוצר בנפרד לכל אתר, אז reuse בין אתרים לא חל כאן.
האם נתונים ביומטריים (טביעת אצבע, פנים) נשלחים לשרת?
לא. טביעת אצבע או פנים משמשות רק להתאמה מקומית במכשיר — לפתוח את ה-private key — ולפי תכנון FIDO ביומטריה לא יוצאת מהמכשיר. השרת מקבל רק חתימה עם דגל ש-user verification בוצע. אין שם את טביעת האצבע עצמה, וגם לא feature vector שנגזר ממנה. כשביומטריה לא זמינה אפשר PIN, וגם ה-PIN הזה, כמו PIN של Windows Hello, מאומת רק מקומית במכשיר. ההבדל הקריטי מסיסמה: הוא לא עובר ברשת.
למה passkey עמיד ל-phishing?
כי המשתמש לא צריך לזהות אתר מזויף מלכתחילה. passkey נוצר כבול לדומיין של האתר (RP ID), והדפדפן מציע רק passkey שמתאים לדומיין שמוצג עכשיו. גם אם נכנסים לדומיין מזויף שנראה זהה, ה-passkey של האתר האמיתי פשוט לא מופיע ברשימה, אז אין דרך 'להזין בטעות' את ה-credential. בנוסף, החתימה כוללת את ה-origin שהדפדפן אימת ואת ה-hash של ה-RP ID, כך שאפילו אם ממסרים את החתימה, השרת האמיתי דוחה אותה. אי אפשר מבנית לעשות את התאונה של סיסמה וקוד SMS — להזין credential אמיתי באתר מזויף. זה ההבדל מאמצעים שמסתמכים על הדרכה וערנות.
אם איבדתי את הטלפון, ננעלתי מחוץ לחשבונות?
אם זה synced passkey — כזה שנשמר ב-iCloud Keychain או ב-Google Password Manager — אפשר לשחזר אותו למכשיר חדש שנכנס לאותו Apple ID או חשבון Google. אבל שחזור ה-vault המוצפן end-to-end דורש לא רק את סיסמת החשבון אלא גם אימות נוסף, למשל screen lock (passcode) של המכשיר הקודם. אם גם אמצעי השחזור האלה אבדו, השחזור עלול להיות בלתי אפשרי. לא כדאי לשים הכול על טלפון אחד. device-bound passkey (security key, Windows Hello וכדומה) קשור לגורל המכשיר, ולכן לחשבונות חשובים רושמים יותר מ-passkey אחד. רוב השירותים מאפשרים כמה passkeys בחשבון אחד. שימו לב: ביטול passkey שאבד משתנה לפי הסוג. ב-synced passkey העותקים בכל מכשיר הם אותו credential אחד, אז קודם מסירים את המכשיר שאבד או עושים remote wipe בצד חשבון הפלטפורמה כדי להשבית את העותק על המכשיר (מחיקת ה-passkey בהגדרות החשבון של השירות עצמו מבטלת את העותקים בכל המכשירים בבת אחת). ב-device-bound, מחיקת ה-passkey של ה-authenticator בצד השירות מבטלת רק את המפתח שאבד. בארגון מתכננים יחד גם יתירות כדי שמשתמשים יוכלו לשחזר לבד, וגם נוהל למנהלים לבטל במקרה אובדן.
יש גם חולשות ל-passkey?
כן. מדויק יותר לומר שמקום החולשה זז. האימות עצמו מתחזק עם public-key cryptography, ולכן תוקפים עוברים לאזורים החלשים יותר מסביב. בפועל: אם סיסמאות או SMS עדיין זמינים במקביל, זו נשארת החוליה החלשה ביותר; אפשר לנצל את תהליך שחזור החשבון כדי לרשום passkey של התוקף; וב-synced passkey, השתלטות על חשבון הענן עצמו הופכת ל-single point of failure חדש. בנוסף, גניבת session cookie אחרי login לא נעצרת ב-passkey, אז איומים לא קשורים לא נעלמים. פריסה צריכה לכלול לא רק 'מוסיפים passkey' אלא גם חיזוק תהליך השחזור וצמצום מתוכנן של fallback.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג