مساء الخير اسمي ديميتري وأنا مدرس الدورة الأساسية "Android Developer" في Otus. قررت اليوم مشاركة ترجمة للمقالة ، والتي أجدها مثيرة للاهتمام وأعتقد أنها قد تكون مفيدة لكثير من قراء مدونتنا.

تخزين البيانات في SharedPreferences سريع جدًا ومريح. من السهل أيضًا على المهاجمين الاطلاع على البيانات المخزنة في SharedPreferences ... لذا كن حذراً فيما تضعه هناك ، وقد تضطر إلى التفكير في كيفية تخزين البيانات بتنسيق مشفر.
بالنسبة إلى كميات صغيرة من البيانات التي لا تبرر استخدام محرك قاعدة بيانات ، مثل SqlCipher ، كانت قدراتنا محدودة:
- طرق التشفير الأصلية (إذا كنت تعرف ما تفعله)
- حلول جاهزة مثل تفضيلات الأمان ، تفضيلات الأمان الأخرى ، أرماديلو ، إلخ.
- محاربة أغرب مشكلات دورة حياة نظام Keystore Android في كل إصدار من Android
لقد نجح هذا من قبل ، ولكن الآن لدينا
الحل الصحيح
والرسمية .
على الرغم من أنها لا تزال ألفا ، فقد عملت بشكل جيد لفترة من الوقت عندما كنت أستخدمها في مشاريعي. يُعد استخدام
EncryptedSharedPreferences مرحبًا به (أو يمكنك استخدامه) ، لكل ما
لديك باستخدام
min-sdk 23+ .
دعونا نلقي نظرة على مثال عن كيفية استخدامه:
مثال EncryptedSharedPreferences
الحد الأدنى من SDK
اليوم 23 (Android 6.0)
minSdkVersion 23
إضافة التبعيات
implementation "androidx.security:security-crypto:1.0.0-alpha02"
تهيئة / فتح
ما عليك سوى إنشاء أو استرداد المفتاح الرئيسي من keystore Android واستخدامه لتهيئة / فتح مثيل EncryptedSharedPreferences:
حفظ السجلات
احفظ البيانات كما فعلت دائمًا باستخدام SharedPreferences:
قراءة الملاحظات
اقرأ البيانات كما فعلت دائمًا باستخدام SharedPreferences:
هل الإعدادات مشفرة حقًا؟
نعم ، ومشفرة بشكل جيد حقا.
لنفترض أنني وضعت قيمة
akaita
في
SharedPreferences
. إليك ما سيبدو عليه الملف:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="DATA">akaita</string> </map>
إذا أضفت قيمة
akaita
إلى
EncryptedSharedPreferences
،
akaita
على شيء مختلف تمامًا:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map>
"> 12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001 </ سلسلة> <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map>
"> 12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001 </ سلسلة> <?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <string name="AVz2qCVxm1KudCCJKYuxuoaAXoPeWKjG0w==">ASnO9uni11t3m9sNgDJbiYllL/tE+i99TYKfQ0h8XV6AUN0O3rBxBsMmcpw2DCY=</string> <string name="__androidx_security_crypto_encrypted_prefs_key_keyset__">12a901eb372af4775b09f5b51d20d49428931c5d8e0b17dd103d2169c1879b8b13958274d7e25d3cc052f301461495fd40b70806ae244f456726802460318bdf19dce444e7a60f20c903c5a57140ea8e90a19a1b48559961d145a50000d1c0e22ca918b02ea0cc34e433900f44c00e9c791ecb678f26d293c0226d6c2a9e25e610616ec34241b06410481427a850eeedf85ee4c725d5dbd715b5a8d0e017be9a568a9f960989271d14d2d0531a4408a5d0dae705123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e4165735369764b6579100118a5d0dae7052001</string> <string name="__androidx_security_crypto_encrypted_prefs_value_keyset__">12880189e734bbbf9cfa3bc15b5e53ea8df03341269cf97112a60a1f6482732dd33248b3f821397fb04ef3372ff54336e9045a0b0c0fb7afdf475dbc98a1107d09de66afcc5ad063e5e5b59a7d616e14834e19769bc84de7e5c8716a811814a6cd7a6d72a1c64ce4317f2f482181c437b70f010219ca6407a98bac18f1101c02fd8e2c4a9009ad2a1ebbdc1a4408e9edbbce02123c0a30747970652e676f6f676c65617069732e636f6d2f676f6f676c652e63727970746f2e74696e6b2e41657347636d4b6579100118e9edbbce022001</string> </map>
علاوة على ذلك ، سيتغير الملف المشفر في كل مرة نقوم بحفظها ، مما يجعل من الصعب الوصول إليها.
تحذير كبير : الأداء
يوجد اختلاف كبير في الأداء بين SharedPreferences و EncryptedSharedPreferences.
يمكنك التحقق من ذلك بنفسك باستخدام نموذج التعليمة البرمجية الخاصة بي أو مجرد تنزيل نموذج التطبيق من متجر Play. أنا نفسي أجرت عدة اختبارات على جهاز حقيقي ، وأحصل على النتائج التالية:
EncryptedSharedPreferences مقابل SharedPreferences
الرسم البياني "EncryptedSharedPreferences مقابل SharedPreferences"استنتاج
EncryptedSharedPreferences هو حل موثوق به وبسيط للغاية لنظام Android 6.0 والإصدارات الأحدث.
لديها اثنين من إيجابيات كبيرة:
- نحن لسنا بحاجة لترميز أي شيء في التعليمات البرمجية لدينا. إنه يستخدم فقط Android Keystore لنا ، مما يلغي الحاجة إلى التعامل معه.
- لا يحتاج المستخدم لضبط قفل الشاشة. ستعمل EncryptedSharedPreferences تمامًا بدون قفل الشاشة
هذا بديل كامل تقريبًا لـ SharedPreferences. فقط تأكد من أن تهيئة / فتح EncryptedSharedPreferences لا يؤثر سلبًا على المستخدمين لديك.
سيبقى هذا القرار بالتأكيد. أنا استخدم هذا في أي سيناريو مناسب. الآن أريد فقط أن أقول إن اللاعبين من Android سيحسنون أدائه ، لذلك يمكننا القلق أقل :)
مثال التطبيق
فقط لتسهيل الاختبار والتأكد من أن كل شيء على اتصال جيد ، قمت بإنشاء تطبيق لك. قم بتنزيله أو تجميعه وتجربته!
https://github.com/akaita/encryptedsharedpreferences-exampleضع علامة زائد إذا وجدت المقال مفيدًا ، وسأكون سعيدًا بالإجابة على أي أسئلة في التعليقات.