Keychain — مفاهیم کلیدی، معماری و نحوه کار

نویسنده: IT Sectr منتشر شده: 2026-03-14 زمان مطالعه: 10 دقیقه

Keychain — یک مخزن امن اطلاعات احراز هویت در iOS، watchOS، macOS و tvOS است که رمزهای عبور، کلیدها و گواهی‌ها را در سطح سخت‌افزاری مدیریت می‌کند. برخلاف UserDefaults، داده‌ها در Keychain رمزگذاری شده و توسط sandbox برنامه ایزوله می‌شوند. طبق Apple Developer Documentation، Keychain از مکانیزم‌های Secure Enclave و رمزگذاری سخت‌افزاری AES-256 برای محافظت از اطلاعات محرمانه استفاده می‌کند.

نکات اصلی

  • Keychain — مخزن سیستمی iOS برای رمزهای عبور، کلیدها و گواهی‌ها با رمزگذاری سخت‌افزاری
  • Security framework توابع C SecItemAdd، SecItemCopyMatching و SecItemDelete را برای کار با Keychain فراهم می‌کند
  • دسترسی به Keychain توسط sandbox برنامه محدود شده است، اما دسترسی مشترک از طریق keychain access groups امکان‌پذیر است
  • ویژگی kSecAttrAccessible سطح حفاظت را تعیین می‌کند: از Always تا WhenUnlockedThisDeviceOnly
  • Keychain از ذخیره رمزهای عبور، کلیدهای متقارن و نامتقارن، گواهی‌های X.509 پشتیبانی می‌کند

Keychain چیست؟

Keychain — یک پایگاه داده امن از سیستم عامل اپل است که برای ذخیره‌سازی امن رمزهای عبور، کلیدهای رمزنگاری، گواهی‌ها و سایر داده‌های محرمانه طراحی شده است. Keychain اولین بار در Mac OS 8.6 در سال 1999 ظاهر شد و در iOS از اولین نسخه SDK حضور دارد.

تعریف و هدف

Keychain یک مشکل اساسی توسعه موبایل را حل می‌کند: ذخیره‌سازی اسرار (توکن‌ها، رمزهای عبور، کلیدهای رمزگذاری) در سیستم فایل محافظت‌نشده. برخلاف UserDefaults یا SQLite، داده‌ها در Keychain به صورت رمزگذاری شده ذخیره می‌شوند و هنگام نوشتن روی دیسک به طور خودکار رمزگذاری می‌شوند.

هر برنامه iOS در یک sandbox ایزوله کار می‌کند و فقط به keychain خود دسترسی دارد. با این حال، توسعه‌دهنده می‌تواند دسترسی مشترک به Keychain بین برنامه‌های یک توسعه‌دهنده را از طریق keychain access groups پیکربندی کند. کاربر iCloud Keychain همچنین داده‌ها را بین دستگاه‌ها از طریق رمزگذاری end-to-end همگام‌سازی می‌کند.

طبق Apple Security White Paper (2025)، Keychain از رمزگذاری سخت‌افزاری AES-256 با کلید متصل به شناسه یکتای دستگاه (UID) استفاده می‌کند که داده‌ها را هنگام استخراج از دستگاه غیرقابل دسترس می‌کند.

Keychain در iOS چگونه کار می‌کند؟

Keychain به عنوان یک سرویس لایه‌ای عمل می‌کند: برنامه به Security framework مراجعه می‌کند که با دیمن securityd تعامل دارد و پایگاه داده رمزگذاری شده SQLite Keychain را مدیریت می‌کند. هر رکورد با یک کلید جداگانه رمزگذاری می‌شود و خود کلیدها توسط ماژول سخت‌افزاری Secure Enclave در دستگاه‌های دارای تراشه A7 و جدیدتر محافظت می‌شوند.

معماری Security framework

Security framework یک رابط C برای کار با Keychain Services فراهم می‌کند. توابع اصلی: SecItemAdd (افزودن)، SecItemCopyMatching (جستجو)، SecItemUpdate (به‌روزرسانی) و SecItemDelete (حذف). هر عملیات یک دیکشنری از ویژگی‌های CFDictionaryRef را دریافت می‌کند که نوع درخواست را توصیف می‌کند.

