/*
* Part of the CCNx Java Library.
*
* Copyright (C) 2008, 2009 Palo Alto Research Center, Inc.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 2.1
* as published by the Free Software Foundation.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. You should have received
* a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.ccnx.ccn.impl.security.keys;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyStore;
import org.ccnx.ccn.CCNHandle;
import org.ccnx.ccn.config.ConfigurationException;
import org.ccnx.ccn.config.SystemConfiguration;
import org.ccnx.ccn.impl.support.Log;
import org.ccnx.ccn.impl.support.Tuple;
import org.ccnx.ccn.io.CCNVersionedInputStream;
import org.ccnx.ccn.io.CCNVersionedOutputStream;
import org.ccnx.ccn.io.content.ContentEncodingException;
import org.ccnx.ccn.profiles.VersioningProfile;
import org.ccnx.ccn.protocol.CCNTime;
import org.ccnx.ccn.protocol.ContentName;
import org.ccnx.ccn.protocol.ContentObject;
import org.ccnx.ccn.protocol.PublisherPublicKeyDigest;
/**
* This is a network-based implementation of key manager.
* In comparison with BasicKeyManager, this class reads (or writes) the user's
* private key (as a java keystore) from (or to) CCN.
* @see BasicKeyManager, KeyManager
*/
public class NetworkKeyManager extends BasicKeyManager {
ContentName _keystoreName;
PublisherPublicKeyDigest _publisher;
/** Constructor
* @param userName
* @param keystoreName
* @param publisher
* @param password
* @throws ConfigurationException
* @throws IOException
*/
public NetworkKeyManager(String userName,
ContentName keystoreName,
PublisherPublicKeyDigest publisher,
char [] password) throws ConfigurationException, IOException {
// key repository created by superclass constructor
super(userName, null, null, password);
_keystoreName = keystoreName;
_publisher = publisher;
// loading done by initialize()
}
/**
* Reads the user's keys from CCN
* @throws ConfigurationException
*/
@Override
protected KeyStoreInfo loadKeyStore() throws ConfigurationException, IOException {
// Is there an existing version of this key store? don't assume repo, so don't enumerate.
// timeouts should be ok.
// DKS TODO -- once streams pull first block on creation, don't need this much work.
ContentObject keystoreObject = null;
KeyStoreInfo keyStoreInfo = null;
try {
keystoreObject =
VersioningProfile.getFirstBlockOfLatestVersion(_keystoreName, null, _publisher,
SystemConfiguration.getDefaultTimeout(),
new ContentObject.SimpleVerifier(_publisher, this), handle());
if (null == keystoreObject) {
Log.info("Creating new CCN key store..." + _keystoreName);
keyStoreInfo = createKeyStore();
}
} catch (IOException e) {
Log.warning("Cannot get first block of existing key store: " + _keystoreName);
throw e;
}
if ((null == keyStoreInfo) && (null != keystoreObject)){
CCNVersionedInputStream in = null;
Log.info("Loading CCN key store from " + _keystoreName + "...");
try {
in = new CCNVersionedInputStream(keystoreObject, null, handle());
KeyStore keyStore = readKeyStore(in);
keyStoreInfo = new KeyStoreInfo(_keystoreName.toURIString(), keyStore, in.getVersion());
} catch (IOException e) {
Log.warning("Cannot open existing key store: " + _keystoreName);
throw e;
}
}
return keyStoreInfo;
}
protected CCNTime getKeyStoreVersion(OutputStream out) throws IOException {
// in our case, our output stream should be a file output stream...
if (!(out instanceof CCNVersionedOutputStream)) {
throw new IOException("Unexpected output stream type in getKeyStoreVersion: " + out.getClass().getName());
}
return ((CCNVersionedOutputStream)out).getVersion();
}
/**
* Override to give different storage behavior.
* Output stream is CCN
* @return
* @throws ContentEncodingException
* @throws IOException
*/
@Override
protected Tuple<KeyStoreInfo, OutputStream> createKeyStoreWriteStream() throws IOException {
// Pull the version after we write
return new Tuple<KeyStoreInfo, OutputStream>(new KeyStoreInfo(_keystoreName.toURIString(), null, null),
new CCNVersionedOutputStream(_keystoreName, CCNHandle.getHandle()));
}
@Override
public URI getConfigurationDataURI() {
try {
return new URI(_keystoreName.toURIString());
} catch (URISyntaxException e) {
Log.warning(Log.FAC_ENCODING, "Cannot parse CCN URI {0} as Java URI!", _keystoreName.toURIString());
return null;
}
}
}