package edu.uw.cse.netlab.reputation; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.security.Key; import java.security.KeyPair; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.logging.Logger; import org.gudy.azureus2.core3.util.SystemProperties; import sun.security.x509.CertAndKeyGen; import sun.security.x509.X500Name; public class LocalIdentity { private static Logger logger = Logger.getLogger(LocalIdentity.class.getName()); // DEFAULTS public static final int KEY_SIZE_BITS = 1024; public static final String PRIVATE_KEY_ALIAS = "OneSwarm_local_private_key"; public static final String KEY_STORE_NAME = "oneswarm.keystore"; KeyPair mKeys = null; private X509Certificate mLocalCertificate = null; private static LocalIdentity mInstance = null; static { try { mInstance = new LocalIdentity(); } catch( Exception e ) { logger.severe("Couldn't create local identity: " + e); } } private LocalIdentity() throws Exception { mKeys = loadOrGenerateKeys(); } public static LocalIdentity get() { return mInstance; } public KeyPair getKeys() { return mKeys; } public X509Certificate getCertificate() { return mLocalCertificate; } private String getKeyStorePath() { if( System.getProperty("keystore") == null ) return SystemProperties.getUserPath() + "/" + KEY_STORE_NAME; else return System.getProperty("keystore") + "/" + KEY_STORE_NAME; } public KeyPair loadOneSwarmKeyPair( String inPassword ) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException { File keystoreFile = new File(getKeyStorePath()); FileInputStream fis = new FileInputStream(keystoreFile); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(fis, inPassword.toCharArray()); Key privateKey = ks.getKey(PRIVATE_KEY_ALIAS, inPassword.toCharArray()); Certificate cert = ks.getCertificate(PRIVATE_KEY_ALIAS); mLocalCertificate = (X509Certificate)cert; PublicKey publicKey = cert.getPublicKey(); if( !(privateKey instanceof PrivateKey) ) throw new IOException(PRIVATE_KEY_ALIAS + " is not of type PrivateKey / " + privateKey.getClass().getName() ); logger.fine("loaded local key pair"); return new KeyPair(publicKey, (PrivateKey)privateKey); } public void saveOneSwarmKeyPair( CertAndKeyGen inKeyPair, Certificate [] inCertChain, char [] inPassword ) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { // Create a keystore for the private key and public key certificate KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); String password = "foobear"; ks.load(null, password.toCharArray()); ks.setKeyEntry(PRIVATE_KEY_ALIAS, inKeyPair.getPrivateKey(), password.toCharArray(), inCertChain ); // Save the key store file as temp... File file = new File(getKeyStorePath()); FileOutputStream fos = new FileOutputStream(file); ks.store(fos, password.toCharArray()); fos.flush(); fos.close(); logger.fine("saved local key pair"); } public KeyPair loadOrGenerateKeys() throws Exception { KeyPair keys = null; X500Name certName = new X500Name("OneSwarm User", "Organiational Unit", "Organization", "City/Locality", "State/Province", "CountryCode"); try { keys = loadOneSwarmKeyPair("foobear"); } catch( Exception e ) { logger.fine("couldn't load existing key store: " + e); // Generate public/private key pair and self-signed certificate CertAndKeyGen keyPair = new CertAndKeyGen("RSA", "SHA1withRSA", null); keyPair.generate(KEY_SIZE_BITS); // This certificate is good for ~100 years X509Certificate[] chain = new X509Certificate[1]; int validDays = 100*365; chain[0] = keyPair.getSelfCertificate(certName, 60*60*24*validDays); mLocalCertificate = chain[0]; saveOneSwarmKeyPair( keyPair, chain, "foobear".toCharArray() ); keys = new KeyPair(keyPair.getPublicKey(), keyPair.getPrivateKey()); } return keys; } public void exportLocalCertificate( File outFile ) throws IOException { if( mLocalCertificate == null ) throw new IOException("no local certificate exists!"); try { (new FileOutputStream(outFile)).write(mLocalCertificate.getEncoded()); } catch (CertificateEncodingException e) { throw new IOException("Certificate encoding exception: " + e); } } }