de.schlichtherle.key
Class KeyManager

java.lang.Object
  extended by de.schlichtherle.key.KeyManager
Direct Known Subclasses:
PromptingKeyManager

public class KeyManager
extends Object

An abstract class which maintains a static map of KeyProvider instances for any protected resource which clients need to create or open. This key manager class is designed to be of general purpose: Resources are simply represented by a string as their identifier, called the resource identifier or resource ID for short. For each resource ID, a key provider may be associated to it which handles the actual retrieval of the key.

Clients need to call getInstance() to get the default instance. Because the map of key providers and some associated methods are static members of this class, the default instance of this class may be changed dynamically (using setInstance(de.schlichtherle.key.KeyManager)) without affecting already mapped key providers. This allows to change other aspects of the implementation dynamically (the user interface for example) without affecting the key providers and hence the keys.

Implementations need to subclass this class and provide a public no-arguments constructor. Finally, an instance of the implementation must be installed either by calling setInstance(KeyManager) or by setting the system property de.schlichtherle.key.KeyManager to the fully qualified class name of the implementation before this class is ever used. In the latter case, the class will be loaded using the context class loader of the current thread.

Note that class loading and instantiation may happen in a JVM shutdown hook, so class initializers and constructors must behave accordingly. In particular, it's not permitted to construct or use a Swing GUI there.

This class is thread safe.

Since:
TrueZIP 6.0
Version:
TrueZIP 6.7
Author:
Christian Schlichtherle

Nested Class Summary
protected static interface KeyManager.KeyProviderCommand
          Implemented by sub classes to define commands which shall be executed on key providers with the forEachKeyProvider(de.schlichtherle.key.KeyManager.KeyProviderCommand) method.
 
Constructor Summary
KeyManager()
          Creates a new KeyManager.
 
Method Summary
protected static void forEachKeyProvider(KeyManager.KeyProviderCommand command)
          Executes a KeyManager.KeyProviderCommand for each mapped key provider.
static KeyManager getInstance()
          Returns the default instance of the key manager.
 KeyProvider getKeyProvider(String resourceID)
          Deprecated. Use #getKeyProvider(String, Class) instead.
 KeyProvider getKeyProvider(String resourceID, Class keyProviderType)
          Returns the KeyProvider for the given resource identifier.
protected  void mapKeyProviderType(Class forKeyProviderType, Class useKeyProviderType)
          Subclasses must use this method to register default implementation classes for the interfaces KeyProvider and AesKeyProvider and optionally other subinterfaces or subclasses of KeyProvider.
static boolean moveKeyProvider(String oldResourceID, String newResourceID)
          Moves a key provider from one resource identifier to another.
static void resetAndClearKeyProviders()
          Deprecated. Use resetAndRemoveKeyProviders() instead.
static boolean resetAndRemoveKeyProvider(String resourceID)
          Resets the key provider for the given resource identifier, causing it to forget its common key, and throws the key provider away.
static void resetAndRemoveKeyProviders()
          Resets all key providers, causing them to forget their key, and removes them from the map.
static boolean resetKeyProvider(String resourceID)
          Resets the key provider for the given resource identifier, causing it to forget its common key.
static void resetKeyProviders()
          Resets all key providers, causing them to forget their respective common key.
static void setInstance(KeyManager keyManager)
          Sets the default instance of the key manager explicitly.
 void setKeyProvider(String resourceID, KeyProvider provider)
          Sets the key provider programmatically.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

KeyManager

public KeyManager()
Creates a new KeyManager. This class does not map any key provider types. This must be done in the subclass using mapKeyProviderType(java.lang.Class, java.lang.Class).

Method Detail

getInstance

public static KeyManager getInstance()
Returns the default instance of the key manager.

If the default instance has been explicitly set using setInstance(de.schlichtherle.key.KeyManager), then this instance is returned.

Otherwise, the value of the system property de.schlichtherle.key.KeyManager is considered:

If this system property is set, it must denote the fully qualified class name of a subclass of this class. The class is loaded by name using the current thread's context class loader and instantiated using its public, no-arguments constructor.

Otherwise, if the JVM is running in headless mode and the API conforms to JSE 6 (where the class java.io.Console is available), then the console I/O based implementation in the class PromptingKeyManager is loaded by name using the current thread's context class loader and instantiated using its public, no-arguments constructor.

Otherwise, the Swing based implementation in the class PromptingKeyManager is loaded by name using the current thread's context class loader and instantiated using its public, no-arguments constructor.

In order to support this plug-in architecture, you should not cache the instance returned by this method!

Throws:
ClassCastException - If the class name in the system property does not denote a subclass of this class.
UndeclaredThrowableException - If any other precondition on the value of the system property does not hold.

setInstance

public static void setInstance(KeyManager keyManager)
Sets the default instance of the key manager explicitly.

Parameters:
keyManager - The key manager to use as the default instance. If this is set to null, on the next call to getInstance() the default instance will be recreated.

resetKeyProvider

public static boolean resetKeyProvider(String resourceID)
Resets the key provider for the given resource identifier, causing it to forget its common key. This works only if the key provider associated with the given resource identifier is an instance of AbstractKeyProvider. Otherwise, nothing happens.

Parameters:
resourceID - The resource identifier.
Returns:
Whether or not an instance of AbstractKeyProvider is mapped for the resource identifier and has been reset.

resetAndRemoveKeyProvider

public static boolean resetAndRemoveKeyProvider(String resourceID)
Resets the key provider for the given resource identifier, causing it to forget its common key, and throws the key provider away. If the key provider associated with the given resource identifier is not an instance of AbstractKeyProvider, it is just removed from the map.

Parameters:
resourceID - The resource identifier.
Returns:
Whether or not a key provider was mapped for the resource identifier and has been removed.

resetKeyProviders

public static void resetKeyProviders()
Resets all key providers, causing them to forget their respective common key. If a mapped key provider is not an instance of AbstractKeyProvider, nothing happens.


resetAndClearKeyProviders

public static final void resetAndClearKeyProviders()
Deprecated. Use resetAndRemoveKeyProviders() instead.


resetAndRemoveKeyProviders

public static void resetAndRemoveKeyProviders()
Resets all key providers, causing them to forget their key, and removes them from the map. If the key provider associated with the given resource identifier is not an instance of AbstractKeyProvider, it is just removed from the map.

Throws:
IllegalStateException - If resetting or unmapping one or more key providers is prohibited by a constraint in a subclass of AbstractKeyProvider, in which case the respective key provider(s) are reset but remain mapped. The operation is continued normally for all other key providers. Please refer to the respective subclass documentation for more information about its constraint(s).
Since:
TrueZIP 6.1

forEachKeyProvider

protected static void forEachKeyProvider(KeyManager.KeyProviderCommand command)
Executes a KeyManager.KeyProviderCommand for each mapped key provider. It is safe to call any method of this class within the command, even if it modifies the map of key providers.


moveKeyProvider

public static boolean moveKeyProvider(String oldResourceID,
                                      String newResourceID)
                               throws NullPointerException,
                                      IllegalStateException
Moves a key provider from one resource identifier to another. This may be useful if a protected resource changes its identifier. For example, if the protected resource is a file, the most obvious identifier would be its canonical path name. Calling this method then allows you to rename a file without the need to retrieve its keys again, thereby possibly prompting (and confusing) the user.

Returns:
true if and only if the operation succeeded, which means that there was an instance of KeyProvider associated with oldResourceID.
Throws:
NullPointerException - If oldResourceID or newResourceID is null.
IllegalStateException - If unmapping or mapping the key provider is prohibited by a constraint in a subclass of AbstractKeyProvider, in which case the transaction is rolled back before this exception is (re)thrown. Please refer to the respective subclass documentation for more information about its constraint(s).

mapKeyProviderType

protected final void mapKeyProviderType(Class forKeyProviderType,
                                        Class useKeyProviderType)
Subclasses must use this method to register default implementation classes for the interfaces KeyProvider and AesKeyProvider and optionally other subinterfaces or subclasses of KeyProvider. This is best done in the constructor of the subclass.

Parameters:
forKeyProviderType - The type which shall be substituted with useKeyProviderType when determining a suitable run time type in getKeyProvider(String, Class).
useKeyProviderType - The type which shall be substituted for forKeyProviderType when determining a suitable run time type in getKeyProvider(String, Class).
Throws:
NullPointerException - If any of the parameters is null.
IllegalArgumentException - If forKeyProviderType is not assignment compatible to the KeyProvider interface, or if useKeyProviderType is the same as forKeyProviderType, or if useKeyProviderType is not assignment compatible to forKeyProviderType, or if useKeyProviderType does not provide a public constructor with no parameters.
Since:
TrueZIP 6.1
See Also:
getKeyProvider(String, Class)

getKeyProvider

public KeyProvider getKeyProvider(String resourceID)
Deprecated. Use #getKeyProvider(String, Class) instead.

Equivalent to return getKeyProvider(resourceID, KeyProvider.class); - provided for convenience.


getKeyProvider

public KeyProvider getKeyProvider(String resourceID,
                                  Class keyProviderType)
                           throws NullPointerException,
                                  ClassCastException,
                                  IllegalArgumentException
Returns the KeyProvider for the given resource identifier. If no key provider is mapped, this key manager will determine an appropriate class which is assignment compatible to keyProviderType (but is not necessarily the same), instantiate it, map the instance for the protected resource and return it.

Client applications should specify an interface rather than an implementation as the keyProviderType in order to allow the key manager to instantiate a useful default implementation of this interface unless another key provider was already mapped for the protected resource.

Example: The following example asks the default key manager to provide a suitable implementation of the AesKeyProvider interface for a protected resource.

 String pathname = file.getCanonicalPath();
 KeyManager km = KeyManager.getInstance();
 KeyProvider kp = km.getKeyProvider(pathname, AesKeyProvider.class);
 Object key = kp.getCreateKey(); // may prompt the user
 int ks;
 if (kp instanceof AesKeyProvider) {
      // The run time type of the implementing class is determined
      // by the key manager.
      // Anyway, the AES key provider can be safely asked for a cipher
      // key strength.
      ks = ((AesKeyProvider) kp).getKeyStrength();
 } else {
      // Unfortunately, another key provider was already mapped for the
      // pathname before - use default key strength.
      ks = AesKeyProvider.KEY_STRENGTH_256;
 }
 
.

Parameters:
resourceID - The identifier of the protected resource.
keyProviderType - Unless another key provider is already mapped for the protected resource, this denotes the root of the class hierarchy to which the run time type of the returned instance may belong. In case the key manager does not know a more suitable class in this hierarchy, this parameter must denote an implementation of the KeyProvider interface with a public no-argument constructor.
Returns:
The KeyProvider mapped for the protected resource. If no key provider has been previously mapped for the protected resource, the run time type of this instance is guaranteed to be assignment compatible to the given keyProviderType.
Throws:
NullPointerException - If resourceID or keyProviderType is null.
ClassCastException - If no other key provider is mapped for the protected resource and the given class is not an implementation of the KeyProvider interface.
IllegalArgumentException - If any other precondition on the parameter keyProviderType does not hold.
See Also:
getInstance()

setKeyProvider

public void setKeyProvider(String resourceID,
                           KeyProvider provider)
                    throws NullPointerException,
                           IllegalStateException
Sets the key provider programmatically.

Warning: This method replaces any key provider previously associated with the given resource ID and installs it as the return value for getKeyProvider(java.lang.String). While this allows a reasonable level of flexibility, it may easily confuse users if they have already been prompted for a key by the previous provider before and may negatively affect the security if the provider is not properly guarded by the application. Use with caution only!

If you are using this method in order to set the key provider for a RAES encrypted ZIP file, then the resource ID must be the canonical or at least absolute path of this file - see File.getCanOrAbsPath().

Parameters:
resourceID - The resource identifier to associate the key provider with. For an RAES encrypted ZIP file, this must be the canonical path name of the archive file.
provider - The key provider for resourceID. For an RAES encrypted ZIP file, this must be an instance of the AesKeyProvider interface.
Throws:
NullPointerException - If resourceID or provider is null.
IllegalStateException - If mapping this instance is prohibited by a constraint in a subclass of AbstractKeyProvider. Please refer to the respective subclass documentation for more information about its constraint(s).