Realm Cocoa Tutorial: Encryption with Realm

When a user inputs personal information into an app, there’s an implicit promise to keep that information safe. A large number of products and services still treat security as an after-thought as opposed to a core component of their design.

In version 0.89 of Realm Objective-C (and later Realm Swift), we introduced the ability to encrypt Realm files. Utilizing a 64-byte key backed by AES-256+SHA2 encryption, Realm’s encryption ability is secure enough that banks started using it in their customer smartphone apps.

Incorporating encryption in Realm is incredibly easy, only requiring one extra setting in the Realm’s configuration settings.

Implementation

To enable encryption on a file in Realm, set the encryptionKey property in the Configuration / RLMRealmConfiguration object of a Realm / RLMRealm instance:

Swift

// Generate 64 bytes of random data to serve as the encryption key
let key = NSMutableData(length: 64)!
SecRandomCopyBytes(kSecRandomDefault, key.length, UnsafeMutablePointer<UInt8>(key.mutableBytes))

// Set up a new Realm Configuration object with the key
let encryptionConfig = Realm.Configuration(encryptionKey: key)

// Attempt to open the encrypted Realm
do {
  let realm = try Realm(configuration: encryptionConfig)
  // At this point, the key was accepted and we can use the Realm as normal
  let dogs = realm.objects(Dog.self).filter("name contains 'Fido'")
}
catch let error as NSError {
  // If the encryption key was not accepted, the error will state that the database was invalid
  fatalError("Error opening Realm: \(error)")
}

Objective-C

// Generate 64 bytes of random data to serve as the encryption key
uint8_t buffer[64];
SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
NSData *keyData = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];

// Create a Realm Configuration object with the encryption key
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
configuration.encryptionKey = keyData;

// Attempt to open a Realm file with the encryption key
NSError *error = nil;
RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration error:&error];

// If the encryption key was not accepted, the error will state that the database was invalid
if (error != nil) {
  NSLog(@"%@", error.localizedDescription);
  return;
}

// At this point, the key was accepted and we can use the Realm as normal
RLMResults *dogs = [Dog objectsWhere:@"name contains 'Fido'"];

Implementation Continued

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 arbitrary error stating that the database was ‘invalid’.

Before, it wasn’t possible to have a debugger attached to your app while an encrypted Realm was in use, as it interfered with LLDB. However as of version 0.97, the encrypted Realms can be debugged as easily as normal ones.

Limitations

Once a encryption key has been set, it’s not possible to change it for that Realm file. If you want to change the encryption key, you can export copies of the Realm file (using writeCopyToPath(_:encryptionKey:)), setting a new encryption key on the copy. To note, encryption does introduce a small amount of overhead into Realm due to the necessary data encryption and decryption operations.

Keeping the Encryption Key Safe

While the data itself is safely protected by Realm, the biggest security concern is protecting the encryption key. Keeping the encryption key secure is the responsibility of the developer, and should be treated with the same level of scrutiny as handling a user’s account password.

For Realm files created specifically on a single device and are guaranteed to never be transferred off the device, the safest option to do this is to save the encryption key to the system security keychain.

The security keychain is a very strong storage location, and is the industry standard for storing user passwords on devices. For examples of how to save data to the security keychain, see the ‘Encryption’ example in our range of sample apps.

Regarding multiple devices, when an encrypted Realm file is copied to a new device, the encryption key must be made available on the new device. There are many ways to allow this - such as saving the encryption key to the keychain and synchronizing the keychain through iCloud, or through a custom online user login service.

When distributing apps via Apple’s App Store, there are certain legal obligations in regards to export compliance for apps that incorporate encryption.

This usually involves declaring to Apple that your app incorporates encryption, and depending on the nature of the data encrypted, filing a request for export registration with the United States Bureau of Industry and Security.

Certain exemptions from needing to register for most of the common encryption use-cases (such as user authentication) were introduced in 2010. As such, it is only necessary to declare to Apple that the app incorporates encryption during the submission process and nothing more.

More information about U.S. export compliance as well as the specific exemptions can be found on the Bureau of Industry and Security’s website.

Disclaimer: The information in this section should not be taken as formal legal advice. Your specific use-cases for encryption may vary. If you are unsure as to whether your app falls within the export compliance exemptions, please contact an attorney.

Conclusion

While normally considered a time-consuming and complex process, Realm makes encrypting sensitive user data inside apps a completely trivial process. All it takes is defining a key in a Realm file’s configuration, and everything beyond that is handled completely transparently.

By making encryption so easy to incorporate, we hope this helps encourage developers to properly protect their users’ data, and minimize data leaks in the future.

New Features in Realm Obj-C & Swift

We’ve released version 2.7 of Realm Objective‑C and Realm Swift! In this release, we’re introducing improved permission APIs, faster reconnects, password change and applying a few bug fixes to keep your apps running strong.


Tim Oliver

Tim Oliver

Tim Oliver hails from Perth, Australia! He has been an iOS developer for 6 years, and recently joined Realm in March 2015. Tim has a cool app called iComics and he loves karaoke! He does, in fact, also sometimes have the problem of too many kangaroos in his backyard.