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 ซึ่งสื่อสารกับ daemon securityd ที่จัดการฐานข้อมูล SQLite ที่เข้ารหัสของ Keychain แต่ละเรกคอร์ดถูกเข้ารหัสด้วยคีย์แยกต่างหาก และคีย์เองได้รับการปกป้องโดยโมดูลฮาร์ดแวร์ Secure Enclave บนอุปกรณ์ที่มีชิป A7 และใหม่กว่า
Security framework มีอินเทอร์เฟซ C สำหรับทำงานกับ Keychain Services ฟังก์ชันหลัก: SecItemAdd (เพิ่ม), SecItemCopyMatching (ค้นหา), SecItemUpdate (อัปเดต) และ SecItemDelete (ลบ) แต่ละการดำเนินการรับพจนานุกรมแอตทริบิวต์ CFDictionaryRef ที่อธิบายประเภทของคำขอ
ข้อมูลถูกจำแนกตาม คลาส: kSecClassGenericPassword (รหัสผ่านทั่วไป), kSecClassInternetPassword (รหัสผ่านบริการอินเทอร์เน็ต), kSecClassCertificate (ใบรับรอง), kSecClassKey (คีย์การเข้ารหัส) และ kSecClassIdentity (คู่คีย์และใบรับรอง)
เมื่อบันทึกรหัสผ่าน แอปพลิเคชันจะสร้างพจนานุกรมพร้อมแอตทริบิวต์: บริการ บัญชี ระดับการเข้าถึง ป้ายกำกับ Security framework ส่งข้อมูลไปยัง daemon 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 KB ต่อเรกคอร์ด สำหรับปริมาณที่มากขึ้น ให้ใช้การเข้ารหัสไฟล์และเก็บคีย์ใน Keychain ในขณะที่ข้อมูลอยู่ใน Documents
บนอุปกรณ์ที่ เจลเบรก การป้องกัน Keychain จะลดลงเนื่องจากผู้โจมตีสามารถเข้าถึงรูทและอ่าน SQLite ของ Keychain ได้โดยตรง สำหรับข้อมูลสำคัญ ให้ใช้การเข้ารหัสเพิ่มเติมด้วยคีย์ที่ได้รับจากเซิร์ฟเวอร์
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม