org.ccnx.ccn.io.content.KeyDirectory Class Reference

A key directory holds a key (secret or private), distributed to entities (represented by public keys), by a set of key blocks each of which wrapping that key under different target keys. More...

Inheritance diagram for org.ccnx.ccn.io.content.KeyDirectory:

org.ccnx.ccn.profiles.nameenum.EnumeratedNameList org.ccnx.ccn.profiles.nameenum.BasicNameEnumeratorListener org.ccnx.ccn.profiles.security.access.group.PrincipalKeyDirectory

List of all members.

Public Member Functions

 KeyDirectory (ContentName directoryName, CCNHandle handle) throws IOException
 Directory name should be versioned, else we pull the latest version; start enumeration.
 KeyDirectory (ContentName directoryName, boolean enumerate, CCNHandle handle) throws IOException
 Directory name should be versioned, else we pull the latest version.
boolean hasResult ()
 Subclasses should override this test to answer true if waiters should break out of a waitForNoUpdatesOrResult loop.
TreeSet< byte[]> getCopyOfWrappingKeyIDs () throws ContentNotReadyException
 Return a copy to avoid synchronization problems.
TreeSet< byte[]> getCopyOfOtherNames () throws ContentNotReadyException
 Returns a copy to avoid synchronization problems.
WrappedKeyObject getWrappedKeyForKeyID (byte[] keyID) throws ContentDecodingException, IOException
 Returns the wrapped key object corresponding to a public key specified by its digest.
ContentName getWrappedKeyNameForKeyID (byte[] keyID)
 Returns the wrapped key name for a public key specified by its digest.
boolean hasSupersededBlock () throws ContentNotReadyException
 Checks for the existence of a superseded block.
ContentName getSupersededBlockName ()
WrappedKeyObject getSupersededWrappedKey () throws ContentDecodingException, ContentNotReadyException, IOException
 We have several choices for how to represent superseded and previous keys.
WrappedKeyObject getWrappedKey (ContentName wrappedKeyName) throws ContentDecodingException, IOException
 Returns the wrapped key object corresponding to the specified wrapped key name.
boolean hasPreviousKeyBlock () throws ContentNotReadyException
 Checks for the existence of a previous key block.
ContentName getPreviousKeyBlockName ()
Link getPreviousKey (long timeout) throws ContentNotReadyException, IOException
 Returns a link to the previous key.
boolean hasPrivateKeyBlock () throws ContentNotReadyException
 We store a private key as a single block wrapped under a nonce key, which is then wrapped under the public keys of various principals.
ContentName getPrivateKeyBlockName ()
Key getUnwrappedKey (byte[] expectedKeyID) throws InvalidKeyException, ContentDecodingException, IOException, NoSuchAlgorithmException
 Unwrap and return the key wrapped in a wrapping key specified by its digest.
boolean isPrivateKeyInCache ()
PrivateKey getPrivateKey () throws AccessDeniedException, InvalidKeyException, ContentNotReadyException, ContentGoneException, ContentDecodingException, IOException, NoSuchAlgorithmException
 Returns the private key stored in the KeyDirectory.
WrappedKeyObject addWrappedKeyBlock (Key secretKeyToWrap, ContentName publicKeyName, PublicKey publicKey) throws ContentEncodingException, IOException, InvalidKeyException, VersionMissingException
 Writes a wrapped key block to the repository.
void addPrivateKeyBlock (PrivateKey privateKey, Key privateKeyWrappingKey) throws ContentEncodingException, IOException, InvalidKeyException
 Writes a private key block to the repository.
void addSupersededByBlock (Key oldPrivateKeyWrappingKey, ContentName storedSupersedingKeyName, byte[] storedSupersedingKeyID, Key newPrivateKeyWrappingKey) throws InvalidKeyException, ContentEncodingException, IOException
 Add a superseded-by block to our key directory.
void addPreviousKeyLink (ContentName previousKey, PublisherID previousKeyPublisher) throws ContentEncodingException, IOException
 Writes a link to a previous key to the repository.
void addPreviousKeyBlock (Key oldPrivateKeyWrappingKey, ContentName supersedingKeyName, Key newPrivateKeyWrappingKey) throws InvalidKeyException, ContentEncodingException, IOException
 Writes a previous key block to the repository.

Static Public Member Functions

static ContentName getSupersededBlockNameForKey (ContentName versionedKeyName)
static ContentName getPreviousKeyBlockName (ContentName keyDirectoryName)
static void addSupersededByBlock (ContentName oldKeyVersionedNameToAddBlockTo, Key oldKeyToBeSuperseded, ContentName storedSupersedingKeyName, byte[] storedSupersedingKeyID, Key supersedingKey, CCNHandle handle) throws ContentEncodingException, IOException, InvalidKeyException
 Add a superseded-by block to another node key, where we may have only its name, not its enumeration.

Static Public Attributes

static final byte[] SUPERSEDED_MARKER = "SupersededBy".getBytes()
static final byte[] PREVIOUS_KEY_NAME = "PreviousKey".getBytes()
static final byte[] GROUP_PUBLIC_KEY_NAME = "Key".getBytes()
static final byte[] GROUP_PRIVATE_KEY_NAME = "PrivateKey".getBytes()

Protected Member Functions

void initialize (boolean startEnumerating) throws IOException
 We don't start enumerating until we get here.
void processNewChildren (SortedSet< ContentName > newChildren)
 Called each time new data comes in, gets to parse it and load processed arrays.
void processNewChild (byte[] wkChildName)
WrappedKeyObject getPrivateKeyObject () throws ContentGoneException, IOException
 Returns the private key object, if one exists as a wrapped key object.
Key findUnwrappedKey (byte[] expectedKeyID) throws IOException, ContentNotReadyException, InvalidKeyException, ContentDecodingException, NoSuchAlgorithmException
Key unwrapKeyViaCache (byte[] keyIDOfCachedKeytoUse) throws ContentDecodingException, IOException, InvalidKeyException, NoSuchAlgorithmException
 Fast path -- once we have an idea which of our keys will unwrap this key, get it.
Key unwrapKeyViaCache () throws InvalidKeyException, ContentDecodingException, IOException, NoSuchAlgorithmException
Key unwrapKeyViaSupersededKey () throws InvalidKeyException, ContentDecodingException, IOException, NoSuchAlgorithmException
KeyDirectory factory (ContentName name) throws IOException

Protected Attributes

CCNHandle _handle
boolean cacheHit

Static Protected Attributes

static final Comparator< byte[]> byteArrayComparator = new ByteArrayCompare()

Package Attributes

TreeSet< byte[]> _keyIDs = new TreeSet<byte []>(byteArrayComparator)
 The set _keyIDs contains the digests of the (public) wrapping keys of the wrapped key objects stored in the KeyDirectory.
final ReadWriteLock _keyIDLock = new ReentrantReadWriteLock()
TreeSet< byte[]> _otherNames = new TreeSet<byte []>(byteArrayComparator)
 The set _otherNames records the presence of superseded keys, previous keys, group private keys, etc.
final ReadWriteLock _otherNamesLock = new ReentrantReadWriteLock()

Classes

class  NoPrivateKeyException


Detailed Description

A key directory holds a key (secret or private), distributed to entities (represented by public keys), by a set of key blocks each of which wrapping that key under different target keys.

If the key to be distributed is a private key, it is first wrapped under a nonce key, and that nonce key is stored encrypted under the keys of the receiving entitites.

Essentially a KeyDirectory is a software wrapper for managing a set of content stored in CCNx (writing and reading portions of that content); that content consists of a set of key blocks used to give one key to a number of target entities.

Key blocks are implemented as a set of wrapped key objects all stored in one directory. Wrapped key objects are typically short and only need one segment. The directory the keys are stored in is prefixed by a version, to allow the contents to evolve. In addition some potential supporting information pointing to previous or subsequent versions of this key is kept. A particular wrapped key entry's name would look like:

<keyname>/version/xxx/s0

