Keychain ใน iOS: คืออะไร สถาปัตยกรรม และการทำงานกับความลับ

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-04-04 เวลาอ่าน: 9 นาที

Keychain คือพื้นที่จัดเก็บข้อมูลที่ปลอดภัยใน iOS ที่ออกแบบมาเพื่อจัดเก็บรหัสผ่าน คีย์การเข้ารหัส ใบรับรอง และบันทึกที่เป็นความลับอย่างปลอดภัย ตาม Apple Security Documentation (2025) Keychain ใช้การเข้ารหัสผ่านฮาร์ดแวร์ผ่าน Secure Enclave บนอุปกรณ์ทั้งหมดที่มีชิป A7 ขึ้นไป การทำความเข้าใจสถาปัตยกรรมของ iOS Keychain เป็นสิ่งจำเป็นสำหรับนักพัฒนาทุกคนในการจัดเก็บโทเค็นและความลับของแอปพลิเคชันอย่างถูกต้อง

ประเด็นสำคัญ

  • iOS Keychain คือฐานข้อมูล SQLite ที่เข้ารหัสสำหรับจัดเก็บความลับด้วยการป้องกันผ่านฮาร์ดแวร์ผ่าน Secure Enclave
  • Protection Class กำหนดว่าข้อมูลจะพร้อมใช้งานเมื่อใด: เมื่ออุปกรณ์ปลดล็อก หลังจากปลดล็อกครั้งแรก หรือตลอดเวลา
  • Access Control List (ACL) เป็นกลไกสำหรับจำกัดการเข้าถึงรายการ Keychain รวมถึงการยืนยันตัวตนด้วยชีวมาตร
  • SecItemAdd และ SecItemCopyMatching เป็น API หลักของ Security framework สำหรับการเขียนและอ่านรายการ
  • kSecAttrSynchronizable คือแฟล็กที่เปิดใช้งานการซิงค์ Keychain ผ่าน iCloud เพื่อการเข้าถึงบนอุปกรณ์ทั้งหมดของผู้ใช้

Keychain ใน iOS คืออะไร?

iOS Keychain เป็นกลไกที่ปลอดภัยสำหรับจัดเก็บข้อมูลที่เป็นความลับ ซึ่งสร้างไว้ในระบบปฏิบัติการของ Apple แตกต่างจาก UserDefaults หรือไฟล์ทั่วไป Keychain เข้ารหัสรายการทั้งหมดในระดับฮาร์ดแวร์และให้การควบคุมการเข้าถึงอย่างละเอียดตามนโยบายความปลอดภัย

Keychain ถูกนำมาใช้ใน iOS 2.0 และตั้งแต่นั้นมาก็ผ่านการเปลี่ยนแปลงครั้งสำคัญ: iOS 7 เพิ่มการสนับสนุนคีย์ฮาร์ดแวร์ผ่าน Secure Enclave, iOS 9 เปิดตัวการแชร์ Keychain ระหว่างแอปผ่าน Access Groups, iOS 13 เพิ่มการสนับสนุนการผูกชีวมาตรผ่าน LAContext ตาม Apple WWDC Session (2024) แอป iOS มากกว่า 90% ใน 100 อันดับแรกของ App Store ใช้ Keychain สำหรับจัดเก็บโทเค็นการยืนยันตัวตน

ในเชิงสถาปัตยกรรม Keychain คือฐานข้อมูล SQLite ที่เข้ารหัสซึ่งอยู่ภายนอกแซนด์บ็อกซ์ของแอปพลิเคชัน แต่ละรายการ (SecItem) จะถูกเข้ารหัสด้วยคีย์แยกต่างหาก ซึ่งจะถูกป้องกันโดยคีย์ฮาร์ดแวร์ Secure Enclave บริการระบบ Securityd จัดการการเข้าถึง Keychain ตามสิทธิ์ของแอปพลิเคชันและคลาสการป้องกันที่ร้องขอ

ข้อได้เปรียบที่สำคัญของ Keychain เหนือวิธีการจัดเก็บอื่นๆ: ข้อมูลถูกเข้ารหัสและถอดรหัสโดยอัตโนมัติโดยระบบปฏิบัติการ นักพัฒนาไม่จำเป็นต้องใช้งานการเข้ารหัสด้วยตนเอง - เพียงเรียก SecItemAdd ด้วยพารามิเตอร์ที่ถูกต้อง iOS รับประกันว่าแอปพลิเคชันอื่นไม่สามารถอ่านข้อมูลจาก Keychain ได้ (เมื่อกำหนดค่า Access Groups อย่างถูกต้อง)

สถาปัตยกรรมของ Keychain

สถาปัตยกรรม Keychain ประกอบด้วยหลายระดับ: ทางกายภาพ (Secure Enclave), ระบบ (Security.framework), แอปพลิเคชัน (API SecItem*) และเชิงตรรกะ (Access Groups, Protection Classes) การทำความเข้าใจแต่ละระดับช่วยออกแบบพื้นที่จัดเก็บความลับได้อย่างถูกต้อง

SecItemAdd และ SecItemCopyMatching

API หลักสำหรับทำงานกับ Keychain คือฟังก์ชันของ Security framework: SecItemAdd สำหรับเพิ่ม, SecItemCopyMatching สำหรับอ่าน, SecItemUpdate สำหรับอัปเดต และ SecItemDelete สำหรับลบ แต่ละฟังก์ชันรับพจนานุกรมคำค้นหาที่อธิบายคุณลักษณะของรายการที่ต้องการค้นหาหรือจัดเก็บ

คุณลักษณะหลักของคำค้นหา: kSecClass - ประเภทรายการ (kSecClassGenericPassword, kSecClassKey, kSecClassCertificate), kSecAttrAccount - ตัวระบุเฉพาะภายในคลาส, kSecValueData - ข้อมูลที่จัดเก็บ (Data), kSecAttrAccessible - คลาสการป้องกัน SecItemCopyMatching ด้วยแฟล็ก kSecReturnData ส่งคืนข้อมูลรายการ, ด้วย kSecMatchLimit - จำนวนผลลัพธ์

สำคัญ: ฟังก์ชันทั้งหมดส่งคืน OSStatus การดำเนินการที่สำเร็จส่งคืน errSecSuccess (0) ข้อผิดพลาด: errSecItemNotFound (-25300) - ไม่พบรายการ, errSecDuplicateItem (-25299) - รายการมีอยู่แล้ว, errSecAuthFailed (-25293) - การยืนยันตัวตนด้วยชีวมาตรล้มเหลว นักพัฒนาต้องจัดการแต่ละสถานะอย่างถูกต้อง

คลาสการป้องกัน (Protection Class)

Protection Class คือคุณลักษณะ kSecAttrAccessible ที่กำหนดว่าข้อมูลใน Keychain พร้อมใช้งานสำหรับการอ่านเมื่อใด iOS รองรับคลาสการป้องกันหกคลาสที่มีระดับความพร้อมใช้งานและความปลอดภัยต่างกัน

คลาสที่แนะนำสำหรับสถานการณ์ส่วนใหญ่คือ kSecAttrAccessibleWhenUnlockedThisDeviceOnly: ข้อมูลจะพร้อมใช้งานเมื่ออุปกรณ์ปลดล็อกเท่านั้นและไม่ถูกคัดลอกไปยัง iCloud Backup สำหรับข้อมูลที่ควรพร้อมใช้งานหลังจากรีบูต (แต่หลังจากการปลดล็อกครั้งแรกเท่านั้น) ให้ใช้ kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly สำหรับข้อมูลที่สำคัญซึ่งต้องการการยืนยันตัวตนด้วยชีวมาตรในทุกการเข้าถึง ให้รวม kSecAttrAccessibleWhenUnlockedThisDeviceOnly เข้ากับ ACL ที่ต้องการชีวมาตร

คลาสที่ไม่มีคำต่อท้าย ThisDeviceOnly (kSecAttrAccessibleWhenUnlocked, kSecAttrAccessibleAfterFirstUnlock) อนุญาตให้คัดลอกไปยัง iCloud Backup สะดวกสำหรับผู้ใช้แต่ลดความปลอดภัย - ข้อมูลสามารถกู้คืนจากการสำรองข้อมูลได้ สำหรับโทเค็นการยืนยันตัวตน ให้ใช้ ThisDeviceOnly เสมอ

รายการควบคุมการเข้าถึง (ACL)

Access Control List (ACL) เป็นกลไกที่จำกัดการดำเนินการกับรายการ Keychain ตามการยืนยันตัวตนของผู้ใช้ ACL ถูกกำหนดผ่าน SecAccessControlCreateWithFlags และส่งต่อไปยังคุณลักษณะ kSecAttrAccessControl เมื่อบันทึกรายการ

แฟล็กที่รองรับ: kSecAccessControlUserPresence - การยืนยันตัวตนใดๆ (Face ID, Touch ID หรือรหัสผ่าน), kSecAccessControlBiometryCurrentSet - เฉพาะชีวมาตร (ลายนิ้วมือหรือใบหน้าที่ลงทะเบียนอยู่ในปัจจุบัน), kSecAccessControlDevicePasscode - เฉพาะรหัสผ่าน ACL ใช้กับการดำเนินการทุกครั้ง: การอ่าน อัปเดต และลบรายการก็ต้องมีการยืนยันตัวตนเช่นกัน

บน iOS 15+ แฟล็ก kSecAccessControlWatch ปรากฏขึ้น - สำหรับ Apple Watch ซึ่งอนุญาตให้ยืนยันตัวตนผ่านนาฬิกาที่เชื่อมต่ออยู่ ACL สามารถรวมกันได้: ตัวอย่างเช่น kSecAccessControlUserPresence หรือ kSecAccessControlBiometryAny พร้อมรหัสผ่านเสริม (การวางแนว .or)

ประเภทข้อมูลใน Keychain

iOS Keychain รองรับคลาสรายการหลักสี่คลาส (kSecClass) แต่ละคลาสออกแบบมาสำหรับประเภทข้อมูลของตัวเอง การเลือกคลาสที่ถูกต้องช่วยให้การจัดระเบียบและการค้นหารายการง่ายขึ้น

kSecClassGenericPassword - รหัสผ่านทั่วไป: คลาสที่ใช้บ่อยที่สุด จัดเก็บข้อมูลไบนารีตามอำเภอใจ (Data) ด้วยคีย์เฉพาะ (kSecAttrAccount) เหมาะสำหรับโทเค็น คีย์ API รหัส PIN ไม่ต้องการสิทธิ์เพิ่มเติมในการใช้งาน

kSecClassInternetPassword - รหัสผ่านอินเทอร์เน็ต: จัดเก็บข้อมูลที่เกี่ยวข้องกับทรัพยากรเครือข่าย คุณลักษณะเพิ่มเติม: kSecAttrServer (โดเมนเซิร์ฟเวอร์), kSecAttrProtocol (https, ftp), kSecAttrPort, kSecAttrAuthenticationType iOS สามารถกรอกรหัสผ่านเหล่านี้โดยอัตโนมัติผ่าน AutoFill

kSecClassKey - คีย์การเข้ารหัส: สำหรับจัดเก็บคีย์การเข้ารหัส (AES, RSA, EC) คีย์ถูกจัดเก็บเป็น SecKeyRef ไม่ใช่ Data kSecClassCertificate - ใบรับรอง X.509 สำหรับจัดเก็บและตรวจสอบใบรับรองดิจิทัล ทั้งสองคลาสต้องการความเข้าใจเกี่ยวกับการดำเนินการเข้ารหัสและการกำหนดค่าคุณลักษณะที่ถูกต้อง

ในทางปฏิบัติ 95% ของการใช้ Keychain ในแอปมือถือครอบคลุมโดย kSecClassGenericPassword สำหรับจัดเก็บโทเค็นการยืนยันตัวตนและ kSecClassKey สำหรับจัดเก็บคีย์การเข้ารหัสส่วนตัว kSecClassCertificate ถูกใช้น้อยมาก - โดยทั่วไปในแอประดับองค์กรที่มี PKI ของตัวเอง

ตัวอย่างโค้ด: การทำงานกับ Keychain ใน Swift

มาดูตัวอย่างเชิงปฏิบัติของการทำงานกับ Keychain ใน Swift โดยใช้ Security framework แต่ละตัวอย่างรวมถึงการจัดการข้อผิดพลาดและการกำหนดค่า Protection Class ที่ถูกต้อง

การบันทึกและอ่านโทเค็น

ตัวอย่างพื้นฐานบันทึกโทเค็นการยืนยันตัวตนใน Keychain ด้วยการป้องกัน WhenUnlockedThisDeviceOnly คีย์ (kSecAttrAccount) คือตัวระบุบริการ ข้อมูล (kSecValueData) คือโทเค็นในรูปแบบ Data

swift
import Security

enum KeychainError: Error {
    case unexpectedStatus(OSStatus)
}

func saveToken(token: String, service: String) throws {
    let data = Data(token.utf8)
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrService as String: service,
        kSecAttrAccount as String: "auth_token",
        kSecValueData as String: data,
        kSecAttrAccessible as String:
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    ]
    SecItemDelete(query as CFDictionary)
    let status = SecItemAdd(query as CFDictionary, nil)
    guard status == errSecSuccess else {
        throw KeychainError.unexpectedStatus(status)
    }
}

func readToken(service: String) throws -> String {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrService as String: service,
        kSecAttrAccount as String: "auth_token",
        kSecReturnData as String: true,
        kSecMatchLimit as String: kSecMatchLimitOne
    ]
    var result: AnyObject?
    let status = SecItemCopyMatching(
        query as CFDictionary, &result
    )
    guard status == errSecSuccess,
        let data = result as? Data else {
        throw KeychainError.unexpectedStatus(status)
    }
    return String(decoding: data, as: UTF8.self)
}

การบันทึกด้วยการผูกชีวมาตร

ตัวอย่างสาธิตการใช้ SecAccessControlCreateWithFlags เพื่อผูกคีย์กับชีวมาตร การเข้าถึงรายการแต่ละครั้งจะต้องใช้ Face ID หรือ Touch ID

swift
import LocalAuthentication

func saveWithBiometry(data: Data, key: String) throws {
    let accessControl = SecAccessControlCreateWithFlags(
        nil,
        kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
        .biometryCurrentSet,
        nil
    )

    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: key,
        kSecValueData as String: data,
        kSecAttrAccessControl as String: accessControl as Any
    ]

    SecItemDelete(query as CFDictionary)
    let status = SecItemAdd(query as CFDictionary, nil)
    guard status == errSecSuccess else {
        throw KeychainError.unexpectedStatus(status)
    }
}

การแชร์ Keychain ระหว่างแอป

ตัวอย่างแสดงการกำหนดค่า Access Group สำหรับการเข้าถึง Keychain ร่วมกันระหว่างแอปของนักพัฒนาคนเดียวกัน ต้องใช้สิทธิ์ keychain-access-groups

swift
// Capabilities: Keychain Sharing เปิดใช้งานแล้ว
// App IDs: group.com.example.shared

func saveSharedToken(token: Data) {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: "shared_token",
        kSecValueData as String: token,
        kSecAttrAccessGroup as String:
            "group.com.example.shared",
        kSecAttrAccessible as String:
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly
    ]
    SecItemAdd(query as CFDictionary, nil)
}

แนวปฏิบัติที่ดีที่สุดสำหรับการทำงานกับ Keychain

การใช้ iOS Keychain อย่างถูกต้องต้องปฏิบัติตามกฎสำคัญหลายข้อที่ป้องกันช่องโหว่ทั่วไปและการสูญเสียข้อมูล

ใช้ ThisDeviceOnly สำหรับความลับการยืนยันตัวตนทั้งหมด: kSecAttrAccessibleWhenUnlockedThisDeviceOnly รับประกันว่าโทเค็นจะไม่ไปอยู่ใน iCloud Backup หากผู้โจมตีเข้าถึงการสำรองข้อมูล ข้อมูล Keychain ที่มีแฟล็กนี้จะไม่พร้อมใช้งาน ข้อยกเว้นคือข้อมูลที่ควรพร้อมใช้งานบนอุปกรณ์ทั้งหมดของผู้ใช้ (เช่น คีย์การเข้ารหัสสำหรับบริการที่เป็นกรรมสิทธิ์) ซึ่งใช้ kSecAttrAccessibleWhenUnlocked ร่วมกับ kSecAttrSynchronizable

อย่าจัดเก็บรหัสผ่านดิบ - จัดเก็บแฮชหรือโทเค็นเซสชัน Apple Security Guide (2025) แนะนำไม่ให้บันทึกรหัสผ่านผู้ใช้ใน Keychain ในรูปแบบข้อความธรรมดา ให้บันทึกโทเค็นรีเฟรชที่ได้รับจากเซิร์ฟเวอร์หลังจากการยืนยันตัวตนที่สำเร็จผ่าน OAuth 2.0 แทน รหัสผ่านใช้สำหรับรับโทเค็นเท่านั้นและถูกลบออกจากหน่วยความจำทันที

จัดการข้อผิดพลาด Keychain อย่างถูกต้อง: การดำเนินการ Keychain แต่ละครั้งส่งคืน OSStatus ที่ต้องตรวจสอบ ให้ความสนใจเป็นพิเศษกับ errSecItemNotFound (โทเค็นหมดอายุหรือถูกลบ) และ errSecAuthFailed (ชีวมาตรล้มเหลว) ในกรณีแรก แอปควรขอการยืนยันตัวตนใหม่ ในกรณีที่สอง แสดงวิธีอื่นให้ผู้ใช้ (รหัสผ่าน) อย่าละเลยสถานะ errSecItemNotFound - จะทำให้แอปขัดข้องเมื่อพยายามอ่าน nil

ทดสอบ Keychain บนอุปกรณ์จริง: ตัวจำลองไม่มี Secure Enclave และไม่รองรับ ACL ทางชีวมาตร ตรวจสอบสถานการณ์เสมอ: การเปิดใช้ครั้งแรก การกู้คืนจากการสำรองข้อมูล การเปลี่ยนรหัสผ่านอุปกรณ์ การลบและติดตั้งแอปใหม่ บนอุปกรณ์จริง Keychain จะคงอยู่เมื่อแอปถูกลบ แต่เฉพาะในกรณีที่ไม่ได้ใช้แฟล็ก kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly ซึ่งจะถูกล้างเมื่อรหัสผ่านถูกลบ

ลดจำนวนการดำเนินการ Keychain: การอ่านหรือเขียนแต่ละครั้งเป็นการเรียกไปยังบริการระบบ Securityd ซึ่งสามารถบล็อกเธรดได้ แคชโทเค็นที่อ่านแล้วในหน่วยความจำระหว่างเซสชันและเข้าถึง Keychain อีกครั้งเมื่อรีสตาร์ทแอปหรือข้อผิดพลาดการยืนยันตัวตน (401 จากเซิร์ฟเวอร์) เท่านั้น iOS จะล็อก Keychain โดยอัตโนมัติเมื่ออุปกรณ์ถูกล็อก ดังนั้นให้วางแผนการอ่านผ่าน LAContext ด้วยคำขอชีวมาตร

คำถามที่พบบ่อย

ฉันสามารถบันทึกข้อมูลใน Keychain และอ่านหลังจากรีบูตได้หรือไม่?

ได้ ใช้คลาสการป้องกัน kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly หรือ kSecAttrAccessibleAfterFirstUnlock ข้อมูลจะพร้อมใช้งานหลังจากปลดล็อกอุปกรณ์ครั้งแรกหลังรีบูต สำหรับการเข้าถึงอัตโนมัติเมื่อเปิดแอป (โดยไม่รอการปลดล็อก) ให้ใช้ kSecAttrAccessibleAlways แต่จะลดความปลอดภัย

จะล้าง Keychain เมื่อผู้ใช้ออกจากระบบได้อย่างไร?

เรียก SecItemDelete ด้วยคำค้นหาที่มี kSecClass สำหรับแต่ละประเภทข้อมูล สำหรับการล้างรายการแอปทั้งหมดอย่างสมบูรณ์ ให้ดำเนินการ: SecItemDelete([kSecClass as String: kSecClassGenericPassword] as CFDictionary) ทำซ้ำสำหรับ kSecClassKey, kSecClassCertificate และ kSecClassInternetPassword

ความแตกต่างระหว่าง kSecAttrAccessible และ kSecAttrAccessControl คืออะไร?

kSecAttrAccessible กำหนดว่าข้อมูลพร้อมใช้งานเมื่อใด (เมื่อปลดล็อก หลังจากปลดล็อกครั้งแรก ฯลฯ) kSecAttrAccessControl กำหนดว่าใครสามารถเข้าถึงได้ (ชีวมาตร รหัสผ่าน การยืนยันตัวตนใดๆ) รวมกัน: อันดับแรก Protection Class จากนั้น ACL ตัวอย่างเช่น ข้อมูลพร้อมใช้งานเมื่อปลดล็อกเท่านั้น และหลังจาก Face ID เท่านั้น

ทำไม SecItemCopyMatching ถึงส่งคืน errSecItemNotFound?

สาเหตุ: ไม่เคยบันทึกรายการ, รายการถูกลบเมื่อลบรหัสผ่าน (หากใช้ kSecAttrAccessibleWhenPasscodeSet), แอปถูกติดตั้งใหม่ (Keychain คงอยู่แต่ไม่ถูกกู้คืนจากการสำรองข้อมูลบนอุปกรณ์ใหม่), Access Group หรือตัวระบุทีมนักพัฒนาเปลี่ยนแปลงไป ตรวจสอบ kSecAttrService และ kSecAttrAccount

จะตรวจสอบว่าอุปกรณ์รองรับชีวมาตรใน Keychain ได้อย่างไร?

ใช้ LAContext จาก LocalAuthentication: เรียก context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) หากส่งคืน true - อุปกรณ์รองรับ Touch ID หรือ Face ID สำหรับ ACL Keychain ให้ใช้แฟล็ก biometryCurrentSet (เฉพาะข้อมูลชีวมาตรปัจจุบัน) หรือ biometryAny (ข้อมูลที่ลงทะเบียนก่อนหน้านี้)

สรุป

  • iOS Keychain คือพื้นที่จัดเก็บที่ป้องกันด้วยฮาร์ดแวร์สำหรับความลับด้วยการเข้ารหัสผ่าน Secure Enclave และควบคุมการเข้าถึงผ่าน ACL
  • Security framework ให้ฟังก์ชัน SecItemAdd, SecItemCopyMatching, SecItemUpdate และ SecItemDelete สำหรับทำงานกับรายการ
  • Protection Class (kSecAttrAccessible) ถูกเลือกตามสถานการณ์: WhenUnlockedThisDeviceOnly เป็นมาตรฐานสำหรับโทเค็น
  • ACL ด้วยชีวมาตร (kSecAttrAccessControl) เพิ่มข้อกำหนด Face ID หรือ Touch ID สำหรับการอ่านแต่ละครั้ง
  • kSecClassGenericPassword ครอบคลุม 95% ของกรณี - จัดเก็บโทเค็น คีย์ API รหัส PIN และบันทึก
  • ThisDeviceOnly ป้องกันการคัดลอกความลับไปยัง iCloud Backup - บังคับสำหรับโทเค็นการยืนยันตัวตน
  • การจัดการ OSStatus ที่ถูกต้องและการทดสอบบนอุปกรณ์จริง เป็นแนวปฏิบัติที่จำเป็นสำหรับการใช้ Keychain ที่เชื่อถือได้

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม