Android Keystore — یک ارائهدهنده رمزنگاری است که کلیدهای رمزنگاری را در یک محیط اجرایی ایزوله (TEE) تولید و ذخیره میکند که حتی برای سیستمعامل نیز قابل دسترسی نیست. بر اساس AOSP Security Documentation (2025)، Keystore در بیش از 80% اپلیکیشنهای Android از صد برتر 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() برای کلیدهای ایجادشده در Keystore مقدار null برمیگردانند. این تفاوت بنیادین با کلیدهای نرمافزاری است — یک مهاجم نمیتواند کلید خصوصی را حتی با کنترل کامل دستگاه استخراج کند.
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 دارای CPU خود، حافظه دسترسی تصادفی (RAM)، مولد تصادفی واقعی (TRNG) و حافظه محافظتشده (One-Time Programmable memory) است. 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 استفاده کنید.
Software-based Keystore — یک پیادهسازی نرمافزاری است که در دستگاههای بدون پشتیبانی سختافزاری TEE یا StrongBox استفاده میشود. کلیدها به صورت رمزنگاریشده در سیستم فایلی ذخیره میشوند، اما کلید خصوصی ممکن است به طور موقت در حافظه RAM رمزگشایی شود. Keystore نرمافزاری امنیت کمتری دارد — یک مهاجم با دسترس root میتواند کلید را در حافظه رهگیری کند.
از 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، رمزنگاری دادهها و ایجاد جفت نامتناظر برای امضا.
مصدر یک کلید 256-بیتی AES/GCM با پیوند به احراز هویت بیومتریک ایجاد میکند. کلید برای صادرات از طریق 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() برای کلیدهای ایجادشده در Keystore مقدار null را برمیگرداند. کلید فقط از طریق Cipher، Signature یا Mac API قابل استفاده است — مواد خام قابل دسترسی نیستند.
TEE (TrustZone) — ایزولاسیون مجازی روی همان پروازنده، از تقسیم زمانی استفاده میکند. StrongBox — یک تراشه جداگانه با CPU و حافظه خود. StrongBox امنتر است (Common Criteria EAL 4+)، اما کندتر است و الگوریتمهای کمتری را پشتیبانی میکند. TEE برای عملیات مکرر و StrongBox برای کلیدهای حساس مناسب است.
پس از تولید کلید با فلاگ setIsStrongBoxBacked(true) از KeyStore.getKeyCharacteristics() استفاده کنید. ویژگی SECURITY_LEVEL_STRONGBOX پشتیبانی سختافزاری را تأیید میکند. اگر دستگاه از StrongBox پشتیبانی نکند، Keystore بدون خطا به TEE تغییر میکند — باید سطح امنیت را به صورت صریح بررسی کنید.
کلیدهای Keystore با حذف اپلیکیشن از دستگاه به طور خودکار حذف میشوند. در Android 10+، اگر اپلیکیشن فلاگ allowBackup=true را در مانیفست داشته باشد، کلیدها ممکن است حفظ شوند، اما پس از نصب مجدد قابل دسترس نخواهند بود. توصیه میشود در نصب تمیز کلیدها را دوباره تولید کنید.
خیر، Android Keystore به سختافزار مشخص یک دستگاه متصل است. کلیدی که در TEE یک دستگاه تولید شده نمیتواند به دستگاه دیگری منتقل شود. برای رمزنگاری چندساختی از شکل زیر استفاده کنید: Keystore کلید را در دستگاه حفاظت میکند و کلیدهای جلسه از طریق API با رمزنگاری نامتناظر محافظتشده انتقال مییابند.
نتیجهگیری
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید