Android Keystore — موفر تشفيري يقوم بتوليد وتخزين مفاتيح التشفير في بيئة تنفيذ معزولة (TEE)، لا يمكن لنظام التشغيل الوصول إليها. وفقًا لـ AOSP Security Documentation (2025)، يتم استخدام Keystore في أكثر من 80% من تطبيقات Android من أصل 100 في Google Play لحماية الرمزات وتشفير البيانات. فهم Android Keystore أمر بالغ الأهمية لتخزين المفاتيح بأمان على Android.
النقاط الرئيسية
Android Keystore — مكون نظام من منصة Android يوفر API لتوليد وتخزين واستخدام المفاتيح التشفيرية في بيئة محمية. على عكس مكتبات التشفير البرمجية (Bouncy Castle, Conscrypt)، يضمن Keystore عدم مغادرة المفاتيح الخاصة لمنطقة التنفيذ المعزولة أبدًا.
ظهر Keystore لأول مرة في Android 4.3 (API 18) كموفر برمجي مع دعم RSA. بدءًا من Android 6.0 (API 23)، حصل Keystore على دعم عتاد من خلال Keymaster Hardware Abstraction Layer (HAL)، الذي يفوض العمليات التشفيرية إلى Trusted Execution Environment (TEE) على الأجهزة المتوافقة. وفقًا لـ Android Compatibility Definition Document (2025)، جميع الأجهزة التي تعمل بـ Android 9+ مطلوب منها دعم Keystore بالعتاد من خلال TEE أو StrongBox.
تتم تحديد المفاتيح في Keystore عن طريق اسم مستعار (alias) — سلسلة تُمرر عند إنشاء أو تحميل المفتاح. لا يسمح Keystore بالوصول إلى مادة المفتاح الخام: تعيد طرق getEncoded() قيمة null للمفاتيح المنشآة في Keystore. هذا فرق أساسي عن المفاتيح البرمجية — لا يستطيع المهاجم استخراج المفتاح الخاص حتى مع السيطرة الكاملة على الجهاز.
Keystore متكامل مع آليات الأمان الأخرى في Android: المصادقة البيومترية (BiometricPrompt)، التشفير على مستوى الملفات (File-Based Encryption) ووظائف التحقق SafetyNet / Play Integrity. يمكن تكوين المفاتيح للحذف التلقائي في ظروف معينة: عند إزالة رمز المرور، عند إضافة بصمة إصبع جديدة أو عند انتهاء الصلاحية.
تشمل معمارية Android Keystore ثلاثة مستويات تنفيذ تختلف في درجة الحماية العتادية. يعتمد المستوى على قدرات عتاد الجهاز.
TEE (Trusted Execution Environment) — منطقة معزولة تعمل بالتوازي مع نظام التشغيل الرئيسي على نفس المعالج. يستخدم TEE تقنية ARM TrustZone، التي تقسم نواة المعالج المادية إلى نواتين افتراضيتين: Normal World (Android) وSecure World (TEE). للكود في Secure World إمكانية الوصول إلى الذاكرة والملحقات التي لا يمكن الوصول إليها من Normal World.
عندمت يستدعي تطبيق عملية تشفيرية من خلال Keystore، يتم إرسال الطلب من خلال Keymaster HAL إلى TEE، حيث تتم العملية عتاديًا. يتم إعادة النتيجة إلى التطبيق، ولكن المفتاح الخاص يبقى في ذاكرة TEE المحمية. TEE معتمد للتوافق مع GlobalPlatform TEE Protection Profile وهو مطلوب إلزامي لـ Android 9+ على الأجهزة المزودة بمعالجات تدعم TrustZone.
يدعم TEE خوارزميات AES/GCM (128، 256 بت)، RSA (2048، 4096 بت)، EC (P-256، P-384، P-521) وHMAC-SHA256. أداء TEE أقل من التشفير البرمجي (بنسبة 20–40%)، ولكن للعمليات النموذجية (توقيع JWT، فك تشفير مفتاح الجلسة)، لا تتجاوز زمن الانتظار 10–50 ملي ثانية.
StrongBox — شريحة أمان مخصصة، منفصلة فيزيائيًا عن المعالج الرئيسي. على عكس TEE، الذي يتقاسم وقت المعالج مع Android، يمتلك StrongBox وحدة معالجة مركزية خاصة به، وذاكرة RAM، ومولد أعداد عشوائية حقيقي (TRNG)، وتخزينا آمنًا (ذاكرة قابلة للبرمجة لمرة واحدة). StrongBox معتمد لـ Common Criteria EAL 4+ وSecure IC Protection Profile.
StrongBox متوفر على الأجهزة التي تعمل بـ Android 9+ بشرط وجود الشريحة المناسبة (على سبيل المثال، Titan M في Google Pixel، Knox في Samsung Galaxy). يقوم المطور بتفعيل StrongBox من خلال العلامة setIsStrongBoxBacked(true) في KeyGenParameterSpec. في حال عدم وجود دعم عتاد، يتم تجاهل العلامة ويعود Keystore إلى TEE.
قيود StrongBox: يدعم مجموعة محدودة من الخوارزميات (AES-256، EC P-256، HMAC-SHA256)، طابور العمليات — واحدة فقط في كل مرة، عدد العمليات — محدود بموارد الشريحة. StrongBox ليس مصممًا لسيناريوهات الحمل العالي — استخدم TEE للعمليات المتكررة وStrongBox فقط للمفاتيح الحاسمة (مفاتيح التشفير الرئيسية، مفاتيح التوقيع).
Keystore البرمجي هو تنفيذ برمجي يستخدم على الأجهزة دون دعم عتاد لـ TEE أو StrongBox. تختزن المفاتيح بشكل مشفر في نظام الملفات، ولكن قد يتم فك تشفير المفتاح الخاص مؤقتًا في الذاكرة العشوائية. Keystore البرمجي أقل أمانًا — يستطيع المهاجم بوصول جذري اعتراض المفتاح في الذاكرة.
بدءًا من Android 12 (API 31)، تطلب Google Keystore بالعتاد لجميع الأجهزة الجديدة. قد تحتوي الأجهزة التي تعمل بـ Android 9–11 على Keystore برمجي في النماذج المنخفضة التكلفة. يمكن للمطور التحقق من مستوى الحماية من خلال KeyStore.getKeyCharacteristics() — السمة SECURITY_LEVEL_TRUSTED_ENVIRONMENT أو SECURITY_LEVEL_STRONGBOX تؤكد الحماية العتادية.
Android Keystore يدعم مجموعة واسعة من الخوارزميات التشفيرية، مقسمة إلى فئات حسب نوع المفتاح. يؤثر اختيار الخوارزمية على الأداء، التوافق ومستوى الأمان.
AES (Advanced Encryption Standard) — تشفير متماثل لحماية البيانات على الجهاز. الوضع الموصى به: AES/GCM/NoPadding (256 بت). يوفر GCM تشفيرًا مُوثقًا (AEAD) — التحقق من سلامة البيانات المشفرة. حجم IV (متجه التهيئة): 12 بايت لـ GCM. لا تستخدم AES/ECB — لا يوفر حماية مناسبة.
RSA (Rivest–Shamir–Adleman) — تشفير غير متماثل لحماية مفاتيح الجلسات والتوقيعات الرقمية. الحجم الموصى به: 2048 أو 4096 بت. الأوضاع: RSA/ECB/PKCS1Padding (تشفير) وRSA/ECB/PKCS1Sign (توقيع). RSA 1024 يعتبر متقادمًا ولا يوصى به للتطبيقات الجديدة (NIST SP 800-131A Rev. 2).
EC (Elliptic Curve) — تشفير غير متماثل باستخدام المنحنيات الإيليتيكية للتوقيع وتبادل المفاتيح. المنحنيات المدعومة: secp256r1 (P-256، إلزامي)، secp384r1 (P-384) وsecp521r1 (P-521). يوفر EC أمانًا مقارنًا بـ RSA مع حجم مفتاح أصغر بشكل كبير. P-256 موصى به لمعظم السيناريوهات: يدعمه جميع الأجهزة ويوفر مستوى أمان 128 بت.
HMAC (Hash-based Message Authentication Code) — مصادقة رسائل متماثلة. دوال التجزئة المدعومة: SHA-256، SHA-384، SHA-512. يستخدم HMAC للتحقق من سلامة وصحة البيانات، على سبيل المثال، للتحقق من طلبات webhook أو فحص سلامة التهيئة.
يمكن ربط جميع الخوارزميات بالمصادقة البيومترية من خلال KeyGenParameterSpec.Builder.setUserAuthenticationRequired(true). على Android 11+ تتوفر العلامة setUserAuthenticationParameters() مع مهلة زمنية (بالثواني) خلالها يكون المفتاح متاحًا بعد المصادقة البيومترية، دون طلب متكرر.
دعونا نلق نظرة على أمثلة عملية للعمل مع Android Keystore باستخدام Kotlin: توليد مفتاح AES، تشفير البيانات وإنشاء زوج غير متماثل للتوقيع.
المثال ينشئ مفتاح AES/GCM بحجم 256 بت مع ربط بالمصادقة البيومترية. لا يمكن تصدير المفتاح من خلال getEncoded().
import android.security.keystore.KeyGenParameterSpec
import android.security.keystore.KeyProperties
import java.security.KeyStore
private val keyStore = KeyStore.getInstance("AndroidKeyStore").apply { load(null) }
fun generateAesKey(alias: String) {
val spec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_ENCRYPT or
KeyProperties.PURPOSE_DECRYPT
)
.setKeySize(256)
.setBlockModes(KeyProperties.KEY_BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthenticationRequired(true)
.setInvalidatedByBiometricEnrollment(true)
.build()
val generator = KeyGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_AES,
"AndroidKeyStore"
)
generator.init(spec)
generator.generateKey()
}
يقوم المثال بتشفير البيانات باستخدام مفتاح من Android Keystore. يحصل Cipher على المفتاح بالاسم المستعار، يقوم بتهيئة تشفير AES/GCM ويعيد البيانات المشفرة مع IV.
fun encryptData(alias: String, plaintext: ByteArray): ByteArray {
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val secretKey = keyStore.getKey(alias, null) as SecretKey
cipher.init(Cipher.ENCRYPT_MODE, secretKey)
val iv = cipher.getIV()
val encrypted = cipher.doFinal(plaintext)
// IV + بيانات مشفرة
return iv + encrypted
}
fun decryptData(alias: String, ciphertextWithIv: ByteArray): ByteArray {
val iv = ciphertextWithIv.copyOfRange(0, 12)
val encrypted = ciphertextWithIv.copyOfRange(12, ciphertextWithIv.size)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
val secretKey = keyStore.getKey(alias, null) as SecretKey
val spec = GCMParameterSpec(128, iv)
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec)
return cipher.doFinal(encrypted)
}
ينشئ المثال زوج مفاتيح RSA-2048 في Keystore مع ربط StrongBox. يستخدم المفتاح الخاص للتوقيع، ويمكن تصدير المفتاح العام من خلال getEncoded().
fun generateRsaKeyPair(alias: String) {
val spec = KeyGenParameterSpec.Builder(
alias,
KeyProperties.PURPOSE_SIGN or
KeyProperties.PURPOSE_VERIFY
)
.setKeySize(2048)
.setSignaturePaddings(
KeyProperties.SIGNATURE_PADDING_RSA_PKCS1
)
.setDigests(KeyProperties.DIGEST_SHA256)
.setIsStrongBoxBacked(true)
.build()
val pair = KeyPairGenerator.getInstance(
KeyProperties.KEY_ALGORITHM_RSA,
"AndroidKeyStore"
).apply { init(spec) }
.generateKeyPair()
// يمكن تصدير المفتاح العام
val publicKey = pair.public // X509EncodedKeySpec
}
يتطلب الاستخدام الفعال لـ Android Keystore اتباع قواعد تضمن الحماية القصوى مع الحفاظ على الأداء.
استخدم KeyGenParameterSpec بأدنى المعلمات الضرورية: حدد فقط أغراض الاستخدام وأوضاع الكتل والحشو المستخدمة فعليًا. تؤدي المعلمات الزائدة (على سبيل المثال، PURPOSE_ENCRYPT لمفتاح يستخدم فقط للتوقيع) إلى إنشاء نقاط هجوم غير ضرورية. Android يوصي بتحديد digest بشكل صريح للتوقيع — SHA256 هو أدنى مستوى مقبول (SHA1 قديم).
اربط المفاتيح بالبيومتريا للعمليات الحاسمة: يضمن setUserAuthenticationRequired(true) عدم إمكانية استخدام المفتاح إلا بعد المصادقة البيومترية. على Android 11+ استخدم setUserAuthenticationParameters() مع مهلة زمنية (موصى بها 30–60 ثانية) لتجنب طلب البيومتريا في كل عملية ضمن جلسة واحدة. setInvalidatedByBiometricEnrollment(true) يحذف المفتاح تلقائيًا عند إضافة بصمة إصبع أو وجه جديد — هذا يمنع الوصول ببيانات بيومترية قديمة.
تحقق من مستوى الأمان عند التهيئة: استخدم KeyStore.getKeyCharacteristics() لتحديد SECURITY_LEVEL. إذا كان الجهاز يدعم فقط Keystore برمجي (SECURITY_LEVEL_SOFTWARE)، اتخذ قرارًا: إما رفض الوظيفة أو استخدام تشفير إضافي (على سبيل المثال، تغليف المفتاح بكلمة مرور المستخدم). لا تعتمد على StrongBox إذا لم يكن مضمونًا — حدد دائمًا العلامة setIsStrongBoxBacked(true) وتحقق من النتيجة من خلال getKeyCharacteristics.
قم بتدوير المفاتيح بشكل دوري: للمفاتيح التشفيرية عمر افتراضي موصى به. NIST SP 800-57 يوصي بتغيير مفاتيح AES كل 1–2 سنة، وأزواج RSA/EC كل 2–3 سنة. قم بتنفيذ آلية تدوير المفاتيح: تحقق من تاريخ إنشاء المفتاح عند تشغيل التطبيق (KeyGenParameterSpec.Builder.setKeyValidityStart/End) وقم بتوليد مفتاح جديد عند انتهاء الصلاحية. يجب فك تشفير البيانات القديمة المشفرة بالمفتاح القديم وإعادة تشفيرها بالجديد.
لا تستخدم Keystore للبيانات الكبيرة: Keystore مصمم لتخزين المفاتيح (بضعة مئات بايت)، ليس لتشفير الملفات الكبيرة. لتشفير البيانات، استخدم المخطط التالي: قم بتوليد مفتاح AES عشوائي (DEK — Data Encryption Key)، قم بتشفير البيانات بهذا المفتاح، وقم بتشفير DEK بمفتاح Keystore (KEK — Key Encryption Key). Android EncryptedSharedPreferences يستخدم هذا المخطط بالضبط: المفتاح الرئيسي في Keystore، البيانات — AES-256 GCM.
الأسئلة الشائعة
لا، Android Keystore مصمم بحيث لا يغادر المفتاح الخاص TEE أو StrongBox أبدًا. تعيد طريقة getEncoded() قيمة null للمفاتيح المنشآة في Keystore. يمكن استخدام المفتاح فقط من خلال Cipher، Signature أو Mac API — المادة الخام غير قابلة للوصول.
TEE (TrustZone) — عزل افتراضي على نفس المعالج، يستخدم تقاسم الوقت. StrongBox — شريحة منفصلة مع وحدة معالجة وذاكرة خاصتين. StrongBox أكثر أمانًا (Common Criteria EAL 4+)، ولكن أبطأ ويدعم عددًا أقل من الخوارزميات. TEE مناسب للعمليات المتكررة، StrongBox للمفاتيح الحاسمة.
استخدم KeyStore.getKeyCharacteristics() بعد توليد مفتاح بالعلامة setIsStrongBoxBacked(true). تؤكد السمة SECURITY_LEVEL_STRONGBOX دعم العتاد. إذا لم يدعم الجهاز StrongBox، يعود Keystore إلى TEE دون خطأ — يجب التحقق صراحة من مستوى الأمان.
المفاتيح في Keystore تحذف تلقائيًا عند إزالة التطبيق من الجهاز. على Android 10+ قد تبقى المفاتيح إذا كان للتطبيق العلامة allowBackup=true في البيان، ولكنها ستكون غير قابلة للوصول بعد إعادة التثبيت. يوصى بتوليد المفاتيح مرة أخرى عند التثبيت النظيف.
لا، Android Keystore مرتبط بعتاد جهاز محدد. لا يمكن نقل مفتاح تم توليده في TEE جهاز واحد إلى آخر. للتشفير عبر المنصات، استخدم المخطط التالي: Keystore يحمي المفتاح على الجهاز، وتنتقل مفاتيح الجلسات من خلال API آمن باستخدام التشفير غير المتماثل.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.