Mengenkripsi Realm dengan kunci yang disimpan di KeyStore

Saya mencoba menyiapkan instance ranah default terenkripsi di aplikasi saya. Idenya adalah membuat kunci menggunakan KeyPairGenerator dengan alias tertentu, menyimpannya di AndroidKeyStore dan menggunakan kunci tersebut setiap kali diperlukan.

APA YANG SAYA LAKUKAN

Inilah cara saya menghasilkan kunci:

  KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
        ks.load(null);

        if (!ks.containsAlias(KEY_ALIAS)) {

            Calendar start = Calendar.getInstance();
            Calendar end = Calendar.getInstance();
            end.add(Calendar.YEAR, 99);

            KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
                    .setAlias(KEY_ALIAS)
                    .setSubject(new X500Principal("CN=Example, O=ExampleOrg"))
                    .setSerialNumber(BigInteger.ONE)
                    .setStartDate(start.getTime())
                    .setEndDate(end.getTime())
                    .build();

            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
            generator.initialize(spec);

            KeyPair keyPair = generator.generateKeyPair();
        }

Saya menggunakan KeyPairGenerator karena saya perlu mendukung api versi 18 dan lebih tinggi.

Inilah cara saya mengatur instance ranah default di Aplikasi saya:

 RealmConfiguration config = null;
    try {
        config = new RealmConfiguration
                .Builder(this)
                .encryptionKey(ks.getKey(KEY_ALIAS, null).getEncoded())
                .name("dealmatrix.realm")
                .schemaVersion(1)
                .build();

di mana ks adalah instance Keystore yang diperoleh seperti:

Keystore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);

APA YANG SALAH

Masalah saya adalah ungkapan ini:

ks.getKey(KEY_ALIAS, null).getEncoded()

mengembalikan null, yang tentu saja mengarah pada pengecualian.

Saya telah membaca secara online bahwa ini adalah perilaku yang diinginkan dari sistem KeyStore.

Jika memang saya tidak bisa mendapatkan array byte kunci enkripsi yang disimpan, bagaimana saya bisa mengenkripsi wilayah saya menggunakan kunci tersebut?

Apakah ada metode lain untuk menyimpan kunci enkripsi dengan aman sehingga saya dapat menggunakannya dalam konfigurasi ranah saya?


person Rakatan    schedule 08.04.2016    source sumber
comment
Sudahkah Anda menemukan solusinya, saya juga menghadapi masalah ini   -  person Bala Saikrupa Puram    schedule 13.02.2018


Jawaban (3)


Ada proyek contoh WIP di cabang feature/example/store_password di repositori Realm yang menggunakan keystore Android.

https://github.com/realm/realm-java/tree/feature/example/store_password/examples/StoreEncryptionPassword

Logika inti ditulis dalam Store.java

Kami memerlukan beberapa pekerjaan lagi (pembersihan, menambahkan komentar, mendukung perangkat lama) sebelum merilis proyek contoh ini. Tapi menurut saya proyek ini membantu Anda.

person zaki50    schedule 01.05.2016

Kunci Android Keystore yang mengembalikan null dari getEncoded berfungsi sebagaimana mestinya. getEncoded seharusnya mengembalikan materi kunci kunci privat (biasanya dalam format berkode DER PKCS#8) atau null jika ekspor materi kunci tidak didukung. Android Keystore menurut desainnya tidak mengungkapkan/mengekspor materi kunci dari kunci pribadi atau rahasia sehingga getEncoded mengembalikan null. Lihat https://developer.android.com/training/articles/keystore.html#SecurityFeatures.

Anda masih dapat menggunakan kunci ini dengan baik dengan abstraksi Tanda Tangan dan Sandi.

person Alex Klyubin    schedule 10.04.2016
comment
Baik, saya mengerti. Apa yang Anda katakan masuk akal, tetapi ini tidak menjawab pertanyaan saya. Bagaimana saya bisa menyimpan kunci enkripsi untuk konfigurasi Realm saya dengan aman? - person Rakatan; 11.04.2016
comment
Apa itu Alam? Secara umum, Anda dapat mengenkripsi sesuatu menggunakan Cipher primitif yang Anda inisialisasi dengan instance Key. Dalam hal ini, Anda bisa mendapatkan instance Key dari Android Keystore. - person Alex Klyubin; 11.04.2016
comment
realm.io . Itu adalah basis data. Saya mengetahui cara kerja Keystore, tetapi metode enkripsi database hanya menerima array byte. - person Rakatan; 11.04.2016
comment
Dalam hal ini, sepertinya realm.io tidak kompatibel dengan kripto yang tidak membocorkan materi kunci ke dalam proses yang menjalankan realm.io, seperti kripto Android Keystore. - person Alex Klyubin; 12.04.2016

Android Keystore melarang ekstraksi kunci pribadi darinya. Jadi desainnya adalah menghasilkan kunci Realm di luar Android Keystore, sehingga Anda dapat menggunakannya untuk enkripsi/dekripsi database Realm.

Namun untuk menyimpan kunci Realm tersebut dengan aman, Anda akan menggunakan kekuatan Android Keystore, dengan mengenkripsi kunci Realm dengan Android Keystore dan kemudian menyimpannya secara lokal (misalnya, Preferensi Bersama). Nanti Anda dapat membaca kunci Realm terenkripsi itu, mendekripsinya dengan Android Keystore dan menggunakannya lagi untuk membuka kunci database Realm Anda.

person Stefan Arn    schedule 01.03.2019