داده‌ها بر اساس کلاس‌ها طبقه‌بندی می‌شوند: kSecClassGenericPassword (رمز عبور دلخواه)، kSecClassInternetPassword (رمز عبور سرویس اینترنتی)، kSecClassCertificate (گواهی)، kSecClassKey (کلید رمزنگاری) و kSecClassIdentity (ترکیب کلید و گواهی).

فرآیند ذخیره‌سازی داده

هنگام ذخیره رمز عبور، برنامه یک دیکشنری با ویژگی‌ها می‌سازد: سرویس، حساب، سطح دسترسی، برچسب. Security framework داده‌ها را به دیمن securityd ارسال می‌کند که رکورد را با کلید متصل به دستگاه رمزگذاری کرده و در Keychain SQLite ذخیره می‌کند. استخراج به طور مشابه انجام می‌شود: درخواست بر اساس ویژگی‌ها، جستجو، رمزگشایی و بازگرداندن داده.

یک ویژگی مهم: هنگام حذف برنامه، iOS به طور خودکار Keychain را پاک می‌کند از رکوردهایی که توسط این برنامه ایجاد شده‌اند (از iOS 10.3+). هنگام نصب مجدد برنامه، داده‌های Keychain نصب قبلی غیرقابل دسترس هستند، مگر اینکه از iCloud Keychain استفاده شده باشد.

swift
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

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.509SecCertificate
kSecClassKeyکلید رمزنگاریSecKey
kSecClassIdentityکلید + گواهیSecIdentity

کار با Keychain از طریق API

رابط اصلی تعامل با Keychain در کد بومی iOS — توابع Security framework. برای Swift و Objective-C یک رابط C موجود است که در توابع راحت پیچیده شده است.

عملیات پایه SecItemAdd و SecItemCopyMatching

تابع SecItemAdd یک عنصر جدید به Keychain اضافه می‌کند. ورودی یک دیکشنری با کلاس، داده و ویژگی‌ها را دریافت می‌کند. وضعیت errSecSuccess (0) یا کد خطا را برمی‌گرداند. تابع SecItemCopyMatching جستجو بر اساس ویژگی‌ها را انجام می‌دهد و داده‌های یافت شده را برمی‌گرداند.

برای جستجو از پرچم kSecReturnData استفاده می‌شود — اگر true باشد، تابع محتوای رکورد را برمی‌گرداند. پرچم kSecMatchLimit تعداد نتایج را تعیین می‌کند: kSecMatchLimitOne (یک) یا kSecMatchLimitAll (همه).

swift
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 تمام رکوردهای مطابق با دیکشنری ارسال شده را حذف می‌کند. هنگام حذف، مهم است که ویژگی‌های کافی مشخص شود تا به طور تصادفی رکوردهای دیگران در shared keychain حذف نشود.

swift
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 و همگام‌سازی

iCloud Keychain رکوردها را بین دستگاه‌های اپل از طریق رمزگذاری end-to-end همگام‌سازی می‌کند. اپل به داده‌های رمزگشایی شده دسترسی ندارد. برای فعال‌سازی همگام‌سازی، ویژگی kSecAttrSynchronizable را با مقدار kCFBooleanTrue اضافه کنید.

مهم: رکوردهای همگام‌سازی شده نمی‌توانند ویژگی ThisDeviceOnly را داشته باشند، زیرا باید در دستگاه‌های دیگر در دسترس باشند. هنگام از دست دادن همه دستگاه‌ها، iCloud Keychain از طریق کد بازیابی یا کلید پشتیبان iCloud بازیابی می‌شود.

Best Practices برای انتخاب سطح دسترسی

برای توکن‌های احراز هویت از kSecAttrAccessibleWhenUnlockedThisDeviceOnly استفاده کنید — داده‌ها فقط در دستگاه باز در دسترس هستند و به پشتیبان کپی نمی‌شوند. برای گواهی‌هایی که باید برای وظایف پس‌زمینه در دسترس باشند، از kSecAttrAccessibleAfterFirstUnlock استفاده کنید. هرگز از kSecAttrAccessibleAlways برای داده‌های محرمانه استفاده نکنید.

