realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.45k stars 1.75k forks source link

Encryption in realm file #2544

Closed kentcheung2000 closed 8 years ago

kentcheung2000 commented 8 years ago

I have a json file and load the data to my realm file. I like to encrypt the realm file. Both are giving me an error. I look at the sample in realm website. It said don't use it... My question is that is there a simple program using encryption in realm?

My other question is if I load the json file to realm file, is the json file secure? And can I just ender the data directly into realm file and put it in the project? If I can do it, where do I put it and how I can load the file directly?

My two sample as followed:

KeyPairGenerator kpg = KeyPairGenerator.getInstance(
        KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
kpg.initialize(new KeyGenParameterSpec.Builder(
        alias,
        KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
        .setDigests(KeyProperties.DIGEST_SHA256,
            KeyProperties.DIGEST_SHA512)
        .build());

KeyPair kp = kpg.generateKeyPair();

// I got the key and I suppose it will encrypt the file
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this)
                .encryptionKey(kp)
                .build();

or

KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder("key1",
        KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT);
KeyGenParameterSpec keySpec = builder
        .setKeySize(256) 
        .setRandomizedEncryptionRequired(true)
        .setUserAuthenticationRequired(true)
        .setUserAuthenticationValidityDurationSeconds(5 * 60)
        .build();
KeyGenerator kg = KeyGenerator.getInstance("AES", "AndroidKeyStore");
kg.init(keySpec);
SecretKey key = kg.generateKey();

// I got the key and I suppose it will encrypt the file
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this)
                .encryptionKey(key)
                .build();
cmelchior commented 8 years ago

Hi @kentcheung2000 Currently we don't have an example showing how to create encryption keys. The primary reason is that it is a relatively complex subject with a lot of trade-offs. Especially regarding how you want to store your key.

In your case, it doesn't compile because we only accept that key as raw bytes, which means you have to call .encryptionKey(key.getEncoded()). Also note the key length has to be 64 byte (512 bit).

kentcheung2000 commented 8 years ago

Thank you for your reply. I can compile the following code. However, I got an error saying "Illegal Argument: Invalid format of Realm file."

Did I miss anything in the code? I try to get my realm file encrypted by a generate key. Thanks for your help.

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        try {
            yourKey = generateKey();
            key = yourKey.getEncoded();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this).name("bibleindex.realm").encryptionKey(key).build();
       // Realm.deleteRealm(realmConfiguration);
        Realm.setDefaultConfiguration(realmConfiguration);

        realm = Realm.getDefaultInstance();

My generateKey Method

  public SecretKey generateKey() throws NoSuchAlgorithmException{

        SecureRandom secureRandom = new SecureRandom();
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(512, secureRandom);
        yourKey = keyGenerator.generateKey();

        return yourKey;
    }
beeender commented 8 years ago

If your key changed since last time you created the db, ""Illegal Argument: Invalid format of Realm file." will be thrown.

kentcheung2000 commented 8 years ago

If I delete the realm file and I could solve the problem, I could have solved the issue because the encryption key will be regenerated. What if there is some information I want to store? Is there a way I can save the original key somewhere safely and reuse it when I open the apps? Many thanks.

beeender commented 8 years ago

Saving the key is a bit huge topic and beyond the scope of Realm issue list a little bit. But the suggestion is that you can use Android's Keystore system. See docs here http://developer.android.com/training/articles/keystore.html

stk1m1 commented 8 years ago

Hi @kentcheung2000,

Has @beeender's suggestion helped you making progress? We'd appreciate if you can share your progress.

kentcheung2000 commented 8 years ago

Hi stk1m1,

I did not make any progress, unfortunately.... I am still looking for a very basic way to store the encryption key so I can use it to open the realm file in the future. I will keep you up to date. Thanks for asking.

cmelchior commented 8 years ago

Hi @kentcheung2000 We are working on a sample project that shows how you can use the Keystore to work with encrypted Realms. The basic idea is having 2 keys and saving one in SharedPreferences, but you can see this StackOverflow answer with a link to the project: http://stackoverflow.com/questions/36505418/encrypting-realm-with-key-stored-in-keystore

cmelchior commented 8 years ago

The above should answer you question, so I'll close this question now, but feel free to re-open if you run into any problems.