For up-to-date product documentation, see the IBM MobileFirst Foundation Developer Center.


Encrypting data on the device

To enable the encryption of local data stores on mobile devices, we must make updates to our application to include encryption capabilities and create encrypted data stores.

Parent topic: Migrating apps storing mobile data in Cloudant with IMFData or Cloudant SDK


Encrypting data on iOS devices


Procedure

  1. Obtain the encryption capabilities with CocoaPods.
    1. Open your Podfile and add the following line:

      BEFORE (with IMFData/CloudantToolkit):

      pod 'IMFDataLocal/SQLCipher'

      AFTER (with Cloudant Sync):

      pod 'CDTDatastore/SQLCipher' For more information, see the CDTDatastore encryption documentation.

    2. Run the following command to add the dependencies to your application.

      pod install

  2. To use the encryption feature within a Swift application, add the following imports to the associated bridging header for the application: BEFORE (with IMFData/CloudantToolkit):

    #import <CloudantSync.h> #import <CloudantSyncEncryption.h> #import <CloudantToolkit/CloudantToolkit.h> #import <IMFData/IMFData.h>

    AFTER (with Cloudant Sync):

    #import <CloudantSync.h> #import <CloudantSyncEncryption.h>

  3. Initialize your local store for encryption with a key provider.

    Warning: If you change the password after creating the database, an error occurs because the existing database cannot be decrypted. We cannot change your password after the database has been encrypted. You must delete the database to change passwords.

    BEFORE (with IMFData/CloudantToolkit):

    //Get reference to data manager IMFDataManager *manager = [IMFDataManager sharedInstance]; NSString *name = @"automobiledb"; NSError *error = nil; // Initalize a key provider id<CDTEncryptionKeyProvider> keyProvider = [CDTEncryptionKeychainProvider providerWithPassword: @"passw0rd" forIdentifier: @"identifier"]; //Initialize local store CDTStore *localStore = [manager localStore: name withEncryptionKeyProvider: keyProvider error: &error];

    let manager = IMFDataManager.sharedInstance() let name = "automobiledb" let keyProvider = CDTEncryptionKeychainProvider(password: "passw0rd", forIdentifier: "identifier") var store:CDTStore? do { store = try manager.localStore(name, withEncryptionKeyProvider: keyProvider) } catch let error as NSError { // Handle error }

    AFTER (with Cloudant Sync):

    // Get reference to datastore manager CDTDatastoreManager *datastoreManager = existingDatastoreManager; NSString *name = @"automobiledb"; NSError *error = nil; // Create KeyProvider id<CDTEncryptionKeyProvider> keyProvider = [CDTEncryptionKeychainProvider providerWithPassword: @"passw0rd" forIdentifier: @"identifier"]; //Create local store CDTDatastore *datastore = [datastoreManager datastoreNamed:name withEncryptionKeyProvider:keyProvider error:&error];

    // Get reference to datastore manager let datastoreManager:CDTDatastoreManager = existingDatastoreManager let name:String = "automobiledb" //Create local store var datastore:CDTDatastore? let keyProvider = CDTEncryptionKeychainProvider(password: "passw0rd", forIdentifier: "identifier") do{ datastore = try datastoreManager.datastoreNamed(name, withEncryptionKeyProvider: keyProvider) }catch let error as NSError{ // Handle error }

  4. When we are replicating data with an encrypted local store, we must initialize the CDTPullReplication and CDTPushReplication methods with a key provider.

    BEFORE (with IMFData/CloudantToolkit):

    //Get reference to data manager IMFDataManager *manager = [IMFDataManager sharedInstance]; NSString *databaseName = @"automobiledb"; // Initalize a key provider id<CDTEncryptionKeyProvider> keyProvider = [CDTEncryptionKeychainProvider providerWithPassword:@"password" forIdentifier:@"identifier"]; // pull replication CDTPullReplication *pull = [manager pullReplicationForStore: databaseName withEncryptionKeyProvider: keyProvider]; // push replication CDTPushReplication *push = [manager pushReplicationForStore: databaseName withEncryptionKeyProvider: keyProvider];

    //Get reference to data manager let manager = IMFDataManager.sharedInstance() let databaseName = "automobiledb" // Initalize a key provider let keyProvider = CDTEncryptionKeychainProvider(password: "password", forIdentifier: "identifier") // pull replication let pull:CDTPullReplication = manager.pullReplicationForStore(databaseName, withEncryptionKeyProvider: keyProvider) // push replication let push:CDTPushReplication = manager.pushReplicationForStore(databaseName, withEncryptionKeyProvider: keyProvider) AFTER (with Cloudant Sync):

    Replication with an encrypted database requires no changes from replication with an unencrypted database.

Android


Encrypting data on Android devices

To encrypt data on an Android device, obtain encryption capabilities by including the correct libraries in your application. Then, we can initialize your local store for encryption and replicate data.


Procedure

  1. Add the Cloudant Toolkit library as a dependency in your build.gradle file: BEFORE (with IMFData/CloudantToolkit):

    repositories { mavenCentral() } dependencies { compile 'com.ibm.mobile.services:cloudant-toolkit-local:1.0.0' }

    AFTER (with Cloudant Sync):

    repositories { mavenLocal() maven { url "http://cloudant.github.io/cloudant-sync-eap/repository/" } mavenCentral() } dependencies { compile group: 'com.cloudant', name: 'cloudant-sync-datastore-core', version:'0.13.2' compile group: 'com.cloudant', name: 'cloudant-sync-datastore-android', version:'0.13.2' compile group: 'com.cloudant', name: 'cloudant-sync-datastore-android-encryption', version:'0.13.2' }

  2. Download the SQLCipher for Android v3.2 .jar and .so binary files and include them in your application in the appropriate folders within your app structure:
    1. Add libraries. Add the shared library files and SQLCipher archive to the jniLibs folder under your Android app directory.
    2. Add the required ICU compressed file to the assets folder in your app.
    3. Add sqlcipher.jar as a file dependency. From the app folder menu in Android studio, select the Dependencies tab under Open Module Settings.
  3. Initialize your local store for encryption with a key provider.

    Warning: If you change the password after you create the database, an error occurs because the existing database cannot be decrypted. We cannot change your password after the database is encrypted. You must delete the database to change passwords.

    BEFORE (with IMFData/CloudantToolkit):Android

    // Get reference to DataManager DataManager manager = DataManager.getInstance(); // Initalize a key provider KeyProvider keyProvider = new AndroidKeyProvider(getContext(),"password","identifier"); // Create local store String databaseName = "automobiledb"; Task<Store> storeTask = manager.localStore(databaseName, keyProvider); storeTask.continueWith(new Continuation<Store, Void >() { @Override public Void then(Task<Store> task) throws Exception { if (task.isFaulted()) { // Handle error } else { // Do something with Store Store store = task.getResult(); } return null; } });

    AFTER (with Cloudant Sync):Android

    // Load SQLCipher libs SQLiteDatabase.loadLibs(context); // Create DatastoreManager File path = context.getDir("databasedir", Context.MODE_PRIVATE); DatastoreManager manager = new DatastoreManager(path.getAbsolutePath()); // Create encrypted local store String name = "automobiledb"; KeyProvider keyProvider = new AndroidKeyProvider(context,"passw0rd","identifier"); Datastore datastore = manager.openDatastore(name, keyProvider);

  4. When we are replicating data with an encrypted local store, we must pass a KeyProvider object into the pullReplicationForStore() or pushReplicationForStore() method.

    BEFORE (with IMFData/CloudantToolkit):Android

    //Get reference to data manager DataManager manager = DataManager.getInstance(); String databaseName = "automobiledb"; // Initalize a key provider KeyProvider keyProvider = new AndroidKeyProvider(getContext(),"password","identifier"); // pull replication Task<PushReplication> pullTask = manager.pullReplicationForStore(databaseName, keyProvider); // push replication Task<PushReplication> pushTask = manager.pushReplicationForStore(databaseName, keyProvider); AFTER (with Cloudant Sync):

    Replication with an encrypted database requires no changes from replication with an unencrypted database.