Realm Custom Configuration and Encryption (RealmSwift Part 3)

https://realm.io/docs/swift/latest/

In this part we will cover following topics

  1. How to store data on your custom location
  2. How to Pre bundle Realm file
  3. How to Create Pre Bundle Data and How to Use it
  4. How to do encryption in Realm
  5. Limitations of encryption in Realm
  6. Sharing Of Realm Between App and Extension with example

This is the continuation of the previous part . If you know the basics operation in Realm you can continue this.

As shown in Figure 1 this create a Realm file with default configuration and Realm by default created a file on Documents folder with name default.realm. You can change the name of the file and location by giving configuration parameter

Note: Storing files in a documents folder are automatically backed up to the user’s iCloud and iTunes storage. According to the App Backup Best Practices section of the iOS App Programming Guide <Application_Data>/Library/Caches or <Application_Data>/tmp will not backup to iCloud. Generally, you can use <Application_Data>/Library/Caches directory to save your data that you won’t backup to iCloud.

Custom Location

As shown in Figure 2 we created a realm file on custom location with the name main.realm . You are thinking if you are working on the real project you have to create configuration and realm instance every time. There is a better way and we will discuss it shortly.

Pre Bundle Realm File

You can ship pre bundle data with the application since bundle data is read only you can’t modify it and if you want to modify that data, you need to move this data to some writable location

Creation Of Pre Bundle Data

Download the starter project for playaround this. All code is written in there you can comment out methods to understand thing and make sure whenever told delete the application as well. To do that, tap and hold the app icon until it starts to jiggle and then tap the top-left “X” icon to delete it.

As shown in Figure 3 we added two airports object into the realm and created a realm file with name “Bundle.realm”.

As shown in Figure 3.1 inLibrarayFolder utility method code

Drag and drop the realm file into the project to bundle the data into the project and delete the application

Usage Of Pre Bundle Data

As shown in figure 5 we are reading from the bundle data that is shipped with the application

Copy Pre Bundle Data

As shown in Figure 6 we made a case for a user who has the existing data of the previous version and for the new version we need to copy new data. We will copy only the new pieces of data to the app’s working file.

As shown in Figure 7 we successfully added newly object into the existing database. We performed these steps to accomplish this

  1. Get the reference of existing Realm file instance
  2. Get the reference of bundled Realm file instance
  3. Iterate through the bundled objects and check if it exists in the existing database and add the ones that aren’t present in both to needsToCopy variable
  4. Copy all of the objects from needsToCopy over to mainRealm.

Note: To make it efficient use primary key and check the existing of object through it

As shown in Figure 8 objects are stored physically. Refer to part 1 if you don’t know how to see objects stored on a disk.

You are thinking why we use realm.create instead of realm.add and you will find the answer in the console in Figure 9, since we are adding object which is managed by bundle realm into some other realm (main.Realm). realm.create first create an object on main Realm and then add it to the realm.

add(_:update:) → Adds or updates an object to be persisted it in this Realm.
create(_:value:update:) → Creates or updates an instance of this object and adds it to the Realm populating the object with the given value.

Sometimes you only need pre bundle when user first install your application. In this case you can completely replace the bundled data into the some writable location as shown in Figure 10 so that in future you can update the data from the server.

Encryption

One of the reason people are choosing Realm over CoreData is that they makes creating and working with encrypted data incredibly simple. You set the encryptionKey property on your configuration with the desired key to encrypt and decrypt the file, and Realm automatically does the rest for you. The first time you open your encrypted file, Realm creates it on disk and encrypts it with the given key. Any time in the future you’d like to read or write data, you need to use the same configuration with the same encryption key.

Realm supports encrypting the database file on disk with AES-256+SHA2 by supplying a 64-byte encryption key when creating a Realm.There is a small performance hit (typically less than 10% slower) when using encrypted Realms.

Since key should be 64-byte we will use SHA-512 hash algorithm that generates 512 bits, that is 64 bytes from the string. A hash is a string or number generated from a string of text. The resulting string or number is a fixed length, and will vary widely with small variations in input. The best hashing algorithms are designed so that it’s impossible to turn a hash back into its original string.

Note: There is no support of sharing encrypted realms across processes. Issue is open https://github.com/realm/realm-cocoa/issues/1693 Opening encrypted realms on multiple threads works as normal.

As shown in Figure 11 we created a String extension that return 64 bytes hash key in Data format which is needed for the configuration of the Realm file.

As shown in Figure 12 we copied main.realm data into encrypted.realm file and Realm used our 64 bytes key to do AES-256+SHA2 encryption of the file. Use an autorelease pool to close the Realm at the end of the block otherwise it will take some time to close. You can create some utility to delete main.realm, main.realm.lock and main.realm.management to free space.

As shown in Figure 13 we are reading from the encrypted Realm file.

Note: 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. The safest option to do this is to save the encryption key to the system security keychain

As shown in Figure 14 opening a encrypted Realm with a wrong key generate an exception

As shown in Figure 15 opening a encrypted Realm with Realm Studio also ask key for the decryption of the Realm file

Sharing Of Realm Between App and Extension

As shown in Figure 16 we are successfully get the airports object from the application and it return airports store in the database

As shown in Figure 17 when accessing main.realm in Today extension we don’t get any airports object.

Today extension are a way to give users quick access to information that’s important right now. The data stored within an app is not visible to the extension and vice versa since both are different process and direct interprocess communication is not allowed by apple for the security reasons.

Apple offers a way to solve the issue through app groups. App groups, like bundle identifiers, are defined by a reverse URI and they are prefixed with group.. They let you share data between your apps and are tightly bound to your provisioning profile .

As we created main.realm in host application Library folder which is not visible to Today extension since it has its Library folder, you can see the difference of the Library folder path in Figure 16 and 17. We can take advantage of App Group to create our Realm database in a shared space that will be visible (and writeable) by both our app and the app’s WatchKit extension

App groups allow multiple apps produced by a single development team to access shared containers and communicate using interprocess communication (IPC). Apps may belong to one or more app groups.

As shown in Figure 18 we copied bundled Realm into shared Realm which is in shared container that is accessible by host and extension apps. Make sure first check if file not exists before copy otherwise you will get “bundle.realm” couldn’t be copied to “53BF3E8A-8C6C-4E8A-A212–45CCAA759808” because an item with the same name already exists”.

As shown in Figure 19 we are now successfully accessing shared data between host and extension apps using app group. You can see the Realm file path is same also . You can download complete code from this url with title “PreBundleDataRealm

Note: There is no support of sharing encrypted realms across processes. Issue is open https://github.com/realm/realm-cocoa/issues/1693 Opening encrypted realms on multiple threads works as normal.

Useful Links

https://store.raywenderlich.com/products/realm-building-modern-swift-apps-with-realm-database

Senior iOS Engineer | HungerStation | Delivery Hero