[iOS] KeyChain

Youngwoo Lee·2021년 6월 27일
2

iOS

목록 보기
34/46
post-thumbnail

KeyChain

OAuth 기반 서버에서 인증이 필요한 API를 호출할 경우 Access Token을 사용해서 호출하는데, 해당 Access Token 을 발급받았을 경우 어디에 저장을 할까?

UserDefaults 나 다른 방법을 이용하는 경우에는, 암호화 과정이 거쳐지지 않아서 좋지 않다

이럴 경우 KeyChain을 활용한다

KeyChain Services

키체인은 사용자의 Mac, 앱, 서버 및 웹 사이트 계정과 암호 및 신용 카드 번호 또는 은행계좌 PIN 번호와 같은 중요 정보를 암호화하여 안전하게 저장한다

  • Passwords, Cryptographic keys, Certs & identities, Notes 등을 암호화해서 저장해둘 수 있는 열쇠 묶음
  • password뿐만 아니라, 알아야하는 정보인 신용카드나 note도 저장할 수 있고, 인식할 필요는 없지만 필요한 것(보안통신에 있어서 필요한 정보, 다른 유저나 디바이스와 신뢰를 쌓기 위해서 필요한 정보)도 저장가능!
  • 앱을 삭제해도 키체인 정보는 남아있다

Securely store small chunks of data on behalf of the user
The keychain services API helps you solve this problem by giving your app a mechanism to store small bits of user data in an encrypted database called a keychain. When you securely remember the password for them, you free the user to choose a complicated one.

키 체인은 애플 계열의 운영체제에서 동작하는 다양한 응용 프로그램에서 비밀번호나 계정 등 보안이 필요한 요소를 저장하는데 사용되는 암호화된 저장소이다. iOS뿐만 아니라, macOS, tvOS, watchOS 등에서도 모두 제공된다. 사용하는 곳이 생각보다 많아서, iCloud의 로그인 정보가 키 체인을 통해 관리되고 있고, 와이파이의 패스워드도 키 체인에 저장되며, 사파리에서 웹 사이트별 패스워드를 관리할 때에도 키 체인이 사용된다

ref) https://developer.apple.com/documentation/security/keychain_services


키체인의 특징

  1. 기본적으로 App은 자기 자신의 키 체인에만 접근할 수 있다
  2. iOS에서 키 체인의 위치는 샌드박스(외부에서 받은 파일을 바로 실행하지 않고 보호된 영역에서 실행시켜 봄으로써 잘못된 파일과 프로그램이 내부시스템 전체에 악영향을 주는 것을 미연에 방지하는 기술) 외부이므로, 앱을 삭제해도 키 체인에 저장된 정보는 삭제되지 않는다
  3. 앱의 프로비저닝 파일을 이용해서 앱 간의 사용 경로를 구분하기 때문에, 동일한 앱이라도 프로비저닝 파일을 변경해서 빌드하면 기존 정보를 더 이상 조회할 수 없다.
  4. 키 체인 그룹을 사용하여 서로 다른 앱에서도 저장된 데이터를 공유할 수 있다
  5. 비밀번호 또는 개인 키처럼 보호가 필요한 항목은 암호화되어 키 체인으로 보호되며, 인증서처럼 보호가 필요하지 않은 항목은 암호화되지 않은 채로 저장된다
  6. 키 체인은 잠글 수 있어서, 잠기면 해제하기 전까지 저장된 데이터에 접근할 수 없지만, iOS에서는 기기의 잠금이 해제되는 순간 키 체인의 잠금도 함께 해제된다.

샌드박스
외부에서 받은 파일을 바로 실행하지 않고 보호된 영역에서 실행시켜 봄으로써 잘못된 파일과 프로그램이 내부시스템 전체에 악영향을 주는지 확인하는 기술. 이를 확장해서 iOS에서는 애플리케이션 간에 데이터 공유가 불가능하도록 격리된 각자의 샌드박스 공간을 제공하는데, iOS 시스템 자체에는 파일을 함부로 쓸 수 없지만 샌드박스 내에서는 파일 쓰기가 허용된다
-> 망할거면 혼자 망해라 식으 운영 방법



Keyed Archiver, User Defaults, CoreData와 다른 점은 무엇일까? (사용 목적에 따라 구분될 수 있을 것 같음)

Keyed Archiver

An encoder that stores an object’s data to an archive referenced by keys.

  • https://developer.apple.com/documentation/foundation/nskeyedarchiver/
  • 객체같은 사용자 정의 타입을 UserDefaults에 데이터의 형태로 저장
  • NSCoding 프로토콜을 채택하고 NSKeyedArchiver, NSKeyedUnarchiver 인코딩/디코딩 하여 사용
  • 앱을 삭제하면 함께 삭제됨
  • 인스턴스의 정보를 시스템에 저장
  • 딕셔너리와 같이 key-value 쌍으로 저장하기 위해 썼던 클래스
  • Objective-C에서 사용하기 위해 설계 되었지만 현재도 사용할 수 있음.
  • Swift 에서는 사용하는 일이 많이 없다
  • Serialization - 인스턴스를 파일 형태로 저장하기 위한 클래스
  • key-value 형태로 아카이빙
  • 암호화 지원하지 않음

UserDefaults

An interface to the user’s defaults database, where you store key-value pairs persistently across launches of your app.

CoreData

Persist or cache data on a single device, or sync data to multiple devices with CloudKit.

  • https://developer.apple.com/documentation/coredata/
  • 복잡하고 큰 데이터를 저장
  • 앱이 많은 데이터를 필요로 하고 여러 다른 객체 간의 관계를 관리하고 객체에 빠르고 쉽게 접근해야한다면 CoreData 를 사용하는 것이 좋다.
  • CoreData의 역할
    • Persistence - 데이터 지속 관리
    • Undo and Redo of individual or Batched Changes - 데이터 변경사항에 대한 실행취소/재실행 기능
      • 코어데이터의 변경 사항을 추적하여 이에 대한 취소작업이 가능
    • Background Data Tasks - 백그라운드 상의 데이터 작업 지원
    • View Synchronization - 뷰 동기화
      • 테이블뷰/ 컬렉션뷰 등의 UI에게 섹션, 행, 열 아이템을 관리해주는 DataSource를 제공하여 뷰와 데이터가 동기화 되도록 함
    • Versioning and Migration - 버전 관리 및 데이터 이전 기능
    • 오프라인 활용
    • undo, redo 이용

개략적인 비교

  • Though core data is slightly more complicated, it is useful when the stored information requires structure
  • NSKeyedArchiver is less complex and slower than core data, but is much simpler to use
  • UserDefaults is the simplest method to persist data



iOS의 키체인과 macOS의 키체인의 차이는?

In iOS, apps have access to a single keychain (which logically encompasses the iCloud keychain). This keychain is automatically unlocked when the user unlocks the device then locked when the device is locked. An app can access only its own keychain items, or those shared with a group to which the app belongs. It can't manage the keychain container itself.

In macOS, however, the system supports an arbitrary number of keychains. You typically rely on the user to manage these with the Keychain Access app and work implicitly with the default keychain, much as you would in iOS. Nevertheless, the keychain services API does provide functions that you can use to manipulate keychains directly. For example, you can create and manage a keychain that is private to your app. On the other hand, robust access control mechanisms typically make this unnecessary for anything other than an app trying to replicate the keychain access utility.

  • 키체인의 개수가 다르다 (1개 vs 여러개)
  • macOS는 앱마다 다른 keychain을 사용할 수도 있고, iOS같이 기본 keychain을 다 같이 사용할 수도 있다
  • macOS는 keychain services API가 직접적으로 keychain을 관리할 수 있는 기능을 제공한다.

KeyChain의 구조

  • 단순하게도 키 체인은 파일 시스템에 저장된 데이터베이스이다. SQLite 데이터베이스로 구현되어 있다
  • macOS에서 사용자나 애플리케이션은 원하는 만큼 키 체인을 만들 수 있지만,

But, iOS에서는 모든 앱에서 사용할 수 있는 하나의 키 체인만 사용한다


  1. 키 체인 아이템(Key chain Item) : 키 체인에 저장되는 데이터로, 키 체인은 여러 개의 키 체인 아이템을 가질 수 있다
  2. 아이텀 클래스(Item class) : 저장할 데이터의 종류이다.
    • ID/PW, 인증서, 인터넷 비밀번호 및 클래스로는 인터넷용 아이디 패스워드를 저장할 때 사용하는 kSecClassInternetPassword
    • 인증서를 저장할 때 사용하는 kSecClassCertificate
    • 일반 비밀번호를 저장할 때 사용하는 kSecClassGenericPassword 등이 있습니다
  3. 어트리뷰트(Attributes) : 아이템 클래스에 대한 속성이다. 아이템 클래스에 따라 설정할 수 있는 어트리뷰트의 종류가 달라진다

키 체인 아이템을 정의할 때에는 저장할 데이터에 맞는 아이템 클래스를 선택해야 한다. 각 아이템 클래스는 저장값의 특성에 따라 서로 다른 어트리뷰트를 제공하기 때문에...

예를 들자면)

kSecClassGenericPassword 라는 아이템 클래스를 통해서 인증 토큰을 저장하려고 하는데, 여기에는 핵심 어트리뷰트가 kSecAttrAccount / kSecAttrService 가 있다

  • kSecAttrAccount : 앱을 식별할 수 있는 서비스 아이디
  • kSecAttrService : 저장할 비밀번호에 대한 사용자 계정

그래서 키 체인은 이 두개의 어트리뷰트를 메인 키로 하여 저장된 비밀번호를 식별한다.

키체인 서비스를 사용하기 위해 k- 접두어를 사용하는 여러 타입과 값을 사용합니다

k- 접두어의 비밀은?

상수의 의미로 표현되는것 (변하지 않는 값) https://green1229.tistory.com/56

https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFDesignConcepts/Articles/NamingConventions.html#//apple_ref/doc/uid/20001110-CJBEJBHH

Core Foundation 등의 Core Framework 헤더파일들을 보면, 헝가리언 네이밍 규칙을 따른 흔적들을 제법 볼 수 있다. 일단 'k' 는 헝가리언 네이밍에 따라 사용된 걸로 보인다. Constants 의 'c' 는 이미 헝가리안에서 'char' 의 'c' 로 예약이 되어 있는 상황이니 중복을 피하기 위해 동일한 발음기호인 'k' 를 사용한 것으로 추측된다. Core Foundation 의 역사를 고려하면 헝가리언 네이밍을 따른것이 어느정도 이해가 된다.

https://metalkin.tistory.com/20

어떤 프레임워크의 값일까?

CoreFoundation

그 프레임워크와 Foundation 프레임워크와의 차이는?

키체인은 언제 사용하면 좋을까?

  • 로그인 비밀번호
  • 결제 데이터
  • 암호화를 위한 키

키 체인 작업에 사용되는 코드

앞에서 말했듯이, KeyChain은 파일 시스템에 저장된 데이터베이스와 크게 다를 것이 없는데, 그래서 데이터베이스의 핵심인 CRUD에 크게 벗어나지 않는다. 그러니깐, 이것에 대응되는 메소드가 쓰인다는 것이겠지??

  • Create : SecItemAdd
  • Read : SecItemCopyMatching
  • Update : SecItemUpdate
  • Delete : SecItemDelete
  • 키 체인 쿼리(Key Chain Query)

위 메소드들은 모두 C스타일로 코딩되어 있으며, 키 체인 쿼리 라고 불리는 CFDictionary 타입의 데이터 집합을 인자값으로 받아 사용합니다. 데이터베이스로 치자면 테이블과 키 값, 저장할 내용 등이 모두 어우러진 SQL문에 해당하는 셈이다. 우리는 저장할 데이터, 아이템 클래스, 서비스명 등을 키 체인 쿼리에 정의한 다음, 목적에 맞는 함수를 호출하면 원하는 CRUD 작업을 처리하게 됩니다.

import Foundation
import Security

let keyChainQuery: NSDictionary = [
	kSecClass: <아이템 클래스>,
	kSecAttrService: <서비스 아이디>,
	kSecAttrAccount: <사용자 계정>,
	kSecValueData: <저장할 값>
]

//기존에 저장된 값 삭제해주기
SecItemDelete(keyChainQuery)

//새로운 값 추가
SecItemAdd(keyChainQuery, nil)
profile
iOS Developer Student

0개의 댓글