아이폰 유저라면 한 번쯤은 키체인 로그인을 사용해봤을 것 같습니다. 저는 이번 동아리 프로젝트에서, 그리고 스타트업과 계약해서 진행하고 있는 다른 프로젝트에서 자동로그인 기능을 구현해야하는 상황이 생겼는데요!
사실 자동로그인이라길래 처음에는 로그인 후 받은 token을 저장하거나, 아이디와 비밀번호를 UserDefaults로 저장해서 사용하면 되는건가? 하고 생각했는데, 그렇게 하면 거의 뭐 보안이 💩..ㅋㅋㅋ UserDefaults는 데이터를 있는 그대로 저장하기 때문에 개인정보를 UserDefaults로 저장하게 되면 정말 보안이 취약해집니다!!! 그렇다고 개인정보를 직접 암호화해서 저장하기에는 많이 복잡해지죠ㅠㅠ
그래서 키체인을 사용하려합니다
키체인은 암호화된 데이터베이스로써, 사용자의 Mac, 앱, 웹 사이트 계정이나 신용 카드 번호 등의 중요한 정보들을 암호화하여 안전하게 저장합니다. 그리고 이 암호화되어 저장된 데이터에 쉽게 접근할 수 있도록 도와줍니다.
암호화된 데이터가 없다면, 유저가 입력한 정보가 유효한지 인증한 후에 키체인 아이템으로 저장합니다. 만약 암호화된 데이터가 있다면, 그 정보다 유효한지 검사합니다. 여기서 유효하다면 키체인 로그인 과정은 끝나게 되고, 만약 유효하지 않다면 다시 유저가 정보를 입력하도록 하여 정보가 유효한지 검사한 후에 키체인 아이템을 다시 업데이트 하게 됩니다. 이 과정을 그림으로 나타낸다면 아래와 같겠죠??
기본적으로 애플리케이션은 자기 자신의 키체인에만 접근할 수 있습니다. iOS에서 키체인의 위치는 샌드박스 외부이므로, 앱을 삭제해도 키체인에 저장된 정보는 삭제되지 않습니다. 키체인 그룹을 사용하면 서로 다른 앱에서도 저장된 데이터를 공유할 수 있고, 비밀번호나 개인키와 같이 보호가 필요한 항목은 암호화되어 키체인에 저장됩니다.
여기서 샌드박스란 미국에서 어린아이를 보호하기 위해 모래통에서만 놀도록 하는데에서 유래한 보안 모델을 말합니다. iOS 시스템의 sandbox는 기본적으로 앱마다 별도의 파일을 생성하여 공유되지 않도록 하여 외부로부터 접근할 수 없도록 막는 보안 형태를 말합니다.
App Sandbox가 적용되지 않은 App은 앱을 실행하는 사용자의 모든 권한을 가지며, 사용자가 모든 리소스에 접근할 수 있습니다. 아래 그림을 보면 그 차이를 느끼실 수 있겠죠?
그렇다면 키체인은 어떻게 이루어져있을까?
일단 키체인은 단순히 파일 시스템에 저장된 데이터베이스라고 생각할 수 있습니다. iOS에서는 모든 앱에서 사용할 수 있는 하나의 키체인만을 제공하고, macOS에서는 단순히 애플리케이션이 원하는만큼 키체인을 만들 수 있죠.
키체인을 구성하는 데에는 크게 3가지 요소가 있습니다.
- Key Chain Item: Key Chain에 저장되는 데이터.
- Item Class: 키체인 아이템에 저장되는 데이터의 종류를 지정하는 역할
- Attribute: Item Class에 대한 속성을 저장
키체인은 여러개의 키체인 아이템을 가질 수 있고, 아이템 클래스를 통해 저장되는 데이터의 종류를 지정할 수 있습니다. 대표적으로 웹 사이트용 아이디와 비밀번호를 저장할 때는 kSecClassInternetPassword를 사용하고, 인증서를 저장할 때는 kSecClassCertificate, 일반 비밀번호를 저장할 때는 kSecClassGenericPassword를 사용합니다.
그리고 이런 Item Class 별로 존재하는 다양한 attribute들을 통해 속성을 지정하여 사용합니다. 만약 여러 개의 계정을 가질 수 있는 서비스에서 각 계정에 대한 token을 관리한다면, Item Class로 kSecClassGenericPassword를 사용하고, 필요한 attribute들을 설정하면 됩니다. 대표적으로 어떤 앱에서 사용되는 token인지 표시하는 kSecAttrService, 어떤 사용자의 인증토큰인지 식별하는데에 사용되는 kdSecAttrAccount 등이 있습니다.
주요 Item Class 및 Attributes
- Item Class
- kSecClassGenericPassword
- kSecAttrService: 키체인 아이템과 연관되어 있는 서비스의 이름
- kSecAttrAccount: 저장할 아이템의 계정 이름 (아이디)
- kSecAttrGeneric: 저장할 아이템의 데이터 (비밀번호)
- kSecClassInternetPassword
- kSecAttrAccount: 저장할 아이템의 계정 이름 (아이디)
- kSecClassCertificate
- kSecClassKey
- kSecClassIdentity
- kSecClassGenericPassword
- Attributes
- kSecMatchLimit: 키의 값을 저장할 경우, 이 값은 반환하거나 다른 조치를 취할 최대 결과 수를 지정
- kSecMatchLimitOne
- kSecMatchLimitAll
- kSecReturnAttributes: 키의 값으로 true를 저장할 경우, CFDictionary 타입으로 반환
- kSecReturnData: 키의 값으로 true를 저장할 경우, CFData 타입으로 반환
- kSecMatchLimit: 키의 값을 저장할 경우, 이 값은 반환하거나 다른 조치를 취할 최대 결과 수를 지정
그럼 이제 키체인 기능들을 구현해보자!
생성
SecItemAdd(_:_:) 함수를 사용해 키체인 아이템을 생성하고, 성공하면 true를 반환합니다.
조회
SecItemCopyMatching(_:_:) 함수를 사용해 키체인 아이템을 조회하고, 성공하면 User를 반환합니다.
수정
SecItemUpdate(_:_:) 함수를 사용해 키체인 아이템을 수정하고, 성공하면 true를 반환합니다.
삭제
SecItemDelete(_:) 함수를 사용해 키체인 아이템을 삭제하고, 성공하면 true를 반환합니다.
+ 추가적으로 FaceID도 구현해보았습니다.
생체인식 ID 구현을 하기 위해서는 info.plist에 Privacy - Face ID Usage Description 을 추가해야합니다.
사용 기기가 생체인식 ID를 지원하는지 확인
생체인식 ID 인증 과정
Reference
'iOS > iOS' 카테고리의 다른 글
UIResponder (0) | 2021.04.16 |
---|---|
첫 테스트코드를 작성해보다. (0) | 2021.04.14 |
GCD (Grand Central Dispatch) (0) | 2021.03.23 |
XCTest tips and tricks that can level up your Swift testing (0) | 2021.03.03 |
Frame과 Bounds (0) | 2021.02.26 |
댓글