Reputation: 706
I want to use an encrypted Realm database that is pre-populated with data. The problem is that I generate and store the key on the device locally, and so as you can imagine, the key doesn't work the moment I bring that realm file to another device. This is how I generate the encryption key.
func getKey() -> NSData {
// Identifier for our keychain entry - should be unique for your application
let keychainIdentifier = "io.Realm.Test12345"
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)!
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
}
Is there any way I could do this without explicitly stating a key that can open the file on all devices? I guess I could generate the database line-by-line in the code, and ensure it is encrypted from the start, however it isn't as convenient.
Upvotes: 2
Views: 567
Reputation: 15991
It's not possible to encrypt a Realm without explicitly specifying an encryption key. If you do not supply an encryption key at the time of the Realm file's creation, it will be created un-encrypted, and if you try and use a different key after that, the file will refuse to open.
It's possible to change the encryption key of a Realm file by saving a copy with a new key. Something you could potentially do is provide your encrypted Realm with an obfuscated encryption key along with the app, and on the first time of the app's launch, it creates a local copy of that Realm file, with a device-generated encryption key that becomes the main Realm after that point.
If you want extra security and don't want to bake an initial encryption key into the app, you could also consider including the encrypted Realm file along with the app, but you need to perform a secure web request to download the encryption key to open it.
I hope this gave you some ideas! :)
Upvotes: 2