Bekerja lebih aman dengan data Bagian dari Android Jetpack.
Library Security menyediakan implementasi praktik terbaik keamanan yang berkaitan dengan pembacaan dan penulisan data dalam penyimpanan, serta pembuatan dan verifikasi kunci.
Library ini menggunakan pola builder untuk menyediakan setelan default yang aman untuk tingkat keamanan berikut:
- Keamanan kuat yang menyeimbangkan enkripsi yang hebat dengan performa yang baik. Tingkat keamanan ini sesuai untuk aplikasi konsumen, seperti aplikasi perbankan dan chat, serta aplikasi perusahaan yang menjalankan pemeriksaan pembatalan sertifikat.
- Keamanan maksimum. Tingkat keamanan ini sesuai untuk aplikasi yang memerlukan keystore yang didukung hardware dan kehadiran pengguna untuk memberikan akses kunci.
Panduan ini menunjukkan cara menggunakan konfigurasi keamanan yang direkomendasikan oleh library Security, serta cara membaca dan menulis data terenkripsi yang tersimpan dalam file dan preferensi bersama.
Pengelolaan kunci
Library Security menggunakan sistem dua bagian untuk pengelolaan kunci:
-
Keyset yang berisi satu atau beberapa kunci untuk mengenkripsi file atau data preferensi bersama. Keyset disimpan di
SharedPreferences
. -
Kunci (
master
) utama yang mengenkripsi semua keyset. Kunci ini disimpan menggunakan sistem keystore Android.
Class yang disertakan dalam library
Library Security berisi class berikut untuk menyediakan data dalam penyimpanan yang lebih aman:
EncryptedFile
-
Menyediakan implementasi kustom
FileInputStream
danFileOutputStream
, yang memberikan aliran operasi baca dan tulis yang lebih aman ke aplikasi Anda.Untuk memberikan operasi baca dan tulis yang aman dari aliran file, library Security menggunakan primitive Streaming Authenticated Encryption with Associated Data (AEAD). Pelajari primitive ini lebih lanjut dalam dokumentasi library Tink di GitHub.
EncryptedSharedPreferences
-
Menggabungkan class
SharedPreferences
dan otomatis mengenkripsi kunci dan nilai menggunakan metode dua skema:- Kunci dienkripsi menggunakan algoritme enkripsi deterministik sehingga kunci tersebut dapat dienkripsi dan dicari dengan benar.
- Nilai dienkripsi menggunakan AES-256 GCM dan bersifat non-deterministik.
Bagian berikut menunjukkan cara menggunakan class ini untuk menjalankan operasi umum dengan file dan preferensi bersama.
Menyertakan library dalam project Anda
Untuk menggunakan library Security, tambahkan dependensi berikut sebagaimana mestinya ke
file build.gradle
modul aplikasi:
Groovy
dependencies { implementation "androidx.security:security-crypto:1.0.0" // For Identity Credential APIs implementation "androidx.security:security-identity-credential:1.0.0-alpha03" // For App Authentication APIs implementation "androidx.security:security-app-authenticator:1.0.0-alpha02" // For App Authentication API testing androidTestImplementation "androidx.security:security-app-authenticator:1.0.0-alpha01" }
Kotlin
dependencies { implementation("androidx.security:security-crypto:1.0.0") // For Identity Credential APIs implementation("androidx.security:security-identity-credential:1.0.0-alpha03") // For App Authentication APIs implementation("androidx.security:security-app-authenticator:1.0.0-alpha02") // For App Authentication API testing androidTestImplementation("androidx.security:security-app-authenticator:1.0.0-alpha01") }
Membaca file
Cuplikan kode berikut menunjukkan cara menggunakan EncryptedFile
untuk membaca
konten file:
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 mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) val fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(DIRECTORY, fileToRead), applicationContext, mainKeyAlias, 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()
Java
Context context = getApplicationContext(); // 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 mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec); String fileToRead = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder( new File(DIRECTORY, fileToRead), context, mainKeyAlias, 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();
Menulis file
Cuplikan kode berikut menunjukkan cara menggunakan EncryptedFile
untuk menulis
konten file:
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 mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec) // Create a file with this name or replace an entire existing file // that has the same name. Note that you cannot append to an existing file, // and the filename cannot contain path separators. val fileToWrite = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder( File(DIRECTORY, fileToWrite), applicationContext, mainKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() val fileContent = "MY SUPER-SECRET INFORMATION" .toByteArray(StandardCharsets.UTF_8) encryptedFile.openFileOutput().apply { write(fileContent) flush() close() }
Java
Context context = getApplicationContext(); // 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 mainKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec); // Create a file with this name or replace an entire existing file // that has the same name. Note that you cannot append to an existing file, // and the filename cannot contain path separators. String fileToWrite = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder( new File(DIRECTORY, fileToWrite), context, mainKeyAlias, 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();
Untuk kasus penggunaan yang mengharuskan keamanan tambahan, selesaikan langkah-langkah berikut:
- Buat objek
KeyGenParameterSpec.Builder
dengan meneruskantrue
kesetUserAuthenticationRequired()
dan nilai yang lebih besar dari 0 sebagai argumen pertamasetUserAuthenticationParameters()
. Minta pengguna memasukkan kredensial menggunakan
createConfirmDeviceCredentialIntent()
. Pelajari lebih lanjut cara meminta autentikasi pengguna untuk penggunaan kunci.Ganti
onActivityResult()
untuk mendapatkan callback kredensial yang telah dikonfirmasi.
Mengedit preferensi bersama
Cuplikan kode berikut menunjukkan cara menggunakan EncryptedSharedPreferences
untuk mengedit kumpulan preferensi bersama milik pengguna:
Kotlin
val sharedPrefsFile: String = FILE_NAME val sharedPreferences: SharedPreferences = EncryptedSharedPreferences.create( sharedPrefsFile, mainKeyAlias, applicationContext, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) with (sharedPreferences.edit()) { // Edit the user's shared preferences... apply() }
Java
String sharedPrefsFile = FILE_NAME; SharedPreferences sharedPreferences = EncryptedSharedPreferences.create( sharedPrefsFile, mainKeyAlias, getApplicationContext(), EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ); SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit(); // Edit the user's shared preferences... sharedPrefsEditor.apply();
Mendukung perangkat Android 5.0 dan Android 5.1
Library Security Versi 1.1.0 memungkinkan Anda mendukung perangkat yang menjalankan Android 5.0 (API level 21) dan yang lebih baru. Di Android 5.0 dan Android 5.1 (API level 22), Anda tidak dapat menggunakan keystore Android untuk menyimpan keyset.
Membaca file
Cuplikan kode berikut menunjukkan cara menggunakan
EncryptedFile
untuk membaca
konten file menggunakan library Security
versi 1.1.0:
Kotlin
val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val fileToRead = "my_sensitive_data.txt" val encryptedFile = EncryptedFile.Builder(applicationContext, File(DIRECTORY, fileToRead), mainKey, 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()
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); String fileToRead = "my_sensitive_data.txt"; EncryptedFile encryptedFile = new EncryptedFile.Builder(context, new File(DIRECTORY, fileToRead), mainKey, 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();
Menulis file
Cuplikan kode berikut menunjukkan cara menggunakan
EncryptedFile
untuk menulis
konten file menggunakan library Security
versi 1.1.0:
Kotlin
val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() // 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 = File(DIRECTORY, "my_sensitive_data.txt") val encryptedFile = EncryptedFile.Builder(applicationContext, fileToWrite, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build() // File cannot exist before using openFileOutput if (fileToWrite.exists()) { fileToWrite.delete() } val fileContent = "MY SUPER-SECRET INFORMATION" .toByteArray(StandardCharsets.UTF_8)) encryptedFile.openFileOutput().apply { write(fileContent) flush() close() }
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); // 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. File fileToWrite = new File(DIRECTORY, "my_sensitive_data.txt"); EncryptedFile encryptedFile = new EncryptedFile.Builder(context, fileToWrite, mainKey, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB ).build(); // File cannot exist before using openFileOutput if (fileToWrite.exists()) { fileToWrite.delete(); } byte[] fileContent = "MY SUPER-SECRET INFORMATION" .getBytes(StandardCharsets.UTF_8); OutputStream outputStream = encryptedFile.openFileOutput(); outputStream.write(fileContent); outputStream.flush(); outputStream.close();
Mengedit preferensi bersama
Cuplikan kode berikut menunjukkan cara menggunakan
EncryptedSharedPreferences
untuk mengedit kumpulan preferensi bersama milik pengguna menggunakan library Security
versi 1.1.0:
Kotlin
val context = applicationContext val mainKey = MasterKey.Builder(applicationContext) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build() val sharedPreferences = EncryptedSharedPreferences.create( applicationContext, FILE_NAME, mainKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) with (sharedPreferences.edit()) { // Edit the user's shared preferences... apply() }
Java
Context context = getApplicationContext(); MasterKey mainKey = new MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .build(); SharedPreferences sharedPreferences = EncryptedSharedPreferences .create( context, FILE_NAME, mainKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ); SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit(); // Edit the user's shared preferences... sharedPrefsEditor.apply();