Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Illegal Argument: Invalid format of Realm file" because the realm database requires secretkey for decryption at first #2835

Closed
nidgru opened this issue May 19, 2016 · 9 comments
Labels

Comments

@nidgru
Copy link

nidgru commented May 19, 2016

Just like we open realm database by realm browser and press secretkey, when I load realm database and run the Android Studio, it's always ""Illegal Argument: Invalid format of Realm file"" because I think that I must use secretkey to decrypt it on local disk first. I have AES key (secretkey) right now (I use it to open realm database on Realm Browser everytime this software asks)

how can I pass it to the java code to decrypt realm database or there is any other option for me to decrypt it.

I'm in the urgent situation for the project, please give me a help :(

@cmelchior
Copy link
Contributor

There is method called encryptionKey on RealmConfiguration. You must define it there. You can read more here: https://realm.io/docs/java/latest/#encryption

But the gist of it is this:

byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
RealmConfiguration config = new RealmConfiguration.Builder(context)
  .encryptionKey(key)
  .build();

Realm realm = Realm.getInstance(config);

@nidgru
Copy link
Author

nidgru commented May 19, 2016

It's still "java.lang.IllegalArgumentException: Illegal Argument: Invalid format of Realm file"

The realm database I got from file system of Android (data/user/.../files/default.realm) and I thought that this file have been encrypted by the SecurerRandom() function before it has been stored in (data/user/.../files/default.realm). So now since I want to load it again from my App, I have to decrypt it ... so does these code above give it a help :(

The purpose of my App is to export realm database to csv file. I load realm database from folder raw in source directory. My app works well with unencrypted realm database but not for encrypted realm database.

Here is the code:

`
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;

import com.shayan.realmtest.model.Migration;
import com.shayan.realmtest.model.User;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.crypto.SecretKey;

import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmQuery;
import io.realm.RealmResults;
import java.security.SecureRandom;

public class MainActivity extends Activity {

private static final String outputFileName = "result.csv";
private Realm realm;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    byte[] key = new byte[64];
    new SecureRandom().nextBytes(key);

    setContentView(R.layout.activity_main);
    copyBundledRealmFile(this.getResources().openRawResource(R.raw.default0), "default0");
    RealmConfiguration config0 = new RealmConfiguration.Builder(this)
            .name("default0")
            .encryptionKey(key)
            .schemaVersion(2)
            .migration(new Migration())
            .build();

    Realm.migrateRealm(config0, new Migration());
    realm = Realm.getInstance(config0);
    loadRealmData();
    realm.close();
}

public void loadRealmData() {
    Log.d("", "path: " + realm.getPath());

    RealmQuery<User> query = realm.where(User.class);
    RealmResults<User> users = query.findAll();
    generateCsvFile(users);
}

//calling openFileOutput() to get a FileOutputStream that writes to a file in your internal directory
private void generateCsvFile(RealmResults<User> users) {
    FileOutputStream outputStream;
    String columnHeader = "name, address, password, city";
    String comma = ",";
    String newLine = "\n";

    try {
        outputStream = openFileOutput(outputFileName, Context.MODE_PRIVATE);
        outputStream.write(columnHeader.getBytes());
        outputStream.write(newLine.getBytes());

        for (User user : users) {
            outputStream.write(user.getName().getBytes());
            outputStream.write(comma.getBytes());
            outputStream.write(user.getAddress().getBytes());
            outputStream.write(comma.getBytes());
            outputStream.write(user.getPassword().getBytes());
            outputStream.write(comma.getBytes());
            outputStream.write(user.getCity().getBytes());
            outputStream.write(comma.getBytes());
        }

        outputStream.flush();
        outputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

private String copyBundledRealmFile(InputStream inputStream, String outFileName) {
    try {
        File file = new File(this.getFilesDir(), outFileName);
        FileOutputStream outputStream = new FileOutputStream(file);
        byte[] buf = new byte[1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buf)) > 0) {
            outputStream.write(buf, 0, bytesRead);
        }
        outputStream.close();
        return file.getAbsolutePath();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

}
`

@beeender
Copy link
Contributor

byte[] key = new byte[64];
new SecureRandom().nextBytes(key);

It is only an example to show how to pass key to realm java.
You need use the exact same key when creating the db and open it in java.

@nidgru
Copy link
Author

nidgru commented May 19, 2016

The key (128 bytes key) which i used to open realm database on realm browser is:
"_1694ebc9e6990e10782df2db44445d4dae69bcbcbff3_"

So I convert it to 64 bytes acting as the key in java code.

String s = "***1694ebc9e6990e10782df2db44445d4dae69bcbcbff3***";

byte[] key = new BigInteger(s,16).toByteArray();

 RealmConfiguration config0 = new RealmConfiguration.Builder(this)
                .name("default0")
                .encryptionKey(key)
                .build();

realm = Realm.getInstance(config0);

The Android App starts to crash in the last code "realm = Realm.getInstance(config0)".
I look for the key which I have converted but I strongly think that it is the right key, but maybe it is the wrong one, please helps me to check it again!
Or if the key is the right one, so what is the reason for ""java.lang.IllegalArgumentException: Illegal Argument: Invalid format of Realm file"" ?

@beeender
Copy link
Contributor

The accepted answer http://stackoverflow.com/questions/8890174/in-java-how-do-i-convert-a-hex-string-to-a-byte here doesn't give you the right results.
Try the second one instead.

Also, please verify the conversion result by convert it back and compare.

@nidgru
Copy link
Author

nidgru commented May 19, 2016

I have compared the results from:

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

and
byte[] key = new BigInteger(s,16).toByteArray();

They are the same.

@beeender
Copy link
Contributor

hmmm, my bad. They seem to have the same result.

How did you generate the db file? By realm browser with the same key? Is it OK to share the db file with us privately? To help@realm.io

And what is the Realm browser version and the realm-java version you are using?

@nidgru
Copy link
Author

nidgru commented May 21, 2016

Thank you, I'm about to solve this problem. The problem doesn't result from the wrong key. It's from the version of Realm that I used. Currently I used Realm version 8.2 (is too old), so I decided to change to the newest version and Bing Boong, The problem is gone!
Thank you for your quick support! I very appreciate this!

@kneth
Copy link
Member

kneth commented May 23, 2016

I'll close the issue as it sounds you have solved the issue.

@kneth kneth closed this as completed May 23, 2016
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 17, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants