package jfconfig;
import java.security.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.DataInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.security.spec.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Collection;
import java.util.Iterator;
/**
* ImportKey.java
*
* <p>This class imports a key and a certificate into a keystore.
* If the keystore is
* already present, it is simply deleted. Both the key and the
* certificate file must be in <code>DER</code>-format. The key must be
* encoded with <code>PKCS#8</code>-format. The certificate must be
* encoded in <code>X.509</code>-format.</p>
*
* <p>Key format:</p>
* <p><code>openssl pkcs8 -topk8 -nocrypt -in YOUR.KEY -out YOUR.KEY.der -outform der</code></p>
* <p>Format of the certificate:</p>
* <p><code>openssl x509 -in YOUR.CERT -out YOUR.CERT.der -outform der</code></p>
* <p>Import key and certificate:</p>
* <p><code>java javaforce.ImportKey YOUR.KEY.der YOUR.CERT.der</code></p><br />
*
* <p><em>Caution:</em> the old <code>keystore</code>-file is
* deleted and replaced with a keystore only containing <code>YOUR.KEY</code>
* and <code>YOUR.CERT</code>. The keystore and the key has no password;
* they can be set by the <code>keytool -keypasswd</code>-command for setting
* the key password, and the <code>keytool -storepasswd</code>-command to set
* the keystore password.
* <p>The key and the certificate is stored under the alias
* <code>tomcat</code>; to change this, use <code>keytool -keyclone</code>.
*
* Created: Fri Apr 13 18:15:07 2001
* Updated: Fri Apr 19 11:03:00 2002
*
* @author Joachim Karrer, Jens Carlberg
*
* Modified for jfLinux by Peter Quiring
*
* @version 1.1
**/
public class ImportKey {
/**
* <p>Creates an InputStream from a file, and fills it with the complete
* file. Thus, available() on the returned InputStream will return the
* full number of bytes the file contains</p>
* @param fname The filename
* @return The filled InputStream
* @exception IOException, if the Streams couldn't be created.
**/
private static byte[] getBytes(InputStream fis) throws IOException {
DataInputStream dis = new DataInputStream(fis);
byte[] bytes = new byte[dis.available()];
dis.readFully(bytes);
return bytes;
}
private static InputStream createInputStream(byte bytes[]) {
return new ByteArrayInputStream(bytes);
}
/**
* <p>Takes two file names for a key and the certificate for the key,
* and imports those into a keystore. Optionally it takes an alias
* for the key.
* <p>The first argument is the filename for the key. The key should be
* in PKCS8-format.
* <p>The second argument is the filename for the certificate for the key.
* <p>If a third argument is given it is used as the alias. If missing,
* the key is imported with the alias importkey
* <p>The name of the keystore file can be controlled by setting
* the keystore property(java -Dkeystore=mykeystore). If no name
* is given, the file is named <code>keystore.ImportKey</code>
* and placed in your home directory.
* @param args [0] Name of the key file, [1] Name of the certificate file
* [2] Alias for the key.
**/
public static String importKeys(InputStream certFile, InputStream keyFile, String path) {
StringBuffer errmsg = new StringBuffer();
// change this if you want another password by default
String keypass = "changeit";
// change this if you want another alias by default
String defaultalias = "tomcat";
// change this if you want another keystorefile by default
String keystorename = path;
try {
// initializing and clearing keystore
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
ks.load( null , keypass.toCharArray());
// System.out.println("Using keystore-file : " + keystorename);
ks.store(new FileOutputStream(keystorename), keypass.toCharArray());
ks.load(new FileInputStream(keystorename), keypass.toCharArray());
// loading Key
byte[] key = new byte[keyFile.available()];
keyFile.read(key, 0, keyFile.available());
keyFile.close();
KeyFactory kf = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec(key);
PrivateKey ff = kf.generatePrivate(keysp);
// loading CertificateChain
CertificateFactory cf = CertificateFactory.getInstance("X.509");
byte[] certBytes = getBytes(certFile);
InputStream certStream = createInputStream(certBytes);
Collection c = cf.generateCertificates(certStream);
Certificate[] certs = new Certificate[c.toArray().length];
if (c.size() == 1) {
certStream = createInputStream(certBytes); //reset stream
errmsg.append("Notice:One certificate, no chain.<br>");
Certificate cert = cf.generateCertificate(certStream);
certs[0] = cert;
} else {
errmsg.append("Notice:Certificate chain length: " + c.size() + "<br>");
certs = (Certificate[])c.toArray();
}
// storing keystore
ks.setKeyEntry(defaultalias, ff, keypass.toCharArray(), certs);
errmsg.append("Key and certificate stored.<br>");
// errmsg.append("Alias:"+defaultalias+" Password:"+keypass);
ks.store(new FileOutputStream(keystorename), keypass.toCharArray());
} catch (Exception e) {
errmsg.append(e.toString());
}
return errmsg.toString();
}
public static String status(String path) {
StringBuffer errmsg = new StringBuffer();
errmsg.append("KeyStore Location : " + path + "/.keystore<br>");
errmsg.append("SSL Key Status : ");
// change this if you want another password by default
String keypass = "changeit";
// change this if you want another keystorefile by default
String keystorename = path + "/.keystore";
try {
// initializing and clearing keystore
KeyStore ks = KeyStore.getInstance("JKS", "SUN");
ks.load(new FileInputStream(keystorename), keypass.toCharArray());
if (ks.containsAlias("tomcat")) {
if (ks.size() < 2) {
errmsg.append("Your keystore looks okay.");
} else {
errmsg.append("You are missing some keys.");
}
} else {
errmsg.append("Your keystore does NOT contain the proper alias.");
}
} catch (FileNotFoundException fnfe) {
errmsg.append("Your keystore does NOT exist.");
} catch (Exception e) {
errmsg.append(e.toString());
}
errmsg.append("<br>");
return errmsg.toString();
}
public static String importKeyStore(InputStream keyStore, String path) {
//just copy over keystore
StringBuffer errmsg = new StringBuffer();
// change this if you want another keystorefile by default
String keystorename = path + "../../.keystore";
try {
int size = keyStore.available();
byte buf[] = new byte[size];
keyStore.read(buf, 0, size);
FileOutputStream fos = new FileOutputStream(keystorename);
fos.write(buf, 0, size);
fos.close();
errmsg.append("KeyStore upload successful");
} catch (Exception e) {
errmsg.append(e.toString());
}
return errmsg.toString();
}
}// KeyStore