📄
목차
Keychain 개념
Keychain 개념
- Apple에서 공식적으로 제공하고 있는 보안 프레임워크
- 암호화된 Data Base
- 사용자의 민감한 데이터를 저장
- UserDefaults는 App이 삭제되면 같이 삭제되지만, Keychain은 그와 반대로 App이 삭제돼도 데이터 유지
- Keychain은 중복된 값을 새로운 값이 자동으로 덮어씌우지 못함. 따라서 항상 기존의 값을 삭제 해주어야 함
Keychain Item
Keychain Item
- Keychain에 데이터를 저장할 때, 데이터를 Wrapping해서 Item형태로 저장
- Data & Attribute 형태 → Item
- Attribute를 통해 데이터를 검색 및 접근
Keychain 속성(kSecClass)
Keychain 속성(kSecClass)
💥 kSecClass : 저장된 Item이 어떤 정보를 가지고 있는지 나타낸다.
💥 각 암호화 데이터 별로 다른 Attribute를 가진다.
💥 k- 접두어는 [konstant = constant] 이므로 붙는다.
- kSecClassGenericPassword : 일반 암호 항목
- kSecClassInternetPassword : 인터넷 비밀 항목
- kSecClassCertificate : 인증서 항목
- kSecClassIdentity : 아이디 항목
- kSecClassKey : 암호화 키 항목
- kSecClass : 데이터 종류 지정
- kSecAttrAccount : 데이터 저장하기 위한 Key 입력 [개인키]
- kSecAttrService: 데이터 저장하기 위한 Key 입력 [공개키]
- kSecValueData : 저장할 데이터를 Data Type으로 캐스팅, 실제 저장할 값
- kSecReturnAttributes : 값이 항목 속성을 반환하는 것에 대한 여부
- kSecReturnData : 값이 항목 데이터를 반환하는 것에 대한 여부
- kSecValueData : update할 value
〰️ 등 등 더 많은 속성은 공식 문서를 통해 확인할 수 있습니다 〰️
Keychain 사용
Keychain 사용
SecItemAdd
- SecItemAdd 메소드를 호출하고 Keychain에 Dictionary를 추가
- 결과 값으로 Bool Type 반환됨
- 중복된 Key 값으로 추가될 경우에는 이 전 값을 삭제하던가 updateItem해서 업데이트 해준다.
func addItem(id: Any, password: Any) -> Bool {
// Keychain Query 정의
let addQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: id,
kSecValueData: (password as AnyObject).data(using: String.Encoding.utf8.rawValue) as Any]
let result: Bool = {
let status = SecItemAdd(addQuery as CFDictionary, nil)
if status == errSecSuccess {
return true
} else if status == errSecDuplicateItem {
return updateItem(value: pwd, key: id)
}
print("addItem Error : \(status.description))")
return false
}()
return result
}
SecItemCopyMatching
- SecItemCopyMatching 메소드 호출하고 Keychain에 Key값을 조회
- 결과 값으로는 원하는 형태로 Data를 캐스팅하여 반환
func readItems(key: Any) -> String? {
let query: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key,
kSecReturnAttributes: true,
kSecReturnData: true]
var item: CFTypeRef?
let result = SecItemCopyMatching(query as CFDictionary, &item)
if result == errSecSuccess {
if let existingItem = item as? [String: Any],
let data = existingItem[kSecValueData as String] as? Data,
let password = String(data: data, encoding: .utf8) {
return password
}
}
print("readItems Error : \(result.description)")
return nil
}
SecItemUpdate
- SecItemUpdate 메소드 호출하고 update된 결과 값을 반환
- update할 상황은 Key값이 동일한 상태에서 Value를 최신화 시켜주는 것
- 따라서, 직전의 Keychain Query 정보를 Dictionary 형태로 담아주고 Update할 Query Dictionary와 함께 SecItemUpdate에 전달
func updateItem(value: Any, key: Any) -> Bool {
let previousQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key]
let updateQuery: [CFString: Any] = [kSecValueData: (value as AnyObject).data(using: String.Encoding.utf8.rawValue) as Any]
let result: Bool = {
let status = SecItemUpdate(previousQuery as CFDictionary, updateQuery as CFDictionary)
if status == errSecSuccess { return true }
print("updateItem Error : \(status.description)")
return false
}()
return result
}
SecItemDelete
- Keychain 삭제를 위한 Query를 작성하고 SecItemDelete 메소드 호출
- 매칭되는 Key 값의 Keychain을 Update하여 결과 값을 반환
func deleteItem(key: String) -> Bool {
let deleteQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key]
let status = SecItemDelete(deleteQuery as CFDictionary)
if status == errSecSuccess { return true }
print("deleteItem Error : \(status.description)")
return false
}
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
if KeyChain.shared.addItem(id: "honggildong", pwd: "141433") {
valueLabel.text = "addItem Success!!!"
print("addItem Success!!!")
}
}
@IBAction func tapOnButton(_ sender: Any) {
if KeyChain.shared.deleteItem(key: "honggildong") {
valueLabel.text = "삭제 성공"
}
}Keychain Error Codes
Keychain Error Codes
| Error Code | Error Value | Error Description |
|---|---|---|
| errSecSuccess | 0 | No error encountered 오류가 발생하지 않았습니다. |
| errSecUnimplemented | -4 | Function or operation not implemented 구현되지 않은 기능 및 작업이 있습니다. |
| errSecParam | -50 | One or more parameters passed to the function were not valid 함수에 전달된 하나 이상의 매개변수가 유효하지 않습니다. |
| errSecAllocate | -108 | Failed to allocate memory 메모리 할당에 실패 하였습니다. |
| errSecNotAvailable | -25291 | No trust results are available 신뢰할 수 있는 결과가 없습니다. |
| errSecAuthFailed | -25293 | Authorization / authentication Failed 승인 / 인증 실패 하였습니다. |
| errSecDuplicateItem | -25299 | The item already exists 항목이 이미 존재합니다. |
| errSecItemNotFound | -25300 | The item cannot be found 항목을 찾을 수 없습니다. |
| errSecInteractionNotAllowed | -25308 | Interaction with the Security Server is no allowed 보안 서버와의 상호 작용이 허용되지 않습니다. |
| errSecDecode | -26275 | Unable to decode the provided data 제공된 데이터를 디코딩할 수 없습니다. |
Keychain OpenSource
Keychain OpenSource
💾 KeychainSwift
- 위와 같이 Apple에서 기본적으로 제공해주는 메소드들만으로도 Keychain을 구성할 수 있다.
- 하지만, 더욱 간편하게 사용할 수 있는 오픈소스가 있다.
- Podfile에 KeychainSwift를 install 해준다.
- 프로젝트를 열고 KeychainSwift를 import & 인스턴스 생성을 한다.
- 인스턴스를 통해 get, set, delete, clear 등의 메소드를 사용한다.
- 자세한 내용은
Github Page를 통해 안내하겠습니다.
번외 및 마무리
번외 및 마무리
- Keychain라고 해서 무조건 앱을 삭제해도 데이터가 유지되는 것은 아니다.
- iOS 10.3.3 이상 기기에서 iTunes & iCloud 백업 / 복원을 했을 때, 사라지는 현상이 발생한다고 한다.
- iTunes 백업 / 복원 상황에서는
kSecAttrAccessible설정을 해주면 사라지지 않을 수 있다.
- 다만, iCloud 백업 / 복원 상황에서 사용자가 iCloud 설정 > Keychain 백업 옵션을 OFF 해놓았다면, 삭제될 수 있다.
- 확실한 암호화 & 복호화 방법을 사용하는 솔루션을 사용하거나, 서버를 이용하는 것이 보다 안전할 것이라고 생각한다.
- 위에 작성한 예시들 뿐만 아니라, 다른 Class Type들은 어떻게 사용할 수 있을지에 대한 고민도 필요하다고 생각한다.
References
References
📚 Apple Document
Apple Developer Documentation
⚠️ Error Codes
iOS Components and Frameworks: Understanding the Advanced Features of the iOS SDK
Keychain Error Codes The Keychain can return several specialized error codes depending on any issues encountered at runtime. These errors are described in Table 18.3. Table 18.3 Keychain Error ... - Selection from iOS Components and Frameworks: Understanding the Advanced Features of the iOS SDK [Book]
🐻 Open Source
https://github.com/evgenyneu/keychain-swift
📝 Keychain Example
[iOS] 키체인 (Keychain Service)
안녕하세요~ 차니에요! 오늘은 키체인에 대해 알아보겠습니다~~! 1. 키체인이란? Apple에서 공식으로 제공하는 보안 프레임워크이며, 사용자의 민감한(개인 정보 등) 데이터들을 저장하는 저장소입니다. 키체인은 사용자가 직접 제거하지 않는 한, 앱을 제거해도 키체인 데이터는 남아있고 디바이스가 lock되면 키체인도 함께 lock되며 디바이스가 unlock되면 키체인도 unlock된다는 특징이 있습니다. 키체인은 하나 이상의 Keychain Item을 갖습니다.

Uploaded by N2T

