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();
  }
}

Was this information helpful? Send us your comments.