이번 포스팅은 Android에서 보다 더 안전하게 데이터를 저장하는 방법에 대해 알아보도록 하겠습니다.
Android Jetpack의 일부인 Security Library는 유휴 상태의 데이터를 읽고 쓰는 것과 관련된 보안 모범 사례를 키 생성 및 검증의 구현을 위해 제공합니다.
라이브러리는 빌더 패턴을 사용하여 다음 보안 레벨에 안전한 기본 설정을 제공합니다.
▶ 강력한 암호화와 우수한 성능의 균형을 유지하는 강력한 보안 : 이 보안 수준은 뱅킹 및 채팅 앱과 같은 소비자 앱과 인증서 해지 확인을 수행하는 엔터프라이즈 앱에 적합합니다.
▶ 최대 보안 : 이 수준의 보안은 키 액세스를 제공하기 위해 하드웨어 기반 키 저장소 및 사용자 존재가 필요한 앱에 적합합니다. 이 안내서는 Security Library의 권장 보안 구성과 SharedPreference과 파일에 저장된 암호화된 데이터를 쉽고 안전하게 읽고 쓰는 방법을 보여줍니다.
SharedPreferences에
저장됩니다.
다음 소스 코드는 마스터 키를 정의하는 방법을 보여줍니다.
// 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)
#. Library에 포함된 Class
Security Library에는 보다 안전한 데이터를 제공하기 위해 다음과 같은 클래스가 포함되어 있습니다.
EncryptedFile
▶ FileInputStream 및 FileOutputStream
을 사용자 정의 구현하여 앱에 보다 안전한 스트리밍 읽기 및 쓰기 작업을 제공합니다.
▶ 파일 스트림에서 안전한 읽기 및 쓰기 작업을 제공하기 위해 Security Library는 AEAD (Authenticated Encryption with Associated Data)를 기본을 사용합니다. GitHub GitHub의 Tink 라이브러리 설명서에서 이 기본 요소에 대해 자세히 알아보십시오..
EncryptedSharedPreferences
SharedPreferences
클래스를 감싸고 다음 두 가지 구성 방법을 사용하여 키와 값을 자동으로 암호화합니다.
▶ Key는 암호화되고 적절하게 조회될 수 있도록 결정론적 암호화 알고리즘을 사용하여 암호화합니다
▶ Value는 AES-256 GCM을 사용하여 암호화되며 결정적이지 않습니다.
다음 섹션에서는 이러한 클래스를 사용하여 파일 및 공유 환경 설정으로 공통 작업을 수행하는 방법을 보여줍니다.
#. 파일 읽기
다음 소스 코드는 EncryptedFile을
사용하여 파일의 내용을 보다 안전하게 읽는 방법을 보여줍니다 .
val fileToRead = "my_sensitive_data.txt"
lateinit var byteStream: ByteArrayOutputStream
val encryptedFile = EncryptedFile.Builder(
File(context.getFilesDir(), fileToRead),
context,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
try {
encryptedFile.openFileInput().use { fileInputStream ->
try {
byteStream = ByteArrayOutputStream()
var nextByte = fileInputStream.read()
while (nextByte != -1) {
byteStream.write(nextByte)
nextByte = fileInputStream.read()
}
val fileContents = byteStream.toByteArray()
} catch (ex: Exception) {
// Error occurred opening raw file for reading.
} finally {
fileInputStream.close()
}
})
} catch (ex: IOException) {
// Error occurred opening encrypted file for reading.
}
#. 파일 쓰기
다음 소스 코드는 EncryptedFile
을 사용하여 파일의 내용을 보다 안전하게 쓰는 방법을 보여줍니다.
val fileToWrite = "my_other_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(
File(context.getFilesDir(), fileToWrite),
context,
masterKeyAlias,
EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()
// Write to a file.
try {
val outputStream: FileOutputStream? = encryptedFile.openFileOutput()
outputStream?.apply {
write("MY SUPER SECRET INFORMATION"
.toByteArray(Charset.forName("UTF-8")))
flush()
close()
}
} catch (ex: IOException) {
// Error occurred opening file for writing.
}
추가 보안이 필요한 사용 사례의 경우 다음 단계를 완료하십시오.
▶ KeyGenParameterSpec.Builder
를 생성하십시오. Build 객체로 setUserAuthenticationRequired()
를 true로 전달하고 0보다 큰 값을 setUserAuthenticationValidityDurationSeconds()
로 전달하세요.
createConfirmDeviceCredentialIntent()
을 사용하여 자격 증명을 입력하도록 키 사용을 위해 사용자 인증을 요청하는 방법에 대해 자세히 알아보십시오 .★ 참고 : 보안 라이브러리는
BiometricPrompt
암호화 작업 수준에서 지원하지 않습니다.
▶ 확인된 자격 증명 콜백을 가져오기 위해 onActivityResult()
를 재정의 하십시오. 자세한 정보는 키 사용을 위한 사용자 인증 요구를 참조하십시오.
#. SharedPreference 편집
다음 소스코드는
EncryptedSharedPreferences
은 보다 안전한 방식으로 사용자의 SharedPerference를 편집하는 방법을 보여줍니다 .
val sharedPreferences = EncryptedSharedPreferences
.create(
fileName,
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
val sharedPrefsEditor = sharedPreferences.edit()
Reference
'Development > Security' 카테고리의 다른 글
[Security] 대칭키 암호화 (0) | 2019.08.29 |
---|---|
[Security] PKCS 정의 (0) | 2019.08.29 |
[Security] 중요한(민감한) 데이터 Access permission (0) | 2019.08.28 |
[Security] Android Keystore 시스템 (0) | 2019.08.27 |
[Security] Android Security Tips (0) | 2019.08.26 |