package edu.harvard.i2b2.crc.loader.util.security;
import java.io.*;
import java.text.*;
import java.util.*;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.jdom.input.*;
import org.jdom.*;
//import edu.harvard.i2b2.util.Constant;
public class KeyExtractor {
/**
* @param args
*/
private static String keyServer;
private static String keyFile;
private static String removableDeviceLocation = "A:";
/**
* Will encrypt the master key on the floppy disk
* It uses the serial number on the logicaldisk as the key
* It thans uses the binhex to encrypt the master key
*
*/
public static boolean setRemoveableDeviceKey(String masterKey, String clientHalfKey, String label, String comment) throws Exception
{
label = label.toUpperCase();
if (clientHalfKey.length() != 8)
throw new Exception("Key Length needs to be 8 characters");
File findKey = new File(removableDeviceLocation + File.pathSeparator + keyFile);
if (findKey.exists())
throw new Exception("Master Key already exists on this device");
//Check to see if half key already exists
try
{
getHalfKey(label);
// Should of gotten a exception that it wasn't fonud. So it already exists
throw new Exception(label + " already exists, select a different name");
}
catch (Exception e)
{
setHalfKey(label, clientHalfKey, comment);
// Couldn't find it, so that is a good thing
}
//catch (Exception e)
//{
// throw e;
//}
//ManagementObject disk = null;
File output = null;
BufferedWriter brWriter = null;
try
{
//TODO Convert to Java somehow
/*
disk =
new ManagementObject("win32_logicaldisk.deviceid=\"A:\"");
disk.Get();
string key = disk.GetPropertyValue("VolumeSerialNumber").ToString().Substring(0,8) + clientHalfKey;
disk.SetPropertyValue("VolumeName", label);
disk.Put();
*/
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
// Instantiate the cipher
javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES");
cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted =
cipher.doFinal(masterKey.getBytes());
String ciphertext = asHex(encrypted);
//RijndaelAlgorithm ra = new RijndaelAlgorithm(key,16,32);
//String ciphertext = ra.binhexEncrypt(masterKey); // RijndaelAlgorithm.Encrypt(plaintext,key);
output = new File(removableDeviceLocation + File.pathSeparator + keyFile);
brWriter = new BufferedWriter(new PrintWriter(output));
brWriter.write(ciphertext);
brWriter.close();
//Move current XML doc to backup
java.util.Date currentdate = new java.util.Date();
SimpleDateFormat formatter = new SimpleDateFormat("MMddyyyy-hhmm", Locale.getDefault());
// Move temp files
output = new File(keyServer);
output.renameTo(new File(keyServer + formatter.format(currentdate)));
output = new File(keyServer + ".tmp");
output.renameTo(new File(keyServer));
}
catch (Exception e)
{
//if (brWriter != null)
// brWriter.close();
throw e;
//
}
return true;
}
/**
* Turns array of bytes into string
*
* @param buf Array of bytes to convert to hex string
* @return Generated hex string
*/
public static String asHex (byte buf[]) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
int i;
for (i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
/**
* Private function that will retrieve the the other half of the master key from the
* network share xml document
*
* @paraminput String label
* @return String key
*
*/
private static String getHalfKey(String label) throws Exception
{
Document doc = new Document();
SAXBuilder builder = new SAXBuilder();
String results = null;
try
{
doc = builder.build(new File(keyServer));
List i2b2 = doc.getRootElement().getChildren(label);
for (Iterator i = i2b2.iterator(); i.hasNext();) {
Element e = (Element)i.next();
results= e.getChild("key").getText();
}
}
catch (Exception e)
{
throw e;
}
return results;
}
/**
* Private function that will retrieve the the other half of the master key from the
* network share xml document
*
*/
private static void setHalfKey(String label, String key, String comment) throws Exception
{
label = label.toUpperCase();
//TODO lots of work
if (getHalfKey(label) != null)
throw new Exception("Key (" + label + ") already exists in file.");
Document doc = new Document();
SAXBuilder builder = new SAXBuilder();
String results = null;
try
{
Element e = new Element(label);
e.addContent(new Element("key").setText(key));
e.addContent(new Element("comment").setText(comment));
doc = builder.build(new File(keyServer));
org.jdom.output.XMLOutputter out = new org.jdom.output.XMLOutputter();
List list = doc.getRootElement().getChildren(label);
list.add(e);
} catch (Exception e)
{
throw e;
}
/*
XmlDocument XMLDoc = new XmlDocument();
XmlTextReader myXmlURLreader = new XmlTextReader(keyServer);
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = System.Net.CredentialCache.DefaultCredentials;
myXmlURLreader.XmlResolver = resolver;
XMLDoc.Load(myXmlURLreader);
XmlNode newFloppy = XMLDoc.CreateNode(XmlNodeType.Element, label.ToUpper(), "");
XmlNode newKey = XMLDoc.CreateNode(XmlNodeType.Element, "key", "");
newKey.InnerText = key;
newFloppy.AppendChild(newKey);
XmlNode newComment = XMLDoc.CreateNode(XmlNodeType.Element, "comment", "");
newComment.InnerText = comment;
newFloppy.AppendChild(newComment);
XMLDoc.DocumentElement.AppendChild(newFloppy);
XMLDoc.Save(keyServer + ".tmp");
myXmlURLreader.Close();
*/
}
/**
* Private function that will retrieve the master key from the floppy drive
* Will use the serial number on the device as the key
*
*/
public static String getFloppyKey() throws Exception
{
return getFloppyKey(null, null);
}
/**
* Private function that will retrieve the master key from the floppy drive
* Will use the serial number on the device as the key
*
*/
public static String getFloppyKey(String label, String key) throws Exception
{
String deKey = null;
File inputFile = new File (removableDeviceLocation + File.separator + keyFile);
if (inputFile.exists()) {
try {
FileReader ist = new FileReader(inputFile);
//InputStream ist = new FileInputStream(removableDeviceLocation + File.pathSeparator + keyFile);
BufferedReader istream = new BufferedReader(ist); //new InputStreamReader(ist));
String text[] = new String[2];
text[0] = istream.readLine(); //just read the first line in the text file
text[1] = istream.readLine(); //Read in the label for the the file
if (text[1] != null)
{
if (text[1].length() < 9)
throw new Exception ("Floppy Key label must be greater than 8 characters");
key = text[1].substring(text[1].length()-8); //Last 8 characters
label = text[1].substring(0,text[1].length()-8);
//text[1] = label;
}
key += getHalfKey(label);
RijndaelAlgorithm ra = new RijndaelAlgorithm(key,128); //, "AES");
deKey = ra.decrypt(text[0]);
} catch (Exception e)
{
}
return deKey;
}
else
{
return null;
}
/*
if (File.Exists("A:\\" + msKeyFile))
{
Stream s = File.OpenRead("A:\\" + msKeyFile);
StreamReader sr = new StreamReader(s);
String lineIn = sr.ReadLine();
if( lineIn != null )
{
ManagementObject disk =
new ManagementObject("win32_logicaldisk.deviceid=\"A:\"");
disk.Get();
//old
//key = disk.GetPropertyValue("VolumeSerialNumber").ToString();
key = disk.GetPropertyValue("VolumeSerialNumber").ToString().Substring(0,8);
string label = disk.GetPropertyValue("VolumeName").ToString();
key += getHalfKey(label);
RijndaelAlgorithm ra = new RijndaelAlgorithm(key,16,32);
key = ra.binhexDecrypt(lineIn);
}
sr.Close();
s.Close();
return key;
}
else
return key;
*/
}
public static void main(String[] args) {
KeyExtractor keye = new KeyExtractor();
try {
keye.setKeyServer("\\\\plato\\Load_Programs\\Ceas\\ceas.xml");
keye.setRemovableDeviceLocation("A:");
keye.setKeyFile("A1234.txt");
String mykey = keye.getFloppyKey(); //"MIKENEW");
int i=0;
} catch (Exception e)
{e.printStackTrace();}
// TODO Auto-generated method stub
}
public static String getKeyServer() {
return keyServer;
}
public static void setKeyServer(String keyServer) {
KeyExtractor.keyServer = keyServer;
}
public static String getRemovableDeviceLocation() {
return removableDeviceLocation;
}
public static void setRemovableDeviceLocation(String removableDeviceLocation) {
KeyExtractor.removableDeviceLocation = removableDeviceLocation;
}
public static String getKeyFile() {
return keyFile;
}
public static void setKeyFile(String keyFile) {
KeyExtractor.keyFile = keyFile;
}
}