Encrypting Realms

Last updated last month

Overview

The Realm Database can be configured to encrypt data at rest when using Realm on the mobile device. Enabling encryption of a realm file is as simple as adding a single line of code to the realm configuration. iOS, macOS, tvOS and watchOS versions of Realm use the CommonCrypto library whereas the Windows uses the built-in Crypto library and Android platforms use OpenSSL. Once a realm file has been created with an encryption key, that key will then be required every time that file is subsequently opened. If any attempts are made to open the file with the incorrect key (or no key at all), Realm will simply return an error stating that the database was ‘invalid’.

The User supplies a 64 byte encryption key. We recommend that this key is stored in the secure keychain or keystore of the device, of which most newer devices provide APIs backed by dedicated secure hardware (see Apple’s security white paper or Android’s security white paper for more information). The first 32 bytes are used for encryption. The next 24 bytes are used for the signature, with the remaining 8 bytes not used currently. In terms of how specifically we approach encryption: each 4KB block of data is encrypted with AES-256 using cipher block chaining (CBC) mode and a unique initialization vector (IV) which is never reused within a file, and then signed with a SHA-2 HMAC.

This strategy covers most attack vectors. The only option left for an attacker is to try to gain access to the pieces of decrypted data that is temporarily cached in-memory. On non-jailbroken devices there are operating system safeguards against this and in general this issue exists irrelevant of where the data originated from. In order to combat devices that can be jailbroken or rooted, giving an actor root-level privileges to the device, several Mobile Device Management (MDM) software providers or 3rd party libraries can be used. These give the ability to detect this level of corruption and remove sensitive data and apps from the device as well as flag the individual. The app developer can choose to employ a 3rd party library to detect if the device has been rooted or jailbroken, and refuse the user access to the app.

Swift
Java
// Generate a random encryption key
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { bytes in
SecRandomCopyBytes(kSecRandomDefault, 64, bytes)
}
// Open the encrypted Realm file
let config = Realm.Configuration(encryptionKey: key)
do {
let realm = try Realm(configuration: config)
// Use the Realm as normal
let dogs = realm.objects(Dog.self).filter("name contains 'Fido'")
} catch let error as NSError {
// If the encryption key is wrong, `error` will say that it's an invalid database
fatalError("Error opening realm: \(error)")
}
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
RealmConfiguration config = new RealmConfiguration.Builder()
.encryptionKey(key)
.build();
Realm realm = Realm.getInstance(config);
Realm Object Server
Coupled with the Realm Database, the Realm Object Server is the other half of the coin of the Realm Platform which can also be configured to present a stout security posture for your mobile stack. To configure the data while in transit from the mobile to your backend or vice versa, you will need to add a valid certificate to your backend Realm Object Server. Before starting the server open the configuration file in `/etc/realm/configuration.yml` to enable HTTPS and disable HTTP. Here is a sample configuration:
proxy:
https:
enable: true
listen_address:192.168.0.2'
certificate_path ‘/etc/realm/myCert.pem`
private_key_path ‘/etc/realm/myKey.pem`
http:
enable: false