1

Im trying to encrypt the data stored in the realm database. I followed the Sample Code mentioned on Realm's Swift page. I want to encrypt the data NOT the database file. Below is the code I'm using:

    var error: NSError? = nil
    let configuration = Realm.Configuration(encryptionKey: EncryptionManager().getKey())

    if let realmE = Realm(configuration: configuration, error: &error) {
        // Add an object
        realmE.write {
            realmE.add(objects, update: T.primaryKey() != nil)
        }
    }

Where objects is a list of objects i need to insert in the database. Below is the code fore getKey() func also picked from the sample code:

func getKey() -> NSData {
    // Identifier for our keychain entry - should be unique for your application
    let keychainIdentifier = "io.Realm.test"
    let keychainIdentifierData = keychainIdentifier.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!

    // First check in the keychain for an existing key
    var query: [NSString: AnyObject] = [
        kSecClass: kSecClassKey,
        kSecAttrApplicationTag: keychainIdentifierData,
        kSecAttrKeySizeInBits: 512,
        kSecReturnData: true
    ]

    // To avoid Swift optimization bug, should use withUnsafeMutablePointer() function to retrieve the keychain item
    // See also: http://stackoverflow.com/questions/24145838/querying-ios-keychain-using-swift/27721328#27721328
    var dataTypeRef: AnyObject?
    var status = withUnsafeMutablePointer(&dataTypeRef) { SecItemCopyMatching(query, UnsafeMutablePointer($0)) }
    if status == errSecSuccess {
        return dataTypeRef as! NSData
    }

    // No pre-existing key from this application, so generate a new one
    let keyData = NSMutableData(length: 64)!
    let result = SecRandomCopyBytes(kSecRandomDefault, 64, UnsafeMutablePointer<UInt8>(keyData.mutableBytes))

    // Store the key in the keychain
    query = [
        kSecClass: kSecClassKey,
        kSecAttrApplicationTag: keychainIdentifierData,
        kSecAttrKeySizeInBits: 512,
        kSecValueData: keyData
    ]

    status = SecItemAdd(query, nil)
    assert(status == errSecSuccess, "Failed to insert the new key in the keychain")

    return keyData
}

The problem is this that the code is not getting encrypted. After inserting data when i open the realm file using Realm Browser the code is NOT encrypted.

Tested on both simulator and device. Using Swift 1.2, Xcode 6.4, Realm 0.95.

Any ideas?

iAmd
  • 812
  • 1
  • 12
  • 22
  • Just to be clear, when you say "encrypt the data, not the database", does that really mean that you want to individually encrypt/decrypt just the objects in the database, but leave the whole realm database itself un-encrypted? – TiM Sep 23 '15 at 03:53
  • @TiM Yes, the objects in the database. Not the database itself. – iAmd Sep 23 '15 at 06:41
  • Haha alrighty. This might be a bit of a challenge to pull off. I'll do some research and see what I can come up with. – TiM Sep 23 '15 at 08:32

1 Answers1

7

Realm's encryption feature applies only to the ability to encrypt whole .realm files. There's no feature to encrypt discrete objects within the .realm file and leave the rest as-is.

If you do want to go about doing this, I'm afraid you would need to roll the encryption system yourself.

If I was going to do this, I'd do it this way:

  1. Create a Realm Object subclass with an NSData property called encryptedData.
  2. Serialize any objects you wanted to encrypt to NSData using the NSCoding protocol. (Saving custom SWIFT class with NSCoding to UserDefaults)
  3. Encrypt that resulting NSData object using an encryption method of your choice (AES Encryption for an NSString on the iPhone)
  4. Take the resulting encrypted NSData object and save it to the encryptedData property in your Realm object.
  5. Reverse the process when you want to retrieve that data.

While this process would work, as you can see, it's a non-trivial amount of extra work, and you would also lose all of the speed and memory-saving benefits of Realm in the process.

I would encourage you to rethink your app's design, and see if it is feasible to use Realm's own encryption feature after all. Good luck!

Community
  • 1
  • 1
TiM
  • 15,812
  • 4
  • 51
  • 79
  • Thanks @TiM. I read in the docs that the file based encryption will only work when user has passcode enabled. Only in that case file protection will be enabled. Will this encryption work if user hasn't set the passcode? – iAmd Sep 23 '15 at 12:12
  • 1
    No problems! On the low-level end of the system, that is correct. If you set a passcode on your device, the contents of the flash drive in your iOS device will be encrypted with that passcode. Both Realm's, and the process I mentioned above are separate encryption processes, done manually on the third-party app level. – TiM Sep 23 '15 at 14:47
  • Not at all! Actually, one thing that just occurred to me. If you're looking to encrypt only a specific class of objects (i.e. maybe an object that holds a username and password - very sensitive information), then it might even make sense to simply break all of those objects out and save them to their own encrypted Realm file, and simply leave the rest of your objects unencrypted in the default Realm file. :) – TiM Sep 24 '15 at 05:06