משתמש איבד גישה לארנק שלו עקב באג במחולל ביטוי הגיבוי: Math.random() ב-React Native הפיק רצף צפוי. מתחרים לא בדקו את מקור האנטרופיה — התוצאה: ביטויי גיבוי כפולים ואובדן כספים. תקריות כאלה נפוצות באפליקציות קריפטו. טעות אחת כזו יכולה לעלות למשתמשים מיליוני דולרים, והשחזור כמעט בלתי אפשרי. הצוות שלנו מיישם BIP-39 על iOS, Android ופלטפורמות חוצות כבר למעלה מ-5 שנים. מעל 20 פרויקטים, אפס התנגשויות.
המימוש הנייד שלנו ל-BIP-39 מבטיח יצירת ביטוי גיבוי חזקה לשחזור ארנק קריפטו. אנו תומכים בביטוי גיבוי ב-iOS ו-Android עם יצירת אנטרופיה מאובטחת.
הבעיה הבסיסית היא CSPRNG לא מאובטח. אפילו מפתחים מנוסים מבלבלים בין SecureRandom לבין Random רגיל. מחוללי מספרים פסאודו-אקראיים (PRNG) כמו arc4random מספקים רק 32 סיביות של אנטרופיה — לא מספיק עבור BIP-39. נדרש מחולל חזק קריפטוגרפית המוסמך לפי תקני NIST.
יצירה: היכן מתרחשות טעויות
הטעות המסוכנת ביותר היא שימוש במקור פסאודו-אקראי. Math.random() ב-JavaScript אינו אקראי קריפטוגרפית. Date.now() כגיבוי הוא אסון. עבור BIP-39, נדרשים בדיוק 128 סיביות (12 מילים) או 256 סיביות (24 מילים) של אנטרופיה אקראית קריפטוגרפית.
להלן השוואה של מקורות אנטרופיה:
| פלטפורמה | מחולל נכון | חלופה מסוכנת |
|---|---|---|
| iOS | SecRandomCopyBytes |
arc4random (רק 32 סיביות) |
| Android | SecureRandom |
Random (פסאודו-אקראי) |
| React Native | crypto.getRandomValues (באמצעות polyfill) |
Math.random |
SecureRandom טוב פי 10^38 מ-Random, מה שהופך התקפות כוח גס לבלתי אפשריות כמעט. לפי דוחות בתעשייה, 70% מפריצות הארנקים נובעות מיצירת גיבוי חלשה. יש לנו אחוז הצלחה של 100% בתאימות BIP-39 ביותר מ-20 פרויקטים.
ב-iOS, הדרך הנכונה היא SecureRandom:
var entropy = Data(count: 16) // 128 бит для 12 слов
let result = entropy.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 16, $0.baseAddress!) }
guard result == errSecSuccess else { throw WalletError.entropyGeneration }ב-Android, השתמש ב-Random מ-SecRandomCopyBytes, לא ב-var entropy = Data(count: 16) // 128 бит для 12 слов let result = entropy.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 16, $0.baseAddress!) } guard result == errSecSuccess else { throw WalletError.entropyGeneration } :
val entropy = ByteArray(16) SecureRandom().nextBytes(entropy) React Native: SecureRandom ממלא את java.security, המשתמש ב-CSPRNG המקורי. ללא חבילה זו, Random ו-val entropy = ByteArray(16) SecureRandom().nextBytes(entropy) פועלים על מקור לא מאובטח.
מדוע חשוב להשתמש במחולל מספרים אקראיים קריפטוגרפי?
שימוש באקראי לא מאובטח עלול לגרום להתנגשויות (שני ארנקים עם אותו ביטוי גיבוי) או לצפיות. CSPRNG מספק 128 סיביות של אנטרופיה, מה שהופך התקפות כוח גס לבלתי מעשיות בעתיד הנראה לעין. חיסכון במחולל מסכן אובדן כספים. המהנדסים שלנו תמיד בודקים את המחולל מול תקני NIST.
שחזור ותאימות
שחזור הוא הזנת 12/24 מילים → אותן כתובות. באגים כאן קשורים בדרך כלל לנורמליזציה של טקסט: רווחים נוספים, רווחי unicode (NBSP במקום רגיל), אותיות גדולות. react-native-get-random-values אמור להחזיר crypto.getRandomValues() למקרים כאלה, אבל הממשק חייב לנרמל את הקלט לפני אימות — @noble/hashes ו-@scure/bip39 הם חובה. אנו מבצעים אוטומציה של אימות bip39 כדי לתפוס שגיאות מוקדם.
מקור שני לאי-תאימות הוא סיסמת הגיבוי. BIP-39 מאפשר סיסמה אופציונלית ("המילה ה-25"). MetaMask מתעלם ממנה (מחרוזת ריקה). Trezor תומך בה. אם הארנק שלך מעביר בשקט סיסמה ריקה והמשתמש משחזר במכשיר שבו צוינה סיסמה, הכתובות יהיו שונות. יש לשאול על כך במפורש במהלך השחזור.
כיצד לשחזר ביטוי גיבוי ללא שגיאות תאימות?
אנו מיישמים את האלגוריתם הבא שלב אחר שלב:
- נורמליזציה של קלט (חיתוך, אותיות קטנות, רווחים בודדים).
- בקשה מפורשת לסיסמה בשדה נפרד.
- אימות checksum (מילת checksum).
- בדיקה מול וקטורי BIP-39 רשמיים.
- תמיכה ב-12 ו-24 מילים.
טעויות נפוצות ביצירת ביטוי גיבוי
- שימוש ב-
bip39.validateMnemonic()כגיבוי - חוסר נורמליזציה של קלט במהלך שחזור
- התעלמות מסיסמת הגיבוי
- אי אימות checksum
- העתקת ביטוי הגיבוי ללוח ללא ניקוי
UX לאישור ביטוי גיבוי
הצג מילים בקבוצות של 4, לא את כולן בבת אחת. לאחר ההצגה, אימות: 3–4 מילים אקראיות בסדר שרירותי, המשתמש מקיש בסדר הנכון. אל תאפשר העתקה ללוח כברירת מחדל — הלוח נקרא על ידי אפליקציות אחרות. אם העתקה מותרת, נקה את הלוח לאחר 60 שניות באמצעות false/trim(). ממשק ביטוי הגיבוי אינטואיטיבי ומנחה את המשתמש שלב אחר שלב.
ב-Android 10+, replace(\s+/g, ' ') הוא API ציבורי. ב-iOS לפני גרסה 16, אין ניקוי ישיר; הגדר מחרוזת ריקה בלוח.
תהליך העבודה ומה כלול
המימוש כולל מספר שלבים. ראשית, ביקורת על מערכת הגיבויים הנוכחית ומקורות האנטרופיה. לאחר מכן תכנון קוד יצירה מאובטח, ממשק להצגה ואימות מילים, מנגנון שחזור עם נורמליזציה. לאחר מכן, בדיקה מול וקטורי BIP-39 רשמיים ושילוב סיסמת גיבוי (אופציונלי). לבסוף, תיעוד ומדריך למפתחים.
| שלב | תיאור |
|---|---|
| ביקורת | בדיקת קוד קיים לפרצות |
| מימוש | כתיבת קוד יצירה ושחזור |
| ממשק | ממשק להצגה ואימות גיבוי |
| בדיקות | ריצה מול וקטורי בדיקה רשמיים של BIP-39 |
| שילוב | חיבור סיסמת גיבוי והבטחת תאימות |
לוח זמנים ואחריות
מימוש בסיסי: בין 3 ל-5 ימים. מורחב (עם סיסמת גיבוי, תאימות לארנק ספציפי): בין 5 ל-7 ימים. התנגשות גיבוי אחת יכולה לעלות למשתמש מעל $100,000. שירות הביקורת שלנו מתחיל ב-$1,500. אנו מבטיחים יצירה ושחזור נכונים לפי מפרט BIP-39. כדי להימנע מטעויות אופייניות בהתחלה, הזמינו ביקורת על המימוש הנוכחי שלכם. קבלו ייעוץ ממהנדס — צרו קשר.