Where xxx is the identifier of the wrapped key.

Our model is that higher-level function may use this interface to try many ways to get a given key. Some will work (access is allowed), some may not -- the latter does not mean that the principal doesn't have access, just that the principal doesn't have access by this route. So for the moment, we return null when we don't conclusively know that this principal doesn't have access to this data somehow, rather than throwing AccessDeniedException.


Constructor & Destructor Documentation

org.ccnx.ccn.io.content.KeyDirectory.KeyDirectory ( ContentName  directoryName,
CCNHandle  handle 
) throws IOException

Directory name should be versioned, else we pull the latest version; start enumeration.

Parameters:
manager the access control manager.
directoryName the root of the KeyDirectory.
handle 
Exceptions:
IOException 

org.ccnx.ccn.io.content.KeyDirectory.KeyDirectory ( ContentName  directoryName,
boolean  enumerate,
CCNHandle  handle 
) throws IOException

Directory name should be versioned, else we pull the latest version.

Parameters:
directoryName the root of the KeyDirectory.
handle 
Exceptions:
IOException 


Member Function Documentation

void org.ccnx.ccn.io.content.KeyDirectory.initialize ( boolean  startEnumerating  )  throws IOException [protected]

We don't start enumerating until we get here.

Exceptions:
IOException 

Reimplemented in org.ccnx.ccn.profiles.security.access.group.PrincipalKeyDirectory.

boolean org.ccnx.ccn.io.content.KeyDirectory.hasResult (  ) 

Subclasses should override this test to answer true if waiters should break out of a waitForNoUpdatesOrResult loop.

Note that results must be cleared manually using clearResult. Default behavior always returns false. Subclasses probably want to set a variable in processNewChildren that will be read here.

Reimplemented from org.ccnx.ccn.profiles.nameenum.EnumeratedNameList.

TreeSet<byte []> org.ccnx.ccn.io.content.KeyDirectory.getCopyOfWrappingKeyIDs (  )  throws ContentNotReadyException

Return a copy to avoid synchronization problems.

Exceptions:
ContentNotReadyException 

TreeSet<byte []> org.ccnx.ccn.io.content.KeyDirectory.getCopyOfOtherNames (  )  throws ContentNotReadyException

Returns a copy to avoid synchronization problems.

Exceptions:
ContentNotReadyException 

WrappedKeyObject org.ccnx.ccn.io.content.KeyDirectory.getWrappedKeyForKeyID ( byte[]  keyID  )  throws ContentDecodingException, IOException

Returns the wrapped key object corresponding to a public key specified by its digest.

Up to caller to decide when this is reasonable to call; should call available() on result.

Parameters:
keyID the digest of the specified public key.
Returns:
the corresponding wrapped key object.
Exceptions:
ContentDecodingException 
IOException 

ContentName org.ccnx.ccn.io.content.KeyDirectory.getWrappedKeyNameForKeyID ( byte[]  keyID  ) 

Returns the wrapped key name for a public key specified by its digest.

Parameters:
keyID the digest of the public key.
Returns:
the corresponding wrapped key name.

boolean org.ccnx.ccn.io.content.KeyDirectory.hasSupersededBlock (  )  throws ContentNotReadyException

Checks for the existence of a superseded block.

Exceptions:
ContentNotReadyException 

WrappedKeyObject org.ccnx.ccn.io.content.KeyDirectory.getSupersededWrappedKey (  )  throws ContentDecodingException, ContentNotReadyException, IOException

We have several choices for how to represent superseded and previous keys.

Ignoring for now the case where we might have to have more than one per key directory (e.g. if we represent removal of several interposed ACLs), we could have the wrapped key block stored in the superseded block location, and the previous key block be a link, or the previous key block be a wrapped key and the superseded location be a link. Or we could store wrapped key blocks in both places. Because the wrapped key blocks can contain the name of the key that wrapped them (but not the key being wrapped), they are in essence a pointer forward to the replacing key. So, the superseded block, if it contains a wrapped key, is both a key and a link. If the block was stored at the previous key, it would not be both a key and a link, as its wrapping key is indicated by where it is. So it should indeed be a link -- except in the case of an interposed ACL, where there is nothing to link to; and it instead stores a wrapped key block containing the effective node key that was the previous key. This method checks for the existence of a superseded block.

Returns:
Exceptions:
ContentNotReadyException 
ContentDecodingException 
IOException 

WrappedKeyObject org.ccnx.ccn.io.content.KeyDirectory.getWrappedKey ( ContentName  wrappedKeyName  )  throws ContentDecodingException, IOException

Returns the wrapped key object corresponding to the specified wrapped key name.

We know there is only one version of this object, so avoid getLatestVersion.

Parameters:
wrappedKeyName 
Returns:
Exceptions:
IOException 
ContentDecodingException 

boolean org.ccnx.ccn.io.content.KeyDirectory.hasPreviousKeyBlock (  )  throws ContentNotReadyException

Checks for the existence of a previous key block.

Exceptions:
ContentNotReadyException 

Link org.ccnx.ccn.io.content.KeyDirectory.getPreviousKey ( long  timeout  )  throws ContentNotReadyException, IOException

Returns a link to the previous key.

Previous key might be a link, if we're a simple newer version, or it might be a wrapped key, if we're an interposed node key. DKS TODO

Returns:
Exceptions:
IOException 
ContentNotReadyException 
ContentDecodingException 

boolean org.ccnx.ccn.io.content.KeyDirectory.hasPrivateKeyBlock (  )  throws ContentNotReadyException

We store a private key as a single block wrapped under a nonce key, which is then wrapped under the public keys of various principals.

The WrappedKey structure would allow us to do this (wrap private in public) in a single object, with an inline nonce key, but this option is more efficient. Checks for the existence of a private key block

Returns:
Exceptions:
ContentNotReadyException 

WrappedKeyObject org.ccnx.ccn.io.content.KeyDirectory.getPrivateKeyObject (  )  throws ContentGoneException, IOException [protected]

Returns the private key object, if one exists as a wrapped key object.

Does not check to see if we have a private key block; simply sends a request for it (saves the requirement to do enumeration). Callers should check available() on the result to see if we actually got one. In general, callers will know whether one should exist or not. hasPrivateKeyBlock can be used to test (after enumeration) whether one exists if you don't know.

Returns:
Exceptions:
IOException 
ContentGoneException 
ContentDecodingException 

Key org.ccnx.ccn.io.content.KeyDirectory.getUnwrappedKey ( byte[]  expectedKeyID  )  throws InvalidKeyException, ContentDecodingException, IOException, NoSuchAlgorithmException

Unwrap and return the key wrapped in a wrapping key specified by its digest.

Find a copy of the key block in this directory that we can unwrap (either the private key wrapping key block or a wrapped raw symmetric key). Chase superseding keys if we have to. This mechanism should be generic, and should work for node keys as well as private key wrapping keys in directories following this structure.

Returns:
Exceptions:
InvalidKeyException 
ContentDecodingException 
IOException 
NoSuchAlgorithmException 

Key org.ccnx.ccn.io.content.KeyDirectory.unwrapKeyViaCache ( byte[]  keyIDOfCachedKeytoUse  )  throws ContentDecodingException, IOException, InvalidKeyException, NoSuchAlgorithmException [protected]

Fast path -- once we have an idea which of our keys will unwrap this key, get it.

Can be called after enumeration, or if we have a guess of what key to use.

Parameters:
keyIDOfCachedKeytoUse 
Returns:
Exceptions:
IOException 
ContentDecodingException 
NoSuchAlgorithmException 
InvalidKeyException 

boolean org.ccnx.ccn.io.content.KeyDirectory.isPrivateKeyInCache (  ) 

Returns:
true if the private key is in the secure key cache.

PrivateKey org.ccnx.ccn.io.content.KeyDirectory.getPrivateKey (  )  throws AccessDeniedException, InvalidKeyException, ContentNotReadyException, ContentGoneException, ContentDecodingException, IOException, NoSuchAlgorithmException

Returns the private key stored in the KeyDirectory.

The private key is wrapped in a wrapping key, which is itself wrapped. So the unwrapping proceeds in two steps. First, we unwrap the wrapping key for the private key. Then, we unwrap the private key itself. Relies on the caller, who presumably knows the public key, to add the result to the cache.

Returns:
Exceptions:
AccessDeniedException 
ContentGoneException 
ContentNotReadyException 
InvalidKeyException 
ContentDecodingException 
IOException 
NoSuchAlgorithmException 

WrappedKeyObject org.ccnx.ccn.io.content.KeyDirectory.addWrappedKeyBlock ( Key  secretKeyToWrap,
ContentName  publicKeyName,
PublicKey  publicKey 
) throws ContentEncodingException, IOException, InvalidKeyException, VersionMissingException

Writes a wrapped key block to the repository.

Eventually aggregate signing and repo stream operations at the very least across writing paired objects and links, preferably across larger swaths of data.

Parameters:
secretKeyToWrap either a node key, a data key, or a private key wrapping key
publicKeyName the name of the public key.
publicKey the public key.
Exceptions:
ContentEncodingException 
IOException 
InvalidKeyException 
VersionMissingException 
VersionMissingException 

Reimplemented in org.ccnx.ccn.profiles.security.access.group.PrincipalKeyDirectory.

void org.ccnx.ccn.io.content.KeyDirectory.addPrivateKeyBlock ( PrivateKey  privateKey,
Key  privateKeyWrappingKey 
) throws ContentEncodingException, IOException, InvalidKeyException

Writes a private key block to the repository.

Parameters:
privateKey the private key.
privateKeyWrappingKey the wrapping key used to wrap the private key.
Exceptions:
ContentEncodingException 
IOException 
InvalidKeyException 

void org.ccnx.ccn.io.content.KeyDirectory.addSupersededByBlock ( Key  oldPrivateKeyWrappingKey,
ContentName  storedSupersedingKeyName,
byte[]  storedSupersedingKeyID,
Key  newPrivateKeyWrappingKey 
) throws InvalidKeyException, ContentEncodingException, IOException

Add a superseded-by block to our key directory.

Parameters:
oldPrivateKeyWrappingKey 
supersedingKeyName 
newPrivateKeyWrappingKey 
Exceptions:
ContentEncodingException 
IOException 
InvalidKeyException 

static void org.ccnx.ccn.io.content.KeyDirectory.addSupersededByBlock ( ContentName  oldKeyVersionedNameToAddBlockTo,
Key  oldKeyToBeSuperseded,
ContentName  storedSupersedingKeyName,
byte[]  storedSupersedingKeyID,
Key  supersedingKey,
CCNHandle  handle 
) throws ContentEncodingException, IOException, InvalidKeyException [static]

Add a superseded-by block to another node key, where we may have only its name, not its enumeration.

Use as a static method to add our own superseded-by blocks as well.

Exceptions:
ContentEncodingException 
IOException 
InvalidKeyException 

void org.ccnx.ccn.io.content.KeyDirectory.addPreviousKeyLink ( ContentName  previousKey,
PublisherID  previousKeyPublisher 
) throws ContentEncodingException, IOException

Writes a link to a previous key to the repository.

Parameters:
previousKey 
previousKeyPublisher 
Exceptions:
ContentEncodingException 
IOException 

void org.ccnx.ccn.io.content.KeyDirectory.addPreviousKeyBlock ( Key  oldPrivateKeyWrappingKey,
ContentName  supersedingKeyName,
Key  newPrivateKeyWrappingKey 
) throws InvalidKeyException, ContentEncodingException, IOException

Writes a previous key block to the repository.

Parameters:
oldPrivateKeyWrappingKey 
supersedingKeyName 
newPrivateKeyWrappingKey 
Exceptions:
InvalidKeyException 
ContentEncodingException 
IOException 


The documentation for this class was generated from the following file:

Generated on Thu Feb 16 00:45:02 2012 for Content-Centric Networking in Java by  doxygen 1.5.6