توصیه می‌شود همیشه برای داده‌هایی که نیاز به همگام‌سازی ندارند، پسوند ThisDeviceOnly را اضافه کنید. این کار از کپی شدن تصادفی اسرار در iCloud یا iTunes backup جلوگیری می‌کند، جایی که ممکن است با ابزارهای تحلیل استخراج شوند. برای داده‌های حیاتی، دسترسی را با kSecAccessControlUserPresence ترکیب کنید — این کار برای رمزگشایی رکورد نیاز به بیومتریک یا کد اضافه می‌کند.

هنگام استفاده از iCloud Keychain در نظر داشته باشید که رکوردهای همگام‌سازی شده در تمام دستگاه‌های کاربر در دسترس هستند: اگر مهاجم به یک دستگاه دسترسی پیدا کند، داده‌ها ممکن است در همه دستگاه‌ها به خطر بیفتند. برای اسرار ایزوله از ThisDeviceOnly استفاده کنید.

سوالات متداول

Keychain چه تفاوتی با UserDefaults دارد؟

UserDefaults داده‌ها را به صورت باز در فایل .plist ذخیره می‌کند که در تحلیل IPA قابل دسترس است. Keychain هر رکورد را جداگانه رمزگذاری می‌کند، از رمزگذاری سخت‌افزاری استفاده می‌کند و از سطوح دسترسی، بیومتریک و همگام‌سازی از طریق iCloud پشتیبانی می‌کند.

چگونه Keychain را هنگام تست پاک کنیم؟

در شبیه‌ساز iOS در هر اجرا Keychain پاک می‌شود. در دستگاه واقعی برنامه را حذف کنید — iOS تمام رکوردهای Keychain این توسعه‌دهنده را حذف می‌کند. برای پاک کردن انتخابی، SecItemDelete را با ویژگی‌های مربوطه فراخوانی کنید.

آیا دو برنامه می‌توانند از Keychain مشترک استفاده کنند؟

بله، از طریق keychain access groups. برنامه‌ها باید team ID یکسان در امضا و entitlements با keychain-access-groups یکسان داشته باشند. توسعه‌دهنده دسترسی مشترک را در Xcode Capabilities پیکربندی می‌کند.

حداکثر اندازه داده در Keychain چقدر است؟

اپل محدودیت دقیقی مستند نکرده است، اما در عمل توصیه می‌شود از ۱–۴ کیلوبایت در هر رکورد تجاوز نکنید. برای حجم‌های بزرگ از رمزگذاری فایل و ذخیره کلید در Keychain و خود داده‌ها در Documents استفاده کنید.

آیا Keychain در جیلبریک امن است؟

در جیلبریک حفاظت Keychain کاهش می‌یابد، زیرا مهاجم دسترسی root دریافت می‌کند و می‌تواند Keychain SQLite را مستقیماً بخواند. برای داده‌های حیاتی از رمزگذاری اضافی با کلید دریافتی از سرور استفاده کنید.

خلاصه

  • Keychain — مخزن امن iOS برای رمزهای عبور، کلیدها و گواهی‌ها با رمزگذاری سخت‌افزاری AES-256
  • Security framework C-API ارائه می‌دهد: SecItemAdd برای نوشتن، SecItemCopyMatching برای خواندن، SecItemDelete برای حذف
  • کلاس‌های داده Keychain: GenericPassword, InternetPassword, Certificate, Key, Identity — هر کدام با مجموعه ویژگی‌های خود
  • kSecAttrAccessible سطح دسترسی را مدیریت می‌کند: WhenUnlocked, AfterFirstUnlock, Always, با گزینه ThisDeviceOnly
  • iCloud Keychain رکوردها را بین دستگاه‌ها از طریق رمزگذاری end-to-end با ویژگی kSecAttrSynchronizable همگام‌سازی می‌کند
  • بیومتریک (Face ID / Touch ID) از دسترسی به Keychain از طریق kSecAccessControlBiometryCurrentSet محافظت می‌کند
  • برای ذخیره توکن‌های OAuth، رمزهای عبور و کلیدهای رمزنگاری از Keychain استفاده کنید — اسرار را در UserDefaults ذخیره نکنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید