قائمة التحقق لتخزين آمن في Kotlin للرموز والمفاتيح والبيانات الشخصية
قائمة تحقق لتخزين آمن في Kotlin تساعدك على الاختيار بين Android Keystore و EncryptedSharedPreferences وتشفير قاعدة البيانات للرموز والمفاتيح والبيانات الشخصية.

ما الذي تحاول حمايته (بعبارات بسيطة)
التخزين الآمن في تطبيق أعمال يعني شيئًا واحدًا: حتى لو حصل شخص ما على الهاتف (أو على ملفات التطبيق)، يجب ألا يستطيع قراءة أو إعادة استخدام ما حفظت. يشمل ذلك البيانات في الراحة (على القرص) وأيضًا تسرب الأسرار عبر النسخ الاحتياطية، السجلات، تقارير الأعطال، أو أدوات التصحيح.
اختبار ذهني بسيط: ماذا يمكن لغريب أن يفعل لو فتح مجلد تخزين التطبيق؟ في كثير من التطبيقات، العناصر الأكثر قيمة ليست الصور أو الإعدادات. إنها سلاسل صغيرة تفتح الوصول.
عادةً ما يتضمن التخزين على الجهاز رموز الجلسة (حتى يبقى المستخدم مسجلاً)، رموز التحديث، مفاتيح API، مفاتيح التشفير، بيانات شخصية (PII) مثل الأسماء والبريد الإلكتروني، وسجلات العمل المخبأة للاستخدام دون اتصال (طلبات، تذاكر، ملاحظات العملاء).
إليك أنماط الفشل الشائعة في العالم الحقيقي:
- فحص جهاز مفقود أو مسروق ونسخ الرموز لاستنساخ الهوية.\n- برمجيات خبيثة أو تطبيق "مساعد" يقرأ الملفات المحلية على جهاز مروّت أو عبر حيل إمكانية الوصول.\n- النسخ الاحتياطي التلقائي ينقل بيانات التطبيق إلى مكان لم تخطط له.\n- نسخ التصحيح تسجّل الرموز، تضعها في تقارير الأعطال، أو تعطل فحوصات الأمان في إصدارات التصحيح.
لهذا السبب "فقط خزّنها في SharedPreferences" غير مقبول لأي شيء يفتح وصولًا (الرموز) أو قد يضر المستخدمين والشركة (البيانات الشخصية). SharedPreferences العادية مثل كتابة الأسرار على ورقة لاصقة داخل التطبيق: مريحة وسهلة القراءة إذا سنحت الفرصة.
النقطة المفيدة للبدء هي تسمية كل عنصر مخزن وطرح سؤالين: هل يفتح شيئًا؟ وهل سيكون مشكلة لو أصبح عامًا؟ الباقي (Keystore، التفضيلات المشفّرة، قاعدة البيانات المشفّرة) يتبع ذلك.
صنّف بياناتك: رموز، مفاتيح، وبيانات شخصية
التعامل مع التخزين الآمن يصبح أسهل عندما تتوقف عن معاملة كل "البيانات الحساسة" على أنها واحدة. ابدأ بسرد ما يحفظه التطبيق وماذا يحدث لو تسربت.
الرموز ليست مثل كلمات المرور. رموز الوصول والتحديث تُخزن لكي يبقى المستخدم مسجلًا، لكنها تظل أسرارًا عالية القيمة. لا يجب تخزين كلمات المرور على الإطلاق. إذا احتجت لتسجيل الدخول، خزّن فقط ما يلزم للحفاظ على الجلسة (عادة الرموز) واعتمد على الخادم لفحص كلمات المرور.
المفاتيح فئة مختلفة. مفاتيح API ومفاتيح التوقيع ومفاتيح التشفير يمكنها فتح أنظمة بأكملها، ليس حساب مستخدم واحد فقط. إذا استخرج أحدهم هذه المفاتيح من جهاز، يمكنه أتمتة سوء الاستخدام على نطاق واسع. قاعدة جيدة: إذا كان يمكن استخدام قيمة خارج التطبيق لانتحال التطبيق أو لفك تشفير بيانات، عاملها كمخاطرة أعلى من رمز مستخدم.
البيانات الشخصية (PII) أي شيء يمكن أن يعرّف شخصًا: البريد الإلكتروني، الهاتف، العنوان، ملاحظات العملاء، أرقام الهوية الحكومية، بيانات صحية. حتى الحقول التي تبدو غير ضارة تصبح حساسة عند دمجها.
نظام تصنيف سريع عملي:
- أسرار الجلسة: access token، refresh token، كوكي الجلسة
- أسرار التطبيق: مفاتيح API، مفاتيح التوقيع، مفاتيح التشفير (تجنب وضعها على الأجهزة إن أمكن)
- بيانات المستخدم (PII): تفاصيل الملف الشخصي، المعرفات، المستندات، البيانات الطبية أو المالية
- معرّفات الجهاز والتحليلات: معرّف الإعلانات، معرّف الجهاز، معرّف التثبيت (لا تزال حساسة وفق سياسات كثيرة)
Android Keystore: متى تستخدمه
Android Keystore مناسب عندما تحتاج لحماية أسرار لا يجب أن تخرج من الجهاز بصيغتها الواضحة. إنه خزنة للمفاتيح التشفيرية، ليس قاعدة بيانات لبياناتك الفعلية.
ما هو مناسبًا له: توليد وحفظ مفاتيح تُستخدم للتشفير، فك التشفير، التوقيع، أو التحقق. عادةً تقوم بتشفير رمز أو بيانات دون اتصال في مكان آخر، ومفتاح Keystore هو ما يفتحها.
المفاتيح المدعومة ماديًا: ماذا يعني ذلك فعليًا
على العديد من الأجهزة يمكن أن تكون مفاتيح Keystore مدعومة ماديًا. معنى ذلك أن عمليات المفتاح تحدث داخل بيئة محمية ولا يمكن استخراج مادة المفتاح. يقلّل ذلك المخاطر من برمجياتٍ يمكنها قراءة ملفات التطبيق.
المفاتيح المدعومة ماديًا ليست مضمونة على كل جهاز، والسلوك يختلف بحسب الطراز وإصدار Android. صمّم كأن عمليات المفتاح قد تفشل.
بوابات مصادقة المستخدم
يمكن لـ Keystore طلب وجود المستخدم قبل استخدام المفتاح. هكذا تربط الوصول بالبصمة أو بيانات اعتماد الجهاز. على سبيل المثال، يمكنك تشفير رمز تصدير ولا تفك تشفيره إلا بعد تأكيد المستخدم ببصمة أو PIN.
Keystore مناسب عندما تريد مفتاحًا غير قابل للتصدير، عندما تريد موافقة بيومترية أو اعتماد بيانات الجهاز لإجراءات حساسة، وعندما تريد أسرارًا لكل جهاز لا ينبغي مزامنتها أو أن تتحرك مع النسخ الاحتياطية.
خطّط لما قد يخطئ: يمكن إبطال المفاتيح بعد تغيّر إعدادات قفل الشاشة، تغيّر بيانات البصمة، أو أحداث أمان. توقّع الفشل وطبّق حلًا بديلًا نظيفًا: اكتشاف المفاتيح الملغاة، مسح الكتل المشفّرة، وطلب تسجيل دخول المستخدم مجددًا.
EncryptedSharedPreferences: متى تكفي
EncryptedSharedPreferences هو افتراضي جيد لمجموعة صغيرة من الأسرار على شكل مفتاح-قيمة. إنه "SharedPreferences لكن مشفّر" حتى لا يتمكّن شخص ما من فتح ملف وقراءة القيم.
تحت الغطاء يستخدم مفتاحًا رئيسيًا لتشفير وفك تشفير القيم. ذلك المفتاح محمي بواسطة Android Keystore، لذا تطبيقك لا يخزن مفتاح التشفير الخام نصًا.
غالبًا ما يكفي لعدد قليل من العناصر الصغيرة التي تُقرأ كثيرًا، مثل access و refresh tokens، معرّفات الجلسة، معرّفات الجهاز، أعلام البيئة، أو قطع حالة صغيرة مثل وقت التزامن الأخير. كما يناسب قطعًا صغيرة من بيانات المستخدم إذا لزم الأمر حقًا، لكنه لا يجب أن يتحول إلى مكان إلقاء للـ PII.
لا يناسب أي شيء كبير أو مُهيكل. إذا احتجت لقوائم دون اتصال، بحث، أو استعلام حسب الحقول (عملاء، تذاكر، طلبات)، يصبح EncryptedSharedPreferences بطيئًا ومحرجًا. عندها تريد قاعدة بيانات مشفّرة.
قاعدة بسيطة: إذا يمكنك سرد كل مفتاح مخزن في شاشة واحدة، فـ EncryptedSharedPreferences على الأرجح كافية. إذا كنت تحتاج إلى صفوف واستعلامات، انقل البيانات إلى قاعدة مشفّرة.
تشفير قاعدة البيانات: متى تحتاجه
تشفير قاعدة البيانات مهم عندما تخزن أكثر من إعداد صغير أو رمز وحيد. إذا احتفظ تطبيقك ببيانات عمل على الجهاز، افترض أنها يمكن استخراجها من هاتف مفقود ما لم تحمها.
قاعدة بيانات مناسبة عندما تحتاج وصولًا دون اتصال إلى سجلات، تخزينًا مؤقتًا للأداء، سجلات/تتبعات تاريخية، أو ملاحظات ومرفقات طويلة.
نهجان شائعان للتشفير
تشفير كامل للقاعدة (غالبًا بأسلوب SQLCipher) يشفر الملف بأكمله في الراحة. يفتح التطبيق الملف بمفتاح. هذا سهل الفهم لأنك لا تحتاج لتذكّر أي أعمدة محمية.
تشفير على طبقة التطبيق حسب الحقول يشفر حقولًا معينة قبل الكتابة ثم يفك التشفير بعد القراءة. قد ينجح هذا إذا كانت معظم السجلات غير حساسة، أو إذا كنت تحاول الحفاظ على هيكل قاعدة موجود دون تغيير تنسيق الملف.
موازنات: السرية مقابل البحث والفرز
تشفير القاعدة الكامل يخفي كل شيء على القرص، لكن بمجرد فتح القاعدة، يمكن لتطبيقك الاستعلام بشكل طبيعي.
تشفير الحقول يحمي أعمدة محددة، لكن تفقد البحث والفرز السهل على القيم المشفّرة. الفرز باسم عائلة مشفّر لا يعمل بشكل موثوق، والبحث يصبح إما "البحث بعد فك التشفير" (بطيء) أو "تخزين فهارس إضافية" (تعقيد وتسريبات محتملة).
أساسيات إدارة المفاتيح
لا يجب أبدًا تضمين مفتاح القاعدة في الشيفرة أو شحنه مع التطبيق. نمط شائع هو توليد مفتاح بيانات عشوائي للقاعدة (DEK)، ثم تخزينه مغلفًا (مشفّرًا) باستخدام مفتاح محفوظ في Android Keystore. عند تسجيل الخروج يمكنك حذف المفتاح المغلف والتعامل مع القاعدة المحلية كقابلة للتصرف، أو الاحتفاظ بها إذا كان التطبيق يجب أن يعمل دون اتصال عبر الجلسات.
كيفية الاختيار: مقارنة عملية
أنت لا تختار "الأكثر أمانًا" عمومًا، بل تختار الخيار الآمن الذي يتناسب مع كيفية استخدام تطبيقك للبيانات.
أسئلة تقود للاختيار الصحيح:
- كم مرة تُقرأ البيانات (كل تشغيل أم نادرًا)؟
- كم حجم البيانات (بضع بايتات أم آلاف السجلات)؟
- ماذا يحدث لو تسربت (مزعج، مكلف، يجب الإبلاغ قانونيًا)؟
- هل تحتاج وصولًا دون اتصال، بحثًا، أو فرزًا؟
- هل لديك متطلبات امتثال (الاحتفاظ، التدقيق، قواعد التشفير)؟
مخطط عملي:
- الرموز (OAuth access و refresh) عادةً تنتمي إلى EncryptedSharedPreferences لأنها صغيرة وتُقرأ كثيرًا.
- مادة المفاتيح يجب أن تعيش في Android Keystore كلما أمكن لتقليل فرصة نسخها من الجهاز.
- البيانات الشخصية وسجلات الأعمال دون الاتصال عادةً تحتاج تشفير قاعدة البيانات عند تخزين أكثر من حقول قليلة أو الحاجة إلى قوائم وفرز.
البيانات المختلطة أمر طبيعي في تطبيقات الأعمال. نمط عملي هو توليد مفتاح تشفير بيانات (DEK) لقاعدة البيانات أو الملفات المحلية، وتخزين DEK مغلفًا باستخدام مفتاح مدعوم من Keystore، وتدويره عند الحاجة.
إذا كنت غير متأكد، اختر المسار الآمن الأبسط: خزّن أقل. تجنَّب تخزين PII دون اتصال إلا عند الحاجة فعلاً، واحتفظ بالمفاتيح في Keystore.
خطوة بخطوة: تنفيذ التخزين الآمن في تطبيق Kotlin
ابدأ بكتابة كل قيمة تنوي تخزينها على الجهاز والسبب الدقيق لوجودها هناك. هذا أسرع طريقة لمنع التخزين "للاحتياط".
قبل كتابة الشيفرة، قرر قواعدك: كم تعيش كل قيمة، متى تُستبدل، وماذا يعني "تسجيل الخروج" فعليًا. قد تنتهي صلاحية access token بعد 15 دقيقة، ويمتد refresh token لفترة أطول، وقد تحتاج PII دون اتصال إلى قاعدة "حذف بعد 30 يومًا".
تنفيذ يبقى سهل الصيانة:
- أنشئ غلافًا واحدًا "SecureStorage" حتى لا يلمس بقية التطبيق SharedPreferences أو Keystore أو قاعدة البيانات مباشرةً.
- ضع كل عنصر في المكان المناسب: الرموز في EncryptedSharedPreferences، مفاتيح التشفير محمية بواسطة Android Keystore، ومجموعات البيانات الأكبر دون اتصال في قاعدة بيانات مشفّرة.
- تعامل مع الفشل عمدًا. إذا فشل التخزين الآمن، افشل مغلقًا. لا تتراجع صامتًا إلى التخزين النصي.
- أضف تشخيصات دون تسريب البيانات: سجّل أنواع الأحداث وأكواد الأخطاء، لا تسجّل رموزًا أو مفاتيح أو تفاصيل المستخدم.
- اربط مسارات الحذف: تسجيل الخروج، إزالة الحساب، و"مسح بيانات التطبيق" يجب أن تتجه جميعها إلى نفس روتين المسح.
ثم اختبر الحالات المملة التي تكسر التخزين الآمن في الإنتاج: الاستعادة من نسخة احتياطية، الترقية من إصدار قديم، تغيّر إعدادات قفل الجهاز، الهجرة إلى هاتف جديد. تأكد من أن المستخدمين لا يعلقون في حلقة حيث لا يمكن فك تشفير البيانات لكن التطبيق يستمر في المحاولة.
أخيرًا، دون القرارات في صفحة واحدة يمكن للفريق كله اتباعها: ماذا يُخزن، أين، فترات الاحتفاظ، وماذا يحدث عند فشل فك التشفير.
الأخطاء الشائعة التي تكسر التخزين الآمن
معظم الفشل ليس بسبب اختيار المكتبة الخطأ. يحدث عندما نسخة صغيرة تُنسخ الأسرار إلى أماكن لم تقصدها.
أكبر إشارة حمراء هي حفظ refresh token (أو رمز جلسة طويل العمر) نصًا واضحًا في أي مكان: SharedPreferences، ملف، مخبأ مؤقت "مؤقت"، أو عمود قاعدة بيانات محلي. إذا حصل شخص ما على نسخة احتياطية أو تفريغ جهاز مروّت أو قطعة تصحيح، يمكن لذلك الرمز أن يعيش أكثر من كلمة المرور.
الأسرار تتسرب أيضًا عبر الرؤية، ليس التخزين فقط. طباعة رؤوس الطلب كاملة في السجلات، طباعة الرموز أثناء التصحيح، أو إرفاق سياق "مفيد" بتقارير الأعطال والأحداث التحليلية يمكن أن يكشف بيانات اعتماد خارج الجهاز. عامل السجلات كأنها عامة.
التعامل بالمفاتيح فجوة شائعة أخرى. استخدام مفتاح واحد لكل شيء يزيد نطاق الضرر. عدم تدوير المفاتيح يعني أن الاختراقات القديمة تبقى سارية. ضع خطة لإصدار إصدارات المفاتيح، التدوير، وماذا يحدث للبيانات المشفّرة القديمة.
لا تنسَ مسارات "خارج الخزنة"
التشفير لا يمنع النسخ الاحتياطية السحابية من نسخ بيانات التطبيق المحلية. لا يمنع لقطات الشاشة أو تسجيل الشاشة من التقاط PII. لا يصلح إصدارات التصحيح ذات الإعدادات المرتخية، أو ميزات التصدير (CSV/مشاركة) التي قد تكشف الحقول الحساسة. كما أن الحافظة يمكنها تسريب رموز لمرة واحدة أو أرقام حساب.
أيضًا، التشفير لا يحل مشاكل التفويض. إذا كان تطبيقك يعرض PII بعد تسجيل خروج المستخدم، أو يحتفظ بذاكرة مخبأة يمكن الوصول إليها دون مصادقة، فهذه ثغرة وصول. قفل واجهة المستخدم، امسح الذاكرات الحساسة عند الخروج، وأعد التحقق من الأذونات قبل عرض البيانات المحمية.
التفاصيل التشغيلية: دورة الحياة، الخروج، والحالات الحدية
التخزين الآمن ليس مكانًا فقط لوضع الأسرار. إنه كيف تتصرف عبر الزمن: عند سكون التطبيق، عند تسجيل الخروج، وعند قفل الجهاز.
بالنسبة للرموز، خطط للدورة الكاملة. يجب أن تكون access tokens قصيرة العمر. تعامل مع refresh tokens كما لو كانت كلمات مرور. إذا انتهت صلاحية رمز، جدد بهدوء. إذا فشل التجديد (ملغى، تغيرت كلمة المرور، تم إزالة الجهاز)، أوقف حلقات المحاولة وأجبر على تسجيل دخول نظيف. ادعم أيضًا إبطال الجلسات من الخادم. التخزين المحلي المثالي لا ينفع إذا لم تقم ببطلان بيانات الاعتماد المسروقة.
استخدم البيومترية لإعادة المصادقة، لا لكل شيء. اطلبها عندما تكون العملية خطيرة فعلاً (عرض PII، تصدير البيانات، تغيير تفاصيل الدفع، عرض مفتاح لمرة واحدة). لا تطلبها عند كل فتح للتطبيق.
عند تسجيل الخروج، كن صارمًا ومتوقعًا:
- امسح النسخ في الذاكرة أولًا (الرموز المخزنة في singletons، interceptors، أو ViewModels).
- امسح الرموز المخزنة وحالة الجلسة (بما في ذلك refresh tokens).
- احذف أو أبطل مفاتيح التشفير المحلية إذا صممّت النظام لذلك.
- احذف PII دون اتصال والردود المخبأة من API.
- عطّل وظائف الخلفية التي قد تعيد جلب البيانات.
الحالات الحدية مهمة في تطبيقات الأعمال: حسابات متعددة على جهاز واحد، ملفات العمل، النسخ الاحتياطي/الاستعادة، نقل الجهاز، وتسجيل الخروج الجزئي (تبديل شركة/مساحة عمل بدلًا من الخروج الكامل). اختبر إيقاف الإجباري، ترقيات نظام التشغيل، وتغيّر الساعة لأن انحراف الوقت يكسر منطق انتهاء الصلاحية.
كشف العبث هو موازنة. فحوصات أساسية (بنيات قابلة للتصحيح، مؤشرات المحاكاة، إشارات root بسيطة، نتائج Play Integrity) تقلل الإساءة العرضية، لكن المهاجم الم determined يمكنه تجاوزها. عامل إشارات العبث كمؤشرات خطر: حدّ الوصول دون اتصال، اطلب إعادة مصادقة، وسجل الحدث.
قائمة فحص سريعة قبل النشر
استخدم هذه قبل الإصدار. تستهدف الأماكن التي يفشل فيها التخزين الآمن في تطبيقات الأعمال الحقيقية.
- افترض أن الجهاز قد يكون معاديًا. إذا كان المهاجم لديه جهاز مروّت أو صورة جهاز كاملة، هل يمكنه قراءة الرموز أو المفاتيح أو PII من ملفات التطبيق، التفضيلات، السجلات، أو لقطات الشاشة؟ إذا كانت الإجابة "ربما"، انقل الأسرار إلى حماية مدعومة بـ Keystore وحافظ على الحمولة مشفّرة.
- تحقق من النسخ الاحتياطية ونقل الجهاز. أبقِ الملفات الحساسة خارج Android Auto Backup والنسخ السحابية ونقل الجهاز. إذا فقدت مفتاحًا عند الاستعادة سيكسر فك التشفير، خطّط لتدفق الاسترداد (إعادة المصادقة وإعادة التحميل بدلاً من محاولة فك التشفير).
- ابحث عن نصوص واضحة على القرص. راجع الملفات المؤقتة، مخابئ HTTP، تقارير الأعطال، أحداث التحليل، ومخبئ الصور التي قد تحتوي PII أو رموز. راجع سجلات التصحيح وخرائط JSON.
- انتهِ وصُدّر ودوّر. يجب أن تكون access tokens قصيرة العمر، وrefresh tokens محمية، وجلسات الخادم قابلة للإبطال. حدّد تدوير المفاتيح وماذا يفعل التطبيق عند رفض الرمز (مسح، إعادة مصادقة، محاولة إعادة واحدة).
- سلوك إعادة التثبيت وتغيير الجهاز. اختبر إلغاء التثبيت وإعادة التثبيت ثم الفتح دون اتصال. إذا اختفت مفاتيح Keystore، ينبغي أن يفشل التطبيق بأمان (امسح البيانات المشفّرة، اعرض شاشة تسجيل الدخول، وتجنّب القراءات الجزئية التي تفسد الحالة).
اختبار سريع هو اختبار "اليوم السيئ": يسجل المستخدم الخروج، يغيّر كلمة المرور، يستعيد نسخة احتياطية إلى هاتف جديد، ويفتح التطبيق على متن طائرة. النتيجة يجب أن تكون متوقعة: إما تُفك البيانات للمستخدم الصحيح، أو تُمحى وتُعاد بعد تسجيل الدخول.
مثال عملي: تطبيق أعمال يخزن PII دون اتصال
تخيل تطبيق مبيعات ميدانية يُستخدم في مناطق ذات إشارة ضعيفة. المسوّقون يسجلون الدخول مرة صباحًا، يتصفّحون عملاء مخصصين دون اتصال، يضيفون ملاحظات اجتماع، ثم يزامنون لاحقًا. هنا تصبح قائمة التحقق عملية وتمنع تسريبات حقيقية.
تقسيم عملي:
- Access token: اجعله قصير العمر وخزّنه في EncryptedSharedPreferences.
- Refresh token: احمه بشكل أقوى واغلق الوصول عبر Android Keystore.
- PII العملاء (أسماء، هواتف، عناوين): خزّنها في قاعدة بيانات محلية مشفّرة.
- الملاحظات والمرفقات دون اتصال: خزّنها في القاعدة المشفّرة مع عناية إضافية لعمليات التصدير والمشاركة.
أضف ميزتين ويتغير الخطر.
إذا أضفت "تذكّرني"، يصبح refresh token الباب الرئيسي للعودة للحساب. عاملها ككلمة مرور. اعتمادًا على المستخدمين، قد تطلب فتح الجهاز (PIN/نمط/بصمة) قبل فك تشفيرها.
إذا أضفت وضع دون اتصال، لن تحمي جلسة فقط، بل قائمة عملاء كاملة قد تكون ذات قيمة بحد ذاتها. هذا عادةً يدفعك نحو تشفير قاعدة البيانات مع قواعد خروج واضحة: محو PII المحلية، الاحتفاظ فقط بما يلزم لتسجيل الدخول التالي، وإلغاء مزامنة الخلفية.
اختبر على أجهزة حقيقية، ليس المحاكيات فقط. على الأقل تحقق من سلوك القفل/فتح، سلوك إعادة التثبيت، النسخ الاحتياطي/الاستعادة، وفصل ملفات العمل.
الخطوات التالية: اجعلها عادة فريقية قابلة للتكرار
التخزين الآمن يعمل فقط عندما يصبح عادة. اكتب سياسة تخزين قصيرة يمكن لفريقك اتباعها: ماذا يذهب أين (Keystore، EncryptedSharedPreferences، قاعدة بيانات مشفّرة)، ما الذي لا يُخزن أبدًا، وماذا يجب مسحه عند الخروج.
اجعلها جزءًا من التسليم اليومي: تعريف الإنجاز، مراجعة الشيفرة، وفحوصات الإصدار.
قائمة مراجعة خفيفة للمراجع:
- كل عنصر مخزن مُوسوم (رمز، مادة مفتاح، أو PII).
- اختيار التخزين مبرر في تعليقات الشيفرة.
- الخروج وتبديل الحساب يزيل البيانات الصحيحة (وفقط تلك البيانات).
- الأخطاء والسجلات لا تطبع الأسرار أو PII الكامل.
- هناك شخص مسؤول عن السياسة ويحدّثها.
إذا كان فريقك يستخدم AppMaster (appmaster.io) لبناء تطبيقات أعمال وتصدّر شيفرة Kotlin للعميل على Android، حافظ على نفس نهج غلاف SecureStorage حتى تتبع الشيفرة المولدة والمخصصة سياسة موحّدة.
ابدأ بإثبات مفهوم صغير
أنشئ POC صغير يخزن رمز مصادقة واحدًا وسجل PII واحدًا (مثل رقم هاتف عميل مطلوب دون اتصال). اختبر التثبيت الجديد، الترقية، الخروج، تغيّر قفل الشاشة، ومسح بيانات التطبيق. توسّع فقط بعد أن يكون سلوك المسح صحيحًا وقابلًا للتكرار.
الأسئلة الشائعة
ابدأ بكتابة ما تخزنه بالضبط ولماذا. ضع الأسرار الجلسية الصغيرة مثل access و refresh tokens في EncryptedSharedPreferences، احتفظ بمفاتيح التشفير في Android Keystore، واستخدم قاعدة بيانات مشفّرة لسجلات الأعمال والبيانات الشخصية عند تخزين أكثر من بضعة حقول أو الحاجة للاستعلام.
تخزّن SharedPreferences العادية القيم في ملف يمكن قراءته أحيانًا من النسخ الاحتياطية للجهاز أو عبر وصول جهاز مروّت أو آثار تصحيحية. إذا كانت القيمة رمزًا أو أي بيانات شخصية، فمعاملتها كإعداد عادي تجعلها سهلة النسخ وإعادة الاستخدام خارج التطبيق.
استخدم Android Keystore لتوليد وحفظ مفاتيح تشفير لا يجب استخراجها. عادةً تستخدم هذه المفاتيح لتشفير بيانات أخرى (رموز، مفاتيح قاعدة البيانات، ملفات)، ويمكنك أيضًا طلب مصادقة المستخدم (بصمة أو بيانات الاعتماد) قبل استخدام المفتاح.
يعني أن عمليات المفاتيح قد تتم داخل مكوّن مادي محمي بحيث يصعب استخراج مادة المفتاح حتى لو استطاع المهاجم قراءة ملفات التطبيق. لا تفترض توفر هذه الميزة على كل الأجهزة أو ثبات سلوكها؛ صمّم تطبيقك ليتعامل مع فشل المفاتيح ولديه مسار استرداد.
عادةً ما يكفي لمجموعة صغيرة من أسرار القيم-المفتاح التي تُقرأ كثيرًا مثل رموز الوصول/التحديث، ومعرّفات الجلسة، وقطع الحالة الصغيرة. لا يناسب بيانات كبيرة أو سجلات مُهيكلة أو أي شيء تحتاج للبحث والفرز فيه مثل العملاء أو الطلبات.
اختر قاعدة بيانات مشفّرة عندما تخزن بيانات أعمال أو بيانات شخصية على نطاق واسع، تحتاج للبحث/الفلترة/الفرز محليًا، أو تحتفظ بسجل تاريخي للاستخدام دون اتصال. هذا يقلل خطر كشف قوائم العملاء أو الملاحظات عند فقد الجهاز مع تمكين التطبيق من العمل دون اتصال بمفتاح إدارة واضح.
تشفير قاعدة البيانات الكامل يحمي الملف كله في الراحة وهو أسهل للفهم لأنك لا تحتاج لتتبّع الأعمدة الحساسة. تشفير الحقول مفيد لعدد قليل من الأعمدة لكنه يجعل البحث والفرز صعبين، ومن السهل تسريب بيانات عبر فهارس أو حقول مشتقة.
ولّد مفتاح قاعدة بيانات عشوائيًا، ثم خزّنه مغلفًا (مشفرًا) باستخدام مفتاح محمي في Keystore. لا تُدرج مفاتيح مشفّرة في الشيفرة أو تُشحن مع التطبيق، وقرّر سلوك الخروج أو إبطال المفتاح (غالبًا: حذف المفتاح المغلف والتعامل مع البيانات المحلية كقابلة للإتلاف).
يمكن إبطال المفاتيح بسبب تغيّر قفل الشاشة أو تغيّر البصمات أو أحداث أمان أخرى أو عمليات الاستعادة. تعامل مع ذلك صراحةً: اكتشف فشل فك التشفير، امسح الكتل المشفّرة أو قاعدة البيانات المحلية بأمان، واطلب من المستخدم تسجيل الدخول مجددًا بدلاً من التكرار أو الرجوع للتخزين غير المشفّر.
تحدث التسريبات غالبًا عبر المسارات "خارج الخزنة": السجلات، تقارير الأعطال، أحداث التحليلات، طباعة التصحيح، مخابئ HTTP، لقطات الشاشة، الحافظة، ونسخ/استعادة النسخ الاحتياطية. عامل السجلات كخاصة عامة، لا تسجل الرموز أو البيانات الشخصية الكاملة، عطّل مسارات التصدير العرضي، واحرص أن يمسح الخروج البيانات المخزنة وفي الذاكرة.


