직접 부팅 모드 지원

Android 7.0은 기기에 전원이 들어와 있지만 사용자가 기기의 잠금을 해제하지 않은 경우 안전한 직접 부팅 모드에서 실행됩니다. 이를 지원하기 위해 시스템에서 다음과 같은 두 가지 데이터 저장소 위치를 제공합니다.

  • 사용자 인증 정보 암호화 저장소: 기본 저장소 위치이며, 사용자가 기기의 잠금을 해제한 후에만 사용할 수 있습니다.
  • 기기 암호화 저장소: 직접 부팅 모드 시 그리고 사용자가 기기의 잠금을 해제한 후에 모두 사용할 수 있는 저장소 위치입니다.

기본적으로 앱은 직접 부팅 모드 중에는 실행되지 않습니다. 직접 부팅 모드 중에 앱이 작동해야 하는 경우, 이 모드 중에 실행해야 할 앱 구성요소를 등록할 수 있습니다. 직접 부팅 모드 중에 실행해야 할 앱의 몇 가지 공통 사용 사례는 다음과 같습니다.

  • 알람 시계 앱과 같이 예약된 알림이 있는 앱
  • SMS 앱처럼 중요한 사용자 알림을 제공하는 앱
  • TalkBack처럼 접근성 서비스를 제공하는 앱

앱이 직접 부팅 모드에서 실행되는 동안 데이터에 액세스해야 하는 경우, 기기 암호화 저장소를 사용합니다. 기기 암호화 저장소에는 기기가 성공적으로 자체 검사 부팅을 실행한 후에만 사용할 수 있는 키로 암호화된 데이터가 포함됩니다.

PIN이나 비밀번호와 같이 사용자 인증 정보와 연관된 키로 암호화되어야 하는 데이터는 사용자 인증 정보 암호화 저장소를 사용합니다. 사용자 인증 정보 암호화 저장소는 사용자가 기기의 잠금을 해제한 후, 그리고 사용자가 기기를 다시 시작할 때까지 사용할 수 있습니다. 사용자가 기기를 잠금 해제한 후 잠금 화면을 사용 설정하면 사용자 인증 정보 암호화 저장소를 계속 사용할 수 있습니다.

직접 부팅 중 실행하기 위한 액세스 요청

직접 부팅 모드에서 실행되기 전 또는 기기 암호화 저장소에 액세스하기 전에 앱은 시스템에 구성요소를 등록해야 합니다. 앱은 구성요소를 암호화 인식으로 표시하여 시스템에 등록합니다. 구성요소를 암호화 인식으로 표시하려면 매니페스트에서 android:directBootAware 속성을 true로 설정합니다.

암호화 인식 구성요소로 등록하면 기기가 다시 시작되었을 때 시스템에서 ACTION_LOCKED_BOOT_COMPLETED 브로드캐스트 메시지를 수신할 수 있습니다. 이 시점에서 기기 암호화 저장소를 사용할 수 있으며 구성요소는 예약된 알람 트리거와 같이 직접 부팅 모드에서 실행되어야 하는 작업을 실행할 수 있습니다.

다음 코드 스니펫은 BroadcastReceiver를 암호화 인식으로 등록하고 앱 매니페스트에서 ACTION_LOCKED_BOOT_COMPLETED의 인텐트 필터를 추가하는 방법을 보여주는 예입니다.

<receiver
  android:directBootAware="true" >
  ...
  <intent-filter>
    <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
  </intent-filter>
</receiver>

사용자가 기기의 잠금을 해제하면 모든 구성요소가 기기 암호화 저장소와 사용자 인증 정보 암호화 저장소에 모두 액세스할 수 있습니다.

기기 암호화 저장소에 액세스

기기 암호화 저장소에 액세스하려면 Context.createDeviceProtectedStorageContext()를 호출하여 두 번째 Context 인스턴스를 만듭니다. 이 컨텍스트를 사용하여 실행된 모든 저장소 API 호출은 기기 암호화 저장소에 액세스합니다. 다음은 기기 암호화 저장소에 액세스하고 기존 앱 데이터 파일을 여는 예시입니다.

Kotlin

val directBootContext: Context = appContext.createDeviceProtectedStorageContext()
// Access appDataFilename that lives in device encrypted storage
val inStream: InputStream = directBootContext.openFileInput(appDataFilename)
// Use inStream to read content...

Java

Context directBootContext = appContext.createDeviceProtectedStorageContext();
// Access appDataFilename that lives in device encrypted storage
FileInputStream inStream = directBootContext.openFileInput(appDataFilename);
// Use inStream to read content...

직접 부팅 모드 중에 액세스해야 하는 정보에만 기기 암호화 저장소를 사용합니다. 기기 암호화 저장소를 범용 암호화 저장소로 사용해서는 안 됩니다. 비공개 사용자 정보나 직접 부팅 모드 중에 필요 없는 암호화 데이터에는 사용자 인증 정보 암호화 저장소를 사용합니다.

사용자 잠금 해제 알림 받기

사용자가 다시 시작 후 기기의 잠금을 해제할 경우 앱은 사용자 인증 정보 암호화 저장소에 액세스하도록 전환하여 사용자 인증 정보에 따라 일반 시스템 서비스를 사용할 수 있습니다.

사용자가 재부팅 후 기기의 잠금을 해제할 경우 알림을 받으려면 실행 중인 구성요소의 BroadcastReceiver를 등록하여 잠금 해제 알림 메시지를 수신합니다. 사용자가 부팅 후 기기의 잠금을 해제할 경우 다음과 같은 알림을 받습니다.

  • 앱에 즉시 알림이 필요한 포그라운드 프로세스가 있는 경우 ACTION_USER_UNLOCKED 메시지를 수신합니다.
  • 앱에서 알림 지연 시에 작업할 수 있는 백그라운드 프로세스만 사용하는 경우 ACTION_BOOT_COMPLETED 메시지를 수신합니다.

