Table of Contents
مقدمه ای بر امن سازی داده ها بر روی iOS
محافظت از داده های کاربر حساس مسئولیت اساسی هر برنامه iOS است، چه توکن های تأیید هویت، کلیدهای رمزگذاری، یا اعتبار خصوصی را ذخیره کنید، این پلت فرم یک راه حل سخت افزاری اختصاصی را فراهم می کند: :Keychain [FLT 1] بر خلاف یا فایل های فهرست اموال، کلید داده ها را در بقیه رمزگذاری می کند و کنترل دقیق دسترسی را برای ذخیره سازی اطلاعات جامع فراهم می کند.
آشنایی با زنجیره کلید iOS
زنجیره کلید یک ظرف ذخیره سازی امن است که توسط سیستم عامل مدیریت می شود.این آیتم های کوچک و حساس مانند رمز عبور، کلید های رمزنگاری یا گواهینامه را ذخیره می کند - در یک پایگاه داده رمزگذاری شده داده شده که به زنجیره کلید نوشته شده است، حتی زمانی که دستگاه قفل شده است.
- رمزگذاری در استراحت با استفاده از سخت افزار AES-256 پشتیبانی می شود.
- ] کنترل دسترسی از طریق passcode، Touch ID یا Face ID.
- بر روی برنامه مجدد [FLT 1] و پیکربندی اختیاری iCloud همگام سازی.
- حل و فصل بین برنامه ها: به طور پیش فرض، یک برنامه نمی تواند موارد کلیدی برنامه دیگر را بخواند مگر اینکه آنها یک گروه دسترسی به زنجیره کلید را به اشتراک بگذارند.
زنجیره کلید برای نفخ بزرگ طراحی نشده است؛ هر آیتم را در زیر چند کیلو بایت نگه دارید تا داده های بزرگتر، استفاده از API (FLT:1) یا چارچوب را همراه با رمزگذاری مبتنی بر فایل در نظر بگیرید.
Keychain Services API در مقابل کتابخانه های شخص ثالث
اپل خدمات بومی (FLT:0) Keychain را [FLT1] [FLT] را فراهم می کند که قدرتمند است، اما فعل و انفعال است، شما می توانید به طور مستقیم از آن استفاده کنید، یا یک کتابخانه شخص ثالث محبوب مانند FLT:2Keychain [F3:3] یا [F4] نیاز به کنترل اساسی دارد.
گزینه های کلیدی Storage
قبل از ذخیره هر چیزی، شما باید در مورد کلاس مورد موضوع کلیدی تصمیم بگیرید، رایج ترین برای رمز عبور عمومی (FLT:4) برای رمز عبور اینترنت یا گواهی، هر مورد توسط مجموعه ای از ویژگی ها ارجاع داده می شود - یک فرهنگ لغت (CFctionary) که این آیتم را توصیف می کند.
جریان اصلی همیشه این الگو را دنبال می کند:
- یک دیکشنری پرس و جو با کلاس و ویژگی های مورد نظر بسازید.
- به نام [[رده:رده:]]، ، |[[ویرایش]
- بررسی و بررسی مجدد (FLT 10) ([FLT: 11] یا یک کد خطا (خطای شماره 10)
قبل از نوشتن کد، ماژول امنیتی را وارد کنید:
import Security
import Foundation // for Data and String utilities
دانلود بازی کامپیوتر The Keychain
نوشتن یک رمز عبور Generic
برای ذخیره یک توکن (به عنوان مثال، یک JWT) برای کاربر فعلی:
func saveToken(_ token: String, forAccount account: String) -> Bool {
guard let tokenData = token.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: tokenData,
// Optional: restrict access to when device is unlocked
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
// Delete any existing item first to avoid duplicates
SecItemDelete(query as CFDictionary)
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
نکات کلیدی:
- (FLT:14) به عنوان یک کلید اصلی عمل می کند؛ یک رشته منحصر به فرد (به عنوان مثال، شناسه کاربر یا ثابت مانند را انتخاب کنید.
- [FLT16] کنترل زمانی که آیتم می تواند بخواند، استفاده از برای بهترین امنیت؛ آن را جلوگیری از پشتیبان گیری iCloud و محدود دسترسی به دستگاه فعلی.
- ما پیش از آنکه از آن استفاده کنیم، از آن استفاده می کنیم.
اضافه کردن کنترل دسترسی (Biometry یا Passcode)
برای داده های بسیار حساس، نیاز به Touch ID یا Face ID قبل از خواندن:
let accessControl = SecAccessControlCreateWithFlags(
nil,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.userPresence, // requires passcode, Face ID, or Touch ID
nil
)
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: tokenData,
kSecAttrAccessControl as String: accessControl as Any
]
SecItemAdd(query as CFDictionary, nil)
اکنون هر گونه درخواست (FLT:21) برای این مورد باعث ایجاد یک بیومتریک یا رمز عبور می شود.استفاده از از LocalAuthentication برای رسیدگی به تعامل کاربر با فضل.
بازیابی اطلاعات از زنجیره کلید
برای خواندن توکن ذخیره شده:
func retrieveToken(forAccount account: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
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,
let data = item as? Data,
let token = String(data: data, encoding: .utf8) else {
return nil
}
return token
}
سپس به سمت چپ بروید و به آن ها اجازه دهید تا به آن ها دسترسی پیدا کنند.
گزارشگر: هنگامی که از کنترل دسترسی (biometry) استفاده می کنید، تماس [FLT 27] ممکن است بازگردد (اگر کاربر این مورد را به طور جداگانه و هرگز به ذخیره سازی متن ساده باز گردد.
بالا بردن و حذف وسایل کلیدی
بالا بردن یک ماده موجود
به جای حذف و اضافه کردن، از [FLT 29] استفاده کنید.
func updateToken(_ newToken: String, forAccount account: String) -> Bool {
guard let newData = newToken.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account
]
let attributesToUpdate: [String: Any] = [
kSecValueData as String: newData
]
let status = SecItemUpdate(query as CFDictionary, attributesToUpdate as CFDictionary)
return status == errSecSuccess
}
این کار کارآمدتر از یک +add حذف است و از شرایط بالقوه مسابقه جلوگیری می کند.
حذف یک آیتم
func deleteItem(forAccount account: String) -> Bool {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account
]
let status = SecItemDelete(query as CFDictionary)
return status == errSecSuccess
}
مراقب باشید که موارد متعلق به سایر برنامه ها را به اشتراک گذاری گروه دسترسی مشابه حذف نکنید – همیشه پرس و جو خود را با محدوده کنید، اگر از زنجیره کلید مشترک استفاده می کنید.
قابلیت دسترسی و قابلیت دسترسی
ثابت تعریف می کند هنگامی که آیتم کلیدی می تواند خوانده شود، گزینه محدود کننده ترین که هنوز با نیازهای برنامه شما مطابقت دارد را انتخاب کنید:
| Attribute | Meaning |
|---|---|
kSecAttrAccessibleWhenUnlocked | Available only while device is unlocked (default). |
kSecAttrAccessibleAfterFirstUnlock | Available after device boots and is unlocked once. Allows background access. |
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly | Requires a passcode to be set. Strictest option—prevents access even after unlock if passcode is removed. |
kSecAttrAccessibleWhenUnlockedThisDeviceOnly | Same as WhenUnlocked but does not back up to iCloud, and cannot be restored to another device. |
برای اکثر برنامه ها، [FLT 39] تعادل بین امنیت و قابلیت استفاده را به دست می آورید، اگر شما نیاز به خواندن آیتم ها در پس زمینه دارید (به عنوان مثال، یک توکن تازه پس زمینه)، باید از (FLT:40) استفاده کنید (و قبول کنید که داده ها کمی محافظت می شوند).
خطای مدیریت و سقوط های مشترک
بازگشت به همیشه آن را بررسی و به درستی شکست رایج است:
- (در این میان، هیچ کس با این پرسش موافق نیست.
- (۲۵۲۹۹) - یک آیتم با همان کلید اصلی وجود دارد (اگر شما اول حذف نشد).
- (-128) - کاربر بلافاصله بیومتریک را لغو کرد.
- (25293) - تأیید اعتبار شکست خورده یا بیومتریک در دسترس نیست.
هرگز یک وضعیت غیر موفقیتی را نادیده نگیرید: یک پیام خطا یا تکرار کنید، اما هرگز داده های حساس را در خارج از زنجیره کلید به عنوان یک شکست ذخیره نکنید.شما می توانید از (FLT:47) برای بررسی دسترسی بیومتریک قبل از تلاش برای دسترسی استفاده کنید.
بهترین شیوه ها و ملاحظات تولید
- نام کاربری منحصر به فرد و توصیفی [FLT 1] را در هر کاربر یا هر نوع مورد برای جلوگیری از برخورد استفاده کنید.
- [در این باره]، [[[۱]] [[۱۰]] [[۱۰]]] [[۳]]] [[۳]]] [[۳]]] [[۱]]]] [[۳]]]] [[[[۱]]]]] [[[۳]]]]] [[[[۳]]]] [۱]]] [۱] [۳]]] [۱] [[[[[[[[۳]]]]]]]]]]]] [۱] [۱]]]]] [۳]] [۲]]]]]]] [۳]]]]]]]] [۳] [۳] [۳] [۳] [۳] [۳] [[[[[[[[[[[[[[[[[[[[[[[[[[[[۳]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] [۳] [۳]]]]]]]] [۲]]]] [۱] [۳
- داده های زنجیره ای روشن هنگامی که کاربر وارد می شود - بیش از همه حساب های شناخته شده و حذف موارد.
- از گروه های دسترسی به زنجیره کلید استفاده کنید تنها زمانی که بین برنامه های خود به اشتراک بگذارید، از گروه های گسترده اجتناب کنید.
- هرگز داده های غیر حساس را ذخیره نکنید [FLT 1 ] (مانند ترجیحات کاربر) در زنجیره کلید (FLT:49 یا پایگاه داده به جای آن استفاده کنید.
- [[ویرایش] [۱] [۱۰] استفاده از [FLT: ۵۰] با [FLT] [۲۲] [[۳]] [۳] برای سناریوهای پیشرفته (ماکسن کاتالیزور)
- تست بر روی یک دستگاه واقعی [FLT 1]؛ شبیه ساز از یک کلید نرم افزار استفاده می کند که متفاوت از ذخیره سازی تحت حمایت سخت افزار رفتار می کند.
استفاده از Keychain با SwiftUI و Async/Await
برای برنامه های مدرن، بستن عملیات زنجیره کلید در یک بازیگر یا یک کلاس امن برای جلوگیری از مسدود کردن موضوع اصلی.
actor KeychainManager {
func saveToken(_ token: String, for account: String) async -> Bool {
// same implementation as above, but now it's safe to call from any context
return saveToken(token, forAccount: account)
}
}
اگر از بیومتریک استفاده می کنید، تماس ممکن است موضوع را در حالی که در انتظار تعامل کاربر قرار می گیرد، آن را در یک صف پس زمینه یا بهتر، استفاده کنید روش قبل از تماس زنجیره کلید.
نتیجه گیری
The iOS Keychain is the correct place to store small, sensitive pieces of data. By using the native Keychain Services API, you gain direct control over encryption, accessibility, and authentication policies. Always pair your Keychain usage with solid error handling and remember to clear data when appropriate. For further reading, refer to the Apple Keychain Service Documentation and the Keychain Concepts overview. Adopting these practices will help you ship iOS apps that respect user privacy and withstand security scrutiny.