---
# System prepended metadata

title: KeyChain 230813 Toyo study
tags: [study]

---

### KeyChain Data 저장하기
- KeyChain에 Data를 저장하기 위해 필요한 요소에는 무엇이 있는지 확인해봅시다.
    - Data, Attribute, KeychainItem은 서로 어떤 관계일까요?
        : `Data`는 저장하고 싶은 정보, `Attribute`는 데이터에 대한 접근성을 제어하고 검색을 위한 공개된 속성, `keychainItem`은 이 두 값을 모두 포함한 아이템 
        ![](https://hackmd.io/_uploads/S19UW48h2.png)
    - 우리가 메인 화면에서 비밀번호를 만들어, Data로 저장하고 싶다면, 어떤 과정을 거쳐야 할까요?
        : `kSecClass`를 정해준 뒤 `kSecValueData`에 저장하고 싶은 데이터를 `Data`타입으로 변환하여 `Item query`를 만듬
    - 필요한 KeychainItem의 각 Attribute가 어떤 의미를 가지는지 이해해봅시다.
        - `kSecClass`는 저장하는 데이터의 종류
        - `kSecAttrAccount`는 계정이름

```swift 
static func addPassword(password: String) {
    let password = password.data(using: .utf8)
    
    let addquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                   kSecValueData as String: password]
    
    let status = SecItemAdd(addquery as CFDictionary, nil)
    
    if status == errSecSuccess {
        print("비밀번호 등록 성공")
    } else {
        print("등록 실패")
    }
}
```

### KeyChain Data 꺼내오기
- SecItemCopyMatching 메서드의 두 매개변수를 확인해봅시다.
    - query는 무엇에 활용될까요?
        : 키체인에 저장된 `Data`를 검색하고 접근하는데 사용
    - query 를 구성하는 요소들에는 무엇이 있을까요?
        : 키체인에 `Data`를 저장할때 사용된 `Attribute`를 포함
    - result는 무엇에 활용될까요?
        : 받아온 값을 저장하는 곳

```swift 
static func receivePassword() -> String? {
    let getquery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                   kSecReturnData as String: true]
    var password: AnyObject?
    
    let status = SecItemCopyMatching(getquery as CFDictionary, &password)
    
    if status == errSecSuccess {
        guard let password = password as? Data, let password = String(data: password, encoding: .utf8) else {
            print("가져오기 실패")
            return nil
        }
        
        print("비밀번호 가져오기 성공")
        
        return password
    } else {
        print("가져오기 실패")
        
        return nil
    }
}
```

### KeyChain Data 업데이트하기
``` swift
static func updatePassword(_ changePassword: String) -> Bool {
    let changePassword = changePassword.data(using: .utf8)
    let changequery: [String: Any] = [kSecValueData as String: changePassword]
    
    let genericQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword]
    
    let status = SecItemUpdate(genericQuery as CFDictionary, changequery as CFDictionary)
    
    if status == errSecSuccess {
        print("비밀번호 변경 성공")
        return true
    } else {
        print("비밀번호 변경 실패")
        return false
    }
}
```

### 참고 링크
[🍎 Storing Keys in the Keychain](https://developer.apple.com/documentation/security/certificate_key_and_trust_services/keys/storing_keys_in_the_keychain)
[🍎 Searching for Keychain Items](https://developer.apple.com/documentation/security/keychain_services/keychain_items/searching_for_keychain_items)
[🍎 Updating and Deleting Keychain Items](https://developer.apple.com/documentation/security/keychain_services/keychain_items/updating_and_deleting_keychain_items)
[🍎 Keychain Items](https://developer.apple.com/documentation/security/keychain_services/keychain_items)
[🍎 Item Attribute Keys and Values](https://developer.apple.com/documentation/security/keychain_services/keychain_items/item_attribute_keys_and_values)