EncryptedSharedPreferences: ما هو، واجهة API وكيفية الاستخدام

المؤلف: IT Sectr نُشر: 2026-03-14 وقت القراءة: 10 دق

EncryptedSharedPreferences هو مكون من مكتبة AndroidX Security يوفر تشفيراً شفافاً للبيانات المحفوظة عبر واجهة برمجة تطبيقات SharedPreferences. على عكس SharedPreferences العادية، حيث يتم تخزين البيانات في ملف XML مفتوح، يقوم EncryptedSharedPreferences تلقائياً بتشفير المفاتيح والقيم قبل الكتابة على القرص. وفقاً لـ Android Developers، تستخدم المكتبة AES-256 GCM للقيم وAES-256 SIV (RFC 5297) للمفاتيح، مما يضمن سرية البيانات وسلامتها.

النقاط الرئيسية

  • EncryptedSharedPreferences — غلاف حول SharedPreferences مع تشفير تلقائي لجميع البيانات المحفوظة
  • التشفير يستخدم AES-256 GCM للقيم وAES-256 SIV للمفاتيح عبر Android Keystore
  • التشفير الموثق (AEAD) يضمن عدم تغيير البيانات بعد الكتابة
  • المفتاح الرئيسي يُخزَّن في Android Keystore ومحمي بالأجهزة على الأجهزة المزودة بـ TEE
  • واجهة API متوافقة تماماً مع SharedPreferences — يتم الاستبدال دون تغيير كود القراءة والكتابة

ما هو EncryptedSharedPreferences؟

EncryptedSharedPreferences هي فئة من حزمة androidx.security.crypto، تم تقديمها في AndroidX Security 1.0.0 (2019). تقوم بتطبيق واجهة SharedPreferences، ولكن جميع عمليات الكتابة (putString، putInt، putBoolean، إلخ) تشفر البيانات مسبقاً، وعمليات القراءة تفك تشفيرها قبل الإرجاع.

مشكلة SharedPreferences العادية

SharedPreferences القياسية تحفظ البيانات في ملف XML في دليل التطبيق (/data/data/package/shared_prefs/). الملف غير مشفر — مع وصول الجذر إلى الجهاز أو أثناء تحليل النسخ الاحتياطي، تُقرأ جميع البيانات كـ XML عادي. رموز المصادقة ومفاتيح API والبيانات الشخصية للمستخدم تصبح متاحة للمهاجم.

EncryptedSharedPreferences يحل هذه المشكلة على مستوى المكتبة: يتم تشفير البيانات قبل الكتابة على القرص وفك تشفيرها عند القراءة. لا يحتاج المطور إلى استدعاء وظائف التشفير يدوياً — تبقى واجهة API مطابقة لـ SharedPreferences العادية.

التاريخ والإصدارات

مكتبة AndroidX Security v1.0.0 صدرت في ديسمبر 2019. حلت EncryptedSharedPreferences محل النهج القديم للتشفير اليدوي عبر Cipher + SharedPreferences. الإصدار المستقر الحالي هو 1.1.0-alpha06 (2024)، ويدعم API 19+. المكتبة جزء من Jetpack ولا تتطلب أذونات إضافية.

وفقاً لـ مدونة Google Security (2024)، EncryptedSharedPreferences هي الطريقة الموصى بها لتخزين إعدادات التطبيق الحساسة التي لا تتطلب مزامنة عبر السحابة. للسيناريوهات الأكثر تعقيداً، يُوصى باستخدام Room مع تشفير SQLCipher.

كيف يعمل EncryptedSharedPreferences؟

EncryptedSharedPreferences يستخدم مخطط تشفير ثنائي المستوى: المفتاح الرئيسي يُخزَّن في Android Keystore، وتُستخدم مفاتيح مشتقة لتشفير البيانات. هذا يجمع بين حماية Keystore وأداء التشفير المتماثل.

مخطط التشفير: AES-256 GCM + SIV

لـلقيم يُستخدم AES-256 GCM (وضع Galois/Counter) — وضع تشفير موثق (AEAD) يضمن سرية البيانات وسلامتها. لـلمفاتيح (أسماء المعاملات) يُطبق AES-256 SIV (RFC 5297) — تشفير حتمي ضروري للبحث عن المفتاح دون الكشف عن محتواه.

كل ملف في EncryptedSharedPreferences يحتوي على أزواج مفتاح-قيمة مشفرة. هيكل الملف يشمل: أولاً رأس مع بيانات وصفية (إصدار، معرف مفتاح)، ثم قائمة من الإدخالات المشفرة. الملف ليس XML صالحاً ولا يمكن قراءته بواسطة محررات النصوص.

MasterKey و KeyStore

فئة MasterKey مسؤولة عن إنشاء وإدارة مفتاح رئيسي بحجم 256 بت يُخزَّن في Android Keystore. يتيح MasterKey.Builder تكوين: نوع التخزين (Keystore أو برمجي)، الحماية البيومترية، وعمر المفتاح. افتراضياً، يتم إنشاء المفتاح الرئيسي في Android Keystore باستخدام خوارزمية AES/GCM/NoPadding.

kotlin
import androidx.security.crypto.MasterKey
import androidx.security.crypto.EncryptedSharedPreferences

fun getEncryptedPrefs() {
    val masterKey = MasterKey.Builder(context)
        .setKeyScheme(MasterKey.AES256_GCM_SPEC)
        .build()

    val prefs = EncryptedSharedPreferences.create(
        context,
        "secure_prefs",
        masterKey,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )
}

إعداد وتكوين التشفير

EncryptedSharedPreferences.create يقبل خمس معاملات: السياق، اسم الملف، المفتاح الرئيسي، مخطط تشفير المفاتيح، ومخطط تشفير القيم. اختيار المخططات يؤثر على الأداء ومستوى الأمان.

مخططات تشفير المفاتيح

AES256_SIV — تشفير حتمي: المفاتيح المتطابقة تنتج دائماً نفس النص المشفر. هذا ضروري للبحث عن المفاتيح (SharedPreferences.getX(key)). العيب: يمكن للمهاجم تحديد المفاتيح المستخدمة من خلال مطابقة النصوص المشفرة المتكررة. AES256_SIV2 — إصدار محسّن مع إضافة العشوائية.

لـلقيم يُستخدم AES256_GCM. يضيف GCM IV بحجم 12 بايت (متجه التهيئة) وعلامة مصادقة بحجم 16 بايت لكل قيمة. هذا يوفر السرية (لا يمكن لأحد قراءة القيمة) والمصادقة (لا يمكن لأحد التلاعب بالقيمة دون اكتشاف).

الحماية البيومترية للمفتاح الرئيسي

طريقة setUserAuthenticationRequired(true) في MasterKey.Builder تتطلب تأكيداً بيومترياً قبل استرجاع المفتاح الرئيسي من Keystore. هذا يضيف طبقة إضافية: حتى إذا كان التطبيق يعمل على جهاز غير مقفل، لا يمكن للمهاجم قراءة EncryptedSharedPreferences بدون Face ID أو Touch ID.

هام: مع setUserAuthenticationRequired، يصبح المفتاح الرئيسي غير متاح إذا قام المستخدم بتغيير أو إزالة البيانات البيومترية. يجب معالجة KeyPermanentlyInvalidatedException وإنشاء مفتاح رئيسي جديد مع ترحيل البيانات.

kotlin
fun createBiometricKey(): MasterKey {
    return MasterKey.Builder(context)
        .setKeyScheme(MasterKey.AES256_GCM_SPEC)
        .setUserAuthenticationRequired(true)
        .setRequestStrongBoxBacked(true)
        .build()
}

fun writeSecureToken(token: String) {
    try {
        prefs.edit().putString("auth_token", token).apply()
    } catch (e: KeyPermanentlyInvalidatedException) {
        // تغيرت البيانات البيومترية — يجب إعادة إنشاء المفتاح
    }
}

مثال استخدام في Kotlin

لنلق نظرة على مثال كامل لدمج EncryptedSharedPreferences في تطبيق Android باستخدام Kotlin. مكتبة androidx.security:security-crypto تُضاف عبر Gradle.

إضافة التبعية

في ملف build.gradle (app)، أضف: implementation "androidx.security:security-crypto:1.1.0-alpha06". لمشاريع Kotlin، مطلوب أيضاً kotlin-stdlib. تهيئة MasterKey تحدث مرة واحدة، عادة في Application.onCreate أو عبر حاوية DI.

قراءة وكتابة البيانات

بعد إنشاء مثيل EncryptedSharedPreferences، واجهة API لا تختلف عن SharedPreferences العادية. edit() ترجع Editor، جميع الطرق (putString، getString، putBoolean، getBoolean) تعمل بنفس الطريقة. الفرق الوحيد داخلي: البيانات تُشفر عند الكتابة وتُفك تشفيرها عند القراءة.

kotlin
class AuthRepository(context: Context) {
    private val prefs = createEncryptedPrefs(context)

    fun saveCredentials(login: String, password: String) {
        prefs.edit()
            .putString("login", login)
            .putString("password", password)
            .apply()
    }

    fun getToken(): String? {
        return prefs.getString("auth_token", null)
    }

    fun clearAll() {
        prefs.edit().clear().apply()
    }
}

الترحيل من SharedPreferences العادية

لـترحيل البيانات الموجودة من SharedPreferences غير المشفرة إلى EncryptedSharedPreferences، يجب: قراءة جميع البيانات من الملف القديم، إنشاء EncryptedSharedPreferences جديدة، كتابة جميع البيانات، وحذف الملف القديم. Google لا توفر مرحلة ترحيل مدمجة — المطور ينفذها يدوياً.

مقارنة مع SharedPreferences العادية

الاختيار بين SharedPreferences و EncryptedSharedPreferences يعتمد على نوع البيانات المخزنة. لـإعدادات واجهة المستخدم (السمة، اللغة، الترتيب)، SharedPreferences العادية كافية. للمعلومات السرية (الرموز، كلمات المرور، المفاتيح)، EncryptedSharedPreferences إلزامي.

الأداء

EncryptedSharedPreferences أبطأ من العادي بسبب عمليات التشفير. كتابة قيمة نصية واحدة تستغرق ~5-15 مللي ثانية (حسب حجم البيانات وتسريع AES للعتاد). القراءة تستغرق 2-5 مللي ثانية. لمعظم التطبيقات هذا غير ملحوظ، ولكن للعمليات الدفعية (الترحيل، الاستعادة) استخدم apply() بدلاً من commit().

الأمان

SharedPreferences العادية لا توفر أي حماية تشفيرية: ملف XML يمكن قراءته بواسطة أي عملية مع وصول جذر أو عبر adb backup. EncryptedSharedPreferences يشفر البيانات على مستوى التطبيق، والمفتاح الرئيسي يُخزَّن في Android Keystore مع حماية عتادية اختيارية (StrongBox).

الخاصيةSharedPreferencesEncryptedSharedPreferences
التخزينXML مفتوحملف ثنائي مشفر
التشفيرلا يوجدAES-256 GCM + SIV
حماية المفاتيحلا توجدAndroid Keystore + StrongBox
الأداء0.1-1 مللي ثانية2-15 مللي ثانية
التوصيةإعدادات UIالرموز، المفاتيح، PII

متى تختار EncryptedSharedPreferences

استخدم EncryptedSharedPreferences لتخزين: رموز تحديث OAuth، مفاتيح API للخدمات الخارجية، البريد الإلكتروني أو رقم هاتف المستخدم، وإعدادات التطبيق الحساسة (PIN، علامات المصادقة). EncryptedSharedPreferences غير مناسب لتخزين البيانات البيومترية أو المستندات الكبيرة — استخدم EncryptedFile أو Room مع SQLCipher.

القاعدة العامة: إذا كان تسرب البيانات سيضر بالمستخدم أو العمل — استخدم EncryptedSharedPreferences. إذا كانت البيانات تجميلية فقط (السمة، اللغة، الترتيب) — SharedPreferences العادية. من المنطقي تنفيذ EncryptedSharedPreferences منذ البداية، دون إعادة هيكلة: استبداله في مشروع قائم يتطلب ترحيلاً ومعالجة البيانات القديمة غير المشفرة.

تذكر أن EncryptedSharedPreferences لا يحمي البيانات أثناء تشغيل التطبيق — فقط على القرص. إذا كان للمهاجم وصول إلى ذاكرة العملية، يمكن اعتراض البيانات المفكوك تشفيرها. استخدم حماية إضافية: ProGuard/DexGuard للتمويه.

الأسئلة الشائعة

ما الفرق بين EncryptedSharedPreferences و DataStore؟

Jetpack DataStore هو بديل أكثر حداثة لـ SharedPreferences، يعتمد على Flow و coroutines في Kotlin. DataStore لا يشفر البيانات افتراضياً، ولكن يمكن دمجه مع EncryptedSharedPreferences أو استخدامه مع التشفير اليدوي عبر Proto DataStore مع بروتوكولات التشفير.

هل يمكن استخدام EncryptedSharedPreferences لكميات كبيرة من البيانات؟

لا يُوصى بذلك. EncryptedSharedPreferences مصمم للأحجام الصغيرة (حتى 100-200 كيلوبايت). للبيانات الأكبر، استخدم Room مع SQLCipher أو تشفير الملفات عبر EncryptedFile من نفس مكتبة AndroidX Security.

هل يدعم EncryptedSharedPreferences الترحيل عند تحديث المخطط؟

لا، لا يوجد ترحيل مخطط تلقائي. عند تغيير هيكل البيانات، يجب على المطور قراءة البيانات القديمة يدوياً عبر KeyGen القديم وكتابتها عبر الجديد. يُوصى بتخزين إصدار المخطط في معامل منفصل.

ما هو مستوى API الأدنى المطلوب؟

AndroidX Security 1.0.0 يدعم API 19+ (Android KitKat). الإصدار 1.1.0-alpha06 يدعم أيضاً API 19+. StrongBox يتطلب API 28+ وجهازاً مع دعم عتادي (Google Pixel 3+، Samsung Galaxy S9+).

هل من الآمن تخزين refresh token في EncryptedSharedPreferences؟

نعم، refresh token هو أحد حالات الاستخدام الرئيسية. تشفير AES-256 GCM، المفتاح الرئيسي في Keystore، الحماية البيومترية — مستوى كافٍ لرموز OAuth. لرموز الوصول قصيرة العمر مناسب أيضاً، على الرغم من أن بعض الفرق تفضل تخزينها في الذاكرة.

الخلاصة

  • EncryptedSharedPreferences — غلاف SharedPreferences مع تشفير تلقائي عبر AES-256 GCM (القيم) و SIV (المفاتيح)
  • المفتاح الرئيسي يُنشأ عبر MasterKey.Builder ويُخزَّن في Android Keystore مع خيارات بيومترية و StrongBox
  • واجهة API متوافقة تماماً: edit، putString، getString، apply، clear — كل شيء كما في SharedPreferences العادية
  • الأداء: 2-15 مللي ثانية لكل عملية، غير ملحوظ للمستخدم في السيناريوهات القياسية
  • الأمان: التشفير الموثق (AEAD) يمنع قراءة البيانات والتلاعب بها
  • الترحيل من SharedPreferences العادية يتطلب نقل بيانات يدوي عبر الملفات القديمة والجديدة
  • استخدم EncryptedSharedPreferences للرموز ومفاتيح API وكلمات المرور والإعدادات الحساسة الأخرى

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا