Pratinjau Developer Android 11 kedua kini tersedia, uji dan sampaikan masukan Anda.

Menangani data dengan lebih aman

Library Keamanan, yang merupakan bagian dari Android Jetpack, menyediakan implementasi praktik terbaik keamanan yang terkait dengan pembacaan dan penulisan data saat nonaktif, 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 Keamanan, serta cara membaca dan menulis data terenkripsi yang tersimpan dalam file dan preferensi bersama dengan mudah dan aman.

Pengelolaan kunci

Library Keamanan menggunakan sistem yang terdiri dari 2 bagian untuk pengelolaan kunci:

  • Keyset yang berisi satu atau beberapa kunci untuk mengenkripsi file atau data preferensi bersama. Keyset itu sendiri disimpan di SharedPreferences.

  • Kunci master yang mengenkripsi semua keyset. Kunci ini disimpan menggunakan sistem keystore Android.

Class yang disertakan dalam library

Library Keamanan berisi class berikut untuk menyediakan data yang lebih aman saat nonaktif:

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 Keamanan menggunakan primitive Streaming Authenticated Encryption with Associated Data (AEAD). Pelajari primitive ini lebih lanjut dalam dokumentasi library Tink di GitHub.

EncryptedSharedPreferences

Menggabung 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 non-deterministik.

Bagian berikut menunjukkan cara menggunakan class ini untuk menjalankan operasi umum dengan file dan preferensi bersama.

Membaca file

Cuplikan kode berikut menunjukkan cara menggunakan EncryptedFile untuk membaca isi file dengan cara yang lebih aman:

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 fileToRead = "my_sensitive_data.txt"
    lateinit var byteStream: ByteArrayOutputStream
    val encryptedFile = EncryptedFile.Builder(
        File(directory, fileToRead),
        context,
        masterKeyAlias,
        EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
    ).build()

    val contents = encryptedFile.bufferedReader().useLines { lines ->
        lines.fold("") { working, line ->
            "$working\n$line"
        }
    }
    

Java

    // 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);

    String fileToRead = "my_sensitive_data.txt";
    ByteArrayOutputStream byteStream;

    EncryptedFile encryptedFile = new EncryptedFile.Builder(
            File(directory, fileToRead),
            context,
            masterKeyAlias,
            EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
    ).build();

    StringBuffer stringBuffer = new StringBuffer();
    try (BufferedReader reader =
                 new BufferedReader(new FileReader(encryptedFile))) {

        String line = reader.readLine();
        while (line != null) {
            stringBuffer.append(line).append('\n');
            line = reader.readLine();
        }
    } catch (IOException e) {
        // Error occurred opening raw file for reading.
    } finally {
        String contents = stringBuffer.toString();
    }
    

Menulis file

Cuplikan kode berikut menunjukkan cara menggunakan EncryptedFile untuk menulis isi file dengan cara yang lebih aman:

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()

    encryptedFile.bufferedWriter().use { writer ->
        writer.write("MY SUPER-SECRET INFORMATION")
    }
    

Java

    // 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";
    try {
        EncryptedFile encryptedFile = new EncryptedFile.Builder(
                new File(directory, fileToWrite),
                context,
                masterKeyAlias,
                EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
        ).build();

        // Write to a file.
        BufferedWriter writer = new BufferedWriter(new FileWriter(encryptedFile));
        writer.write("MY SUPER-SECRET INFORMATION");
    } catch (GeneralSecurityException gse) {
        // Error occurred getting or creating keyset.
    } catch (IOException ex) {
        // Error occurred opening file for writing.
    }
    

Untuk kasus penggunaan yang mengharuskan keamanan tambahan, selesaikan langkah-langkah berikut:

  1. Buat objek KeyGenParameterSpec.Builder, yang meneruskan true ke setUserAuthenticationRequired() dan nilai yang lebih besar dari 0 ke setUserAuthenticationValidityDurationSeconds().
  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.

Untuk informasi lebih lanjut, lihat Mengharuskan autentikasi pengguna untuk penggunaan kunci.

Mengedit preferensi bersama

Cuplikan kode berikut menunjukkan cara menggunakan EncryptedSharedPreferences untuk mengedit kumpulan preferensi bersama yang ditetapkan pengguna dengan cara yang lebih aman:

Kotlin

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

    val sharedPrefsEditor = sharedPreferences.edit()
    

Java

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

    SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();