Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

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 dan FileOutputStream, 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:

  1. Buat objek KeyGenParameterSpec.Builder dengan meneruskan true ke setUserAuthenticationRequired() dan nilai yang lebih besar dari 0 sebagai argumen pertama setUserAuthenticationParameters().
  2. Minta pengguna memasukkan kredensial menggunakan createConfirmDeviceCredentialIntent(). Pelajari lebih lanjut cara meminta autentikasi pengguna untuk penggunaan kunci.

  3. 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();