הטמעת הצפנת נתונים מקומית באפליקציה ניידת
אנו משלבים הצפנת נתונים מקומית ב-iOS וב-Android כבר למעלה מ-5 שנים. לקוחות מגיעים אלינו לעיתים קרובות עם בעיה: לאחר שהמכשיר נפרץ, נתוני המשתמש נחשפים לעין כל. הסיבה פשוטה — ההצפנה או שלא מוטמעת כלל או שמוטמעת עם שגיאות. מסד נתונים לא מוצפן של SQLite ב-Android הוא רק קובץ: adb pull /data/data/com.yourapp/databases/app.db במכשיר עם root — וכל הנתונים קריאים עם כל דפדפן SQLite. ב-iOS, המצב מעט טוב יותר הודות ל-Data Protection API, אבל רק אם המפתח לא שכח להגדיר את NSFileProtectionKey הנכון — וזה לעיתים קרובות מוזנח. אנו מבטיחים שאחרי העבודה שלנו, הנתונים שלך יישארו מוגנים גם עם גישה פיזית למכשיר.
מה אנו מצפינים וכיצד
המשימה מתחלקת לשלוש שכבות עצמאיות: מסד נתונים, קבצים, סודות.
מסד נתונים. התקן הוא SQLCipher. פיצול של SQLite עם הצפנת AES-256 שקופה ברמת העמוד. ב-Android הוא משולב דרך net.zetetic:android-database-sqlcipher, ב-iOS דרך SQLCipher.xcframework. Room ב-Android עובד עם SQLCipher דרך SupportOpenHelperFactory — המעבר כולל החלפת ה-factory ב-Room.databaseBuilder() והוספת המפתח. המפתח נוצר פעם אחת, מאוחסן ב-Keystore/Keychain, ולעולם לא מאוחסן ב-SharedPreferences או ב-UserDefaults בטקסט רגיל.
בהפעלה הראשונה ב-Android:
val key = generateAes256Key() // через KeyGenerator с KeyStore provider
val encryptedKey = encryptWithKeystore(key) // RSA/AES через AndroidKeyStore
prefs.putString("db_key_enc", Base64.encode(encryptedKey))לאחר מכן, בכל פתיחת מסד נתונים, אנו מפענחים את המפתח ומעבירים אותו ל-SQLCipher. ללא val key = generateAes256Key() // через KeyGenerator с KeyStore provider val encryptedKey = encryptWithKeystore(key) // RSA/AES через AndroidKeyStore prefs.putString("db_key_enc", Base64.encode(encryptedKey)) , מסד הנתונים פשוט לא ייפתח.
קבצים. עבור תמונות, PDF, מטמון — AES-256-GCM דרך PRAGMA key ב-Android או javax.crypto.Cipher ב-iOS (Swift 5.5+). GCM חשוב: הוא מספק גם סודיות וגם אימות שלמות. CBC ללא MAC הוא בחירה גרועה, פגיע להתקפות padding oracle.
ב-Flutter, החבילה CryptoKit.AES.GCM נוחה עבור סודות ו-flutter_secure_storage עבור קבצים, אבל מתחת למכסה המנוע שניהם משתמשים באותם ממשקי API מקוריים — עטיפות, לא תחליפים.
סודות (מפתחות API, טוקנים). רק Keychain (iOS) ו-Android Keystore. לא encrypt, לא UserDefaults, לא SharedPreferences ב-React Native. Keychain ב-iOS מוצפן עם מפתחות הקשורים ל-Secure Enclave; Keystore ב-Android עם API 23+ קושר מפתחות ל-TEE או SE — לא ניתן לייצא אותם אפילו עם root.
למה חשוב להצפין דווקא את מסד הנתונים
מסד הנתונים הוא הנקודה הפגיעה ביותר. הוא בדרך כלל מאחסן פרופילי משתמש, רשימות קניות, היסטוריית פעולות. אם תוקף משיג גישה פיזית למכשיר (אובדן, גניבה) ועוקף את מסך הנעילה, מסד נתונים לא מוצפן משמעותו גישה מלאה לנתונים. SQLCipher הופך את מסד הנתונים לבלתי קריא ללא המפתח. גם בעת ניתוח dump של זיכרון RAM, המפתח לא נחשף כי הוא מאוחסן ב-Keystore מבוסס חומרה.
שגיאות נפוצות ששוברות את כל התוכנית
ראשית — מחלקת הגנה שגויה ב-iOS. AsyncStorage פירושו שהקובץ אינו נגיש בזמן שהמכשיר נעול. אבל אם האפליקציה מקבלת התראת push ברקע ומנסה לקרוא את מסד הנתונים — קריסה. מפתחים נכנסים לפאניקה ועוברים ל-FileProtectionType.complete או מסירים את ההגנה לחלוטין. הפתרון הנכון הוא להפריד נתונים: קריטיים תחת completeUnlessOpen, פעולות רקע תחת .complete.
שנית — אחסון המפתח לצד הנתונים. נתקלנו במקרה שבו מפתח הצפנת מסד הנתונים היה באותה תיקייה כמו מסד הנתונים המוצפן, פשוט בקובץ .completeUnlessOpen. זו לא הצפנה, זה שינוי שם.
שלישית — שימוש בסיסמת המשתמש ישירות כמפתח. AES דורש 128 או 256 סיביות. סיסמה כמו "qwerty123" אינה מפתח. יש צורך ב-KDF: PBKDF2 עם מינימום 100,000 איטרציות או Argon2id. ב-iOS — key.bin, ב-Android — CommonCrypto.CCKeyDerivationPBKDF עם SecretKeyFactory.
| שכבה | iOS | Android |
|---|---|---|
| מסד נתונים | SQLCipher + CoreData | SQLCipher + Room |
| קבצים | CryptoKit AES-GCM | javax.crypto.Cipher AES-GCM |
| סודות | Keychain (Secure Enclave) | Android Keystore (TEE/SE) |
שילוב עם ביומטריה
אפשרות מתקדמת — מפתח הצפנת מסד הנתונים מוגן על ידי ביומטריה דרך Keystore/Keychain. ב-Android: PBKDF2WithHmacSHA256 עם KeyGenParameterSpec.Builder ו-.setUserAuthenticationRequired(true). המפתח נוצר פעם אחת בכניסה הביומטרית הראשונה; לאחר מכן, בכל פתיחת אפליקציה, המשתמש מאמת, המפתח נפתח מ-Keystore, ומסד הנתונים נפתח.
ב-iOS, באופן דומה דרך .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG) עם kSecAttrAccessControl והדגל SecAccessControlCreateWithFlags או .biometryAny. הבדל: .biometryCurrentSet מבטל את המפתח כאשר מתווספות טביעות אצבע חדשות — זה חשוב לאפליקציות בנקאיות (לפי התיעוד הרשמי של Apple).
מה כלול בעבודה
יישום מלא של הצפנה מקצה לקצה:
- מלאי של נתונים מאוחסנים וסיווג לפי קריטיות.
- בחירת תוכנית מפתחות ושילוב עם Keystore/Keychain.
- יישום שכבת הצפנה עבור מסד נתונים, קבצים וסודות.
- המרת נתונים קיימים (אם יש).
- בדיקת כל התרחישים: עדכון אפליקציה, שחזור מגיבוי, שינויים ביומטריים.
- תיעוד והדרכה לצוות שלך.
תהליך
אנו מתחילים במלאי: מה מאוחסן היכן, האם כבר קיימת הצפנה, אילו נתונים נופלים תחת דרישות (PCI DSS, GDPR, תקנות מקומיות). לאחר מכן — בחירת תוכנית מפתחות, יישום שכבת הצפנה, שילוב עם האחסון הקיים. בנפרד — בדיקת תרחישים: עדכון אפליקציה, שחזור מגיבוי, שינויים ביומטריים של המשתמש.
ציר הזמן תלוי בנפח הנתונים ובקיומה של תוכנית אחסון נוכחית. אם כבר קיים מסד נתונים וצריך להמירו ל-SQLCipher — 3–5 ימים כולל בדיקות. הצפנת מטמון קבצים ושילוב Keychain — יום עד יומיים נוספים. תוכנית מלאה מאפס לפרויקט חדש מהירה יותר.
אנו נעריך את הפרויקט שלך. צור קשר — ננתח את תוכנית האחסון הנוכחית שלך ונציע את הפתרון האופטימלי עם ערובה לאבטחה.







