Keychain هو مخزن آمن لبيانات الاعتماد في iOS و watchOS و macOS و tvOS يدير كلمات المرور والمفاتيح والشهادات على مستوى الأجهزة. على عكس UserDefaults، يتم تشفير البيانات في Keychain وعزلها حسب بيئة التطبيق. وفقًا لـ Apple Developer Documentation، يستخدم Keychain آليات Secure Enclave والتشفير الأجهزة AES-256 لحماية المعلومات الحساسة.
النقاط الرئيسية
Keychain هي قاعدة بيانات آمنة لنظام تشغيل Apple مصممة للتخزين الآمن لكلمات المرور والمفاتيح التشفيرية والشهادات والبيانات الحساسة الأخرى. ظهر Keychain لأول مرة في Mac OS 8.6 عام 1999، وعلى iOS — منذ أول إصدار من SDK.
يحل Keychain مشكلة أساسية في تطوير الأجهزة المحمولة: تخزين الأسرار (الرموز وكلمات المرور ومفاتيح التشفير) في نظام ملفات غير آمن. على عكس UserDefaults أو SQLite، يتم تخزين البيانات في Keychain بشكل مشفر ويتم تشفيرها تلقائيًا عند الكتابة على القرص.
يعمل كل تطبيق iOS في بيئة معزولة ولديه حق الوصول فقط إلى keychain الخاص به. ومع ذلك، يمكن للمطور تكوين وصول مشترك إلى Keychain بين تطبيقات المطور نفسه عبر keychain access groups. كما يقوم iCloud Keychain للمستخدم بمزامنة البيانات بين الأجهزة عبر التشفير من النهاية إلى النهاية.
وفقًا لـ Apple Security White Paper (2025)، يستخدم Keychain تشفير أجهزة AES-256 بمفتاح مرتبط بمعرف الجهاز الفريد (UID)، مما يجعل البيانات غير قابلة للوصول عند استخراجها من الجهاز.
يعمل Keychain كـ خدمة متعددة الطبقات: يصل التطبيق إلى Security framework، والذي يتواصل مع الخفي securityd الذي يدير قاعدة بيانات SQLite المشفرة لـ Keychain. يتم تشفير كل سجل بمفتاح منفصل، والمفاتيح نفسها محمية بواسطة وحدة Secure Enclave الأجهزة على الأجهزة المزودة بشريحة A7 وأحدث.
يوفر Security framework واجهة C للعمل مع Keychain Services. الوظائف الرئيسية: SecItemAdd (إضافة)، SecItemCopyMatching (بحث)، SecItemUpdate (تحديث) و SecItemDelete (حذف). تقبل كل عملية قاموس سمات CFDictionaryRef يصف نوع الطلب.
تُصنف البيانات حسب الفئات: kSecClassGenericPassword (كلمة مرور عشوائية)، kSecClassInternetPassword (كلمة مرور خدمة إنترنت)، kSecClassCertificate (شهادة)، kSecClassKey (مفتاح تشفير) و kSecClassIdentity (مزدوج مفتاح وشهادة).
عند حفظ كلمة المرور، يقوم التطبيق بإنشاء قاموس بالسمات: الخدمة، الحساب، مستوى الوصول، العلامة. يقوم Security framework بتمرير البيانات إلى الخفي securityd، الذي يشفر السجل بمفتاح مرتبط بالجهاز ويخزنه في SQLite لـ Keychain. يتم الاسترجاع بالمثل: استعلام بالسمات، بحث، فك تشفير وإرجاع البيانات.
ميزة مهمة: عند حذف تطبيق، يقوم iOS تلقائيًا بمسح سجلات Keychain التي أنشأها هذا التطبيق (منذ iOS 10.3+). عند إعادة تثبيت التطبيق، تكون بيانات Keychain من التثبيت السابق غير متاحة إلا إذا تم استخدام iCloud Keychain.
import Security
func savePassword(service: String, account: String, password: Data) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecValueData as String: password,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
SecItemAdd(query as CFDictionary, nil)
}
يدعم Keychain خمس فئات بيانات رئيسية، لكل منها مجموعة سمات خاصة بها ونطاق تطبيق. يحدد اختيار الفئة مفاتيح البحث المتاحة وكيفية تشفير البيانات.
الفئتان kSecClassGenericPassword و kSecClassInternetPassword مصممتان لتخزين كلمات المرور النصية. الإصدار الإنترنت يخزن بالإضافة إلى ذلك بيانات الخادم: المجال، البروتوكول، المنفذ ومسار المصادقة. تُستخدم GenericPassword لتخزين أي كلمات مرور دون ربط بالخادم.
عند حفظ كلمة مرور إنترنت، يمكن تحديد kSecAttrServer (المجال)، kSecAttrProtocol (HTTPS، FTP، إلخ)، kSecAttrPort و kSecAttrPath. يتيح ذلك تحديد السجل بدقة أثناء الملء التلقائي عبر AutoFill.
الفئة kSecClassKey تخزن المفاتيح المتماثلة (AES) وغير المتماثلة (RSA، EC). الفئة kSecClassCertificate تخزن شهادات X.509. الفئة kSecClassIdentity تجمع المفتاح الخاص والشهادة المقابلة له في سجل واحد.
للمفاتيح غير المتماثلة، يدعم Keychain السمات: kSecAttrKeyType (RSA، EC)، kSecAttrKeySizeInBits (2048، 256)، kSecAttrIsPermanent (حفظ في Keychain). للشهادات: kSecAttrLabel (اسم مقروء)، kSecAttrSubject (DN المالك)، kSecAttrIssuer (DN المُصدر).
| فئة Keychain | الغرض | نوع البيانات |
|---|---|---|
| kSecClassGenericPassword | كلمة مرور التطبيق | Data (NSString) |
| kSecClassInternetPassword | كلمة مرور الخادم | Data + سمات الخادم |
| kSecClassCertificate | شهادة X.509 | SecCertificate |
| kSecClassKey | مفتاح تشفير | SecKey |
| kSecClassIdentity | مفتاح + شهادة | SecIdentity |
الواجهة الرئيسية للتفاعل مع Keychain في كود iOS الأصلي هي دوال Security framework. لكل من Swift و Objective-C، تتوفر واجهة C واحدة، مغلفة في دوال ملائمة.
الدالة SecItemAdd تضيف عنصرًا جديدًا إلى Keychain. تأخذ كمدخل قاموسًا بالفئة والبيانات والسمات. تُرجع الحالة errSecSuccess (0) أو رمز خطأ. الدالة SecItemCopyMatching تقوم ببحث حسب السمات وتُعيد البيانات الموجودة.
للبحث يُستخدم العلم kSecReturnData — إذا كان true، تُعيد الدالة محتوى السجل. العلم kSecMatchLimit يحدد عدد النتائج: kSecMatchLimitOne (واحد) أو kSecMatchLimitAll (الكل).
func readPassword(service: String, account: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
guard status == errSecSuccess else { return nil }
return item as? Data
}
SecItemUpdate يسمح بتغيير سمات أو بيانات سجل موجود. SecItemDelete يحذف جميع السجلات المطابقة للقاموس المُمرر. عند الحذف، من المهم تحديد سمات كافية لتجنب حذف سجلات الآخرين في keychain المشترك.
func deletePassword(service: String, account: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: account
]
SecItemDelete(query as CFDictionary)
}
كل سجل Keychain له السمة kSecAttrAccessible، التي تحدد متى تكون البيانات متاحة للقراءة. هذا مهم جدًا للأمان: مستوى الوصول الخاطئ قد يجعل البيانات عرضة للخطر أو، على العكس، غير متاحة عند الحاجة.
kSecAttrAccessibleWhenUnlocked — البيانات متاحة فقط عندما يكون الجهاز مفتوحًا. kSecAttrAccessibleAfterFirstUnlock — متاحة بعد أول فتح بعد إعادة التشغيل. kSecAttrAccessibleAlways — متاحة دائمًا (غير موصى به). اللاحقة ThisDeviceOnly تمنع نقل البيانات عبر النسخ الاحتياطي.
على الأجهزة المزودة بـ Secure Enclave، يمكن حماية مفتاح تشفير Keychain بالإضافة إلى ذلك باستخدام القياسات الحيوية: kSecAccessControlBiometryCurrentSet أو kSecAccessControlUserPresence. هذا يضيف شرط Face ID أو Touch ID لكل عملية قراءة.
iCloud Keychain يزامن السجلات بين أجهزة Apple عبر التشفير من النهاية إلى النهاية. Apple ليس لديها إمكانية الوصول إلى البيانات المفكوكة. لتفعيل المزامنة، أضف السمة kSecAttrSynchronizable بالقيمة kCFBooleanTrue.
مهم: السجلات المُزامَنة لا يمكن أن تحتوي على السمة ThisDeviceOnly، حيث يجب أن تكون متاحة على الأجهزة الأخرى. في حالة فقدان جميع الأجهزة، يمكن استعادة iCloud Keychain عبر رمز استرداد أو مفتاح استرداد iCloud.
لـ رموز المصادقة، استخدم kSecAttrAccessibleWhenUnlockedThisDeviceOnly — البيانات متاحة فقط عند فتح الجهاز ولا تُنسخ في النسخ الاحتياطي. للشهادات التي يجب أن تكون متاحة للمهام الخلفية، استخدم kSecAttrAccessibleAfterFirstUnlock. لا تستخدم أبدًا kSecAttrAccessibleAlways للبيانات الحساسة.
يُوصى دائمًا بإضافة اللاحقة ThisDeviceOnly للبيانات التي لا تتطلب مزامنة. هذا يمنع النسخ العرضي للأسرار إلى iCloud أو iTunes backup، حيث يمكن استخراجها بأدوات التحليل. للبيانات الحرجة، ادمج التوفّر مع kSecAccessControlUserPresence — يضيف هذا شرط القياسات الحيوية أو رمز المرور لفك تشفير السجل.
عند استخدام iCloud Keychain، ضع في اعتبارك أن السجلات المُزامَنة متاحة على جميع أجهزة المستخدم: إذا حصل المهاجم على إمكانية الوصول إلى جهاز واحد، يمكن اختراق البيانات على جميع الأجهزة. للأسرار المعزولة، استخدم ThisDeviceOnly.
الأسئلة الشائعة
UserDefaults يخزن البيانات بنص واضح في ملف .plist، متاح أثناء تحليل IPA. Keychain يشفر كل سجل على حدة، ويستخدم تشفير الأجهزة ويدعم مستويات الوصول والقياسات الحيوية والمزامنة عبر iCloud.
عند كل تشغيل لمحاكي iOS، يتم مسح Keychain. على جهاز حقيقي، احذف التطبيق — سيقوم iOS بحذف جميع سجلات Keychain لهذا المطور للمسح الانتقائي، استدعِ SecItemDelete بالسمات المناسبة.
نعم، عبر keychain access groups. يجب أن يكون للتطبيقين نفس team ID في ملف التوقيع و entitlements مع نفس keychain-access-groups. يكوّن المطور الوصول المشترك في Xcode Capabilities.
Apple لا توثق حدًا صارمًا، لكن عمليًا يُوصى بعدم تجاوز 1–4 كيلوبايت لكل سجل. للكميات الأكبر، استخدم تشفير الملفات وخزن المفتاح في Keychain، والبيانات نفسها في Documents.
على جهاز مع jailbreak، تنخفض حماية Keychain لأن المهاجم يحصل على صلاحيات الجذر ويمكنه قراءة SQLite لـ Keychain مباشرة. للبيانات الحرجة، استخدم تشفيرًا إضافيًا بمفتاح يتم الحصول عليه من الخادم.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.