Google은 흑인 공동체를 위한 인종 간 평등을 진전시키기 위해 노력하고 있습니다. Google에서 어떤 노력을 하고 있는지 확인하세요.

더 안전하게 데이터 사용 Android Jetpack의 일부

보안 라이브러리는 저장 데이터 읽기 및 쓰기와 관련된 보안 권장사항의 구현과 키 생성 및 인증을 제공합니다.

라이브러리는 빌더 패턴을 사용하여 다음 보안 수준에 안전한 기본 설정을 제공합니다.

  • 뛰어난 암호화와 우수한 성능 사이에서 균형을 이루는 강력한 보안. 이 보안 수준은 은행 및 채팅 앱, 인증서 취소 확인을 실행하는 기업 앱과 같은 소비자 앱에 적합합니다.
  • 최대 보안. 이 보안 수준은 키 액세스를 제공하는 데 하드웨어 지원 키 저장소와 사용자 정보가 필요한 앱에 적합합니다.

이 가이드에서는 보안 라이브러리의 권장 보안 구성을 사용하는 방법과 파일 및 공유 환경설정에 저장되어 있는 암호화된 데이터를 쉽고 안전하게 읽고 쓰는 방법을 보여줍니다.

키 관리

보안 라이브러리는 키 관리를 위해 다음과 같은 두 요소로 구성된 시스템을 사용합니다.

  • 하나 이상의 키를 포함하여 파일 또는 공유 환경설정 데이터를 암호화하는 키 세트. 키 세트 자체는 SharedPreferences에 저장됩니다.

  • 모든 키 세트를 암호화하는 기본(master) 키. 이 키는 Android 키 저장소 시스템을 사용하여 저장됩니다.

라이브러리에 포함된 클래스

보안 라이브러리에는 다음 클래스가 포함되어 더 안전한 저장 데이터를 제공합니다.

EncryptedFile

FileInputStreamFileOutputStream의 맞춤 구현을 제공하여 앱에서 더 안전하게 스트리밍 읽기 및 쓰기 작업을 할 수 있습니다.

파일 스트림에서 안전한 읽기 및 쓰기 작업을 제공하기 위해 보안 라이브러리는 연결된 데이터와 함께 스트리밍 인증 암호화(AEAD) 프리미티브를 사용합니다. GitHub의 Tink 라이브러리 문서에서 이 프리미티브를 자세히 알아보세요.

EncryptedSharedPreferences

SharedPreferences 클래스를 래핑하고 다음 두 가지 체계 메서드를 사용하여 키와 값을 자동으로 암호화합니다.

  • 가 결정론적 암호화 알고리즘을 사용하여 암호화되므로 키를 암호화하고 올바르게 찾을 수 있습니다.
  • AES-256 GCM을 사용하여 암호화되며 비결정론적입니다.

다음 섹션에서는 이러한 클래스를 사용하여 파일 및 공유 환경설정으로 일반 작업을 실행하는 방법을 보여줍니다.

프로젝트에 라이브러리 포함

보안 라이브러리를 사용하려면 다음 종속 항목을 앱 모듈의 build.gradle 파일에 추가합니다.

dependencies {
    implementation "androidx.security:security-crypto:1.0.0-rc03"

    // For Identity Credential APIs
    implementation "androidx.security:security-identity-credential:1.0.0-alpha01"
}

파일 읽기

다음 코드 스니펫은 EncryptedFile을 사용하여 파일의 콘텐츠를 더 안전하게 읽는 방법을 보여줍니다.

Kotlin

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

val context = applicationContext
val fileToRead = "my_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(
    File(DIRECTORY, fileToRead),
    context,
    masterKeyAlias,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

val inputStream = encryptedFile.openFileInput()
val byteArrayOutputStream = ByteArrayOutputStream()
var nextByte: Int = inputStream.read()
while (nextByte != -1) {
    byteArrayOutputStream.write(nextByte)
    nextByte = inputStream.read()
}

val plaintext: ByteArray = byteArrayOutputStream.toByteArray()

자바

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC;
String masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec);

Context context = getApplicationContext();
String fileToRead = "my_sensitive_data.txt";
EncryptedFile encryptedFile = new EncryptedFile.Builder(
        new File(DIRECTORY, fileToRead),
        context,
        masterKeyAlias,
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();

InputStream inputStream = encryptedFile.openFileInput();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int nextByte = inputStream.read();
while (nextByte != -1) {
    byteArrayOutputStream.write(nextByte);
    nextByte = inputStream.read();
}

byte[] plaintext = byteArrayOutputStream.toByteArray();

파일 쓰기

다음 코드 스니펫은 EncryptedFile을 사용하여 파일의 콘텐츠를 더 안전하게 쓰는 방법을 보여줍니다.

Kotlin

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
val fileToWrite = "my_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(
    File(DIRECTORY, fileToWrite),
    context,
    masterKeyAlias,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

val fileContent = "MY SUPER-SECRET INFORMATION"
        .toByteArray(StandardCharsets.UTF_8)
encryptedFile.openFileOutput().apply {
    write(fileContent)
    flush()
    close()
}

자바

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
KeyGenParameterSpec keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC;
String masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec);

// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
String fileToWrite = "my_sensitive_data.txt";
EncryptedFile encryptedFile = new EncryptedFile.Builder(
        new File(DIRECTORY, fileToWrite),
        context,
        masterKeyAlias,
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();

byte[] fileContent = "MY SUPER-SECRET INFORMATION"
        .getBytes(StandardCharsets.UTF_8);
OutputStream outputStream = encryptedFile.openFileOutput();
outputStream.write(fileContent);
outputStream.flush();
outputStream.close();

추가 보안이 필요한 사용 사례의 경우 다음 단계를 완료하세요.

  1. KeyGenParameterSpec.Builder 객체를 만들어 setUserAuthenticationRequired()true를, setUserAuthenticationValidityDurationSeconds()에 0보다 큰 값을 전달합니다.
  2. createConfirmDeviceCredentialIntent()를 사용하여 사용자 인증 정보를 입력하라는 메시지를 사용자에게 표시합니다. 키 사용을 위한 사용자 인증을 요청하는 방법을 자세히 알아보세요.

  3. onActivityResult()를 재정의하여 확인된 사용자 인증 정보 콜백을 가져옵니다.

자세한 내용은 키 사용을 위한 사용자 인증 요청을 참조하세요.

공유 환경설정 수정

다음 코드 스니펫은 EncryptedSharedPreferences를 사용하여 사용자의 공유 환경설정을 더 안전하게 수정하는 방법을 보여줍니다.

Kotlin

val sharedPreferences = EncryptedSharedPreferences
    .create(
    FILE_NAME,
    masterKeyAlias,
    context,
    EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
    EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)

val sharedPrefsEditor = sharedPreferences.edit()

자바

EncryptedSharedPreferences sharedPreferences = EncryptedSharedPreferences
        .create(
                FILE_NAME,
                masterKeyAlias,
                context,
                EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
                EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
        );

SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();