Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

Security of persistent objects

BlackBerry Device Software provides two main ways to secure objects in the persistent store:

Depending on the needs of your application, you could use both, one, or neither of these approaches.

Restricting access to persistent objects

Objects that are stored using the persistent store are identified by a unique key, which has a value that is of primitive type long. To retrieve an object from the persistent store, the key that was associated with the object when it was stored must be supplied in method calls. For example:

long key = 0x52834c0559055c3L;
PersistentObject rec = PersistentStore.getPersistentObject(key);
String stored_value = (String) rec.getContents();

Relying on the key value being unknown may not provide adequate privacy for stored information. If you want to permit only specific, authorized applications to access your application data, you should wrap the PersistentObject in a net.rim.device.api.system.ControlledAccess class in conjunction with key generation and a key-signing procedure:

  • Create a signing key using the BlackBerry Signing Authority Tool.
  • Associate a ControlledAccess object with the signing key.
  • Wrap the PersistentObject in the ControlledAccess object.
  • Sign applications that require access to the protected data using the same signing key that protects the data.

Here is an example of how to retrieve data that is protected with the ControlledAccess class:

long key = 0x52834c0559055c3L;
try {
    PersistentObject rec = PersistentStore.getPersistentObject(key);
    int moduleHandle = ApplicationDescriptor.currentApplicationDescriptor​().getModuleHandle();
    CodeSigningKey codeSigningKey = CodeSigningKey.get( moduleHandle, "MDW" );
    String b = (String) rec.getContents( codeSigningKey );
    Dialog.inform("Read PersistentObject. Value="+b);
}   catch (ControlledAccessException e) {
    Dialog.alert("ControlledAccessException - not authorised to read this data");
}

For more information about restricting access to persistent objects, see Protect persistent objects from access by unauthorized applications.

For more information about code signing, see the BlackBerry Java SDK Security Development Guide, available at www.blackberry.com/go/devguides.

Code sample

The .cod file for the following code must be signed with the key that is used as the CodeSigningKey to protect the data.

import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.CodeSigningKey;
import net.rim.device.api.system.ControlledAccess;
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
import net.rim.device.api.ui.*;

public class ControlledAccessCreator extends UiApplication {
  public static void main(String[] args) {
    ControlledAccessCreator cac = new ControlledAccessCreator();
    cac.enterEventDispatcher();
  }
  private ControlledAccessCreator() {
    ControlledAccessCreatorScreen screen = new ControlledAccessCreatorScreen();
    pushScreen(screen);
  }
}

class ControlledAccessCreatorScreen extends MainScreen {	
  private MenuItem _initialiseMenuItem = new MenuItem("Initialise", 100, 10) {
    public void run() {
      String a = "Hello";
      long key = 0x52834c0559055c3L;
      PersistentObject rec = PersistentStore.getPersistentObject(key);
      int moduleHandle = ApplicationDescriptor.currentApplicationDescriptor().getModuleHandle();
      CodeSigningKey codeSigningKey = CodeSigningKey.get( moduleHandle, "MDW" );
      rec.setContents(new ControlledAccess(a,codeSigningKey));
      rec.commit();
      String b = (String) rec.getContents( codeSigningKey );
      Dialog.inform("Initialised... now try to acccess the data from another app");
      invalidate();
    }
  };
  ControlledAccessCreatorScreen() {
    setTitle(new LabelField("ControlledAccess Demo",
	   LabelField.USE_ALL_WIDTH));
    addMenuItem(_initialiseMenuItem);
  }
  public boolean onSavePrompt() {
    return true;
  }
  public void close() {
    super.close();
  }
}

The .cod file for the following code must be signed using the key that was used for the sample code above.

import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.CodeSigningKey;
import net.rim.device.api.system.ControlledAccess;
import net.rim.device.api.system.ControlledAccessException;
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
import net.rim.device.api.ui.*;

public class ControlledAccessAuthorisedUser extends UiApplication {
  public static void main(String[] args) {
    ControlledAccessAuthorisedUser caau = new ControlledAccessAuthorisedUser();
    caau.enterEventDispatcher();
  }
  private ControlledAccessAuthorisedUser() {
    ControlledAccessAuthorisedUserScreen screen = new ControlledAccessAuthorisedUserScreen();
    pushScreen(screen);
  }
}
class ControlledAccessAuthorisedUserScreen extends MainScreen {	
  private MenuItem _readMenuItem = new MenuItem("Read protected data", 100, 10) {
      public void run() {
        long key = 0x52834c0559055c3L;
        try {
	 PersistentObject rec = PersistentStore.getPersistentObject(key);
	 int moduleHandle = ApplicationDescriptor.currentApplicationDescriptor().getModuleHandle();
    CodeSigningKey codeSigningKey = CodeSigningKey.get( moduleHandle, "MDW" );
	  String b = (String) rec.getContents( codeSigningKey );
	  Dialog.inform("Read PersistentObject. Value="+b);
        } catch (ControlledAccessException e) {
	  Dialog.alert("ControlledAccessException - not authorised to read this data");
        }
    }
  };
  ControlledAccessAuthorisedUserScreen() {
    setTitle(new LabelField("ControlledAccess Demo",
	      LabelField.USE_ALL_WIDTH));
    addMenuItem(_readMenuItem);
  }

  public boolean onSavePrompt() {
    return true;
  }
  public void close() {
    super.close();
  }
}

Restrict access to persistent store data using code signing keys

Code signing keys can be used to control access to the persistent store. This is a way to restrict or share access with other apps on a BlackBerry smartphone.

Import the required classes and interfaces.

import java.util.Hashtable;
import net.rim.device.api.system.PersistentObject;

Create a hash ID for the object you want to store in a persistent object.

long MY_DATA_ID = 0x33abf322367f9018L;
Hashtable myHashtable = new Hashtable();

Store the object in the persistent object and protect the object with the CodeSigningKey object. For example, after your app runs the following line of code, only .cod files that are signed with the RSAE .key file can read or overwrite the object in the persistent object.

persistentObject.setContents( new ControlledAccess( myHashtable, key ) );

Make sure that the object is protected, and invoke getContents using the CodeSigningKey object as a parameter.

Hashtable myHashtable = (Hashtable) persistentObject.getContents( key );