사용자가 기기의 잠금을 해제한 경우 UserManager.isUserUnlocked()를 호출하여 확인할 수 있습니다.

기존 데이터 이전

사용자가 직접 부팅 모드를 사용하도록 기기를 업데이트하는 경우 기존 데이터를 기기 암호화 저장소로 이전해야 할 수도 있습니다. 대상 컨텍스트를 메서드 호출자로, 소스 컨텍스트를 인수로 설정한 상태로 Context.moveSharedPreferencesFrom()Context.moveDatabaseFrom()을 사용하여 사용자 인증 정보 암호화 저장소와 기기 암호화 저장소 간에 환경설정과 데이터베이스 데이터를 이전합니다.

비밀번호나 승인 토큰과 같은 비공개 사용자 정보는 사용자 인증 정보 암호화 저장소에서 기기 암호화 저장소로 이전하면 안 됩니다. 기기 암호화 저장소로 이전할 다른 데이터를 결정할 때는 현명하게 판단하세요. 일부 시나리오에서는 두 가지 암호화 저장소에 있는 별도의 데이터 세트를 관리해야 할 수 있습니다.

암호화 인식 앱 테스트

직접 부팅 모드를 사용 설정하고 암호화 인식 앱을 테스트합니다.

최신 버전의 Android를 실행하는 대부분의 기기는 잠금 화면 사용자 인증 정보(PIN, 패턴 또는 비밀번호)가 설정될 때마다 직접 부팅 모드를 사용 설정합니다. 특히 파일 기반 암호화를 사용하는 모든 기기가 여기에 해당합니다. 기기에서 파일 기반 암호화를 사용하는지 확인하려면 다음 셸 명령어를 실행하세요.

adb shell getprop ro.crypto.type

출력이 file이면 기기에 파일 기반 암호화가 사용 설정된 것입니다.

기본적으로 파일 기반 암호화를 사용하지 않는 기기에서는 직접 부팅 모드를 테스트하는 다른 옵션이 있을 수 있습니다.

  • 전체 디스크 암호화(ro.crypto.type=block)를 사용하고 Android 7.0~Android 12를 실행하는 일부 기기는 파일 기반 암호화로 변환할 수 있습니다. 다음과 같은 두 가지 방법이 있습니다.

      경고: 파일 기반 암호화로 변환하는 두 가지 방법은 모두 기기의 모든 사용자 데이터를 완전 삭제합니다.

    • 아직 개발자 옵션이 사용 설정되어 있지 않으면 기기에서 설정 > 휴대전화 정보로 이동하여 빌드 번호를 일곱 번 탭하면 사용 설정됩니다. 그런 다음 설정 > 개발자 옵션으로 이동하여 파일 암호화로 변환을 선택합니다.
    • 또는 다음 셸 명령어를 실행합니다.
      adb reboot-bootloader
      fastboot --wipe-and-use-fbe
      
  • Android 13 이하를 실행하는 기기는 파일 권한을 사용하여 암호화된 파일이 잠기거나 잠금 해제되는 효과를 시뮬레이션하는 '에뮬레이션된' 직접 부팅 모드를 지원합니다. 개발 중에는 에뮬레이션된 모드만 사용하세요. 데이터 손실이 발생할 수 있습니다. 에뮬레이션된 직접 부팅 모드를 사용 설정하려면 기기에서 잠금 패턴을 설정합니다. 잠금 패턴을 설정할 때 안전 모드 화면으로 시작할지 묻는 메시지가 나오면 '사용 안 함'을 선택한 뒤 다음 셸 명령어를 실행합니다.

    adb shell sm set-emulate-fbe true
    

    에뮬레이션된 직접 부팅 모드를 사용 중지하려면 다음 셸 명령어를 실행합니다.

    adb shell sm set-emulate-fbe false
    

    이러한 두 가지 명령어를 실행하면 기기가 재부팅됩니다.

기기 정책 암호화 상태 확인

기기 관리 앱에서 DevicePolicyManager.getStorageEncryptionStatus()를 사용하여 기기의 현재 암호화 상태를 확인할 수 있습니다.

앱이 Android 7.0(API 24) 미만의 API 수준을 타겟팅하는 경우 기기가 전체 디스크 암호화 또는 직접 부팅을 통한 파일 기반 암호화를 사용 중이면 getStorageEncryptionStatus()ENCRYPTION_STATUS_ACTIVE를 반환합니다. 두 경우 모두 데이터는 항상 암호화되어 저장됩니다.

앱이 Android 7.0(API 24) 이상을 타겟팅하는 경우 기기가 전체 디스크 암호화를 사용하면 getStorageEncryptionStatus()ENCRYPTION_STATUS_ACTIVE를 반환합니다. 기기가 직접 부팅을 통한 파일 기반 암호화를 사용하면 ENCRYPTION_STATUS_ACTIVE_PER_USER를 반환합니다.

Android 7.0을 타겟팅하는 기기 관리 앱을 빌드하는 경우에는 기기의 암호화 여부를 판별하기 위해 ENCRYPTION_STATUS_ACTIVEENCRYPTION_STATUS_ACTIVE_PER_USER를 둘 다 확인해야 합니다.

추가 코드 샘플

DirectBoot 샘플은 이 페이지에 설명된 API를 사용하는 방법을 자세히 보여줍니다.