Realm-js: React Native - Realm Encryption - Unable to encrypt and then access DB

Created on 18 May 2016  路  8Comments  路  Source: realm/realm-js

Hey guys,

First off, Realm is awesome! We are stoked on the React Native release and will be using it in production soon. We ran into one issue, we are having trouble using the Encryption feature as described in the docs.

The example provided here (https://realm.io/docs/react-native/latest/#encryption) seems incomplete(?) and the sample code here (https://github.com/realm/realm-js) doesn't seem to have any encryption examples. Without storing the encryption key, how can you open the database again exactly? In any case the example doesn't seem to be working, is there a more robust code sample to reference?

For storing the encryption key we went the route of using the react-native-keychain module to store the encryption key/other data. The module itself seems to work great, but when keychain to try to access the Realm DB we have had no luck and see 'Unable to access / open Realm etc etc" red error screen. (seeing errors like this with or without using react-native-keychain)

Thanks much,
Charles

O-Community T-Help

Most helpful comment

You can use a site like https://asecuritysite.com/encryption/PBKDF2z to generate a 64 byte hash as both a hex string and a base64 string.

You can use the hex string in the Realm Browser GUI to unlock the realm file. You can use the base64 string with the base64-js library. Just pass the base64 string into base64js.toByteArray() and that is the key you would use in new Realm({encryptionKey: key...})

All 8 comments

The react-native-keychain only supports password strings, whereas Realm expects a 512-bit (64-byte) data blob as either an ArrayBuffer or ArrayBufferView (e.g. Uint8Array, et al).

If you're randomly generating a password, then I would suggest base64-encoding that data into a string before storing with react-native-keychain, then base64 decoding it when you get it out. I'd recommend checking out base64-js for dealing with raw data.

On the other hand, if the user is providing a password, then you can store that directly in the keychain and use a 512-bit hash of that password as the encryption key. A SHA-512 hash would accomplish that, but typically with encryption you want to use a hashing algorithm that includes a salt and is fundamentally slow, thus making it much harder to brute force. The standard for doing this is PBKDF2, though newer and better hashing methods exist. I'd recommend checking out crypto-js or pbkdf2-js for this.

Appden, thank you very much for your reply, much appreciated. We are going to try this out today, will circle back again soon with results.

@appden @celrak Would you be so kind and share a sample code , I'm also trying to do something similar, much appreciated!

We wil add some example code

You can use a site like https://asecuritysite.com/encryption/PBKDF2z to generate a 64 byte hash as both a hex string and a base64 string.

You can use the hex string in the Realm Browser GUI to unlock the realm file. You can use the base64 string with the base64-js library. Just pass the base64 string into base64js.toByteArray() and that is the key you would use in new Realm({encryptionKey: key...})

@agersoncgps and @alazier The site you've mentioned will always not generate a 64 byte length string and hence the base64-js library also creates a byte array with less than 64 bytes and hence the encryption is failing.

As an alternative, I am trying to use the following method with a plain string, encryption is working fine. But when I try to decrypt this with a hex string in Realm studio it is failing with error -> Realm file decryption failed
Any thoughts on this?

function toByteArray(str) {
    var array = new Int8Array(str.length);
    for (i = 0; i < str.length; i++) {
        array[i] = str.charCodeAt(i);
    }
    return array;
}

I am running Realm 2.11.0 in Node.js 8.11.0. I generated a 64-byte base64 hash at https://asecuritysite.com/encryption/PBKDF2z, copied and pasted it into my code, and ran:

  const b64 = 'mxEfOX1HNhh0Yv1AIggk7HcdoNU3hcJBOGMN5TXf6xtSUgAQySAlQuNLXtQNmh27RVmwXbhaFuO8lvg8hsr5GQ==';
  const key = base64js.toByteArray(b64);
  const user = await Realm.Sync.User.login({AUTH_URL}, {USERNAME}, {PASSWORD});
  const realmConfig = user.createConfiguration({ encryptionKey: key });

I get the following error message:

Error: encryptionKey must be of type 'binary', got ([object Object])

I've tried all kinds of other permutations of ArrayBuffers and Int8Arrays with the same result. Any suggestions? How does Realm expect the encryption key to be sent from Node and Javascript?

Thanks!

Closing as this seems outdated. Please reopen in case this is still a problem.

Was this page helpful?
0 / 5 - 0 ratings