package de.persosim.simulator.perso.xstream; import static org.globaltester.logging.BasicLogger.DEBUG; import static org.globaltester.logging.BasicLogger.ERROR; import static org.globaltester.logging.BasicLogger.log; import java.security.Key; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.globaltester.cryptoprovider.Crypto; import com.thoughtworks.xstream.XStreamException; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; import de.persosim.simulator.crypto.certificates.CvKey; import de.persosim.simulator.utils.HexString; /** * This class is a converter which is responsible for for serializing/deserializing all kind of key objects. * * @author jgoeke * */ public class KeyConverter implements Converter { String keyType = ""; String algorithmValue = ""; String byteValue = ""; @Override public boolean canConvert(@SuppressWarnings("rawtypes") Class type) { if (CvKey.class.isAssignableFrom(type)){ return false; } if (Key.class.isAssignableFrom(type)){ return true; } return false; } @Override public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { Key key = (Key) value; writer.startNode("algorithm"); writer.setValue(key.getAlgorithm()); writer.endNode(); writer.startNode("value"); writer.setValue(HexString.encode(key.getEncoded())); writer.endNode(); } public void getValuesFromXML(HierarchicalStreamReader reader, UnmarshallingContext context) { while (reader.hasMoreChildren()) { keyType = reader.getNodeName().toLowerCase(); reader.moveDown(); String nodeName = reader.getNodeName(); switch(nodeName) { case "algorithm": algorithmValue = reader.getValue().replace("\n", "").replace(" ", ""); break; case "value": byteValue = reader.getValue().replace("\n", "").replace(" ", ""); break; } if(reader.hasMoreChildren()) { getValuesFromXML(reader, context); } reader.moveUp(); } } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { PrivateKey sk = null; PublicKey pk = null; getValuesFromXML (reader, context); if (byteValue == null || algorithmValue == null || algorithmValue.equals("") || byteValue.equals("")) { log(getClass(), "can not create "+ keyType +" object, unmarshal failed", ERROR); throw new XStreamException("can not create "+ keyType +" object, unmarshal failed!"); } PKCS8EncodedKeySpec ks_priv = new PKCS8EncodedKeySpec (HexString.toByteArray(byteValue)); X509EncodedKeySpec ks_pub = new X509EncodedKeySpec (HexString.toByteArray(byteValue)); //XXX split into private and public key converters try { pk = KeyFactory.getInstance(algorithmValue, Crypto.getCryptoProvider()).generatePublic(ks_pub); } catch (InvalidKeySpecException| NoSuchAlgorithmException e1) { log(getClass(), "this is not a valid public key", DEBUG); try { sk = KeyFactory.getInstance(algorithmValue, Crypto.getCryptoProvider()).generatePrivate(ks_priv); } catch (InvalidKeySpecException| NoSuchAlgorithmException e2) { log(getClass(), "this is also not a valid private key", DEBUG); throw new XStreamException("Neither a valid private nor public key could be extracted", e2); } } if (pk != null) { return pk; } else { return sk; } } }